diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index da3247de3b118..3e0016ee40170 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -75,6 +75,7 @@ fn fold_foreign_mod(cx: ctxt, nm: ast::foreign_mod, |a| filter_view_item(cx, *a)); return { sort: nm.sort, + abi: nm.abi, view_items: vec::map(filtered_view_items, |x| fld.fold_view_item(*x)), items: filtered_items }; diff --git a/src/librustc/middle/borrowck.rs b/src/librustc/middle/borrowck.rs index 25e184c2c02c3..5745d2e84bff1 100644 --- a/src/librustc/middle/borrowck.rs +++ b/src/librustc/middle/borrowck.rs @@ -513,6 +513,16 @@ impl borrowck_ctxt { cat_expr(self.tcx, self.method_map, expr) } + fn cat_expr_unadjusted(expr: @ast::expr) -> cmt { + cat_expr_unadjusted(self.tcx, self.method_map, expr) + } + + fn cat_expr_autoderefd(expr: @ast::expr, + adj: @ty::AutoAdjustment) + -> cmt { + cat_expr_autoderefd(self.tcx, self.method_map, expr, adj) + } + fn cat_def(id: ast::node_id, span: span, ty: ty::t, diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 366dd7e7e8504..03bd403bf461d 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -362,7 +362,12 @@ impl check_loan_ctxt { } fn check_assignment(at: assignment_type, ex: @ast::expr) { - let cmt = self.bccx.cat_expr(ex); + // We don't use cat_expr() here because we don't want to treat + // auto-ref'd parameters in overloaded operators as rvalues. + let cmt = match self.bccx.tcx.adjustments.find(ex.id) { + None => self.bccx.cat_expr_unadjusted(ex), + Some(adj) => self.bccx.cat_expr_autoderefd(ex, adj) + }; debug!("check_assignment(cmt=%s)", self.bccx.cmt_to_repr(cmt)); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index ebc06435c64e6..9eafec930f6e4 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -573,6 +573,29 @@ fn cat_expr( return mcx.cat_expr(expr); } +fn cat_expr_unadjusted( + tcx: ty::ctxt, + method_map: typeck::method_map, + expr: @ast::expr) -> cmt { + + let mcx = &mem_categorization_ctxt { + tcx: tcx, method_map: method_map + }; + return mcx.cat_expr_unadjusted(expr); +} + +fn cat_expr_autoderefd( + tcx: ty::ctxt, + method_map: typeck::method_map, + expr: @ast::expr, + adj: @ty::AutoAdjustment) -> cmt { + + let mcx = &mem_categorization_ctxt { + tcx: tcx, method_map: method_map + }; + return mcx.cat_expr_autoderefd(expr, adj); +} + fn cat_def( tcx: ty::ctxt, method_map: typeck::method_map, diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 2e4d95acdfbd0..4927d2773c190 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1572,7 +1572,7 @@ fn trans_assign_op(bcx: block, debug!("trans_assign_op(expr=%s)", bcx.expr_to_str(expr)); // Evaluate LHS (destination), which should be an lvalue - let dst_datum = unpack_datum!(bcx, trans_lvalue(bcx, dst)); + let dst_datum = unpack_datum!(bcx, trans_lvalue_unadjusted(bcx, dst)); // A user-defined operator method if bcx.ccx().maps.method_map.find(expr.id).is_some() { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 353bb26ea9ead..c277aee27dee3 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1861,6 +1861,7 @@ impl foreign_abi : cmp::Eq { #[auto_deserialize] type foreign_mod = {sort: foreign_mod_sort, + abi: ident, view_items: ~[@view_item], items: ~[@foreign_item]}; diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 9d57b5ae814f6..dc7a7feff14e0 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -546,8 +546,9 @@ fn noop_fold_mod(m: _mod, fld: ast_fold) -> _mod { fn noop_fold_foreign_mod(nm: foreign_mod, fld: ast_fold) -> foreign_mod { return {sort: nm.sort, - view_items: vec::map(nm.view_items, |x| fld.fold_view_item(*x)), - items: vec::map(nm.items, |x| fld.fold_foreign_item(*x))} + abi: nm.abi, + view_items: vec::map(nm.view_items, |x| fld.fold_view_item(*x)), + items: vec::map(nm.items, |x| fld.fold_foreign_item(*x))} } fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f340a52a4e7d6..e4d77e7da095f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3043,8 +3043,9 @@ impl Parser { } fn parse_foreign_mod_items(sort: ast::foreign_mod_sort, - +first_item_attrs: ~[attribute]) -> - foreign_mod { + +abi: ast::ident, + +first_item_attrs: ~[attribute]) + -> foreign_mod { // Shouldn't be any view items since we've already parsed an item attr let {attrs_remaining, view_items, items: _, foreign_items} = self.parse_items_and_view_items(first_item_attrs, @@ -3058,8 +3059,12 @@ impl Parser { initial_attrs = ~[]; items.push(self.parse_foreign_item(attrs)); } - return {sort: sort, view_items: view_items, - items: items}; + return { + sort: sort, + abi: move abi, + view_items: view_items, + items: items + }; } fn parse_item_foreign_mod(lo: BytePos, @@ -3068,6 +3073,18 @@ impl Parser { items_allowed: bool) -> item_or_view_item { + // Parse the ABI. + let abi_opt; + match self.token { + token::LIT_STR(copy found_abi) => { + self.bump(); + abi_opt = Some(found_abi); + } + _ => { + abi_opt = None; + } + } + let mut must_be_named_mod = false; if self.is_keyword(~"mod") { must_be_named_mod = true; @@ -3096,9 +3113,18 @@ impl Parser { // extern mod { ... } if items_allowed && self.eat(token::LBRACE) { + let abi; + match move abi_opt { + Some(move found_abi) => abi = move found_abi, + None => abi = special_idents::c_abi, + } + let extra_attrs = self.parse_inner_attrs_and_next(); - let m = self.parse_foreign_mod_items(sort, extra_attrs.next); + let m = self.parse_foreign_mod_items(sort, + move abi, + extra_attrs.next); self.expect(token::RBRACE); + return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_foreign_mod(m), visibility, maybe_append(attrs, @@ -3106,6 +3132,14 @@ impl Parser { inner)))); } + match abi_opt { + None => {} // OK. + Some(_) => { + self.span_err(copy self.span, ~"an ABI may not be specified \ + here"); + } + } + // extern mod foo; let metadata = self.parse_optional_meta(); self.expect(token::SEMI); diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 2e59d2fa45fcc..7b15f00d76197 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -322,6 +322,7 @@ mod special_idents { const intrinsic : ident = ident { repr: 32u }; const clownshoes_foreign_mod: ident = ident { repr: 33 }; const unnamed_field: ident = ident { repr: 34 }; + const c_abi: ident = ident { repr: 35 }; } struct ident_interner { @@ -368,7 +369,8 @@ fn mk_ident_interner() -> @ident_interner { @~"str", @~"TyVisitor", @~"arg", @~"descrim", @~"__rust_abi", @~"__rust_stack_shim", @~"TyDesc", @~"dtor", @~"main", @~"", @~"blk", @~"static", - @~"intrinsic", @~"__foreign_mod__" + @~"intrinsic", @~"__foreign_mod__", @~"__field__", + @~"C" ]; let rv = @ident_interner { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e0523613ee66f..f525436cc3e0e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -485,6 +485,7 @@ fn print_item(s: ps, &&item: @ast::item) { } ast::item_foreign_mod(nmod) => { head(s, visibility_qualified(item.vis, ~"extern")); + print_string(s, *s.intr.get(nmod.abi)); match nmod.sort { ast::named => { word_nbsp(s, ~"mod"); diff --git a/src/test/run-pass/extern-mod-abi.rs b/src/test/run-pass/extern-mod-abi.rs new file mode 100644 index 0000000000000..54befe77360ce --- /dev/null +++ b/src/test/run-pass/extern-mod-abi.rs @@ -0,0 +1,6 @@ +extern "C" { + fn pow(x: f64, y: f64) -> f64; +} + +fn main() {} + diff --git a/src/test/run-pass/operator-overloading-explicit-self.rs b/src/test/run-pass/operator-overloading-explicit-self.rs new file mode 100644 index 0000000000000..3b198078cf827 --- /dev/null +++ b/src/test/run-pass/operator-overloading-explicit-self.rs @@ -0,0 +1,16 @@ +struct S { + x: int +} + +impl S { + pure fn add(&self, other: &S) -> S { + S { x: self.x + other.x } + } +} + +fn main() { + let mut s = S { x: 1 }; + s += S { x: 2 }; + assert s.x == 3; +} +