diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 726e94e49a19e..3a95aec388d30 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -306,7 +306,7 @@ pub fn openssl(build: &Build, target: &str) { println!("Configuring openssl for {}", target); build.run_quiet(&mut configure); println!("Building openssl for {}", target); - build.run_quiet(Command::new("make").current_dir(&obj)); + build.run_quiet(Command::new("make").arg("-j1").current_dir(&obj)); println!("Installing openssl for {}", target); build.run_quiet(Command::new("make").arg("install").current_dir(&obj)); diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index b73079b02bdd9..1dfbda8986ce1 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -39,12 +39,13 @@ use super::sub::Sub; use super::InferCtxt; use super::{MiscVariable, TypeTrace}; +use hir::def_id::DefId; use ty::{IntType, UintType}; use ty::{self, Ty, TyCtxt}; use ty::error::TypeError; -use ty::fold::TypeFoldable; -use ty::relate::{RelateResult, TypeRelation}; -use traits::PredicateObligations; +use ty::relate::{self, Relate, RelateResult, TypeRelation}; +use ty::subst::Substs; +use traits::{Obligation, PredicateObligations}; use syntax::ast; use syntax_pos::Span; @@ -207,11 +208,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 == EqTo)?; + 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 @@ -230,10 +236,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,22 +246,33 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { fn generalize(&self, ty: Ty<'tcx>, for_vid: ty::TyVid, - is_eq_relation: bool) - -> RelateResult<'tcx, Ty<'tcx>> + dir: RelationDir) + -> RelateResult<'tcx, Generalization<'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, + needs_wf: false, }; - let u = ty.fold_with(&mut generalize); - if generalize.cycle_detected { - Err(TypeError::CyclicTy) - } else { - Ok(u) - } + + let ty = generalize.relate(&ty, &ty)?; + let needs_wf = generalize.needs_wf; + Ok(Generalization { ty, needs_wf }) } } @@ -264,16 +280,104 @@ 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, + needs_wf: bool, // see the field `needs_wf` in `Generalization` } -impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> { +/// 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> { + 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_item_substs(&mut self, + item_def_id: DefId, + a_subst: &'tcx Substs<'tcx>, + b_subst: &'tcx Substs<'tcx>) + -> RelateResult<'tcx, &'tcx Substs<'tcx>> + { + if self.ambient_variance == ty::Variance::Invariant { + // Avoid fetching the variance if we are in an invariant + // context; no need, and it can induce dependency cycles + // (e.g. #41849). + relate::relate_substs(self, None, a_subst, b_subst) + } else { + let variances; + let opt_variances = if self.tcx().variance_computed.get() { + variances = self.tcx().item_variances(item_def_id); + Some(&*variances) + } else { + None + }; + relate::relate_substs(self, opt_variances, a_subst, b_subst) + } + } + + 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 +390,63 @@ 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 { + // 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); } } } } + 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: &'tcx ty::Region) -> &'tcx ty::Region { + fn regions(&mut self, r: &'tcx ty::Region, r2: &'tcx ty::Region) + -> RelateResult<'tcx, &'tcx ty::Region> { + 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 +468,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/infer/equate.rs b/src/librustc/infer/equate.rs index f620965ced845..0840dd4e79dff 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -11,9 +11,12 @@ use super::combine::{CombineFields, RelationDir}; use super::{Subtype}; +use hir::def_id::DefId; + use ty::{self, Ty, TyCtxt}; use ty::TyVar; -use ty::relate::{Relate, RelateResult, TypeRelation}; +use ty::subst::Substs; +use ty::relate::{self, Relate, RelateResult, TypeRelation}; /// Ensures `a` is made equal to `b`. Returns `a` on success. pub struct Equate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> { @@ -38,6 +41,22 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> fn a_is_expected(&self) -> bool { self.a_is_expected } + fn relate_item_substs(&mut self, + _item_def_id: DefId, + a_subst: &'tcx Substs<'tcx>, + b_subst: &'tcx Substs<'tcx>) + -> RelateResult<'tcx, &'tcx Substs<'tcx>> + { + // NB: Once we are equating types, we don't care about + // variance, so don't try to lookup the variance here. This + // also avoids some cycles (e.g. #41849) since looking up + // variance requires computing types which can require + // performing trait matching (which then performs equality + // unification). + + relate::relate_substs(self, None, a_subst, b_subst) + } + fn relate_with_variance>(&mut self, _: ty::Variance, a: &T, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 352b6ab1d356f..d547607980099 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -306,6 +306,66 @@ pub enum Variance { Bivariant, // T <: T -- e.g., unused type parameter } +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/ty/relate.rs b/src/librustc/ty/relate.rs index cef24d44d6875..d9a69401120e6 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -51,6 +51,30 @@ pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized { Relate::relate(self, a, b) } + /// Relate the two substitutions for the given item. The default + /// is to look up the variance for the item and proceed + /// accordingly. + fn relate_item_substs(&mut self, + item_def_id: DefId, + a_subst: &'tcx Substs<'tcx>, + b_subst: &'tcx Substs<'tcx>) + -> RelateResult<'tcx, &'tcx Substs<'tcx>> + { + debug!("relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})", + item_def_id, + a_subst, + b_subst); + + let variances; + let opt_variances = if self.tcx().variance_computed.get() { + variances = self.tcx().item_variances(item_def_id); + Some(&*variances) + } else { + None + }; + relate_substs(self, opt_variances, a_subst, b_subst) + } + /// Switch variance for the purpose of relating `a` and `b`. fn relate_with_variance>(&mut self, variance: ty::Variance, @@ -109,31 +133,6 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { } } -// substitutions are not themselves relatable without more context, -// but they is an important subroutine for things that ARE relatable, -// like traits etc. -fn relate_item_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, - item_def_id: DefId, - a_subst: &'tcx Substs<'tcx>, - b_subst: &'tcx Substs<'tcx>) - -> RelateResult<'tcx, &'tcx Substs<'tcx>> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a -{ - debug!("substs: item_def_id={:?} a_subst={:?} b_subst={:?}", - item_def_id, - a_subst, - b_subst); - - let variances; - let opt_variances = if relation.tcx().variance_computed.get() { - variances = relation.tcx().item_variances(item_def_id); - Some(&*variances) - } else { - None - }; - relate_substs(relation, opt_variances, a_subst, b_subst) -} - pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, variances: Option<&Vec>, a_subst: &'tcx Substs<'tcx>, @@ -297,7 +296,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?; + let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?; Ok(ty::TraitRef { def_id: a.def_id, substs: substs }) } } @@ -314,7 +313,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?; + let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?; Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs }) } } @@ -378,7 +377,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, (&ty::TyAdt(a_def, a_substs), &ty::TyAdt(b_def, b_substs)) if a_def == b_def => { - let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?; + let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; Ok(tcx.mk_adt(a_def, substs)) } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 47b41a75cf531..748e7966eb256 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -253,6 +253,45 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return err_info; } + // Here we are considering a case of converting + // `S` to S`. As an example, let's imagine a struct `Foo`, + // which acts like a pointer to `U`, but carries along some extra data of type `T`: + // + // struct Foo { + // extra: T, + // ptr: *mut U, + // } + // + // We might have an impl that allows (e.g.) `Foo` to be unsized + // to `Foo`. That impl would look like: + // + // impl, V> CoerceUnsized> for Foo {} + // + // Here `U = [i32; 3]` and `V = [i32]`. At runtime, + // when this coercion occurs, we would be changing the + // field `ptr` from a thin pointer of type `*mut [i32; + // 3]` to a fat pointer of type `*mut [i32]` (with + // extra data `3`). **The purpose of this check is to + // make sure that we know how to do this conversion.** + // + // To check if this impl is legal, we would walk down + // the fields of `Foo` and consider their types with + // both substitutes. We are looking to find that + // exactly one (non-phantom) field has changed its + // type, which we will expect to be the pointer that + // is becoming fat (we could probably generalize this + // to mutiple thin pointers of the same type becoming + // fat, but we don't). In this case: + // + // - `extra` has type `T` before and type `T` after + // - `ptr` has type `*mut U` before and type `*mut V` after + // + // Since just one field changed, we would then check + // that `*mut U: CoerceUnsized<*mut V>` is implemented + // (in other words, that we know how to do this + // conversion). This will work out because `U: + // Unsize`, and we have a builtin rule that `*mut + // U` can be coerced to `*mut V` if `U: Unsize`. let fields = &def_a.struct_variant().fields; let diff_fields = fields.iter() .enumerate() @@ -264,8 +303,16 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return None; } - // Ignore fields that aren't significantly changed - if let Ok(ok) = infcx.sub_types(false, &cause, b, a) { + // Ignore fields that aren't changed; it may + // be that we could get away with subtyping or + // something more accepting, but we use + // equality because we want to be able to + // perform this check without computing + // variance where possible. (This is because + // we may have to evaluate constraint + // expressions in the course of execution.) + // See e.g. #41936. + if let Ok(ok) = infcx.eq_types(false, &cause, b, a) { if ok.obligations.is_empty() { return None; } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 1bde1eea37c39..fb997e937bc64 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -24,7 +24,6 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use super::terms::*; use super::terms::VarianceTerm::*; -use super::xform::*; use dep_graph::DepNode::ItemSignature as VarianceDepNode; 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: 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() { } 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() { +} diff --git a/src/test/run-pass/issue-41849-variance-req.rs b/src/test/run-pass/issue-41849-variance-req.rs new file mode 100644 index 0000000000000..0557a6ef376b6 --- /dev/null +++ b/src/test/run-pass/issue-41849-variance-req.rs @@ -0,0 +1,43 @@ +// 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 #41849. + +use std::ops::Mul; + +const C: usize = 1; +const CAPACITY: usize = 1 * C; + +struct A { + f: [X; CAPACITY], +} + +struct B { + f: T, +} + +impl Mul for B { + type Output = Self; + fn mul(self, _rhs: B) -> Self::Output { + self + } +} + +impl Mul for B { + type Output = Self; + fn mul(self, _rhs: usize) -> Self::Output { + self + } +} + +fn main() { + let a = A { f: [1] }; + let _ = B { f: a }; +} diff --git a/src/test/run-pass/issue-41936-variance-coerce-unsized-cycle.rs b/src/test/run-pass/issue-41936-variance-coerce-unsized-cycle.rs new file mode 100644 index 0000000000000..bfbead8789178 --- /dev/null +++ b/src/test/run-pass/issue-41936-variance-coerce-unsized-cycle.rs @@ -0,0 +1,38 @@ +// 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 #41936. The coerce-unsized trait check in +// coherence was using subtyping, which triggered variance +// computation, which failed because it required type info for fields +// that had not (yet) been computed. + +#![feature(unsize)] +#![feature(coerce_unsized)] + +use std::{marker,ops}; + +// Change the array to a non-array, and error disappears +// Adding a new field to the end keeps the error +struct LogDataBuf([u8;8]); + +struct Aref +{ + // Inner structure triggers the error, removing the inner removes the message. + ptr: Box>, +} +impl, U: ?Sized> ops::CoerceUnsized> for Aref {} + +struct ArefInner +{ + // Even with this field commented out, the error is raised. + data: T, +} + +fn main(){}