diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 07997577a9ff6..4abfedb87228e 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -681,7 +681,7 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::Explic ebml_w.end_tag(); - fn encode_mutability(ebml_w: &writer::Encoder, + fn encode_mutability(ebml_w: &mut writer::Encoder, m: ast::Mutability) { match m { MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); } diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index b280da31c4537..cfd2c0719b09b 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -22,7 +22,6 @@ use mc = middle::mem_categorization; use middle::borrowck::*; use middle::moves; use middle::ty; -use syntax::ast::{MutImmutable, MutMutable}; use syntax::ast; use syntax::ast_map; use syntax::ast_util; @@ -220,9 +219,8 @@ impl<'a> CheckLoanCtxt<'a> { // Restrictions that would cause the new loan to be illegal: let illegal_if = match loan2.mutbl { - MutableMutability => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM, - ImmutableMutability => RESTR_ALIAS | RESTR_FREEZE, - ConstMutability => RESTR_ALIAS, + MutableMutability => RESTR_FREEZE | RESTR_CLAIM, + ImmutableMutability => RESTR_FREEZE, }; debug!("illegal_if={:?}", illegal_if); @@ -424,7 +422,7 @@ impl<'a> CheckLoanCtxt<'a> { debug!("check_for_aliasable_mutable_writes(cmt={}, guarantor={})", cmt.repr(this.tcx()), guarantor.repr(this.tcx())); match guarantor.cat { - mc::cat_deref(b, _, mc::region_ptr(MutMutable, _)) => { + mc::cat_deref(b, _, mc::region_ptr(ast::MutMutable, _)) => { // Statically prohibit writes to `&mut` when aliasable check_for_aliasability_violation(this, expr, b); @@ -438,43 +436,18 @@ impl<'a> CheckLoanCtxt<'a> { fn check_for_aliasability_violation(this: &CheckLoanCtxt, expr: &ast::Expr, - cmt: mc::cmt) -> bool { - let mut cmt = cmt; - - loop { - match cmt.cat { - mc::cat_deref(b, _, mc::region_ptr(MutMutable, _)) | - mc::cat_downcast(b) | - mc::cat_stack_upvar(b) | - mc::cat_deref(b, _, mc::uniq_ptr) | - mc::cat_interior(b, _) | - mc::cat_discr(b, _) => { - // Aliasability depends on base cmt - cmt = b; - } - - mc::cat_copied_upvar(_) | - mc::cat_rvalue(..) | - mc::cat_local(..) | - mc::cat_arg(_) | - mc::cat_deref(_, _, mc::unsafe_ptr(..)) | - mc::cat_static_item(..) | - mc::cat_deref(_, _, mc::gc_ptr) | - mc::cat_deref(_, _, mc::region_ptr(MutImmutable, _)) => { - // Aliasability is independent of base cmt - match cmt.freely_aliasable() { - None => { - return true; - } - Some(cause) => { - this.bccx.report_aliasability_violation( - expr.span, - MutabilityViolation, - cause); - return false; - } - } - } + cmt: mc::cmt) + -> bool { + match cmt.freely_aliasable() { + None => { + return true; + } + Some(cause) => { + this.bccx.report_aliasability_violation( + expr.span, + MutabilityViolation, + cause); + return false; } } } @@ -598,8 +571,7 @@ impl<'a> CheckLoanCtxt<'a> { // Check for a non-const loan of `loan_path` let cont = this.each_in_scope_loan(expr.id, |loan| { - if loan.loan_path == loan_path && - loan.mutbl != ConstMutability { + if loan.loan_path == loan_path { this.report_illegal_mutation(expr, full_loan_path, loan); diff --git a/src/librustc/middle/borrowck/doc.rs b/src/librustc/middle/borrowck/doc.rs index 04ce2b5846c81..ffc269f8cc8dd 100644 --- a/src/librustc/middle/borrowck/doc.rs +++ b/src/librustc/middle/borrowck/doc.rs @@ -151,14 +151,13 @@ that the value `(*x).f` may be mutated via the newly created reference restrictions `RS` that accompany the loan. The first restriction `((*x).f, [MUTATE, CLAIM, FREEZE])` states that -the lender may not mutate nor freeze `(*x).f`. Mutation is illegal -because `(*x).f` is only supposed to be mutated via the new reference, -not by mutating the original path `(*x).f`. Freezing is +the lender may not mutate, freeze, nor alias `(*x).f`. Mutation is +illegal because `(*x).f` is only supposed to be mutated via the new +reference, not by mutating the original path `(*x).f`. Freezing is illegal because the path now has an `&mut` alias; so even if we the lender were to consider `(*x).f` to be immutable, it might be mutated -via this alias. Both of these restrictions are temporary. They will be -enforced for the lifetime `'a` of the loan. After the loan expires, -the restrictions no longer apply. +via this alias. They will be enforced for the lifetime `'a` of the +loan. After the loan expires, the restrictions no longer apply. The second restriction on `*x` is interesting because it does not apply to the path that was lent (`(*x).f`) but rather to a prefix of @@ -188,11 +187,9 @@ The kinds of expressions which in-scope loans can render illegal are: against mutating `lv`; - *moves*: illegal if there is any in-scope restriction on `lv` at all; - *mutable borrows* (`&mut lv`): illegal there is an in-scope restriction - against mutating `lv` or aliasing `lv`; + against claiming `lv`; - *immutable borrows* (`&lv`): illegal there is an in-scope restriction - against freezing `lv` or aliasing `lv`; -- *read-only borrows* (`&const lv`): illegal there is an in-scope restriction - against aliasing `lv`. + against freezing `lv`. ## Formal rules @@ -238,19 +235,23 @@ live. (This is done via restrictions, read on.) We start with the `gather_loans` pass, which walks the AST looking for borrows. For each borrow, there are three bits of information: the lvalue `LV` being borrowed and the mutability `MQ` and lifetime `LT` -of the resulting pointer. Given those, `gather_loans` applies three +of the resulting pointer. Given those, `gather_loans` applies four validity tests: 1. `MUTABILITY(LV, MQ)`: The mutability of the reference is compatible with the mutability of `LV` (i.e., not borrowing immutable data as mutable). -2. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed +2. `ALIASABLE(LV, MQ)`: The aliasability of the reference is +compatible with the aliasability of `LV`. The goal is to prevent +`&mut` borrows of aliasability data. + +3. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed the lifetime of the value being borrowed. This pass is also responsible for inserting root annotations to keep managed values alive. -3. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the +4. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the restrictions to maintain memory safety. These are the restrictions that will go into the final loan. We'll discuss in more detail below. @@ -313,6 +314,47 @@ be borrowed if MQ is immutable or const: MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Mut TYPE(LV) = &mut Ty +## Checking aliasability + +The goal of the aliasability check is to ensure that we never permit +`&mut` borrows of aliasable data. Formally we define a predicate +`ALIASABLE(LV, MQ)` which if defined means that +"borrowing `LV` with mutability `MQ` is ok". The +Rust code corresponding to this predicate is the function +`check_aliasability()` in `middle::borrowck::gather_loans`. + +### Checking aliasability of variables + +Local variables are never aliasable as they are accessible only within +the stack frame. + + ALIASABLE(X, MQ) // M-Var-Mut + +### Checking aliasable of owned content + +Owned content is aliasable if it is found in an aliasable location: + + ALIASABLE(LV.f, MQ) // M-Field + ALIASABLE(LV, MQ) + + ALIASABLE(*LV, MQ) // M-Deref-Unique + ALIASABLE(LV, MQ) + +### Checking mutability of immutable pointer types + +Immutable pointer types like `&T` are aliasable, and hence can only be +borrowed immutably: + + ALIASABLE(*LV, imm) // M-Deref-Borrowed-Imm + TYPE(LV) = &Ty + +### Checking mutability of mutable pointer types + +`&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut: + + ALIASABLE(*LV, MQ) // M-Deref-Borrowed-Mut + TYPE(LV) = &mut Ty + ## Checking lifetime These rules aim to ensure that no data is borrowed for a scope that exceeds diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 173120e32f5ca..957073ac392bd 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -460,6 +460,11 @@ impl<'a> GatherLoanCtxt<'a> { return; // reported an error, no sense in reporting more. } + // Check that we don't allow mutable borrows of aliasable data. + if check_aliasability(self.bccx, borrow_span, cmt, req_mutbl).is_err() { + return; // reported an error, no sense in reporting more. + } + // Compute the restrictions that are required to enforce the // loan is safe. let restr = restrictions::compute_restrictions( @@ -568,11 +573,6 @@ impl<'a> GatherLoanCtxt<'a> { //! Implements the M-* rules in doc.rs. match req_mutbl { - ConstMutability => { - // Data of any mutability can be lent as const. - Ok(()) - } - ImmutableMutability => { // both imm and mut data can be lent as imm; // for mutable data, this is a freeze @@ -591,16 +591,53 @@ impl<'a> GatherLoanCtxt<'a> { } } } + + fn check_aliasability(bccx: &BorrowckCtxt, + borrow_span: Span, + cmt: mc::cmt, + req_mutbl: LoanMutability) -> Result<(),()> { + //! Implements the A-* rules in doc.rs. + + match req_mutbl { + ImmutableMutability => { + // both imm and mut data can be lent as imm; + // for mutable data, this is a freeze + Ok(()) + } + + MutableMutability => { + // Check for those cases where we cannot control + // the aliasing and make sure that we are not + // being asked to. + match cmt.freely_aliasable() { + None => { + Ok(()) + } + Some(mc::AliasableStaticMut) => { + // This is nasty, but we ignore the + // aliasing rules if the data is based in + // a `static mut`, since those are always + // unsafe. At your own peril and all that. + Ok(()) + } + Some(cause) => { + bccx.report_aliasability_violation( + borrow_span, + BorrowViolation, + cause); + Err(()) + } + } + } + } + } } pub fn restriction_set(&self, req_mutbl: LoanMutability) -> RestrictionSet { match req_mutbl { - ConstMutability => RESTR_EMPTY, - ImmutableMutability => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM, - MutableMutability => { - RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE - } + ImmutableMutability => RESTR_MUTATE | RESTR_CLAIM, + MutableMutability => RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE, } } diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index 22e64064c9ce5..60e0baa3534ba 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -53,16 +53,6 @@ impl<'a> RestrictionsContext<'a> { fn restrict(&self, cmt: mc::cmt, restrictions: RestrictionSet) -> RestrictionResult { - - // Check for those cases where we cannot control the aliasing - // and make sure that we are not being asked to. - match cmt.freely_aliasable() { - None => {} - Some(cause) => { - self.check_aliasing_permitted(cause, restrictions); - } - } - match cmt.cat { mc::cat_rvalue(..) => { // Effectively, rvalues are stored into a @@ -179,28 +169,4 @@ impl<'a> RestrictionsContext<'a> { } } } - - fn check_aliasing_permitted(&self, - cause: mc::AliasableReason, - restrictions: RestrictionSet) { - //! This method is invoked when the current `cmt` is something - //! where aliasing cannot be controlled. It reports an error if - //! the restrictions required that it not be aliased; currently - //! this only occurs when re-borrowing an `&mut` pointer. - //! - //! NB: To be 100% consistent, we should report an error if - //! RESTR_FREEZE is found, because we cannot prevent freezing, - //! nor would we want to. However, we do not report such an - //! error, because this restriction only occurs when the user - //! is creating an `&mut` pointer to immutable or read-only - //! data, and there is already another piece of code that - //! checks for this condition. - - if restrictions.intersects(RESTR_ALIAS) { - self.bccx.report_aliasability_violation( - self.span, - BorrowViolation, - cause); - } - } } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 6f3578f667de0..6a3e2fc63b08f 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -214,7 +214,6 @@ pub enum PartialTotal { #[deriving(Clone, Eq)] pub enum LoanMutability { ImmutableMutability, - ConstMutability, MutableMutability, } @@ -232,7 +231,6 @@ impl ToStr for LoanMutability { fn to_str(&self) -> ~str { match *self { ImmutableMutability => ~"immutable", - ConstMutability => ~"read-only", MutableMutability => ~"mutable", } } @@ -318,7 +316,6 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> { // - `RESTR_MUTATE`: The lvalue may not be modified. // - `RESTR_CLAIM`: `&mut` borrows of the lvalue are forbidden. // - `RESTR_FREEZE`: `&` borrows of the lvalue are forbidden. -// - `RESTR_ALIAS`: All borrows of the lvalue are forbidden. // // In addition, no value which is restricted may be moved. Therefore, // restrictions are meaningful even if the RestrictionSet is empty, @@ -338,7 +335,6 @@ pub static RESTR_EMPTY: RestrictionSet = RestrictionSet {bits: 0b0000}; pub static RESTR_MUTATE: RestrictionSet = RestrictionSet {bits: 0b0001}; pub static RESTR_CLAIM: RestrictionSet = RestrictionSet {bits: 0b0010}; pub static RESTR_FREEZE: RestrictionSet = RestrictionSet {bits: 0b0100}; -pub static RESTR_ALIAS: RestrictionSet = RestrictionSet {bits: 0b1000}; impl RestrictionSet { pub fn intersects(&self, restr: RestrictionSet) -> bool { @@ -663,8 +659,8 @@ impl BorrowckCtxt { kind: AliasableViolationKind, cause: mc::AliasableReason) { let prefix = match kind { - MutabilityViolation => "cannot assign to an `&mut`", - BorrowViolation => "cannot borrow an `&mut`" + MutabilityViolation => "cannot assign to data", + BorrowViolation => "cannot borrow data mutably" }; match cause { @@ -673,17 +669,21 @@ impl BorrowckCtxt { span, format!("{} in an aliasable location", prefix)); } + mc::AliasableStatic | + mc::AliasableStaticMut => { + self.tcx.sess.span_err( + span, + format!("{} in a static location", prefix)); + } mc::AliasableManaged => { - self.tcx.sess.span_err(span, format!("{} in a `@` pointer", - prefix)) + self.tcx.sess.span_err( + span, + format!("{} in a `@` pointer", prefix)); } - mc::AliasableBorrowed(m) => { + mc::AliasableBorrowed(_) => { self.tcx.sess.span_err( span, - format!("{} in a `&{}` pointer; \ - try an `&mut` instead", - prefix, - self.mut_to_keyword(m))); + format!("{} in a `&` reference", prefix)); } } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index f5e3ff5db34d8..93f439b653c59 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1100,7 +1100,9 @@ pub fn field_mutbl(tcx: ty::ctxt, pub enum AliasableReason { AliasableManaged, AliasableBorrowed(ast::Mutability), - AliasableOther + AliasableOther, + AliasableStatic, + AliasableStaticMut, } impl cmt_ { @@ -1130,10 +1132,6 @@ impl cmt_ { } } - pub fn is_freely_aliasable(&self) -> bool { - self.freely_aliasable().is_some() - } - pub fn freely_aliasable(&self) -> Option { /*! * Returns `Some(_)` if this lvalue represents a freely aliasable @@ -1145,20 +1143,36 @@ impl cmt_ { // aliased and eventually recused. match self.cat { + cat_deref(b, _, region_ptr(MutMutable, _)) | + cat_downcast(b) | + cat_stack_upvar(b) | + cat_deref(b, _, uniq_ptr) | + cat_interior(b, _) | + cat_discr(b, _) => { + // Aliasability depends on base cmt + b.freely_aliasable() + } + cat_copied_upvar(CopiedUpvar {onceness: ast::Once, ..}) | cat_rvalue(..) | cat_local(..) | cat_arg(_) | - cat_deref(_, _, unsafe_ptr(..)) | // of course it is aliasable, but... - cat_deref(_, _, region_ptr(MutMutable, _)) => { + cat_deref(_, _, unsafe_ptr(..)) => { // yes, it's aliasable, but... None } - cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) | - cat_static_item(..) => { + cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) => { Some(AliasableOther) } + cat_static_item(..) => { + if self.mutbl.is_mutable() { + Some(AliasableStaticMut) + } else { + Some(AliasableStatic) + } + } + cat_deref(_, _, gc_ptr) => { Some(AliasableManaged) } @@ -1166,14 +1180,6 @@ impl cmt_ { cat_deref(_, _, region_ptr(m @ MutImmutable, _)) => { Some(AliasableBorrowed(m)) } - - cat_downcast(..) | - cat_stack_upvar(..) | - cat_deref(_, _, uniq_ptr) | - cat_interior(..) | - cat_discr(..) => { - None - } } } } diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index d911208e7de30..76cf5997aee75 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -20,8 +20,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, in_items: ~[@Item]) -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "clone", "Clone"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -39,7 +38,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } pub fn expand_deriving_deep_clone(cx: &mut ExtCtxt, @@ -48,8 +47,7 @@ pub fn expand_deriving_deep_clone(cx: &mut ExtCtxt, in_items: ~[@Item]) -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "clone", "DeepClone"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -69,7 +67,7 @@ pub fn expand_deriving_deep_clone(cx: &mut ExtCtxt, ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } fn cs_clone( diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index a469c4a960b40..4672f1a8db689 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -45,8 +45,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, ); let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "cmp", "Eq"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -55,5 +54,5 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, md!("ne", cs_ne) ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index c06b4e30e07cf..1a8ace69307a7 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -35,8 +35,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, ); let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "cmp", "Ord"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -47,7 +46,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, md!("ge", false, true) ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } /// Strict inequality. diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 0a38a2ce30dc8..7b7c1afa4d5cb 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -24,8 +24,7 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, } let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "cmp", "TotalEq"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -42,5 +41,5 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, } ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 68de158e9e78b..157b6dc7521b7 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -21,8 +21,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "cmp", "TotalOrd"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -40,7 +39,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 7324500a8a0eb..fdf1ef17d538b 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -26,8 +26,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new_(~["serialize", "Decodable"], None, ~[~Literal(Path::new_local("__D"))], true), additional_bounds: ~[], @@ -50,7 +49,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span, diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index 922ee16435320..7b87152b7115a 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -18,10 +18,9 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) - -> ~[@Item] { + -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "default", "Default"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -38,7 +37,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, }, ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 4de31adc7f2c7..43edf6006b414 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -87,8 +87,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new_(~["serialize", "Encodable"], None, ~[~Literal(Path::new_local("__E"))], true), additional_bounds: ~[], @@ -111,7 +110,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 01006a0c15d07..47be3067284a5 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -193,13 +193,12 @@ pub use self::ty::*; mod ty; pub struct TraitDef<'a> { - /// The extension context - cx: &'a mut ExtCtxt<'a>, /// The span for the current #[deriving(Foo)] header. span: Span, /// Path of the trait, including any type parameters path: Path<'a>, + /// Additional bounds required of any type parameters of the type, /// other than the current trait additional_bounds: ~[Ty<'a>], @@ -321,6 +320,7 @@ pub type EnumNonMatchFunc<'a> = impl<'a> TraitDef<'a> { pub fn expand(&self, + cx: &mut ExtCtxt, _mitem: @ast::MetaItem, in_items: ~[@ast::Item]) -> ~[@ast::Item] { let mut result = ~[]; @@ -328,12 +328,14 @@ impl<'a> TraitDef<'a> { result.push(*item); match item.node { ast::ItemStruct(struct_def, ref generics) => { - result.push(self.expand_struct_def(struct_def, + result.push(self.expand_struct_def(cx, + struct_def, item.ident, generics)); } ast::ItemEnum(ref enum_def, ref generics) => { - result.push(self.expand_enum_def(enum_def, + result.push(self.expand_enum_def(cx, + enum_def, item.ident, generics)); } @@ -354,9 +356,9 @@ impl<'a> TraitDef<'a> { * */ fn create_derived_impl(&self, + cx: &mut ExtCtxt, type_ident: Ident, generics: &Generics, methods: ~[@ast::Method]) -> @ast::Item { - let cx = &*self.cx; let trait_path = self.path.to_path(cx, self.span, type_ident, generics); let mut trait_generics = self.generics.to_generics(cx, self.span, @@ -372,7 +374,8 @@ impl<'a> TraitDef<'a> { let mut bounds = opt_vec::from( // extra restrictions on the generics parameters to the type being derived upon self.additional_bounds.map(|p| { - cx.typarambound(p.to_path(cx, self.span, type_ident, generics)) + cx.typarambound(p.to_path(cx, self.span, + type_ident, generics)) })); // require the current trait bounds.push(cx.typarambound(trait_path.clone())); @@ -393,15 +396,15 @@ impl<'a> TraitDef<'a> { // Create the type of `self`. let self_type = cx.ty_path( cx.path_all(self.span, false, ~[ type_ident ], self_lifetimes, - opt_vec::take_vec(self_ty_params)), None); + opt_vec::take_vec(self_ty_params)), None); let doc_attr = cx.attribute( self.span, cx.meta_name_value(self.span, InternedString::new("doc"), ast::LitStr(token::intern_and_get_ident( - "Automatically derived."), - ast::CookedStr))); + "Automatically derived."), + ast::CookedStr))); cx.item( self.span, ::parse::token::special_idents::clownshoes_extensions, @@ -411,68 +414,77 @@ impl<'a> TraitDef<'a> { } fn expand_struct_def(&self, + cx: &mut ExtCtxt, struct_def: &StructDef, type_ident: Ident, generics: &Generics) -> @ast::Item { let methods = self.methods.map(|method_def| { let (explicit_self, self_args, nonself_args, tys) = - method_def.split_self_nonself_args(self, type_ident, generics); + method_def.split_self_nonself_args( + cx, self, type_ident, generics); let body = if method_def.is_static() { method_def.expand_static_struct_method_body( + cx, self, struct_def, type_ident, self_args, nonself_args) } else { - method_def.expand_struct_method_body(self, + method_def.expand_struct_method_body(cx, + self, struct_def, type_ident, self_args, nonself_args) }; - method_def.create_method(self, + method_def.create_method(cx, self, type_ident, generics, explicit_self, tys, body) }); - self.create_derived_impl(type_ident, generics, methods) + self.create_derived_impl(cx, type_ident, generics, methods) } fn expand_enum_def(&self, + cx: &mut ExtCtxt, enum_def: &EnumDef, type_ident: Ident, generics: &Generics) -> @ast::Item { let methods = self.methods.map(|method_def| { let (explicit_self, self_args, nonself_args, tys) = - method_def.split_self_nonself_args(self, type_ident, generics); + method_def.split_self_nonself_args(cx, self, + type_ident, generics); let body = if method_def.is_static() { method_def.expand_static_enum_method_body( + cx, self, enum_def, type_ident, self_args, nonself_args) } else { - method_def.expand_enum_method_body(self, + method_def.expand_enum_method_body(cx, + self, enum_def, type_ident, self_args, nonself_args) }; - method_def.create_method(self, + method_def.create_method(cx, self, type_ident, generics, explicit_self, tys, body) }); - self.create_derived_impl(type_ident, generics, methods) + self.create_derived_impl(cx, type_ident, generics, methods) } } impl<'a> MethodDef<'a> { fn call_substructure_method(&self, + cx: &mut ExtCtxt, trait_: &TraitDef, type_ident: Ident, self_args: &[@Expr], @@ -481,26 +493,33 @@ impl<'a> MethodDef<'a> { -> @Expr { let substructure = Substructure { type_ident: type_ident, - method_ident: trait_.cx.ident_of(self.name), + method_ident: cx.ident_of(self.name), self_args: self_args, nonself_args: nonself_args, fields: fields }; - (self.combine_substructure)(trait_.cx, trait_.span, + (self.combine_substructure)(cx, trait_.span, &substructure) } - fn get_ret_ty(&self, trait_: &TraitDef, - generics: &Generics, type_ident: Ident) -> P { - self.ret_ty.to_ty(trait_.cx, trait_.span, type_ident, generics) + fn get_ret_ty(&self, + cx: &mut ExtCtxt, + trait_: &TraitDef, + generics: &Generics, + type_ident: Ident) + -> P { + self.ret_ty.to_ty(cx, trait_.span, type_ident, generics) } fn is_static(&self) -> bool { self.explicit_self.is_none() } - fn split_self_nonself_args(&self, trait_: &TraitDef, - type_ident: Ident, generics: &Generics) + fn split_self_nonself_args(&self, + cx: &mut ExtCtxt, + trait_: &TraitDef, + type_ident: Ident, + generics: &Generics) -> (ast::ExplicitSelf, ~[@Expr], ~[@Expr], ~[(Ident, P)]) { let mut self_args = ~[]; @@ -511,7 +530,7 @@ impl<'a> MethodDef<'a> { let ast_explicit_self = match self.explicit_self { Some(ref self_ptr) => { let (self_expr, explicit_self) = - ty::get_explicit_self(trait_.cx, trait_.span, self_ptr); + ty::get_explicit_self(cx, trait_.span, self_ptr); self_args.push(self_expr); nonstatic = true; @@ -522,11 +541,11 @@ impl<'a> MethodDef<'a> { }; for (i, ty) in self.args.iter().enumerate() { - let ast_ty = ty.to_ty(trait_.cx, trait_.span, type_ident, generics); - let ident = trait_.cx.ident_of(format!("__arg_{}", i)); + let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); + let ident = cx.ident_of(format!("__arg_{}", i)); arg_tys.push((ident, ast_ty)); - let arg_expr = trait_.cx.expr_ident(trait_.span, ident); + let arg_expr = cx.expr_ident(trait_.span, ident); match *ty { // for static methods, just treat any Self @@ -535,7 +554,7 @@ impl<'a> MethodDef<'a> { self_args.push(arg_expr); } Ptr(~Self, _) if nonstatic => { - self_args.push(trait_.cx.expr_deref(trait_.span, arg_expr)) + self_args.push(cx.expr_deref(trait_.span, arg_expr)) } _ => { nonself_args.push(arg_expr); @@ -546,35 +565,37 @@ impl<'a> MethodDef<'a> { (ast_explicit_self, self_args, nonself_args, arg_tys) } - fn create_method(&self, trait_: &TraitDef, + fn create_method(&self, + cx: &mut ExtCtxt, + trait_: &TraitDef, type_ident: Ident, generics: &Generics, explicit_self: ast::ExplicitSelf, arg_types: ~[(Ident, P)], body: @Expr) -> @ast::Method { // create the generics that aren't for Self - let fn_generics = self.generics.to_generics(trait_.cx, trait_.span, type_ident, generics); + let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics); let self_arg = match explicit_self.node { ast::SelfStatic => None, _ => Some(ast::Arg::new_self(trait_.span, ast::MutImmutable)) }; let args = arg_types.move_iter().map(|(name, ty)| { - trait_.cx.arg(trait_.span, name, ty) + cx.arg(trait_.span, name, ty) }); let args = self_arg.move_iter().chain(args).collect(); - let ret_type = self.get_ret_ty(trait_, generics, type_ident); + let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident); - let method_ident = trait_.cx.ident_of(self.name); - let fn_decl = trait_.cx.fn_decl(args, ret_type); - let body_block = trait_.cx.block_expr(body); + let method_ident = cx.ident_of(self.name); + let fn_decl = cx.fn_decl(args, ret_type); + let body_block = cx.block_expr(body); let attrs = if self.inline { ~[ - trait_.cx + cx .attribute(trait_.span, - trait_.cx + cx .meta_word(trait_.span, InternedString::new( "inline"))) @@ -620,6 +641,7 @@ impl<'a> MethodDef<'a> { ~~~ */ fn expand_struct_method_body(&self, + cx: &mut ExtCtxt, trait_: &TraitDef, struct_def: &StructDef, type_ident: Ident, @@ -631,7 +653,7 @@ impl<'a> MethodDef<'a> { // [fields of next Self arg], [etc]] let mut patterns = ~[]; for i in range(0u, self_args.len()) { - let (pat, ident_expr) = trait_.create_struct_pattern(type_ident, struct_def, + let (pat, ident_expr) = trait_.create_struct_pattern(cx, type_ident, struct_def, format!("__self_{}", i), ast::MutImmutable); patterns.push(pat); @@ -655,13 +677,14 @@ impl<'a> MethodDef<'a> { } }).collect() } - [] => { trait_.cx.span_bug(trait_.span, - "no self arguments to non-static method \ - in generic `deriving`") } + [] => { cx.span_bug(trait_.span, + "no self arguments to non-static method \ + in generic `deriving`") } }; // body of the inner most destructuring match let mut body = self.call_substructure_method( + cx, trait_, type_ident, self_args, @@ -672,22 +695,24 @@ impl<'a> MethodDef<'a> { // structs. This is actually right-to-left, but it shoudn't // matter. for (&arg_expr, &pat) in self_args.iter().zip(patterns.iter()) { - body = trait_.cx.expr_match(trait_.span, arg_expr, - ~[ trait_.cx.arm(trait_.span, ~[pat], body) ]) + body = cx.expr_match(trait_.span, arg_expr, + ~[ cx.arm(trait_.span, ~[pat], body) ]) } body } fn expand_static_struct_method_body(&self, + cx: &mut ExtCtxt, trait_: &TraitDef, struct_def: &StructDef, type_ident: Ident, self_args: &[@Expr], nonself_args: &[@Expr]) -> @Expr { - let summary = trait_.summarise_struct(struct_def); + let summary = trait_.summarise_struct(cx, struct_def); - self.call_substructure_method(trait_, + self.call_substructure_method(cx, + trait_, type_ident, self_args, nonself_args, &StaticStruct(struct_def, summary)) @@ -720,14 +745,15 @@ impl<'a> MethodDef<'a> { ~~~ */ fn expand_enum_method_body(&self, + cx: &mut ExtCtxt, trait_: &TraitDef, enum_def: &EnumDef, type_ident: Ident, self_args: &[@Expr], nonself_args: &[@Expr]) - -> @Expr { + -> @Expr { let mut matches = ~[]; - self.build_enum_match(trait_, enum_def, type_ident, + self.build_enum_match(cx, trait_, enum_def, type_ident, self_args, nonself_args, None, &mut matches, 0) } @@ -755,6 +781,7 @@ impl<'a> MethodDef<'a> { the first call). */ fn build_enum_match(&self, + cx: &mut ExtCtxt, trait_: &TraitDef, enum_def: &EnumDef, type_ident: Ident, @@ -764,13 +791,13 @@ impl<'a> MethodDef<'a> { matches_so_far: &mut ~[(uint, P, ~[(Span, Option, @Expr)])], match_count: uint) -> @Expr { - let cx = &trait_.cx; if match_count == self_args.len() { // we've matched against all arguments, so make the final // expression at the bottom of the match tree if matches_so_far.len() == 0 { cx.span_bug(trait_.span, - "no self match on an enum in generic `deriving`"); + "no self match on an enum in \ + generic `deriving`"); } // we currently have a vec of vecs, where each // subvec is the fields of one of the arguments, @@ -820,7 +847,7 @@ impl<'a> MethodDef<'a> { substructure = EnumNonMatching(*matches_so_far); } } - self.call_substructure_method(trait_, type_ident, + self.call_substructure_method(cx, trait_, type_ident, self_args, nonself_args, &substructure) @@ -846,12 +873,14 @@ impl<'a> MethodDef<'a> { // matching-variant match let variant = enum_def.variants[index]; - let (pattern, idents) = trait_.create_enum_variant_pattern(variant, + let (pattern, idents) = trait_.create_enum_variant_pattern(cx, + variant, current_match_str, ast::MutImmutable); matches_so_far.push((index, variant, idents)); - let arm_expr = self.build_enum_match(trait_, + let arm_expr = self.build_enum_match(cx, + trait_, enum_def, type_ident, self_args, nonself_args, @@ -863,18 +892,20 @@ impl<'a> MethodDef<'a> { if enum_def.variants.len() > 1 { let e = &EnumNonMatching(&[]); - let wild_expr = self.call_substructure_method(trait_, type_ident, + let wild_expr = self.call_substructure_method(cx, trait_, type_ident, self_args, nonself_args, e); - let wild_arm = cx.arm(trait_.span, - ~[ cx.pat_wild(trait_.span) ], - wild_expr); + let wild_arm = cx.arm( + trait_.span, + ~[ cx.pat_wild(trait_.span) ], + wild_expr); arms.push(wild_arm); } } else { // create an arm matching on each variant for (index, &variant) in enum_def.variants.iter().enumerate() { - let (pattern, idents) = trait_.create_enum_variant_pattern(variant, + let (pattern, idents) = trait_.create_enum_variant_pattern(cx, + variant, current_match_str, ast::MutImmutable); @@ -885,7 +916,8 @@ impl<'a> MethodDef<'a> { Some(i) if index == i => Some(i), _ => None }; - let arm_expr = self.build_enum_match(trait_, + let arm_expr = self.build_enum_match(cx, + trait_, enum_def, type_ident, self_args, nonself_args, @@ -905,6 +937,7 @@ impl<'a> MethodDef<'a> { } fn expand_static_enum_method_body(&self, + cx: &mut ExtCtxt, trait_: &TraitDef, enum_def: &EnumDef, type_ident: Ident, @@ -915,15 +948,15 @@ impl<'a> MethodDef<'a> { let ident = v.node.name; let summary = match v.node.kind { ast::TupleVariantKind(ref args) => { - Unnamed(args.map(|va| trait_.set_expn_info(va.ty.span))) + Unnamed(args.map(|va| trait_.set_expn_info(cx, va.ty.span))) } ast::StructVariantKind(struct_def) => { - trait_.summarise_struct(struct_def) + trait_.summarise_struct(cx, struct_def) } }; (ident, v.span, summary) }); - self.call_substructure_method(trait_, type_ident, + self.call_substructure_method(cx, trait_, type_ident, self_args, nonself_args, &StaticEnum(enum_def, summary)) } @@ -936,9 +969,11 @@ enum StructType { // general helper methods. impl<'a> TraitDef<'a> { - fn set_expn_info(&self, mut to_set: Span) -> Span { + fn set_expn_info(&self, + cx: &mut ExtCtxt, + mut to_set: Span) -> Span { let trait_name = match self.path.path.last() { - None => self.cx.span_bug(self.span, "trait with empty path in generic `deriving`"), + None => cx.span_bug(self.span, "trait with empty path in generic `deriving`"), Some(name) => *name }; to_set.expn_info = Some(@codemap::ExpnInfo { @@ -952,11 +987,13 @@ impl<'a> TraitDef<'a> { to_set } - fn summarise_struct(&self, struct_def: &StructDef) -> StaticFields { + fn summarise_struct(&self, + cx: &mut ExtCtxt, + struct_def: &StructDef) -> StaticFields { let mut named_idents = ~[]; let mut just_spans = ~[]; for field in struct_def.fields.iter(){ - let sp = self.set_expn_info(field.span); + let sp = self.set_expn_info(cx, field.span); match field.node.kind { ast::NamedField(ident, _) => named_idents.push((ident, sp)), ast::UnnamedField => just_spans.push(sp), @@ -964,9 +1001,9 @@ impl<'a> TraitDef<'a> { } match (just_spans.is_empty(), named_idents.is_empty()) { - (false, false) => self.cx.span_bug(self.span, - "a struct with named and unnamed \ - fields in generic `deriving`"), + (false, false) => cx.span_bug(self.span, + "a struct with named and unnamed \ + fields in generic `deriving`"), // named fields (_, false) => Named(named_idents), // tuple structs (includes empty structs) @@ -975,23 +1012,23 @@ impl<'a> TraitDef<'a> { } fn create_subpatterns(&self, + cx: &mut ExtCtxt, field_paths: ~[ast::Path], mutbl: ast::Mutability) -> ~[@ast::Pat] { field_paths.map(|path| { - self.cx.pat(path.span, + cx.pat(path.span, ast::PatIdent(ast::BindByRef(mutbl), (*path).clone(), None)) }) } fn create_struct_pattern(&self, + cx: &mut ExtCtxt, struct_ident: Ident, struct_def: &StructDef, prefix: &str, mutbl: ast::Mutability) - -> (@ast::Pat, ~[(Span, Option, @Expr)]) { - let cx = &self.cx; - + -> (@ast::Pat, ~[(Span, Option, @Expr)]) { if struct_def.fields.is_empty() { return ( cx.pat_ident_binding_mode( @@ -1006,7 +1043,7 @@ impl<'a> TraitDef<'a> { let mut struct_type = Unknown; for (i, struct_field) in struct_def.fields.iter().enumerate() { - let sp = self.set_expn_info(struct_field.span); + let sp = self.set_expn_info(cx, struct_field.span); let opt_id = match struct_field.node.kind { ast::NamedField(ident, _) if (struct_type == Unknown || struct_type == Record) => { @@ -1024,11 +1061,13 @@ impl<'a> TraitDef<'a> { }; let path = cx.path_ident(sp, cx.ident_of(format!("{}_{}", prefix, i))); paths.push(path.clone()); - let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(path)))); + let val = cx.expr( + sp, ast::ExprParen( + cx.expr_deref(sp, cx.expr_path(path)))); ident_expr.push((sp, opt_id, val)); } - let subpats = self.create_subpatterns(paths, mutbl); + let subpats = self.create_subpatterns(cx, paths, mutbl); // struct_type is definitely not Unknown, since struct_def.fields // must be nonempty to reach here @@ -1046,17 +1085,17 @@ impl<'a> TraitDef<'a> { } fn create_enum_variant_pattern(&self, + cx: &mut ExtCtxt, variant: &ast::Variant, prefix: &str, mutbl: ast::Mutability) -> (@ast::Pat, ~[(Span, Option, @Expr)]) { - let cx = &*self.cx; let variant_ident = variant.node.name; match variant.node.kind { ast::TupleVariantKind(ref variant_args) => { if variant_args.is_empty() { return (cx.pat_ident_binding_mode(variant.span, variant_ident, - ast::BindByValue(ast::MutImmutable)), + ast::BindByValue(ast::MutImmutable)), ~[]); } @@ -1065,21 +1104,22 @@ impl<'a> TraitDef<'a> { let mut paths = ~[]; let mut ident_expr = ~[]; for (i, va) in variant_args.iter().enumerate() { - let sp = self.set_expn_info(va.ty.span); + let sp = self.set_expn_info(cx, va.ty.span); let path = cx.path_ident(sp, cx.ident_of(format!("{}_{}", prefix, i))); paths.push(path.clone()); - let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(path)))); + let val = cx.expr( + sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(path)))); ident_expr.push((sp, None, val)); } - let subpats = self.create_subpatterns(paths, mutbl); + let subpats = self.create_subpatterns(cx, paths, mutbl); (cx.pat_enum(variant.span, matching_path, subpats), ident_expr) } ast::StructVariantKind(struct_def) => { - self.create_struct_pattern(variant_ident, struct_def, + self.create_struct_pattern(cx, variant_ident, struct_def, prefix, mutbl) } } diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs index 5f680745ea7c6..19e81b81df6a6 100644 --- a/src/libsyntax/ext/deriving/iter_bytes.rs +++ b/src/libsyntax/ext/deriving/iter_bytes.rs @@ -20,8 +20,7 @@ pub fn expand_deriving_iter_bytes(cx: &mut ExtCtxt, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "to_bytes", "IterBytes"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -42,7 +41,7 @@ pub fn expand_deriving_iter_bytes(cx: &mut ExtCtxt, ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } fn iter_bytes_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index f74b807bae6a0..1b356667b6b31 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -21,8 +21,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "num", "FromPrimitive"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -62,7 +61,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 15595f6eddc40..a40317286c960 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -20,10 +20,9 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) - -> ~[@Item] { + -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "rand", "Rand"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -47,7 +46,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, } ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 67cfd151f6293..e2d507f303510 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -24,14 +24,13 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) - -> ~[@Item] { + -> ~[@Item] { // &mut ::std::fmt::Formatter let fmtr = Ptr(~Literal(Path::new(~["std", "fmt", "Formatter"])), Borrowed(None, ast::MutMutable)); let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "fmt", "Show"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -48,7 +47,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, } ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } // we construct a format string and then defer to std::fmt, since that diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs index 2f50d5ad121cb..186f12544935d 100644 --- a/src/libsyntax/ext/deriving/to_str.rs +++ b/src/libsyntax/ext/deriving/to_str.rs @@ -21,10 +21,9 @@ pub fn expand_deriving_to_str(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) - -> ~[@Item] { + -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "to_str", "ToStr"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -41,7 +40,7 @@ pub fn expand_deriving_to_str(cx: &mut ExtCtxt, } ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } // It used to be the case that this deriving implementation invoked diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index ecd06b3f49e56..ca5c1543d88dc 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -18,10 +18,9 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) - -> ~[@Item] { + -> ~[@Item] { let trait_def = TraitDef { - cx: cx, span: span, - + span: span, path: Path::new(~["std", "num", "Zero"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -54,7 +53,7 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt, } ] }; - trait_def.expand(mitem, in_items) + trait_def.expand(cx, mitem, in_items) } fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { diff --git a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs index f72dacc2d813c..d19538c5d362b 100644 --- a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs +++ b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs @@ -27,5 +27,10 @@ fn foo3(t0: &mut &mut int) { **t1 = 22; } +fn foo4(t0: & &mut int) { + let x: &mut int = &mut **t0; //~ ERROR cannot borrow + *x += 1; +} + fn main() { }