From cf05cd8abffadd701cab32de43e59b5ac73241f3 Mon Sep 17 00:00:00 2001 From: Dennis Schridde Date: Sun, 7 May 2017 23:20:28 +0200 Subject: [PATCH 01/16] bootstrap: Output name of failed config in case of errors --- src/bootstrap/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 34fbc33d981af..9c536111811aa 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -264,7 +264,7 @@ impl Config { let table = match p.parse() { Some(table) => table, None => { - println!("failed to parse TOML configuration:"); + println!("failed to parse TOML configuration '{}':", file.to_str().unwrap()); for err in p.errors.iter() { let (loline, locol) = p.to_linecol(err.lo); let (hiline, hicol) = p.to_linecol(err.hi); From defcfb21f1a235153ecc03444f0e7b779de0858f Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 9 May 2017 10:55:47 -0700 Subject: [PATCH 02/16] Remove wrong or outdated info from CString docs. --- src/libstd/ffi/c_str.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 29f977ecd8c33..44b62593fa3a6 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -30,12 +30,10 @@ use str::{self, Utf8Error}; /// type is a static guarantee that the underlying bytes contain no interior 0 /// bytes and the final byte is 0. /// -/// A `CString` is created from either a byte slice or a byte vector. After -/// being created, a `CString` predominately inherits all of its methods from -/// the `Deref` implementation to `[c_char]`. Note that the underlying array -/// is represented as an array of `c_char` as opposed to `u8`. A `u8` slice -/// can be obtained with the `as_bytes` method. Slices produced from a `CString` -/// do *not* contain the trailing nul terminator unless otherwise specified. +/// A `CString` is created from either a byte slice or a byte vector. A `u8` +/// slice can be obtained with the `as_bytes` method. Slices produced from a +/// `CString` do *not* contain the trailing nul terminator unless otherwise +/// specified. /// /// # Examples /// From e42875ce6dfc0102b00e6725f403c2f5a1b59fce Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 11 May 2017 06:27:01 +0200 Subject: [PATCH 03/16] doc: break into 2 sentences --- src/libstd/thread/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 4432f898e04f8..4ddd92f159227 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -245,8 +245,8 @@ impl Builder { /// configuration methods can be chained. /// /// If the [`stack_size`] field is not specified, the stack size - /// will be the `RUST_MIN_STACK` environment variable, if it is - /// not specified either, a sensible default size will be set (2MB as + /// will be the `RUST_MIN_STACK` environment variable. If it is + /// not specified either, a sensible default will be set (2MB as /// of the writting of this doc). /// /// # Examples From 67a0d27c6529de335304b10c6ae6b0eed77bfc79 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 11 May 2017 17:45:27 +1200 Subject: [PATCH 04/16] Ensure we walk the root module of the crate --- src/librustc_save_analysis/data.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 27 +++++++++++++++++++ src/librustc_save_analysis/external_data.rs | 4 +-- src/librustc_save_analysis/json_api_dumper.rs | 2 +- src/librustc_save_analysis/json_dumper.rs | 2 +- src/librustc_save_analysis/lib.rs | 2 +- 6 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index d4ded71a33390..cac1a2e3c5af1 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -267,7 +267,7 @@ pub struct ModData { pub items: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 763414c1a555f..dd022dee78cba 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1211,6 +1211,33 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, D> { + fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, id: NodeId) { + // Since we handle explicit modules ourselves in visit_item, this should + // only get called for the root module of a crate. + assert_eq!(id, ast::CRATE_NODE_ID); + + let qualname = format!("::{}", self.tcx.node_path_str(id)); + + let cm = self.tcx.sess.codemap(); + let filename = cm.span_to_filename(span); + self.dumper.mod_data(ModData { + id: id, + name: String::new(), + qualname: qualname, + span: span, + scope: id, + filename: filename, + items: m.items.iter().map(|i| i.id).collect(), + visibility: Visibility::Public, + // TODO Visitor doesn't pass us the attibutes. + docs: String::new(), + sig: None, + // TODO Visitor doesn't pass us the attibutes. + attributes: vec![], + }.lower(self.tcx)); + self.nest_scope(id, |v| visit::walk_mod(v, m)); + } + fn visit_item(&mut self, item: &'l ast::Item) { use syntax::ast::ItemKind::*; self.process_macro_use(item.span, item.id); diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 6fd2de97767e1..02441a0587eb6 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -392,7 +392,7 @@ pub struct ModData { pub items: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -410,7 +410,7 @@ impl Lower for data::ModData { items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), visibility: self.visibility, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig.map(|s| s.lower(tcx)), attributes: self.attributes.lower(tcx), } } diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 41221ad986379..49b14f5eca072 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -293,7 +293,7 @@ impl Into> for ModData { parent: None, decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig.map(|s| s.into()), attributes: vec![], }), _ => None, diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 2d1e12bf0a10d..eaa0c0825f0e9 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -121,7 +121,7 @@ impl<'b, O: DumpOutput + 'b> Dump for JsonDumper { children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: data.docs, - sig: Some(data.sig.into()), + sig: data.sig.map(|s| s.into()), attributes: data.attributes.into_iter().map(|a| a.into()).collect(), }; if def.span.file_name.to_str().unwrap() != def.value { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index fd6898d19d84f..9283c6d7b5380 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -257,7 +257,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { items: m.items.iter().map(|i| i.id).collect(), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: self.sig_base(item), + sig: Some(self.sig_base(item)), attributes: item.attrs.clone(), })) } From 43349e649d9fecac9f6a8e14f31ca660eae2748d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 11 May 2017 16:57:45 +0200 Subject: [PATCH 05/16] Upgrade some comments to doc comments --- src/librustc/ty/sty.rs | 47 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 630e4a239cc65..89960b0e4f678 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -67,8 +67,8 @@ pub enum BoundRegion { /// Fresh bound identifiers created during GLB computations. BrFresh(u32), - // Anonymous region for the implicit env pointer parameter - // to a closure + /// Anonymous region for the implicit env pointer parameter + /// to a closure BrEnv, } @@ -95,8 +95,8 @@ pub struct Issue32330 { pub region_name: ast::Name, } -// NB: If you change this, you'll probably want to change the corresponding -// AST structure in libsyntax/ast.rs as well. +/// NB: If you change this, you'll probably want to change the corresponding +/// AST structure in libsyntax/ast.rs as well. #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum TypeVariants<'tcx> { /// The primitive boolean type. Written as `bool`. @@ -283,11 +283,11 @@ impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx> { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum ExistentialPredicate<'tcx> { - // e.g. Iterator + /// e.g. Iterator Trait(ExistentialTraitRef<'tcx>), - // e.g. Iterator::Item = T + /// e.g. Iterator::Item = T Projection(ExistentialProjection<'tcx>), - // e.g. Send + /// e.g. Send AutoTrait(DefId), } @@ -683,8 +683,8 @@ impl<'a, 'gcx, 'tcx> ParamTy { /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)] pub struct DebruijnIndex { - // We maintain the invariant that this is never 0. So 1 indicates - // the innermost binder. To ensure this, create with `DebruijnIndex::new`. + /// We maintain the invariant that this is never 0. So 1 indicates + /// the innermost binder. To ensure this, create with `DebruijnIndex::new`. pub depth: u32, } @@ -908,7 +908,7 @@ impl DebruijnIndex { } } -// Region utilities +/// Region utilities impl<'tcx> RegionKind<'tcx> { pub fn is_bound(&self) -> bool { match *self { @@ -972,7 +972,7 @@ impl<'tcx> RegionKind<'tcx> { } } -// Type utilities +/// Type utilities impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn as_opt_param_ty(&self) -> Option { match self.sty { @@ -995,8 +995,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - // Test whether this is a `()` which was produced by defaulting a - // diverging type variable with feature(never_type) disabled. + /// Test whether this is a `()` which was produced by defaulting a + /// diverging type variable with feature(never_type) disabled. pub fn is_defaulted_unit(&self) -> bool { match self.sty { TyTuple(_, true) => true, @@ -1171,6 +1171,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + /// panics if called on any type other than `Box` pub fn boxed_ty(&self) -> Ty<'tcx> { match self.sty { TyAdt(def, substs) if def.is_box() => substs.type_at(0), @@ -1178,11 +1179,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - /* - A scalar type is one that denotes an atomic datum, with no sub-components. - (A TyRawPtr is scalar because it represents a non-managed pointer, so its - contents are abstract to rustc.) - */ + /// A scalar type is one that denotes an atomic datum, with no sub-components. + /// (A TyRawPtr is scalar because it represents a non-managed pointer, so its + /// contents are abstract to rustc.) pub fn is_scalar(&self) -> bool { match self.sty { TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) | @@ -1278,10 +1277,10 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - // Returns the type and mutability of *ty. - // - // The parameter `explicit` indicates if this is an *explicit* dereference. - // Some types---notably unsafe ptrs---can only be dereferenced explicitly. + /// Returns the type and mutability of *ty. + /// + /// The parameter `explicit` indicates if this is an *explicit* dereference. + /// Some types---notably unsafe ptrs---can only be dereferenced explicitly. pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference) -> Option> { @@ -1302,7 +1301,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - // Returns the type of ty[i] + /// Returns the type of ty[i] pub fn builtin_index(&self) -> Option> { match self.sty { TyArray(ty, _) | TySlice(ty) => Some(ty), @@ -1317,7 +1316,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - // Type accessors for substructures of types + /// Type accessors for substructures of types pub fn fn_args(&self) -> ty::Binder<&'tcx [Ty<'tcx>]> { self.fn_sig().inputs() } From 641d05353a596311eff9442a3fc50f332baaf857 Mon Sep 17 00:00:00 2001 From: Martin Glagla Date: Thu, 11 May 2017 20:38:15 +0200 Subject: [PATCH 06/16] Fix typo in size_hint example comment --- src/libcore/iter/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index b3f4d75c4da61..67b97afb9769a 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -119,7 +119,7 @@ pub trait Iterator { /// // exactly wouldn't be possible without executing filter(). /// assert_eq!((0, Some(10)), iter.size_hint()); /// - /// // Let's add one five more numbers with chain() + /// // Let's add five more numbers with chain() /// let iter = (0..10).filter(|x| x % 2 == 0).chain(15..20); /// /// // now both bounds are increased by five From a950c37394cf45428c4852359c803e5a3c194ee6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 2 May 2017 15:03:34 -0400 Subject: [PATCH 07/16] replace the type generalizer with one based on variance --- src/librustc/infer/combine.rs | 121 ++++++++++++++------ src/librustc/ty/mod.rs | 60 ++++++++++ src/librustc_typeck/variance/constraints.rs | 1 - src/librustc_typeck/variance/xform.rs | 29 ----- 4 files changed, 146 insertions(+), 65 deletions(-) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 1bac512e20977..ac78d53c02c50 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -42,8 +42,7 @@ use super::{MiscVariable, TypeTrace}; use ty::{IntType, UintType}; use ty::{self, Ty, TyCtxt}; use ty::error::TypeError; -use ty::fold::TypeFoldable; -use ty::relate::{RelateResult, TypeRelation}; +use ty::relate::{self, Relate, RelateResult, TypeRelation}; use traits::PredicateObligations; use syntax::ast; @@ -207,7 +206,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { // `'?2` and `?3` are fresh region/type inference // variables. (Down below, we will relate `a_ty <: b_ty`, // adding constraints like `'x: '?2` and `?1 <: ?3`.) - let b_ty = self.generalize(a_ty, b_vid, dir == EqTo)?; + let b_ty = self.generalize(a_ty, b_vid, dir)?; debug!("instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})", a_ty, dir, b_vid, b_ty); self.infcx.type_variables.borrow_mut().instantiate(b_vid, b_ty); @@ -241,22 +240,30 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { fn generalize(&self, ty: Ty<'tcx>, for_vid: ty::TyVid, - is_eq_relation: bool) + dir: RelationDir) -> RelateResult<'tcx, Ty<'tcx>> { + // Determine the ambient variance within which `ty` appears. + // The surrounding equation is: + // + // ty [op] ty2 + // + // where `op` is either `==`, `<:`, or `:>`. This maps quite + // naturally. + let ambient_variance = match dir { + RelationDir::EqTo => ty::Invariant, + RelationDir::SubtypeOf => ty::Covariant, + RelationDir::SupertypeOf => ty::Contravariant, + }; + let mut generalize = Generalizer { infcx: self.infcx, span: self.trace.cause.span, for_vid_sub_root: self.infcx.type_variables.borrow_mut().sub_root_var(for_vid), - is_eq_relation: is_eq_relation, - cycle_detected: false + ambient_variance: ambient_variance, }; - let u = ty.fold_with(&mut generalize); - if generalize.cycle_detected { - Err(TypeError::CyclicTy) - } else { - Ok(u) - } + + generalize.relate(&ty, &ty) } } @@ -264,16 +271,46 @@ struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, span: Span, for_vid_sub_root: ty::TyVid, - is_eq_relation: bool, - cycle_detected: bool, + ambient_variance: ty::Variance, } -impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> { +impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn tag(&self) -> &'static str { + "Generalizer" + } + + fn a_is_expected(&self) -> bool { + true + } + + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'tcx> + { + Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) + } + + fn relate_with_variance>(&mut self, + variance: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T> + { + let old_ambient_variance = self.ambient_variance; + self.ambient_variance = self.ambient_variance.xform(variance); + + let result = self.relate(a, b); + self.ambient_variance = old_ambient_variance; + result + } + + fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be == + // Check to see whether the type we are genealizing references // any other type variable related to `vid` via // subtyping. This is basically our "occurs check", preventing @@ -286,41 +323,54 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx if sub_vid == self.for_vid_sub_root { // If sub-roots are equal, then `for_vid` and // `vid` are related via subtyping. - self.cycle_detected = true; - self.tcx().types.err + return Err(TypeError::CyclicTy); } else { match variables.probe_root(vid) { Some(u) => { drop(variables); - self.fold_ty(u) + self.relate(&u, &u) } None => { - if !self.is_eq_relation { - let origin = variables.origin(vid); - let new_var_id = variables.new_var(false, origin, None); - let u = self.tcx().mk_var(new_var_id); - debug!("generalize: replacing original vid={:?} with new={:?}", - vid, u); - u - } else { - t + match self.ambient_variance { + ty::Invariant => Ok(t), + + ty::Bivariant | ty::Covariant | ty::Contravariant => { + let origin = variables.origin(vid); + let new_var_id = variables.new_var(false, origin, None); + let u = self.tcx().mk_var(new_var_id); + debug!("generalize: replacing original vid={:?} with new={:?}", + vid, u); + Ok(u) + } } } } } } + ty::TyInfer(ty::IntVar(_)) | + ty::TyInfer(ty::FloatVar(_)) => { + // No matter what mode we are in, + // integer/floating-point types must be equal to be + // relatable. + Ok(t) + } _ => { - t.super_fold_with(self) + relate::super_relate_tys(self, t, t) } } } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn regions(&mut self, r: ty::Region<'tcx>, r2: ty::Region<'tcx>) + -> RelateResult<'tcx, ty::Region<'tcx>> { + assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be == + match *r { // Never make variables for regions bound within the type itself, // nor for erased regions. ty::ReLateBound(..) | - ty::ReErased => { return r; } + ty::ReErased => { + return Ok(r); + } // Early-bound regions should really have been substituted away before // we get to this point. @@ -342,15 +392,16 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx ty::ReScope(..) | ty::ReVar(..) | ty::ReFree(..) => { - if self.is_eq_relation { - return r; + match self.ambient_variance { + ty::Invariant => return Ok(r), + ty::Bivariant | ty::Covariant | ty::Contravariant => (), } } } // FIXME: This is non-ideal because we don't give a // very descriptive origin for this region variable. - self.infcx.next_region_var(MiscVariable(self.span)) + Ok(self.infcx.next_region_var(MiscVariable(self.span))) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 51cdba56cf10a..f5d510c11ae9d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -330,6 +330,66 @@ pub struct CrateVariancesMap { pub empty_variance: Rc>, } +impl Variance { + /// `a.xform(b)` combines the variance of a context with the + /// variance of a type with the following meaning. If we are in a + /// context with variance `a`, and we encounter a type argument in + /// a position with variance `b`, then `a.xform(b)` is the new + /// variance with which the argument appears. + /// + /// Example 1: + /// + /// *mut Vec + /// + /// Here, the "ambient" variance starts as covariant. `*mut T` is + /// invariant with respect to `T`, so the variance in which the + /// `Vec` appears is `Covariant.xform(Invariant)`, which + /// yields `Invariant`. Now, the type `Vec` is covariant with + /// respect to its type argument `T`, and hence the variance of + /// the `i32` here is `Invariant.xform(Covariant)`, which results + /// (again) in `Invariant`. + /// + /// Example 2: + /// + /// fn(*const Vec, *mut Vec` appears is + /// `Contravariant.xform(Covariant)` or `Contravariant`. The same + /// is true for its `i32` argument. In the `*mut T` case, the + /// variance of `Vec` is `Contravariant.xform(Invariant)`, + /// and hence the outermost type is `Invariant` with respect to + /// `Vec` (and its `i32` argument). + /// + /// Source: Figure 1 of "Taming the Wildcards: + /// Combining Definition- and Use-Site Variance" published in PLDI'11. + pub fn xform(self, v: ty::Variance) -> ty::Variance { + match (self, v) { + // Figure 1, column 1. + (ty::Covariant, ty::Covariant) => ty::Covariant, + (ty::Covariant, ty::Contravariant) => ty::Contravariant, + (ty::Covariant, ty::Invariant) => ty::Invariant, + (ty::Covariant, ty::Bivariant) => ty::Bivariant, + + // Figure 1, column 2. + (ty::Contravariant, ty::Covariant) => ty::Contravariant, + (ty::Contravariant, ty::Contravariant) => ty::Covariant, + (ty::Contravariant, ty::Invariant) => ty::Invariant, + (ty::Contravariant, ty::Bivariant) => ty::Bivariant, + + // Figure 1, column 3. + (ty::Invariant, _) => ty::Invariant, + + // Figure 1, column 4. + (ty::Bivariant, _) => ty::Bivariant, + } + } +} + #[derive(Clone, Copy, Debug, RustcDecodable, RustcEncodable)] pub struct MethodCallee<'tcx> { /// Impl method ID, for inherent methods, or trait method ID, otherwise. diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index e986a381cd963..cb2ee7dd1bcda 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -27,7 +27,6 @@ use rustc_data_structures::transitive_relation::TransitiveRelation; use super::terms::*; use super::terms::VarianceTerm::*; -use super::xform::*; pub struct ConstraintContext<'a, 'tcx: 'a> { pub terms_cx: TermsContext<'a, 'tcx>, diff --git a/src/librustc_typeck/variance/xform.rs b/src/librustc_typeck/variance/xform.rs index 507734ce35e44..7106ca4d420a8 100644 --- a/src/librustc_typeck/variance/xform.rs +++ b/src/librustc_typeck/variance/xform.rs @@ -10,35 +10,6 @@ use rustc::ty; -pub trait Xform { - fn xform(self, v: Self) -> Self; -} - -impl Xform for ty::Variance { - fn xform(self, v: ty::Variance) -> ty::Variance { - // "Variance transformation", Figure 1 of The Paper - match (self, v) { - // Figure 1, column 1. - (ty::Covariant, ty::Covariant) => ty::Covariant, - (ty::Covariant, ty::Contravariant) => ty::Contravariant, - (ty::Covariant, ty::Invariant) => ty::Invariant, - (ty::Covariant, ty::Bivariant) => ty::Bivariant, - - // Figure 1, column 2. - (ty::Contravariant, ty::Covariant) => ty::Contravariant, - (ty::Contravariant, ty::Contravariant) => ty::Covariant, - (ty::Contravariant, ty::Invariant) => ty::Invariant, - (ty::Contravariant, ty::Bivariant) => ty::Bivariant, - - // Figure 1, column 3. - (ty::Invariant, _) => ty::Invariant, - - // Figure 1, column 4. - (ty::Bivariant, _) => ty::Bivariant, - } - } -} - pub fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance { // Greatest lower bound of the variance lattice as // defined in The Paper: From a4151ff3c4179587e5601bb529543cf1de5e91d8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 2 May 2017 17:34:31 -0400 Subject: [PATCH 08/16] add a WF obligation if a type variable appears in bivariant position --- src/librustc/infer/combine.rs | 87 +++++++++++++++++++++++++------- src/test/run-pass/issue-41677.rs | 37 ++++++++++++++ 2 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 src/test/run-pass/issue-41677.rs diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index ac78d53c02c50..82578f6aa61d5 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -43,7 +43,7 @@ use ty::{IntType, UintType}; use ty::{self, Ty, TyCtxt}; use ty::error::TypeError; use ty::relate::{self, Relate, RelateResult, TypeRelation}; -use traits::PredicateObligations; +use traits::{Obligation, PredicateObligations}; use syntax::ast; use syntax_pos::Span; @@ -206,11 +206,16 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { // `'?2` and `?3` are fresh region/type inference // variables. (Down below, we will relate `a_ty <: b_ty`, // adding constraints like `'x: '?2` and `?1 <: ?3`.) - let b_ty = self.generalize(a_ty, b_vid, dir)?; + let Generalization { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?; debug!("instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})", a_ty, dir, b_vid, b_ty); self.infcx.type_variables.borrow_mut().instantiate(b_vid, b_ty); + if needs_wf { + self.obligations.push(Obligation::new(self.trace.cause.clone(), + ty::Predicate::WellFormed(b_ty))); + } + // Finally, relate `b_ty` to `a_ty`, as described in previous comment. // // FIXME(#16847): This code is non-ideal because all these subtype @@ -229,10 +234,9 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { /// Attempts to generalize `ty` for the type variable `for_vid`. /// This checks for cycle -- that is, whether the type `ty` - /// references `for_vid`. If `is_eq_relation` is false, it will - /// also replace all regions/unbound-type-variables with fresh - /// variables. Returns `TyError` in the case of a cycle, `Ok` - /// otherwise. + /// references `for_vid`. The `dir` is the "direction" for which we + /// a performing the generalization (i.e., are we producing a type + /// that can be used as a supertype etc). /// /// Preconditions: /// @@ -241,7 +245,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { ty: Ty<'tcx>, for_vid: ty::TyVid, dir: RelationDir) - -> RelateResult<'tcx, Ty<'tcx>> + -> RelateResult<'tcx, Generalization<'tcx>> { // Determine the ambient variance within which `ty` appears. // The surrounding equation is: @@ -261,9 +265,12 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { span: self.trace.cause.span, for_vid_sub_root: self.infcx.type_variables.borrow_mut().sub_root_var(for_vid), ambient_variance: ambient_variance, + needs_wf: false, }; - generalize.relate(&ty, &ty) + let ty = generalize.relate(&ty, &ty)?; + let needs_wf = generalize.needs_wf; + Ok(Generalization { ty, needs_wf }) } } @@ -272,6 +279,41 @@ struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { span: Span, for_vid_sub_root: ty::TyVid, ambient_variance: ty::Variance, + needs_wf: bool, // see the field `needs_wf` in `Generalization` +} + +/// Result from a generalization operation. This includes +/// not only the generalized type, but also a bool flag +/// indicating whether further WF checks are needed.q +struct Generalization<'tcx> { + ty: Ty<'tcx>, + + /// If true, then the generalized type may not be well-formed, + /// even if the source type is well-formed, so we should add an + /// additional check to enforce that it is. This arises in + /// particular around 'bivariant' type parameters that are only + /// constrained by a where-clause. As an example, imagine a type: + /// + /// struct Foo where A: Iterator { + /// data: A + /// } + /// + /// here, `A` will be covariant, but `B` is + /// unconstrained. However, whatever it is, for `Foo` to be WF, it + /// must be equal to `A::Item`. If we have an input `Foo`, + /// then after generalization we will wind up with a type like + /// `Foo`. When we enforce that `Foo <: Foo` (or `>:`), we will wind up with the requirement that `?A + /// <: ?C`, but no particular relationship between `?B` and `?D` + /// (after all, we do not know the variance of the normalized form + /// of `A::Item` with respect to `A`). If we do nothing else, this + /// may mean that `?D` goes unconstrained (as in #41677). So, in + /// this scenario where we create a new type variable in a + /// bivariant context, we set the `needs_wf` flag to true. This + /// will force the calling code to check that `WF(Foo)` + /// holds, which in turn implies that `?C::Item == ?D`. So once + /// `?C` is constrained, that should suffice to restrict `?D`. + needs_wf: bool, } impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> { @@ -332,17 +374,26 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' } None => { match self.ambient_variance { - ty::Invariant => Ok(t), - - ty::Bivariant | ty::Covariant | ty::Contravariant => { - let origin = variables.origin(vid); - let new_var_id = variables.new_var(false, origin, None); - let u = self.tcx().mk_var(new_var_id); - debug!("generalize: replacing original vid={:?} with new={:?}", - vid, u); - Ok(u) - } + // Invariant: no need to make a fresh type variable. + ty::Invariant => return Ok(t), + + // Bivariant: make a fresh var, but we + // may need a WF predicate. See + // comment on `needs_wf` field for + // more info. + ty::Bivariant => self.needs_wf = true, + + // Co/contravariant: this will be + // sufficiently constrained later on. + ty::Covariant | ty::Contravariant => (), } + + let origin = variables.origin(vid); + let new_var_id = variables.new_var(false, origin, None); + let u = self.tcx().mk_var(new_var_id); + debug!("generalize: replacing original vid={:?} with new={:?}", + vid, u); + return Ok(u); } } } diff --git a/src/test/run-pass/issue-41677.rs b/src/test/run-pass/issue-41677.rs new file mode 100644 index 0000000000000..d014382ca39b6 --- /dev/null +++ b/src/test/run-pass/issue-41677.rs @@ -0,0 +1,37 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #41677. The local variable was winding up with +// a type `Receiver` where `?T` was unconstrained, because we +// failed to enforce the WF obligations and `?T` is a bivariant type +// parameter position. + +#![allow(unused_variables, dead_code)] + +use std::marker::PhantomData; + +trait Handle { + type Inner; +} + +struct ResizingHandle(PhantomData); +impl Handle for ResizingHandle { + type Inner = H; +} + +struct Receiver>(PhantomData); + +fn channel(size: usize) -> Receiver> { + let rx = Receiver(PhantomData); + rx +} + +fn main() { +} From 2490ee5080ef1810fc137c676f4906d65a407dde Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 2 May 2017 21:25:15 -0400 Subject: [PATCH 09/16] correct various error messages that changed The new messages seem universally better. I think these result because we recognize that we are in an invariant context more often. --- .../compile-fail/region-invariant-static-error-reporting.rs | 5 ++--- src/test/compile-fail/regions-trait-object-subtyping.rs | 2 +- src/test/compile-fail/variance-contravariant-arg-object.rs | 4 ++-- src/test/compile-fail/variance-covariant-arg-object.rs | 4 ++-- src/test/compile-fail/variance-invariant-arg-object.rs | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/test/compile-fail/region-invariant-static-error-reporting.rs b/src/test/compile-fail/region-invariant-static-error-reporting.rs index d25674a74b1d3..646ae8183a20c 100644 --- a/src/test/compile-fail/region-invariant-static-error-reporting.rs +++ b/src/test/compile-fail/region-invariant-static-error-reporting.rs @@ -13,9 +13,8 @@ // over time, but this test used to exhibit some pretty bogus messages // that were not remotely helpful. -// error-pattern:cannot infer -// error-pattern:cannot outlive the lifetime 'a -// error-pattern:must be valid for the static lifetime +// error-pattern:the lifetime 'a +// error-pattern:the static lifetime struct Invariant<'a>(Option<&'a mut &'a mut ()>); diff --git a/src/test/compile-fail/regions-trait-object-subtyping.rs b/src/test/compile-fail/regions-trait-object-subtyping.rs index e8ada6a175571..948fb7e1ef6c2 100644 --- a/src/test/compile-fail/regions-trait-object-subtyping.rs +++ b/src/test/compile-fail/regions-trait-object-subtyping.rs @@ -22,7 +22,7 @@ fn foo2<'a:'b,'b>(x: &'b mut (Dummy+'a)) -> &'b mut (Dummy+'b) { fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy { // Without knowing 'a:'b, we can't coerce - x //~ ERROR cannot infer an appropriate lifetime + x //~ ERROR lifetime bound not satisfied //~^ ERROR cannot infer an appropriate lifetime } diff --git a/src/test/compile-fail/variance-contravariant-arg-object.rs b/src/test/compile-fail/variance-contravariant-arg-object.rs index d3bf92e85f411..1795ac95358d7 100644 --- a/src/test/compile-fail/variance-contravariant-arg-object.rs +++ b/src/test/compile-fail/variance-contravariant-arg-object.rs @@ -21,7 +21,7 @@ fn get_min_from_max<'min, 'max>(v: Box>) -> Box> where 'max : 'min { - v //~ ERROR cannot infer an appropriate lifetime + v //~ ERROR mismatched types } fn get_max_from_min<'min, 'max, G>(v: Box>) @@ -29,7 +29,7 @@ fn get_max_from_min<'min, 'max, G>(v: Box>) where 'max : 'min { // Previously OK: - v //~ ERROR cannot infer an appropriate lifetime + v //~ ERROR mismatched types } fn main() { } diff --git a/src/test/compile-fail/variance-covariant-arg-object.rs b/src/test/compile-fail/variance-covariant-arg-object.rs index 0e94e35df2839..ad059a467f570 100644 --- a/src/test/compile-fail/variance-covariant-arg-object.rs +++ b/src/test/compile-fail/variance-covariant-arg-object.rs @@ -22,14 +22,14 @@ fn get_min_from_max<'min, 'max>(v: Box>) where 'max : 'min { // Previously OK, now an error as traits are invariant. - v //~ ERROR cannot infer an appropriate lifetime + v //~ ERROR mismatched types } fn get_max_from_min<'min, 'max, G>(v: Box>) -> Box> where 'max : 'min { - v //~ ERROR cannot infer an appropriate lifetime + v //~ ERROR mismatched types } fn main() { } diff --git a/src/test/compile-fail/variance-invariant-arg-object.rs b/src/test/compile-fail/variance-invariant-arg-object.rs index aa3e06c015d50..9edb510b826a1 100644 --- a/src/test/compile-fail/variance-invariant-arg-object.rs +++ b/src/test/compile-fail/variance-invariant-arg-object.rs @@ -18,14 +18,14 @@ fn get_min_from_max<'min, 'max>(v: Box>) -> Box> where 'max : 'min { - v //~ ERROR cannot infer an appropriate lifetime + v //~ ERROR mismatched types } fn get_max_from_min<'min, 'max, G>(v: Box>) -> Box> where 'max : 'min { - v //~ ERROR cannot infer an appropriate lifetime + v //~ ERROR mismatched types } fn main() { } From fb7ba4772cdad24083fa73552425d4f91fd8be33 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 12 May 2017 07:15:29 +1200 Subject: [PATCH 10/16] Pass crate attributes in visit.rs --- src/librustc/lint/context.rs | 2 +- src/librustc_passes/hir_stats.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 8 +++----- src/libsyntax/util/node_count.rs | 2 +- src/libsyntax/visit.rs | 8 +++++--- src/libsyntax_ext/proc_macro_registrar.rs | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 6f3e84247f797..60e671f1772e3 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1055,7 +1055,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { run_lints!(self, check_ident, early_passes, sp, id); } - fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, n: ast::NodeId) { + fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) { run_lints!(self, check_mod, early_passes, m, s, n); ast_visit::walk_mod(self, m); run_lints!(self, check_mod_post, early_passes, m, s, n); diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 749146fe49672..29fac5463e557 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -252,7 +252,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { - fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _n: NodeId) { + fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _a: &[ast::Attribute], _n: NodeId) { self.record("Mod", Id::None, m); ast_visit::walk_mod(self, m) } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index dd022dee78cba..a95236e2a5072 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1211,7 +1211,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, D> { - fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, id: NodeId) { + fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], id: NodeId) { // Since we handle explicit modules ourselves in visit_item, this should // only get called for the root module of a crate. assert_eq!(id, ast::CRATE_NODE_ID); @@ -1229,11 +1229,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, filename: filename, items: m.items.iter().map(|i| i.id).collect(), visibility: Visibility::Public, - // TODO Visitor doesn't pass us the attibutes. - docs: String::new(), + docs: docs_for_attrs(attrs), sig: None, - // TODO Visitor doesn't pass us the attibutes. - attributes: vec![], + attributes: attrs.to_owned(), }.lower(self.tcx)); self.nest_scope(id, |v| visit::walk_mod(v, m)); } diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index 9d9957a0f4534..0a5d0c2e7fe01 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -31,7 +31,7 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_ident(self, span, ident); } - fn visit_mod(&mut self, m: &Mod, _s: Span, _n: NodeId) { + fn visit_mod(&mut self, m: &Mod, _s: Span, _a: &[Attribute], _n: NodeId) { self.count += 1; walk_mod(self, m) } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 2e42c6986e64e..9288d95009c1d 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -56,7 +56,9 @@ pub trait Visitor<'ast>: Sized { fn visit_ident(&mut self, span: Span, ident: Ident) { walk_ident(self, span, ident); } - fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _n: NodeId) { walk_mod(self, m) } + fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) { + walk_mod(self, m); + } fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) } fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) { walk_global_asm(self, ga) } fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) } @@ -172,7 +174,7 @@ pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, ident: Ident) } pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) { - visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID); + visitor.visit_mod(&krate.module, krate.span, &krate.attrs, CRATE_NODE_ID); walk_list!(visitor, visit_attribute, &krate.attrs); } @@ -249,7 +251,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { item.id) } ItemKind::Mod(ref module) => { - visitor.visit_mod(module, item.span, item.id) + visitor.visit_mod(module, item.span, &item.attrs, item.id) } ItemKind::ForeignMod(ref foreign_module) => { walk_list!(visitor, visit_foreign_item, &foreign_module.items); diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index bb89caab709b0..6318abec69f06 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -329,7 +329,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { visit::walk_item(self, item); } - fn visit_mod(&mut self, m: &'a ast::Mod, _s: Span, id: NodeId) { + fn visit_mod(&mut self, m: &'a ast::Mod, _s: Span, _a: &[ast::Attribute], id: NodeId) { let mut prev_in_root = self.in_root; if id != ast::CRATE_NODE_ID { prev_in_root = mem::replace(&mut self.in_root, false); From 084b67f56a66b440657e6aa66227e971790a87a4 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 11 May 2017 19:19:21 +0000 Subject: [PATCH 11/16] Annotate the license exceptions --- src/tools/tidy/src/deps.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3bf396db4d39d..8b7da2267cded 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -23,12 +23,15 @@ static LICENSES: &'static [&'static str] = &[ "Unlicense/MIT", ]; -/// These MPL licensed projects are acceptable, but only these. +// These are exceptions to Rust's permissive licensing policy, and +// should be considered bugs. Exceptions are only allowed in Rust +// tooling. It is _crucial_ that no exception crates be dependencies +// of the Rust runtime (std / test). static EXCEPTIONS: &'static [&'static str] = &[ - "mdbook", - "openssl", - "pest", - "thread-id", + "mdbook", // MPL2, mdbook + "openssl", // BSD+advertising clause, cargo, mdbook + "pest", // MPL2, mdbook via handlebars + "thread-id", // Apache-2.0, mdbook ]; pub fn check(path: &Path, bad: &mut bool) { From b0c80a93e41548bf706dc886b8875952f6456b0c Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 11 May 2017 23:09:31 +0300 Subject: [PATCH 12/16] remove the #[inline] attribute from drop_in_place Apparently LLVM has exponential code growth while inlining landing pads if that attribute is present. Fixes #41696. --- src/libcore/ptr.rs | 1 - src/librustc_trans/common.rs | 6 ++++ src/test/run-pass/issue-41696.rs | 60 ++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/issue-41696.rs diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index a60abefc07650..0944e74f6f18a 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -56,7 +56,6 @@ pub use intrinsics::write_bytes; /// invalid pointers, types, and double drops. #[stable(feature = "drop_in_place", since = "1.8.0")] #[lang="drop_in_place"] -#[inline] #[allow(unconditional_recursion)] pub unsafe fn drop_in_place(to_drop: *mut T) { // Code here does not matter - this is replaced by the diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 025062f7ddef9..efd4f13678502 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -537,6 +537,12 @@ pub fn requests_inline<'a, 'tcx>( if is_inline_instance(tcx, instance) { return true } + if let ty::InstanceDef::DropGlue(..) = instance.def { + // Drop glue wants to be instantiated at every translation + // unit, but without an #[inline] hint. We should make this + // available to normal end-users. + return true + } attr::requests_inline(&instance.def.attrs(tcx)[..]) } diff --git a/src/test/run-pass/issue-41696.rs b/src/test/run-pass/issue-41696.rs new file mode 100644 index 0000000000000..1888be58c57d0 --- /dev/null +++ b/src/test/run-pass/issue-41696.rs @@ -0,0 +1,60 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// this used to cause exponential code-size blowup during LLVM passes. + +#![feature(test)] + +extern crate test; + +struct MayUnwind; + +impl Drop for MayUnwind { + fn drop(&mut self) { + if test::black_box(false) { + panic!() + } + } +} + +struct DS { + may_unwind: MayUnwind, + name: String, + next: U, +} + +fn add(ds: DS, name: String) -> DS> { + DS { + may_unwind: MayUnwind, + name: "?".to_owned(), + next: ds, + } +} + +fn main() { + let deserializers = DS { may_unwind: MayUnwind, name: "?".to_owned(), next: () }; + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); // 0.7s + let deserializers = add(deserializers, "?".to_owned()); // 1.3s + let deserializers = add(deserializers, "?".to_owned()); // 2.4s + let deserializers = add(deserializers, "?".to_owned()); // 6.7s + let deserializers = add(deserializers, "?".to_owned()); // 26.0s + let deserializers = add(deserializers, "?".to_owned()); // 114.0s + let deserializers = add(deserializers, "?".to_owned()); // 228.0s + let deserializers = add(deserializers, "?".to_owned()); // 400.0s + let deserializers = add(deserializers, "?".to_owned()); // 800.0s + let deserializers = add(deserializers, "?".to_owned()); // 1600.0s + let deserializers = add(deserializers, "?".to_owned()); // 3200.0s +} From e6cde9f2a4f5e4d9e20686f29344461eacae3eba Mon Sep 17 00:00:00 2001 From: Mike Lubinets Date: Thu, 11 May 2017 16:48:25 +0300 Subject: [PATCH 13/16] Number of filtered out tests in tests summary Closes #31905 --- src/libtest/lib.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 0d615db3deb47..ef048ac8ca355 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -542,6 +542,7 @@ struct ConsoleTestState { passed: usize, failed: usize, ignored: usize, + filtered_out: usize, measured: usize, metrics: MetricMap, failures: Vec<(TestDesc, Vec)>, @@ -570,6 +571,7 @@ impl ConsoleTestState { passed: 0, failed: 0, ignored: 0, + filtered_out: 0, measured: 0, metrics: MetricMap::new(), failures: Vec::new(), @@ -775,11 +777,12 @@ impl ConsoleTestState { } else { self.write_pretty("FAILED", term::color::RED)?; } - let s = format!(". {} passed; {} failed; {} ignored; {} measured\n\n", + let s = format!(". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", self.passed, self.failed, self.ignored, - self.measured); + self.measured, + self.filtered_out); self.write_plain(&s)?; return Ok(success); } @@ -875,6 +878,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu fn callback(event: &TestEvent, st: &mut ConsoleTestState) -> io::Result<()> { match (*event).clone() { TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()), + TeFilteredOut(filtered_out) => Ok(st.filtered_out = filtered_out), TeWait(ref test, padding) => st.write_test_start(test, padding), TeTimeout(ref test) => st.write_timeout(test), TeResult(test, result, stdout) => { @@ -957,6 +961,7 @@ fn should_sort_failures_before_printing_them() { passed: 0, failed: 0, ignored: 0, + filtered_out: 0, measured: 0, max_name_len: 10, metrics: MetricMap::new(), @@ -1017,6 +1022,7 @@ pub enum TestEvent { TeWait(TestDesc, NamePadding), TeResult(TestDesc, TestResult, Vec), TeTimeout(TestDesc), + TeFilteredOut(usize), } pub type MonitorMsg = (TestDesc, TestResult, Vec); @@ -1028,11 +1034,16 @@ pub fn run_tests(opts: &TestOpts, tests: Vec, mut callback: F) use std::collections::HashMap; use std::sync::mpsc::RecvTimeoutError; + let tests_len = tests.len(); + let mut filtered_tests = filter_tests(opts, tests); if !opts.bench_benchmarks { filtered_tests = convert_benchmarks_to_tests(filtered_tests); } + let filtered_out = tests_len - filtered_tests.len(); + callback(TeFilteredOut(filtered_out))?; + let filtered_descs = filtered_tests.iter() .map(|t| t.desc.clone()) .collect(); From 75b69c453b0fcde2ab9008f0968e0d38c75666b8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 11 May 2017 22:28:13 +0200 Subject: [PATCH 14/16] Fix search when looking to sources --- src/librustdoc/html/static/rustdoc.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index ddaa00aa4fb14..fc879dc0705f6 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -236,6 +236,9 @@ nav.sub { overflow: auto; padding-left: 0; } +#search { + margin-left: 230px; +} .content pre.line-numbers { float: left; border: none; From 68c1ce91701a322601dec0e0c8845e535909f9b2 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 12 May 2017 00:14:31 +0300 Subject: [PATCH 15/16] rustc_trans: do not attempt to truncate an i1 const to i1. --- src/librustc_trans/mir/constant.rs | 7 +++++-- src/test/run-pass/issue-41744.rs | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/issue-41744.rs diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 040194e63d07e..1305d6fff8cb0 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -415,8 +415,11 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { Value(base)); } if projected_ty.is_bool() { - unsafe { - val = llvm::LLVMConstTrunc(val, Type::i1(self.ccx).to_ref()); + let i1_type = Type::i1(self.ccx); + if val_ty(val) != i1_type { + unsafe { + val = llvm::LLVMConstTrunc(val, i1_type.to_ref()); + } } } (Base::Value(val), extra) diff --git a/src/test/run-pass/issue-41744.rs b/src/test/run-pass/issue-41744.rs new file mode 100644 index 0000000000000..276067d7d7491 --- /dev/null +++ b/src/test/run-pass/issue-41744.rs @@ -0,0 +1,16 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Tc {} +impl Tc for bool {} + +fn main() { + let _: &[&Tc] = &[&true]; +} From c85501b9c18ab396096239a52350e12fa9d24db2 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Fri, 12 May 2017 01:38:26 +0300 Subject: [PATCH 16/16] box large variants in MIR Operand: 72 -> 24 B Statement: 192 -> 96 B Terminator: 256 -> 112 B librustc translation memory usage: 1795 -> 1669 MB next step would be interning lvalues, I suppose? --- src/librustc/mir/mod.rs | 14 +++++++------- src/librustc/mir/tcx.rs | 2 +- src/librustc/mir/visit.rs | 1 + .../borrowck/mir/elaborate_drops.rs | 4 ++-- src/librustc_mir/build/cfg.rs | 4 ++-- src/librustc_mir/build/expr/as_operand.rs | 2 +- src/librustc_mir/build/expr/as_rvalue.rs | 9 +++++---- src/librustc_mir/build/expr/stmt.rs | 2 +- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/build/misc.rs | 4 ++-- src/librustc_mir/build/scope.rs | 2 +- src/librustc_mir/shim.rs | 4 ++-- src/librustc_mir/transform/copy_prop.rs | 2 +- src/librustc_mir/transform/deaggregator.rs | 8 ++++---- src/librustc_mir/transform/promote_consts.rs | 4 ++-- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/transform/simplify_branches.rs | 5 ++--- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_passes/mir_stats.rs | 2 +- src/librustc_trans/mir/analyze.rs | 2 +- src/librustc_trans/mir/constant.rs | 2 +- src/librustc_trans/mir/rvalue.rs | 2 +- 22 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index b517ebabbe767..fe2ad498e9961 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -799,7 +799,7 @@ pub enum StatementKind<'tcx> { StorageDead(Lvalue<'tcx>), InlineAsm { - asm: InlineAsm, + asm: Box, outputs: Vec>, inputs: Vec> }, @@ -995,7 +995,7 @@ pub struct VisibilityScopeData { #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)] pub enum Operand<'tcx> { Consume(Lvalue<'tcx>), - Constant(Constant<'tcx>), + Constant(Box>), } impl<'tcx> Debug for Operand<'tcx> { @@ -1015,7 +1015,7 @@ impl<'tcx> Operand<'tcx> { substs: &'tcx Substs<'tcx>, span: Span, ) -> Self { - Operand::Constant(Constant { + Operand::Constant(box Constant { span: span, ty: tcx.type_of(def_id).subst(tcx, substs), literal: Literal::Value { value: ConstVal::Function(def_id, substs) }, @@ -1062,7 +1062,7 @@ pub enum Rvalue<'tcx> { /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case /// that `Foo` has a destructor. These rvalues can be optimized /// away after type-checking and before lowering. - Aggregate(AggregateKind<'tcx>, Vec>), + Aggregate(Box>, Vec>), } #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] @@ -1185,7 +1185,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { tuple_fmt.finish() } - match *kind { + match **kind { AggregateKind::Array(_) => write!(fmt, "{:?}", lvs), AggregateKind::Tuple => { @@ -1603,7 +1603,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Discriminant(ref lval) => Discriminant(lval.fold_with(folder)), Box(ty) => Box(ty.fold_with(folder)), Aggregate(ref kind, ref fields) => { - let kind = match *kind { + let kind = box match **kind { AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), AggregateKind::Tuple => AggregateKind::Tuple, AggregateKind::Adt(def, v, substs, n) => @@ -1631,7 +1631,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Discriminant(ref lval) => lval.visit_with(visitor), Box(ty) => ty.visit_with(visitor), Aggregate(ref kind, ref fields) => { - (match *kind { + (match **kind { AggregateKind::Array(ty) => ty.visit_with(visitor), AggregateKind::Tuple => false, AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor), diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index b6020df072853..7bc1dc58c29d2 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -183,7 +183,7 @@ impl<'tcx> Rvalue<'tcx> { tcx.mk_box(t) } Rvalue::Aggregate(ref ak, ref ops) => { - match *ak { + match **ak { AggregateKind::Array(ty) => { tcx.mk_array(ty, ops.len()) } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 31bdd99ef3221..557fedadeba62 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -515,6 +515,7 @@ macro_rules! make_mir_visitor { Rvalue::Aggregate(ref $($mutability)* kind, ref $($mutability)* operands) => { + let kind = &$($mutability)* **kind; match *kind { AggregateKind::Array(ref $($mutability)* ty) => { self.visit_ty(ty); diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 4ae8bdc284b22..4b7d52c25173a 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -517,11 +517,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { - Rvalue::Use(Operand::Constant(Constant { + Rvalue::Use(Operand::Constant(Box::new(Constant { span: span, ty: self.tcx.types.bool, literal: Literal::Value { value: ConstVal::Bool(val) } - })) + }))) } fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) { diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index c503b8c7fe06f..40a78933aad2d 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -60,7 +60,7 @@ impl<'tcx> CFG<'tcx> { temp: &Lvalue<'tcx>, constant: Constant<'tcx>) { self.push_assign(block, source_info, temp, - Rvalue::Use(Operand::Constant(constant))); + Rvalue::Use(Operand::Constant(box constant))); } pub fn push_assign_unit(&mut self, @@ -68,7 +68,7 @@ impl<'tcx> CFG<'tcx> { source_info: SourceInfo, lvalue: &Lvalue<'tcx>) { self.push_assign(block, source_info, lvalue, Rvalue::Aggregate( - AggregateKind::Tuple, vec![] + box AggregateKind::Tuple, vec![] )); } diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index 22a36bb21d875..f7534737edc03 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -66,7 +66,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match category { Category::Constant => { let constant = this.as_constant(expr); - block.and(Operand::Constant(constant)) + block.and(Operand::Constant(box constant)) } Category::Lvalue | Category::Rvalue(..) => { diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 8dc7745cd9eb9..46e2408c38d5d 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -166,7 +166,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .map(|f| unpack!(block = this.as_operand(block, scope, f))) .collect(); - block.and(Rvalue::Aggregate(AggregateKind::Array(el_ty), fields)) + block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields)) } ExprKind::Tuple { fields } => { // see (*) above // first process the set of fields @@ -175,14 +175,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .map(|f| unpack!(block = this.as_operand(block, scope, f))) .collect(); - block.and(Rvalue::Aggregate(AggregateKind::Tuple, fields)) + block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields)) } ExprKind::Closure { closure_id, substs, upvars } => { // see (*) above let upvars = upvars.into_iter() .map(|upvar| unpack!(block = this.as_operand(block, scope, upvar))) .collect(); - block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars)) + block.and(Rvalue::Aggregate(box AggregateKind::Closure(closure_id, substs), upvars)) } ExprKind::Adt { adt_def, variant_index, substs, fields, base @@ -215,7 +215,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { field_names.iter().filter_map(|n| fields_map.get(n).cloned()).collect() }; - let adt = AggregateKind::Adt(adt_def, variant_index, substs, active_field_index); + let adt = + box AggregateKind::Adt(adt_def, variant_index, substs, active_field_index); block.and(Rvalue::Aggregate(adt, fields)) } ExprKind::Assign { .. } | diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index c03432312b0ab..3c7ab373651d2 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -129,7 +129,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.cfg.push(block, Statement { source_info: source_info, kind: StatementKind::InlineAsm { - asm: asm.clone(), + asm: box asm.clone(), outputs: outputs, inputs: inputs }, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 0833342927fec..28386fa598ce6 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -308,7 +308,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let eq_block = self.cfg.start_new_block(); let cleanup = self.diverge_cleanup(); self.cfg.terminate(block, source_info, TerminatorKind::Call { - func: Operand::Constant(Constant { + func: Operand::Constant(box Constant { span: test.span, ty: mty, literal: method diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 35a8b245f2bb6..6c93e073de6b1 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ty: Ty<'tcx>, literal: Literal<'tcx>) -> Operand<'tcx> { - let constant = Constant { + let constant = box Constant { span: span, ty: ty, literal: literal, @@ -49,7 +49,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } pub fn unit_rvalue(&mut self) -> Rvalue<'tcx> { - Rvalue::Aggregate(AggregateKind::Tuple, vec![]) + Rvalue::Aggregate(box AggregateKind::Tuple, vec![]) } // Returns a zero literal operand for the appropriate type, works for diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index f9c08f34eaf3f..6043a696183f2 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -786,7 +786,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); let substs = tcx.intern_substs(&[Kind::from(data.item_ty)]); TerminatorKind::Call { - func: Operand::Constant(Constant { + func: Operand::Constant(box Constant { span: data.span, ty: tcx.type_of(free_func).subst(tcx, substs), literal: Literal::Value { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 1458ea7fdd6a2..a6f9952b23ca5 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -323,7 +323,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, let (callee, mut args) = match call_kind { CallKind::Indirect => (rcvr, vec![]), CallKind::Direct(def_id) => ( - Operand::Constant(Constant { + Operand::Constant(box Constant { span: span, ty: tcx.type_of(def_id).subst(tcx, param_env.free_substs), literal: Literal::Value { @@ -449,7 +449,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, kind: StatementKind::Assign( Lvalue::Local(RETURN_POINTER), Rvalue::Aggregate( - AggregateKind::Adt(adt_def, variant_no, substs, None), + box AggregateKind::Adt(adt_def, variant_no, substs, None), (1..sig.inputs().len()+1).map(|i| { Operand::Consume(Lvalue::Local(Local::new(i))) }).collect() diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index fbb67161bac9d..08a4961c6cd1b 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -316,7 +316,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstantPropagationVisitor<'tcx> { _ => return, } - *operand = Operand::Constant(self.constant.clone()); + *operand = Operand::Constant(box self.constant.clone()); self.uses_replaced += 1 } } diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 4309f91c635bb..d21dbeafb5d0a 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -49,8 +49,8 @@ impl MirPass for Deaggregator { &Rvalue::Aggregate(ref agg_kind, ref operands) => (agg_kind, operands), _ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs), }; - let (adt_def, variant, substs) = match agg_kind { - &AggregateKind::Adt(adt_def, variant, substs, None) + let (adt_def, variant, substs) = match **agg_kind { + AggregateKind::Adt(adt_def, variant, substs, None) => (adt_def, variant, substs), _ => span_bug!(src_info.span, "expected struct, not {:?}", rhs), }; @@ -114,8 +114,8 @@ fn get_aggregate_statement_index<'a, 'tcx, 'b>(start: usize, &Rvalue::Aggregate(ref kind, ref operands) => (kind, operands), _ => continue, }; - let (adt_def, variant) = match kind { - &AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant), + let (adt_def, variant) = match **kind { + AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant), _ => continue, }; if operands.len() == 0 { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index ed9a0d3809f24..e1c4602b045eb 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -230,7 +230,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { (if self.keep_original { rhs.clone() } else { - let unit = Rvalue::Aggregate(AggregateKind::Tuple, vec![]); + let unit = Rvalue::Aggregate(box AggregateKind::Tuple, vec![]); mem::replace(rhs, unit) }, statement.source_info) }; @@ -288,7 +288,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { fn promote_candidate(mut self, candidate: Candidate) { let span = self.promoted.span; - let new_operand = Operand::Constant(Constant { + let new_operand = Operand::Constant(box Constant { span: span, ty: self.promoted.return_ty, literal: Literal::Promoted { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 0d592b4d72be5..df837a32133b3 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -730,7 +730,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } Rvalue::Aggregate(ref kind, _) => { - if let AggregateKind::Adt(def, ..) = *kind { + if let AggregateKind::Adt(def, ..) = **kind { if def.has_dtor(self.tcx) { self.add(Qualif::NEEDS_DROP); self.deny_drop(); diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index d21a6ddfdfb97..1dcacb29c3ecc 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -37,7 +37,7 @@ impl MirPass for SimplifyBranches { for block in mir.basic_blocks_mut() { let terminator = block.terminator_mut(); terminator.kind = match terminator.kind { - TerminatorKind::SwitchInt { discr: Operand::Constant(Constant { + TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant { literal: Literal::Value { ref value }, .. }), ref values, ref targets, .. } => { if let Some(ref constint) = value.to_const_int() { @@ -54,7 +54,7 @@ impl MirPass for SimplifyBranches { continue } }, - TerminatorKind::Assert { target, cond: Operand::Constant(Constant { + TerminatorKind::Assert { target, cond: Operand::Constant(box Constant { literal: Literal::Value { value: ConstVal::Bool(cond) }, .. @@ -66,4 +66,3 @@ impl MirPass for SimplifyBranches { } } } - diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index b325470ec818c..be384218a414e 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -534,7 +534,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { fn is_box_free(&self, operand: &Operand<'tcx>) -> bool { match operand { - &Operand::Constant(Constant { + &Operand::Constant(box Constant { literal: Literal::Value { value: ConstVal::Function(def_id, _), .. }, .. diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index d9921e62330b9..2421872518662 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -190,7 +190,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { Rvalue::Aggregate(ref kind, ref _operands) => { // AggregateKind is not distinguished by visit API, so // record it. (`super_rvalue` handles `_operands`.) - self.record(match *kind { + self.record(match **kind { AggregateKind::Array(_) => "AggregateKind::Array", AggregateKind::Tuple => "AggregateKind::Tuple", AggregateKind::Adt(..) => "AggregateKind::Adt", diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index 889f9dc4cded5..96ef26d3f6f83 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -108,7 +108,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> { location: Location) { match *kind { mir::TerminatorKind::Call { - func: mir::Operand::Constant(mir::Constant { + func: mir::Operand::Constant(box mir::Constant { literal: Literal::Value { value: ConstVal::Function(def_id, _), .. }, .. diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 040194e63d07e..6ba00c7e10331 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -537,7 +537,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } failure?; - match *kind { + match **kind { mir::AggregateKind::Array(_) => { self.const_array(dest_ty, &fields) } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index b8e9a490b0e7c..667075e6970e1 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -104,7 +104,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } mir::Rvalue::Aggregate(ref kind, ref operands) => { - match *kind { + match **kind { mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => { let discr = adt_def.discriminant_for_variant(bcx.tcx(), variant_index) .to_u128_unchecked() as u64;