From f22755f4cfe522213d8c75925054ff74b31cf47d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 22 Feb 2019 13:40:21 +0100 Subject: [PATCH 01/13] Fix #57979 by allowing a legitimate type error to take precedence over an ICE. --- src/librustc/infer/canonical/canonicalizer.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 408cba42ae04b..5a2686718185c 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -191,7 +191,16 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse { // response should be executing in a fully // canonicalized environment, so there shouldn't be // any other region names it can come up. - bug!("unexpected region in query response: `{:?}`", r) + // + // rust-lang/rust#57464: `impl Trait` can leak local + // scopes (in manner violating typeck). Therefore, use + // `delay_span_bug` to allow type error over an ICE. + ty::tls::with_context(|c| { + c.tcx.sess.delay_span_bug( + syntax_pos::DUMMY_SP, + &format!("unexpected region in query response: `{:?}`", r)); + }); + r } } } From 687c44977ab66a433d8c9dec8f3a2f643f27e5c6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 1 Feb 2019 10:41:08 -0500 Subject: [PATCH 02/13] make generalization code create new variables in correct universe In our type inference system, when we "generalize" a type T to become a suitable value for a type variable V, we sometimes wind up creating new inference variables. So, for example, if we are making V be some subtype of `&'X u32`, then we might instantiate V with `&'Y u32`. This generalized type is then related `&'Y u32 <: &'X u32`, resulting in a region constriant `'Y: 'X`. Previously, however, we were making these fresh variables like `'Y` in the "current universe", but they should be created in the universe of V. Moreover, we sometimes cheat in an invariant context and avoid creating fresh variables if we know the result must be equal -- we can only do that when the universes work out. --- src/librustc/infer/combine.rs | 71 +++++++++++++------ src/librustc/infer/mod.rs | 12 ++++ src/librustc/infer/region_constraints/mod.rs | 2 +- ...project-fn-ret-invariant.krisskross.stderr | 14 ++-- .../cache/project-fn-ret-invariant.rs | 4 +- .../project-fn-ret-invariant.transmute.stderr | 2 +- .../higher-ranked-projection.bad.stderr | 4 +- .../ui/hrtb/hrtb-perfect-forwarding.stderr | 4 +- src/test/ui/issues/issue-57843.rs | 24 +++++++ src/test/ui/issues/issue-57843.stderr | 12 ++++ 10 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 src/test/ui/issues/issue-57843.rs create mode 100644 src/test/ui/issues/issue-57843.stderr diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 40c11695d51e2..97f9c2ceba005 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -255,10 +255,24 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { RelationDir::SupertypeOf => ty::Contravariant, }; + debug!("generalize: ambient_variance = {:?}", ambient_variance); + + let for_universe = match self.infcx.type_variables.borrow_mut().probe(for_vid) { + v @ TypeVariableValue::Known { .. } => panic!( + "instantiating {:?} which has a known value {:?}", + for_vid, + v, + ), + TypeVariableValue::Unknown { universe } => universe, + }; + + debug!("generalize: for_universe = {:?}", for_universe); + 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), + for_universe, ambient_variance, needs_wf: false, root_ty: ty, @@ -288,6 +302,11 @@ struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { /// that means we would have created a cyclic type. for_vid_sub_root: ty::TyVid, + /// The universe of the type variable that is in the process of + /// being instantiated. Any fresh variables that we create in this + /// process should be in that same universe. + for_universe: ty::UniverseIndex, + /// Track the variance as we descend into the type. ambient_variance: ty::Variance, @@ -386,6 +405,8 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' 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 == + debug!("generalize: t={:?}", t); + // 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 @@ -403,12 +424,17 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' match variables.probe(vid) { TypeVariableValue::Known { value: u } => { drop(variables); + debug!("generalize: known value {:?}", u); self.relate(&u, &u) } TypeVariableValue::Unknown { universe } => { match self.ambient_variance { // Invariant: no need to make a fresh type variable. - ty::Invariant => return Ok(t), + ty::Invariant => { + if self.for_universe.can_name(universe) { + return Ok(t); + } + } // Bivariant: make a fresh var, but we // may need a WF predicate. See @@ -422,7 +448,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' } let origin = *variables.var_origin(vid); - let new_var_id = variables.new_var(universe, false, origin); + let new_var_id = variables.new_var(self.for_universe, false, origin); let u = self.tcx().mk_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); @@ -448,6 +474,8 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' -> RelateResult<'tcx, ty::Region<'tcx>> { assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be == + debug!("generalize: regions r={:?}", r); + match *r { // Never make variables for regions bound within the type itself, // nor for erased regions. @@ -456,37 +484,40 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' return Ok(r); } - // Always make a fresh region variable for placeholder - // regions; the higher-ranked decision procedures rely on - // this. - ty::RePlaceholder(..) => { } + ty::ReClosureBound(..) => { + span_bug!( + self.span, + "encountered unexpected ReClosureBound: {:?}", + r, + ); + } - // For anything else, we make a region variable, unless we - // are *equating*, in which case it's just wasteful. + ty::RePlaceholder(..) | + ty::ReVar(..) | ty::ReEmpty | ty::ReStatic | ty::ReScope(..) | - ty::ReVar(..) | ty::ReEarlyBound(..) | ty::ReFree(..) => { - match self.ambient_variance { - ty::Invariant => return Ok(r), - ty::Bivariant | ty::Covariant | ty::Contravariant => (), - } + // see common code below } + } - ty::ReClosureBound(..) => { - span_bug!( - self.span, - "encountered unexpected ReClosureBound: {:?}", - r, - ); + // If we are in an invariant context, we can re-use the region + // as is, unless it happens to be in some universe that we + // can't name. (In the case of a region *variable*, we could + // use it if we promoted it into our universe, but we don't + // bother.) + if let ty::Invariant = self.ambient_variance { + let r_universe = self.infcx.universe_of_region(r); + if self.for_universe.can_name(r_universe) { + return Ok(r); } } // FIXME: This is non-ideal because we don't give a // very descriptive origin for this region variable. - Ok(self.infcx.next_region_var(MiscVariable(self.span))) + Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe)) } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 958982545750f..1e2faaf506926 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1016,6 +1016,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_region(ty::ReVar(region_var)) } + /// Return the universe that the region `r` was created in. For + /// most regions (e.g., `'static`, named regions from the user, + /// etc) this is the root universe U0. For inference variables or + /// placeholders, however, it will return the universe which which + /// they are associated. + fn universe_of_region( + &self, + r: ty::Region<'tcx>, + ) -> ty::UniverseIndex { + self.borrow_region_constraints().universe(r) + } + /// Number of region variables created so far. pub fn num_region_vars(&self) -> usize { self.borrow_region_constraints().num_region_vars() diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 56ae850226c91..deae1e2357a49 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -814,7 +814,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { new_r } - fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex { + pub fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex { match *region { ty::ReScope(..) | ty::ReStatic diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr index 46901b44c4b6d..fa831ea81dcfb 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr @@ -9,15 +9,15 @@ LL | let a = bar(foo, y); //[krisskross]~ ERROR E0623 | ^ ...but data from `x` is returned here error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:55:8 + --> $DIR/project-fn-ret-invariant.rs:54:21 | LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... -... -LL | (a, b) //[krisskross]~ ERROR E0623 - | ^ ...but data from `x` is returned here + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... +LL | let a = bar(foo, y); //[krisskross]~ ERROR E0623 +LL | let b = bar(foo, x); //[krisskross]~ ERROR E0623 + | ^ ...but data from `y` is returned here error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index dfcf31b3b1f26..54b6e3642c2ea 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -51,8 +51,8 @@ fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { #[cfg(krisskross)] // two instantiations, mixing and matching: BAD fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { let a = bar(foo, y); //[krisskross]~ ERROR E0623 - let b = bar(foo, x); - (a, b) //[krisskross]~ ERROR E0623 + let b = bar(foo, x); //[krisskross]~ ERROR E0623 + (a, b) } #[rustc_error] diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 947844c45c408..dd1212eaac91d 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,4 +1,4 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/project-fn-ret-invariant.rs:48:8 | LL | bar(foo, x) //[transmute]~ ERROR E0495 diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index e4704494e1492..811c9a8f5e12b 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | foo(()); | ^^^ one type is more general than the other | - = note: expected type `Mirror` - found type `Mirror` + = note: expected type `&'a ()` + found type `&()` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index ec3bf8a1a1be3..439a5ffcff59d 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | foo_hrtb_bar_not(&mut t); //~ ERROR E0308 | ^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected type `Foo<&'a isize>` - found type `Foo<&isize>` + = note: expected type `Bar<&'a isize>` + found type `Bar<&'b isize>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57843.rs b/src/test/ui/issues/issue-57843.rs new file mode 100644 index 0000000000000..466082552667b --- /dev/null +++ b/src/test/ui/issues/issue-57843.rs @@ -0,0 +1,24 @@ +// Regression test for an ICE that occurred with the universes code: +// +// The signature of the closure `|_|` was being inferred to +// `exists<'r> fn(&'r u8)`. This should result in a type error since +// the signature `for<'r> fn(&'r u8)` is required. However, due to a +// bug in the type variable generalization code, the placeholder for +// `'r` was leaking out into the writeback phase, causing an ICE. + +trait ClonableFn { + fn clone(&self) -> Box; +} + +impl ClonableFn for F +where F: Fn(T) + Clone { + fn clone(&self) -> Box { + Box::new(self.clone()) + } +} + +struct Foo(Box ClonableFn<&'a bool>>); + +fn main() { + Foo(Box::new(|_| ())); //~ ERROR mismatched types +} diff --git a/src/test/ui/issues/issue-57843.stderr b/src/test/ui/issues/issue-57843.stderr new file mode 100644 index 0000000000000..4ef884cb3f589 --- /dev/null +++ b/src/test/ui/issues/issue-57843.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-57843.rs:23:9 + | +LL | Foo(Box::new(|_| ())); //~ ERROR mismatched types + | ^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(&'a bool,)>` + found type `std::ops::FnOnce<(&bool,)>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From f599ab6e0f6da00e42ea24b66e3f75f7e335cbd5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Feb 2019 04:57:32 -0500 Subject: [PATCH 03/13] s/skol_/placeholder_/ --- src/librustc/traits/select.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6db6fe31fba70..a87571d123638 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1639,15 +1639,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ) -> bool { let poly_trait_predicate = self.infcx() .resolve_type_vars_if_possible(&obligation.predicate); - let (skol_trait_predicate, _) = self.infcx() + let (placeholder_trait_predicate, _) = self.infcx() .replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ - skol_trait_predicate={:?}", - skol_trait_predicate, + placeholder_trait_predicate={:?}", + placeholder_trait_predicate, ); - let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty { + let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().sty { ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs), ty::Opaque(def_id, substs) => (def_id, substs), _ => { @@ -1655,7 +1655,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.cause.span, "match_projection_obligation_against_definition_bounds() called \ but self-ty is not a projection: {:?}", - skol_trait_predicate.trait_ref.self_ty() + placeholder_trait_predicate.trait_ref.self_ty() ); } }; @@ -1680,7 +1680,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.match_projection( obligation, bound.clone(), - skol_trait_predicate.trait_ref.clone(), + placeholder_trait_predicate.trait_ref.clone(), ) }) }); @@ -1697,7 +1697,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let result = self.match_projection( obligation, bound, - skol_trait_predicate.trait_ref.clone(), + placeholder_trait_predicate.trait_ref.clone(), ); assert!(result); @@ -1710,12 +1710,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, - skol_trait_ref: ty::TraitRef<'tcx>, + placeholder_trait_ref: ty::TraitRef<'tcx>, ) -> bool { - debug_assert!(!skol_trait_ref.has_escaping_bound_vars()); + debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); self.infcx .at(&obligation.cause, obligation.param_env) - .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) + .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .is_ok() } From 4916c8fdbd0d88341909dcd593321267272fd907 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 19 Feb 2019 18:38:42 -0500 Subject: [PATCH 04/13] reintroduce `commit_if_ok` call into `higher_ranked_sub` --- src/librustc/infer/higher_ranked/mod.rs | 47 ++++++++++++++----------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 709e8c0ba9b24..ff3ffd8ce499c 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -29,27 +29,29 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { let span = self.trace.cause.span; - // First, we instantiate each bound region in the supertype with a - // fresh placeholder region. - let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); + return self.infcx.commit_if_ok(|_snapshot| { + // First, we instantiate each bound region in the supertype with a + // fresh placeholder region. + let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); - // Next, we instantiate each bound region in the subtype - // with a fresh region variable. These region variables -- - // but no other pre-existing region variables -- can name - // the placeholders. - let (a_prime, _) = - self.infcx - .replace_bound_vars_with_fresh_vars(span, HigherRankedType, a); + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other pre-existing region variables -- can name + // the placeholders. + let (a_prime, _) = + self.infcx + .replace_bound_vars_with_fresh_vars(span, HigherRankedType, a); - debug!("a_prime={:?}", a_prime); - debug!("b_prime={:?}", b_prime); + debug!("a_prime={:?}", a_prime); + debug!("b_prime={:?}", b_prime); - // Compare types now that bound regions have been replaced. - let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; + // Compare types now that bound regions have been replaced. + let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; - debug!("higher_ranked_sub: OK result={:?}", result); + debug!("higher_ranked_sub: OK result={:?}", result); - Ok(ty::Binder::bind(result)) + Ok(ty::Binder::bind(result)) + }); } } @@ -72,10 +74,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html pub fn replace_bound_vars_with_placeholders( &self, - binder: &ty::Binder + binder: &ty::Binder, ) -> (T, PlaceholderMap<'tcx>) where - T: TypeFoldable<'tcx> + T: TypeFoldable<'tcx>, { let next_universe = self.create_next_universe(); @@ -96,10 +98,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t); debug!( - "replace_bound_vars_with_placeholders(binder={:?}, result={:?}, map={:?})", + "replace_bound_vars_with_placeholders(\ + next_universe={:?}, \ + binder={:?}, \ + result={:?}, \ + map={:?})", + next_universe, binder, result, - map + map, ); (result, map) From 2a8c36c949d4594f4cb91092f3f5b0276474f41f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 19 Feb 2019 18:48:29 -0500 Subject: [PATCH 05/13] reintroduce `commit_if_ok` calls to `subtype_predicate` --- src/librustc/infer/mod.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 1e2faaf506926..fa89eb3bddf85 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -935,20 +935,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return None; } - let ( - ty::SubtypePredicate { - a_is_expected, - a, - b, - }, - _, - ) = self.replace_bound_vars_with_placeholders(predicate); - - Some( - self.at(cause, param_env) - .sub_exp(a_is_expected, a, b) - .map(|ok| ok.unit()), - ) + Some(self.commit_if_ok(|_snapshot| { + let ( + ty::SubtypePredicate { + a_is_expected, + a, + b, + }, + _, + ) = self.replace_bound_vars_with_placeholders(predicate); + + Ok( + self.at(cause, param_env) + .sub_exp(a_is_expected, a, b)? + .unit(), + ) + })) } pub fn region_outlives_predicate( From 3693f1844e0414ed69a8f84569b1b1f0c346ee3c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Feb 2019 05:22:23 -0500 Subject: [PATCH 06/13] introduce a dummy leak check and invoke it in all the right places This set of diffs was produced by combing through b68fad670bb3612cac26e50751e4fd9150e59977 and seeing where the `leak_check` used to be invoked and how. --- src/librustc/infer/higher_ranked/mod.rs | 26 ++++++++++++-- src/librustc/infer/mod.rs | 33 +++++++++++------- src/librustc/traits/auto_trait.rs | 8 ++++- src/librustc/traits/error_reporting.rs | 11 ++++-- src/librustc/traits/fulfill.rs | 6 ++-- src/librustc/traits/project.rs | 14 ++++---- src/librustc/traits/select.rs | 46 ++++++++++++++++++------- 7 files changed, 105 insertions(+), 39 deletions(-) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index ff3ffd8ce499c..aed6a5673d526 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -4,6 +4,7 @@ use super::combine::CombineFields; use super::{HigherRankedType, InferCtxt, PlaceholderMap}; +use infer::CombinedSnapshot; use ty::relate::{Relate, RelateResult, TypeRelation}; use ty::{self, Binder, TypeFoldable}; @@ -29,10 +30,10 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { let span = self.trace.cause.span; - return self.infcx.commit_if_ok(|_snapshot| { + return self.infcx.commit_if_ok(|snapshot| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. - let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); + let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- @@ -48,6 +49,9 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // Compare types now that bound regions have been replaced. let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; + self.infcx + .leak_check(!a_is_expected, &placeholder_map, snapshot)?; + debug!("higher_ranked_sub: OK result={:?}", result); Ok(ty::Binder::bind(result)) @@ -111,4 +115,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { (result, map) } + + /// Searches region constraints created since `snapshot` that + /// affect one of the placeholders in `placeholder_map`, returning + /// an error if any of the placeholders are related to another + /// placeholder or would have to escape into some parent universe + /// that cannot name them. + /// + /// This is a temporary backwards compatibility measure to try and + /// retain the older (arguably incorrect) behavior of the + /// compiler. + pub fn leak_check( + &self, + _overly_polymorphic: bool, + _placeholder_map: &PlaceholderMap<'tcx>, + _snapshot: &CombinedSnapshot<'_, 'tcx>, + ) -> RelateResult<'tcx, ()> { + Ok(()) + } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index fa89eb3bddf85..a831c46ce7245 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -935,21 +935,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return None; } - Some(self.commit_if_ok(|_snapshot| { + Some(self.commit_if_ok(|snapshot| { let ( ty::SubtypePredicate { a_is_expected, a, b, }, - _, + placeholder_map, ) = self.replace_bound_vars_with_placeholders(predicate); - Ok( - self.at(cause, param_env) - .sub_exp(a_is_expected, a, b)? - .unit(), - ) + let ok = self.at(cause, param_env) + .sub_exp(a_is_expected, a, b)?; + + self.leak_check(false, &placeholder_map, snapshot)?; + + Ok(ok.unit()) })) } @@ -957,12 +958,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { &self, cause: &traits::ObligationCause<'tcx>, predicate: &ty::PolyRegionOutlivesPredicate<'tcx>, - ) { - let (ty::OutlivesPredicate(r_a, r_b), _) = - self.replace_bound_vars_with_placeholders(predicate); - let origin = - SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); - self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + ) -> UnitResult<'tcx> { + self.commit_if_ok(|snapshot| { + let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) = + self.replace_bound_vars_with_placeholders(predicate); + let origin = SubregionOrigin::from_obligation_cause( + cause, + || RelateRegionParamBound(cause.span), + ); + self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + self.leak_check(false, &placeholder_map, snapshot)?; + Ok(()) + }) } pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid { diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 92004ece26d00..f96c4e9014b36 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -771,7 +771,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } } &ty::Predicate::RegionOutlives(ref binder) => { - let () = select.infcx().region_outlives_predicate(&dummy_cause, binder); + if select + .infcx() + .region_outlives_predicate(&dummy_cause, binder) + .is_err() + { + return false; + } } &ty::Predicate::TypeOutlives(ref binder) => { match ( diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 367a7eacdfcaf..c40af035c7273 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -726,9 +726,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } ty::Predicate::RegionOutlives(ref predicate) => { - // These errors should show up as region - // inference failures. - panic!("region outlives {:?} failed", predicate); + let predicate = self.resolve_type_vars_if_possible(predicate); + let err = self.region_outlives_predicate(&obligation.cause, + &predicate).err().unwrap(); + struct_span_err!( + self.tcx.sess, span, E0279, + "the requirement `{}` is not satisfied (`{}`)", + predicate, err, + ) } ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 2e00d4d4b7c3b..219e971b3c927 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -331,8 +331,10 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, } ty::Predicate::RegionOutlives(ref binder) => { - let () = self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder); - ProcessResult::Changed(vec![]) + match self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder) { + Ok(()) => ProcessResult::Changed(vec![]), + Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)), + } } ty::Predicate::TypeOutlives(ref binder) => { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 21151276e7299..39b2d118fddfd 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -191,12 +191,15 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( obligation); let infcx = selcx.infcx(); - infcx.commit_if_ok(|_| { - let (placeholder_predicate, _) = + infcx.commit_if_ok(|snapshot| { + let (placeholder_predicate, placeholder_map) = infcx.replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation = obligation.with(placeholder_predicate); - project_and_unify_type(selcx, &placeholder_obligation) + let result = project_and_unify_type(selcx, &placeholder_obligation)?; + infcx.leak_check(false, &placeholder_map, snapshot) + .map_err(|err| MismatchedProjectionTypes { err })?; + Ok(result) }) } @@ -1427,9 +1430,8 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - poly_cache_entry: ty::PolyProjectionPredicate<'tcx>) - -> Progress<'tcx> -{ + poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, +) -> Progress<'tcx> { let infcx = selcx.infcx(); let cause = &obligation.cause; let param_env = obligation.param_env; diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index a87571d123638..20d95de60b312 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -29,7 +29,7 @@ use super::{ use dep_graph::{DepKind, DepNodeIndex}; use hir::def_id::DefId; -use infer::{InferCtxt, InferOk, TypeFreshener}; +use infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; use middle::lang_items; use mir::interpret::GlobalId; use ty::fast_reject; @@ -1624,8 +1624,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => return, } - let result = self.infcx.probe(|_| { - self.match_projection_obligation_against_definition_bounds(obligation) + let result = self.infcx.probe(|snapshot| { + self.match_projection_obligation_against_definition_bounds( + obligation, + snapshot, + ) }); if result { @@ -1636,10 +1639,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { let poly_trait_predicate = self.infcx() .resolve_type_vars_if_possible(&obligation.predicate); - let (placeholder_trait_predicate, _) = self.infcx() + let (placeholder_trait_predicate, placeholder_map) = self.infcx() .replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ @@ -1681,6 +1685,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, bound.clone(), placeholder_trait_predicate.trait_ref.clone(), + &placeholder_map, + snapshot, ) }) }); @@ -1698,6 +1704,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, bound, placeholder_trait_predicate.trait_ref.clone(), + &placeholder_map, + snapshot, ); assert!(result); @@ -1711,12 +1719,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, + placeholder_map: &PlaceholderMap<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .is_ok() + && + self.infcx.leak_check(false, placeholder_map, snapshot).is_ok() } /// Given an obligation like ``, search the obligations that the caller @@ -1917,8 +1929,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.infcx.probe(|_| { - if let Ok(_substs) = self.match_impl(impl_def_id, obligation) + self.infcx.probe(|snapshot| { + if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) { candidates.vec.push(ImplCandidate(impl_def_id)); } @@ -2697,9 +2709,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.infcx.in_snapshot(|_| { + self.infcx.in_snapshot(|snapshot| { let result = - self.match_projection_obligation_against_definition_bounds(obligation); + self.match_projection_obligation_against_definition_bounds( + obligation, + snapshot, + ); assert!(result); }) } @@ -2851,8 +2866,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.in_snapshot(|_| { - let substs = self.rematch_impl(impl_def_id, obligation); + self.infcx.in_snapshot(|snapshot| { + let substs = self.rematch_impl(impl_def_id, obligation, snapshot); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); self.vtable_impl( @@ -3443,8 +3458,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Normalized<'tcx, &'tcx Substs<'tcx>> { - match self.match_impl(impl_def_id, obligation) { + match self.match_impl(impl_def_id, obligation, snapshot) { Ok(substs) => substs, Err(()) => { bug!( @@ -3460,6 +3476,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Result>, ()> { let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); @@ -3470,7 +3487,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return Err(()); } - let (skol_obligation, _) = self.infcx() + let (skol_obligation, placeholder_map) = self.infcx() .replace_bound_vars_with_placeholders(&obligation.predicate); let skol_obligation_trait_ref = skol_obligation.trait_ref; @@ -3502,6 +3519,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); + if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) { + debug!("match_impl: failed leak check due to `{}`", e); + return Err(()); + } + debug!("match_impl: success impl_substs={:?}", impl_substs); Ok(Normalized { value: impl_substs, From 85a24b1a7d3dbbce905457494a151d4502a15a39 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Feb 2019 05:39:04 -0500 Subject: [PATCH 07/13] restore the actual leak-check --- src/librustc/infer/higher_ranked/mod.rs | 19 +- .../infer/region_constraints/leak_check.rs | 162 ++++++++++++++++++ src/librustc/infer/region_constraints/mod.rs | 2 + src/librustc/ty/error.rs | 16 +- src/librustc/ty/structural_impls.rs | 8 + src/test/ui/hrtb/issue-46989.rs | 42 +++++ src/test/ui/hrtb/issue-57639.rs | 29 ++++ src/test/ui/hrtb/issue-58451.rs | 13 ++ 8 files changed, 277 insertions(+), 14 deletions(-) create mode 100644 src/librustc/infer/region_constraints/leak_check.rs create mode 100644 src/test/ui/hrtb/issue-46989.rs create mode 100644 src/test/ui/hrtb/issue-57639.rs create mode 100644 src/test/ui/hrtb/issue-58451.rs diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index aed6a5673d526..70ab5a9b3c05e 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -116,21 +116,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { (result, map) } - /// Searches region constraints created since `snapshot` that - /// affect one of the placeholders in `placeholder_map`, returning - /// an error if any of the placeholders are related to another - /// placeholder or would have to escape into some parent universe - /// that cannot name them. - /// - /// This is a temporary backwards compatibility measure to try and - /// retain the older (arguably incorrect) behavior of the - /// compiler. + /// See `infer::region_constraints::RegionConstraintCollector::leak_check`. pub fn leak_check( &self, - _overly_polymorphic: bool, - _placeholder_map: &PlaceholderMap<'tcx>, - _snapshot: &CombinedSnapshot<'_, 'tcx>, + overly_polymorphic: bool, + placeholder_map: &PlaceholderMap<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> RelateResult<'tcx, ()> { - Ok(()) + self.borrow_region_constraints() + .leak_check(self.tcx, overly_polymorphic, placeholder_map, snapshot) } } diff --git a/src/librustc/infer/region_constraints/leak_check.rs b/src/librustc/infer/region_constraints/leak_check.rs new file mode 100644 index 0000000000000..4056b9e2d83bc --- /dev/null +++ b/src/librustc/infer/region_constraints/leak_check.rs @@ -0,0 +1,162 @@ +use super::*; +use crate::infer::{CombinedSnapshot, PlaceholderMap}; +use crate::ty::error::TypeError; +use crate::ty::relate::RelateResult; + +impl<'tcx> RegionConstraintCollector<'tcx> { + /// Searches region constraints created since `snapshot` that + /// affect one of the placeholders in `placeholder_map`, returning + /// an error if any of the placeholders are related to another + /// placeholder or would have to escape into some parent universe + /// that cannot name them. + /// + /// This is a temporary backwards compatibility measure to try and + /// retain the older (arguably incorrect) behavior of the + /// compiler. + /// + /// NB. The use of snapshot here is mostly an efficiency thing -- + /// we could search *all* region constraints, but that'd be a + /// bigger set and the data structures are not setup for that. If + /// we wind up keeping some form of this check long term, it would + /// probably be better to remove the snapshot parameter and to + /// refactor the constraint set. + pub fn leak_check( + &mut self, + tcx: TyCtxt<'_, '_, 'tcx>, + overly_polymorphic: bool, + placeholder_map: &PlaceholderMap<'tcx>, + _snapshot: &CombinedSnapshot<'_, 'tcx>, + ) -> RelateResult<'tcx, ()> { + debug!("leak_check(placeholders={:?})", placeholder_map); + + assert!(self.in_snapshot()); + + // Go through each placeholder that we created. + for (_, &placeholder_region) in placeholder_map { + // Find the universe this placeholder inhabits. + let placeholder = match placeholder_region { + ty::RePlaceholder(p) => p, + _ => bug!( + "leak_check: expected placeholder found {:?}", + placeholder_region, + ), + }; + + // Find all regions that are related to this placeholder + // in some way. This means any region that either outlives + // or is outlived by a placeholder. + let mut taint_set = TaintSet::new( + TaintDirections::both(), + placeholder_region, + ); + taint_set.fixed_point(tcx, &self.undo_log, &self.data.verifys); + let tainted_regions = taint_set.into_set(); + + // Report an error if two placeholders in the same universe + // are related to one another, or if a placeholder is related + // to something from a parent universe. + for &tainted_region in &tainted_regions { + if let ty::RePlaceholder(_) = tainted_region { + // Two placeholders cannot be related: + if tainted_region == placeholder_region { + continue; + } + } else if self.universe(tainted_region).can_name(placeholder.universe) { + continue; + } + + return Err(if overly_polymorphic { + debug!("Overly polymorphic!"); + TypeError::RegionsOverlyPolymorphic(placeholder.name, tainted_region) + } else { + debug!("Not as polymorphic!"); + TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, tainted_region) + }); + } + } + + Ok(()) + } +} + +#[derive(Debug)] +struct TaintSet<'tcx> { + directions: TaintDirections, + regions: FxHashSet>, +} + +impl<'tcx> TaintSet<'tcx> { + fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self { + let mut regions = FxHashSet::default(); + regions.insert(initial_region); + TaintSet { + directions: directions, + regions: regions, + } + } + + fn fixed_point( + &mut self, + tcx: TyCtxt<'_, '_, 'tcx>, + undo_log: &[UndoLog<'tcx>], + verifys: &[Verify<'tcx>], + ) { + let mut prev_len = 0; + while prev_len < self.len() { + debug!( + "tainted: prev_len = {:?} new_len = {:?}", + prev_len, + self.len() + ); + + prev_len = self.len(); + + for undo_entry in undo_log { + match undo_entry { + &AddConstraint(Constraint::VarSubVar(a, b)) => { + self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b))); + } + &AddConstraint(Constraint::RegSubVar(a, b)) => { + self.add_edge(a, tcx.mk_region(ReVar(b))); + } + &AddConstraint(Constraint::VarSubReg(a, b)) => { + self.add_edge(tcx.mk_region(ReVar(a)), b); + } + &AddConstraint(Constraint::RegSubReg(a, b)) => { + self.add_edge(a, b); + } + &AddGiven(a, b) => { + self.add_edge(a, tcx.mk_region(ReVar(b))); + } + &AddVerify(i) => span_bug!( + verifys[i].origin.span(), + "we never add verifications while doing higher-ranked things", + ), + &Purged | &AddCombination(..) | &AddVar(..) => {} + } + } + } + } + + fn into_set(self) -> FxHashSet> { + self.regions + } + + fn len(&self) -> usize { + self.regions.len() + } + + fn add_edge(&mut self, source: ty::Region<'tcx>, target: ty::Region<'tcx>) { + if self.directions.incoming { + if self.regions.contains(&target) { + self.regions.insert(source); + } + } + + if self.directions.outgoing { + if self.regions.contains(&source) { + self.regions.insert(target); + } + } + } +} diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index deae1e2357a49..07a676a86d3d7 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -17,6 +17,8 @@ use ty::{Region, RegionVid}; use std::collections::BTreeMap; use std::{cmp, fmt, mem, u32}; +mod leak_check; + #[derive(Default)] pub struct RegionConstraintCollector<'tcx> { /// For each `RegionVid`, the corresponding `RegionVariableOrigin`. diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 834b541d4c01b..774c538500b2d 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -1,5 +1,5 @@ use hir::def_id::DefId; -use ty::{self, Region, Ty, TyCtxt}; +use ty::{self, BoundRegion, Region, Ty, TyCtxt}; use std::borrow::Cow; use std::fmt; use rustc_target::spec::abi; @@ -27,6 +27,8 @@ pub enum TypeError<'tcx> { ArgCount, RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>), + RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>), + RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>), RegionsPlaceholderMismatch, Sorts(ExpectedFound>), @@ -101,6 +103,18 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { RegionsDoesNotOutlive(..) => { write!(f, "lifetime mismatch") } + RegionsInsufficientlyPolymorphic(br, _) => { + write!(f, + "expected bound lifetime parameter{}{}, found concrete lifetime", + if br.is_named() { " " } else { "" }, + br) + } + RegionsOverlyPolymorphic(br, _) => { + write!(f, + "expected concrete lifetime, found bound lifetime parameter{}{}", + if br.is_named() { " " } else { "" }, + br) + } RegionsPlaceholderMismatch => { write!(f, "one type is more general than the other") } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index dd9ffd08a4ef5..b09437813bd03 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -434,6 +434,12 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { RegionsDoesNotOutlive(a, b) => { return tcx.lift(&(a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b)) } + RegionsInsufficientlyPolymorphic(a, b) => { + return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b)) + } + RegionsOverlyPolymorphic(a, b) => { + return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b)) + } RegionsPlaceholderMismatch => RegionsPlaceholderMismatch, IntMismatch(x) => IntMismatch(x), FloatMismatch(x) => FloatMismatch(x), @@ -1021,6 +1027,8 @@ EnumTypeFoldableImpl! { (ty::error::TypeError::FixedArraySize)(x), (ty::error::TypeError::ArgCount), (ty::error::TypeError::RegionsDoesNotOutlive)(a, b), + (ty::error::TypeError::RegionsInsufficientlyPolymorphic)(a, b), + (ty::error::TypeError::RegionsOverlyPolymorphic)(a, b), (ty::error::TypeError::RegionsPlaceholderMismatch), (ty::error::TypeError::IntMismatch)(x), (ty::error::TypeError::FloatMismatch)(x), diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs new file mode 100644 index 0000000000000..2c85905545807 --- /dev/null +++ b/src/test/ui/hrtb/issue-46989.rs @@ -0,0 +1,42 @@ +// Regression test for #46989: +// +// In the move to universes, this test started passing. +// It is not necessarily WRONG to do so, but it was a bit +// surprising. The reason that it passed is that when we were +// asked to prove that +// +// for<'a> fn(&'a i32): Foo +// +// we were able to use the impl below to prove +// +// fn(&'empty i32): Foo +// +// and then we were able to prove that +// +// fn(&'empty i32) = for<'a> fn(&'a i32) +// +// This last fact is somewhat surprising, but essentially "falls out" +// from handling variance correctly. In particular, consider the subtyping +// relations. First: +// +// fn(&'empty i32) <: for<'a> fn(&'a i32) +// +// This holds because -- intuitively -- a fn that takes a reference but doesn't use +// it can be given a reference with any lifetime. Similarly, the opposite direction: +// +// for<'a> fn(&'a i32) <: fn(&'empty i32) +// +// holds because 'a can be instantiated to 'empty. + +trait Foo { + +} + +impl Foo for fn(A) { } + +fn assert_foo() {} + +fn main() { + assert_foo::(); + //~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied +} diff --git a/src/test/ui/hrtb/issue-57639.rs b/src/test/ui/hrtb/issue-57639.rs new file mode 100644 index 0000000000000..4bcaef3616bd5 --- /dev/null +++ b/src/test/ui/hrtb/issue-57639.rs @@ -0,0 +1,29 @@ +// Regression test for #57639: +// +// In the move to universes, this test stopped working. The problem +// was that when the trait solver was asked to prove `for<'a> T::Item: +// Foo<'a>` as part of WF checking, it wound up "eagerly committing" +// to the where clause, which says that `T::Item: Foo<'a>`, but it +// should instead have been using the bound found in the trait +// declaration. Pre-universe, this used to work out ok because we got +// "eager errors" due to the leak check. +// +// See [this comment on GitHub][c] for more details. +// +// run-pass +// +// [c]: https://github.com/rust-lang/rust/issues/57639#issuecomment-455685861 + +trait Foo<'a> {} + +trait Bar { + type Item: for<'a> Foo<'a>; +} + +fn foo<'a, T>(_: T) +where + T: Bar, + T::Item: Foo<'a>, +{} + +fn main() { } diff --git a/src/test/ui/hrtb/issue-58451.rs b/src/test/ui/hrtb/issue-58451.rs new file mode 100644 index 0000000000000..7ca6914d2ea96 --- /dev/null +++ b/src/test/ui/hrtb/issue-58451.rs @@ -0,0 +1,13 @@ +// Regression test for #58451: +// +// Error reporting here encountered an ICE in the shift to universes. + +fn f(i: I) +where + I: IntoIterator, + I::Item: for<'a> Into<&'a ()>, +{} + +fn main() { + f(&[f()]); +} From 542ad5e2a017f542784ee0bcd7c44583389bb897 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Feb 2019 12:52:23 -0500 Subject: [PATCH 08/13] update test files to reflect new output One surprise: old-lub-glb-object.rs, may indicate a bug --- .../infer/region_constraints/leak_check.rs | 12 ++ .../ui/anonymous-higher-ranked-lifetime.rs | 11 + .../anonymous-higher-ranked-lifetime.stderr | 196 ++++++++++++++++-- .../associated-types-eq-hr.rs | 8 +- .../associated-types-eq-hr.stderr | 95 +++++++-- .../higher-ranked-projection.bad.stderr | 15 +- .../higher-ranked-projection.good.stderr | 2 +- .../higher-ranked-projection.rs | 2 +- .../expect-fn-supply-fn.rs | 6 +- .../expect-fn-supply-fn.stderr | 57 +++-- .../coherence/coherence-subtyping.old.stderr | 14 -- .../coherence/coherence-subtyping.re.stderr | 14 -- src/test/ui/coherence/coherence-subtyping.rs | 6 +- ...pe.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 2 +- .../hr-subtype.bound_a_b_vs_bound_a.stderr | 22 +- .../hr-subtype.bound_a_vs_bound_a.stderr | 6 +- .../hr-subtype.bound_a_vs_bound_b.stderr | 6 +- .../hr-subtype.bound_a_vs_free_x.stderr | 2 +- ...-subtype.bound_co_a_b_vs_bound_co_a.stderr | 22 +- ...ubtype.bound_co_a_co_b_ret_contra_a.stderr | 22 +- ...hr-subtype.bound_co_a_vs_bound_co_b.stderr | 6 +- ...pe.bound_contra_a_contra_b_ret_co_a.stderr | 22 +- ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 2 +- ...-subtype.bound_inv_a_vs_bound_inv_b.stderr | 6 +- .../hr-subtype.free_x_vs_free_x.stderr | 6 +- src/test/ui/hr-subtype/hr-subtype.rs | 8 +- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 18 +- src/test/ui/hrtb/hrtb-exists-forall-fn.stderr | 2 +- .../hrtb-exists-forall-trait-contravariant.rs | 7 +- ...b-exists-forall-trait-contravariant.stderr | 21 ++ .../hrtb-exists-forall-trait-covariant.rs | 7 +- .../hrtb-exists-forall-trait-covariant.stderr | 21 ++ .../hrtb-exists-forall-trait-invariant.rs | 2 +- .../hrtb-exists-forall-trait-invariant.stderr | 21 +- ...igher-ranker-supertraits-transitive.stderr | 17 +- .../ui/hrtb/hrtb-higher-ranker-supertraits.rs | 4 +- .../hrtb-higher-ranker-supertraits.stderr | 41 +++- src/test/ui/hrtb/hrtb-just-for-static.stderr | 35 +++- src/test/ui/hrtb/issue-46989.stderr | 17 ++ src/test/ui/hrtb/issue-58451.rs | 2 +- src/test/ui/hrtb/issue-58451.stderr | 16 ++ src/test/ui/issues/issue-40000.stderr | 6 +- src/test/ui/lub-glb/old-lub-glb-hr.rs | 5 +- src/test/ui/lub-glb/old-lub-glb-hr.stderr | 17 ++ src/test/ui/lub-glb/old-lub-glb-object.rs | 6 +- src/test/ui/lub-glb/old-lub-glb-object.stderr | 16 -- .../closure-arg-type-mismatch.rs | 4 +- .../closure-arg-type-mismatch.stderr | 33 +-- .../ui/mismatched_types/closure-mismatch.rs | 3 +- .../mismatched_types/closure-mismatch.stderr | 34 ++- src/test/ui/mismatched_types/issue-36053-2.rs | 1 + .../ui/mismatched_types/issue-36053-2.stderr | 10 +- ...regions-fn-subtyping-return-static-fail.rs | 4 +- ...ons-fn-subtyping-return-static-fail.stderr | 17 +- ...lifetime-bounds-on-fns-where-clause.stderr | 4 +- ...lifetime-bounds-on-fns-where-clause.stderr | 4 +- .../regions-fn-subtyping-return-static.rs | 4 +- .../regions-fn-subtyping-return-static.stderr | 12 ++ .../regions-lifetime-bounds-on-fns.stderr | 4 +- .../unboxed-closures-unsafe-extern-fn.rs | 2 + .../unboxed-closures-unsafe-extern-fn.stderr | 34 ++- .../unboxed-closures-wrong-abi.rs | 2 + .../unboxed-closures-wrong-abi.stderr | 34 ++- ...boxed-closures-wrong-arg-type-extern-fn.rs | 2 + ...d-closures-wrong-arg-type-extern-fn.stderr | 34 ++- src/test/ui/where-clauses/where-for-self-2.rs | 2 +- .../ui/where-clauses/where-for-self-2.stderr | 19 +- 67 files changed, 826 insertions(+), 288 deletions(-) delete mode 100644 src/test/ui/coherence/coherence-subtyping.old.stderr delete mode 100644 src/test/ui/coherence/coherence-subtyping.re.stderr create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr create mode 100644 src/test/ui/hrtb/issue-46989.stderr create mode 100644 src/test/ui/hrtb/issue-58451.stderr create mode 100644 src/test/ui/lub-glb/old-lub-glb-hr.stderr delete mode 100644 src/test/ui/lub-glb/old-lub-glb-object.stderr create mode 100644 src/test/ui/regions/regions-fn-subtyping-return-static.stderr diff --git a/src/librustc/infer/region_constraints/leak_check.rs b/src/librustc/infer/region_constraints/leak_check.rs index 4056b9e2d83bc..8085258610d84 100644 --- a/src/librustc/infer/region_constraints/leak_check.rs +++ b/src/librustc/infer/region_constraints/leak_check.rs @@ -31,6 +31,18 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.in_snapshot()); + // If the user gave `-Zno-leak-check`, then skip the leak + // check completely. This is wildly unsound and also not + // unlikely to cause an ICE or two. It is intended for use + // only during a transition period, in which the MIR typeck + // uses the "universe-style" check, and the rest of typeck + // uses the more conservative leak check. Since the leak + // check is more conservative, we can't test the + // universe-style check without disabling it. + if tcx.sess.opts.debugging_opts.no_leak_check { + return Ok(()); + } + // Go through each placeholder that we created. for (_, &placeholder_region) in placeholder_map { // Find the universe this placeholder inhabits. diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.rs b/src/test/ui/anonymous-higher-ranked-lifetime.rs index 55b1667da50b1..2e2a124db9a5d 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.rs +++ b/src/test/ui/anonymous-higher-ranked-lifetime.rs @@ -1,15 +1,26 @@ fn main() { f1(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch f2(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch f3(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch f4(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch f5(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch g1(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch g2(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch g3(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch g4(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch } // Basic diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr index d2c722e32b210..378f352cb9228 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr +++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr @@ -7,13 +7,27 @@ LL | f1(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _` | note: required by `f1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:16:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1 | LL | fn f1(_: F) where F: Fn(&(), &()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5 + | +LL | f1(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), &()) -> _` + | +note: required by `f1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1 + | +LL | fn f1(_: F) where F: Fn(&(), &()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 | LL | f2(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -21,7 +35,7 @@ LL | f2(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _` | note: required by `f2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:17:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1 | LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,19 +43,47 @@ LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 | +LL | f2(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&'a (), &()) -> _` + | +note: required by `f2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1 + | +LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 + | LL | f3(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&(), &'r ()) -> _` | note: required by `f3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:18:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 | LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 + | +LL | f3(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), &()) -> _` + | +note: required by `f3` + --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 + | +LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 | LL | f4(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -49,13 +91,27 @@ LL | f4(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _` | note: required by `f4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:19:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 | LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 + | +LL | f4(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), &'r ()) -> _` + | +note: required by `f4` + --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 + | +LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 | LL | f5(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -63,13 +119,27 @@ LL | f5(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r> fn(&'r (), &'r ()) -> _` | note: required by `f5` - --> $DIR/anonymous-higher-ranked-lifetime.rs:20:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1 | LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 + | +LL | f5(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&'r (), &'r ()) -> _` + | +note: required by `f5` + --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1 + | +LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 | LL | g1(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -77,13 +147,27 @@ LL | g1(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>) -> _` | note: required by `g1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:23:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1 | LL | fn g1(_: F) where F: Fn(&(), Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 + | +LL | g1(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` + | +note: required by `g1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1 + | +LL | fn g1(_: F) where F: Fn(&(), Box) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 | LL | g2(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -91,13 +175,27 @@ LL | g2(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _` | note: required by `g2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:24:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1 | LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 + | +LL | g2(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` + | +note: required by `g2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1 + | +LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 | LL | g3(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -105,13 +203,27 @@ LL | g3(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'s> fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` | note: required by `g3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:25:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1 | LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 + | +LL | g3(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` + | +note: required by `g3` + --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1 + | +LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 | LL | g4(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -119,13 +231,27 @@ LL | g4(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _` | note: required by `g4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:26:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1 + | +LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 + | +LL | g4(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` + | +note: required by `g4` + --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1 | LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 | LL | h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` @@ -133,13 +259,27 @@ LL | h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<(dyn for<'t0> std::ops::Fn(&'t0 ()) + 'static)>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _` | note: required by `h1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1 | LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 + | +LL | h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` + | | + | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &(), for<'r, 's> fn(&'r (), &'s ())) -> _` + | +note: required by `h1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1 + | +LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 | LL | h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` @@ -147,11 +287,25 @@ LL | h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _` | note: required by `h2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1 + | +LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 + | +LL | h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` + | | + | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _` + | +note: required by `h2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1 | LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index 20fa1e7a48db1..e6afa3f71c2f0 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -89,12 +89,14 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::(); - //~^ ERROR not general enough + //~^ ERROR not satisfied + //~| ERROR type mismatch } pub fn call_tuple_two() { tuple_two::(); - //~^ ERROR not general enough + //~^ ERROR not satisfied + //~| ERROR type mismatch } pub fn call_tuple_three() { @@ -103,7 +105,7 @@ pub fn call_tuple_three() { pub fn call_tuple_four() { tuple_four::(); - //~^ ERROR not general enough + //~^ ERROR not satisfied } fn main() { } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index d3eaa894b5043..3721b69898876 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -34,36 +34,93 @@ LL | | // ok for UintStruct, but not IntStruct LL | | } | |_^ -error: implementation of `TheTrait` is not general enough +error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied --> $DIR/associated-types-eq-hr.rs:91:5 | LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` | - = note: Due to a where-clause on `tuple_one`, - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` + = help: the following implementations were found: + > +note: required by `tuple_one` + --> $DIR/associated-types-eq-hr.rs:56:1 + | +LL | / fn tuple_one() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> +LL | | { +LL | | // not ok for tuple, two lifetimes and we pick first +LL | | } + | |_^ -error: implementation of `TheTrait` is not general enough - --> $DIR/associated-types-eq-hr.rs:96:5 +error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'x isize` + --> $DIR/associated-types-eq-hr.rs:91:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | +note: required by `tuple_one` + --> $DIR/associated-types-eq-hr.rs:56:1 + | +LL | / fn tuple_one() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> +LL | | { +LL | | // not ok for tuple, two lifetimes and we pick first +LL | | } + | |_^ + +error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied + --> $DIR/associated-types-eq-hr.rs:97:5 | LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | + = help: the following implementations were found: + > +note: required by `tuple_two` + --> $DIR/associated-types-eq-hr.rs:62:1 | - = note: Due to a where-clause on `tuple_two`, - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` +LL | / fn tuple_two() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> +LL | | { +LL | | // not ok for tuple, two lifetimes and we pick second +LL | | } + | |_^ + +error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'y isize` + --> $DIR/associated-types-eq-hr.rs:97:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | +note: required by `tuple_two` + --> $DIR/associated-types-eq-hr.rs:62:1 + | +LL | / fn tuple_two() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> +LL | | { +LL | | // not ok for tuple, two lifetimes and we pick second +LL | | } + | |_^ -error: implementation of `TheTrait` is not general enough - --> $DIR/associated-types-eq-hr.rs:105:5 +error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied + --> $DIR/associated-types-eq-hr.rs:107:5 | LL | tuple_four::(); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | + = help: the following implementations were found: + > +note: required by `tuple_four` + --> $DIR/associated-types-eq-hr.rs:74:1 | - = note: Due to a where-clause on `tuple_four`, - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` +LL | / fn tuple_four() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> +LL | | { +LL | | // not ok for tuple, two lifetimes, and lifetime matching is invariant +LL | | } + | |_^ -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors occurred: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index 811c9a8f5e12b..cc69e849fe144 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,12 +1,17 @@ -error[E0308]: mismatched types +error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` --> $DIR/higher-ranked-projection.rs:25:5 | LL | foo(()); - | ^^^ one type is more general than the other + | ^^^ expected bound lifetime parameter 'a, found concrete lifetime | - = note: expected type `&'a ()` - found type `&()` +note: required by `foo` + --> $DIR/higher-ranked-projection.rs:14:1 + | +LL | / fn foo(_t: T) +LL | | where for<'a> &'a T: Mirror +LL | | {} + | |__^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.good.stderr b/src/test/ui/associated-types/higher-ranked-projection.good.stderr index db15ec51d87c6..165e5213e0d34 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.good.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.good.stderr @@ -3,7 +3,7 @@ error: compilation successful | LL | / fn main() { //[good]~ ERROR compilation successful LL | | foo(()); -LL | | //[bad]~^ ERROR E0308 +LL | | //[bad]~^ ERROR type mismatch LL | | } | |_^ diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index 5b380c982f041..a2ea6d8f206b6 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -23,5 +23,5 @@ fn foo(_t: T) #[rustc_error] fn main() { //[good]~ ERROR compilation successful foo(()); - //[bad]~^ ERROR E0308 + //[bad]~^ ERROR type mismatch } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index 6977fd47a2e85..a4e43da91baf8 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -28,14 +28,14 @@ fn expect_free_supply_bound() { // Here, we are given a function whose region is bound at closure level, // but we expect one bound in the argument. Error results. with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - //~^ ERROR mismatched types + //~^ ERROR type mismatch } fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { // Here, we are given a `fn(&u32)` but we expect a `fn(&'x // u32)`. In principle, this could be ok, but we demand equality. with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - //~^ ERROR mismatched types + //~^ ERROR type mismatch } fn expect_bound_supply_free_from_closure() { @@ -44,7 +44,7 @@ fn expect_bound_supply_free_from_closure() { // the argument level. type Foo<'a> = fn(&'a u32); with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - //~^ ERROR mismatched types + //~^ ERROR type mismatch }); } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index b1cfd6cef1022..ab35aeff697b7 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -36,33 +36,58 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the b LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:30:52 +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-fn-supply-fn.rs:30:5 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` + | | + | expected signature of `fn(fn(&'a u32), &i32) -> _` | - = note: expected type `fn(&u32)` - found type `for<'r> fn(&'r u32)` +note: required by `with_closure_expecting_fn_with_free_region` + --> $DIR/expect-fn-supply-fn.rs:1:1 + | +LL | / fn with_closure_expecting_fn_with_free_region(_: F) +LL | | where F: for<'a> FnOnce(fn(&'a u32), &i32) +LL | | { +LL | | } + | |_^ -error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:37:53 +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-fn-supply-fn.rs:37:5 | LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` | - = note: expected type `for<'r> fn(&'r u32)` - found type `fn(&'x u32)` +note: required by `with_closure_expecting_fn_with_bound_region` + --> $DIR/expect-fn-supply-fn.rs:6:1 + | +LL | / fn with_closure_expecting_fn_with_bound_region(_: F) +LL | | where F: FnOnce(fn(&u32), &i32) +LL | | { +LL | | } + | |_^ -error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:46:53 +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-fn-supply-fn.rs:46:5 | LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | +note: required by `with_closure_expecting_fn_with_bound_region` + --> $DIR/expect-fn-supply-fn.rs:6:1 | - = note: expected type `for<'r> fn(&'r u32)` - found type `fn(&u32)` +LL | / fn with_closure_expecting_fn_with_bound_region(_: F) +LL | | where F: FnOnce(fn(&u32), &i32) +LL | | { +LL | | } + | |_^ error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors occurred: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/coherence/coherence-subtyping.old.stderr b/src/test/ui/coherence/coherence-subtyping.old.stderr deleted file mode 100644 index db9f9f7665374..0000000000000 --- a/src/test/ui/coherence/coherence-subtyping.old.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0119]: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:15:1 - | -LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { - | --------------------------------------------------------- first implementation here -... -LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - | - = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-subtyping.re.stderr b/src/test/ui/coherence/coherence-subtyping.re.stderr deleted file mode 100644 index db9f9f7665374..0000000000000 --- a/src/test/ui/coherence/coherence-subtyping.re.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0119]: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:15:1 - | -LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { - | --------------------------------------------------------- first implementation here -... -LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - | - = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-subtyping.rs b/src/test/ui/coherence/coherence-subtyping.rs index f27e14eab63da..e74067578069e 100644 --- a/src/test/ui/coherence/coherence-subtyping.rs +++ b/src/test/ui/coherence/coherence-subtyping.rs @@ -1,7 +1,11 @@ // Test that two distinct impls which match subtypes of one another // yield coherence errors (or not) depending on the variance. +// +// Note: This scenario is currently accepted, but as part of the +// universe transition (#56105) may eventually become an error. // revisions: old re +// compile-pass #![cfg_attr(re, feature(re_rebalance_coherence))] @@ -13,8 +17,6 @@ impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { } impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - //[old]~^ ERROR - //[re]~^^ ERROR } fn main() { } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index bdfabdabbebb7..8e2b0b8c60045 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index 25b74d855bb48..dbb5018139076 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr @@ -1,14 +1,16 @@ -error: compilation successful - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful -LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful -LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful -LL | | } - | |_^ +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a +... +LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), +LL | | for<'a> fn(&'a u32, &'a u32)) } + | |__________________________________________________________________- in this macro invocation + | + = note: expected type `std::option::Option fn(&'a u32, &'b u32)>` + found type `std::option::Option fn(&'a u32, &'a u32)>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index 74b8c89b6e86f..db9892b48a6f7 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), LL | | fn(&'x u32)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index 25b74d855bb48..e9fb73411bd39 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr @@ -1,14 +1,16 @@ -error: compilation successful - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful -LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful -LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful -LL | | } - | |_^ +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a +... +LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), +LL | | for<'a> fn(Co<'a>, Co<'a>)) } + | |______________________________________________________________________- in this macro invocation + | + = note: expected type `std::option::Option fn(Co<'a>, Co<'b>)>` + found type `std::option::Option fn(Co<'a>, Co<'a>)>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index 25b74d855bb48..d0e80faa68e8b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr @@ -1,14 +1,16 @@ -error: compilation successful - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful -LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful -LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful -LL | | } - | |_^ +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a +... +LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, +LL | | for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } + | |______________________________________________________________________________________- in this macro invocation + | + = note: expected type `std::option::Option fn(Co<'a>, Co<'b>) -> Contra<'a>>` + found type `std::option::Option fn(Co<'a>, Co<'a>) -> Contra<'a>>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index 25b74d855bb48..3605ecf4f8667 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -1,14 +1,16 @@ -error: compilation successful - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful -LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful -LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful -LL | | } - | |_^ +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a +... +LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, +LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } + | |______________________________________________________________________________________________- in this macro invocation + | + = note: expected type `std::option::Option fn(Contra<'a>, Contra<'b>) -> Co<'a>>` + found type `std::option::Option fn(Contra<'a>, Contra<'a>) -> Co<'a>>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index 8168941e2777c..fae6e9b5c89ca 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index ad4f39f840528..2f7c1e6fd8c0d 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -42,6 +42,10 @@ macro_rules! check { //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR + //[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types + //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR + //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR + //[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR } } } @@ -99,8 +103,4 @@ fn main() { //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful //[free_x_vs_free_x]~^^^^^ ERROR compilation successful -//[bound_a_b_vs_bound_a]~^^^^^^ ERROR compilation successful -//[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR compilation successful -//[bound_co_a_b_vs_bound_co_a]~^^^^^^^^ ERROR compilation successful -//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful } diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 2ee398e3dd3b2..50e1af8f14231 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,12 +1,20 @@ -error: implementation of `Foo` is not general enough +error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied --> $DIR/hrtb-conflate-regions.rs:28:10 | LL | fn b() { want_foo2::(); } //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` | - = note: Due to a where-clause on `want_foo2`, - = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `SomeStruct` only implements `Foo<(&'2 isize, &'2 isize)>` for some lifetime `'2` + = help: the following implementations were found: + > +note: required by `want_foo2` + --> $DIR/hrtb-conflate-regions.rs:8:1 + | +LL | / fn want_foo2() +LL | | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> +LL | | { +LL | | } + | |_^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 6301ed45ac277..8e8892552b701 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hrtb-exists-forall-fn.rs:17:34 | LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types - | ^^^^^ one type is more general than the other + | ^^^^^ expected concrete lifetime, found bound lifetime parameter 'b | = note: expected type `for<'b> fn(&'b u32)` found type `fn(&u32)` diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs index 8801760056ecb..4c1d4d28a09b0 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -1,9 +1,7 @@ -// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// Test a case where variance and higher-ranked types interact in surprising ways. // // In particular, we test this pattern in trait solving, where it is not connected // to any part of the source code. -// -// compile-pass trait Trait {} @@ -30,6 +28,9 @@ fn main() { // - `?a: ?b` -- solveable if `?b` is also inferred to `'empty` // - So the subtyping check succeeds, somewhat surprisingly. // This is because we can use `'empty`. + // + // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); + //~^ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr new file mode 100644 index 0000000000000..7f2ca037f0f49 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `(): Trait fn(&'b u32)>` is not satisfied + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 + | +LL | foo::<()>(); + | ^^^^^^^^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Trait> +note: required by `foo` + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:8:1 + | +LL | / fn foo() +LL | | where +LL | | T: Trait fn(&'b u32)>, +LL | | { +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs index da1bb7cd5fd0b..95b57d6c5bb5e 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs @@ -1,9 +1,7 @@ -// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// Test a case where variance and higher-ranked types interact in surprising ways. // // In particular, we test this pattern in trait solving, where it is not connected // to any part of the source code. -// -// compile-pass trait Trait {} @@ -32,6 +30,9 @@ fn main() { // - `?b: ?a` -- solveable if `?b` is inferred to `'static` // - So the subtyping check succeeds, somewhat surprisingly. // This is because we can use `'static`. + // + // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); + //~^ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr new file mode 100644 index 0000000000000..cd5982e7588a7 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `(): Trait fn(fn(&'b u32))>` is not satisfied + --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:5 + | +LL | foo::<()>(); + | ^^^^^^^^^ the trait `Trait fn(fn(&'b u32))>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Trait> +note: required by `foo` + --> $DIR/hrtb-exists-forall-trait-covariant.rs:8:1 + | +LL | / fn foo() +LL | | where +LL | | T: Trait fn(fn(&'b u32))>, +LL | | { +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs index da3f8ad1b8957..827a68beee8bd 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs @@ -25,5 +25,5 @@ fn main() { // yielding `fn(&!b u32)`, in a fresh universe U1 // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. - foo::<()>(); //~ ERROR not general enough + foo::<()>(); //~ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 6a61181e2407c..f56b81759fede 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -1,12 +1,21 @@ -error: implementation of `Trait` is not general enough +error[E0277]: the trait bound `(): Trait fn(std::cell::Cell<&'b u32>)>` is not satisfied --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | foo::<()>(); //~ ERROR not general enough - | ^^^^^^^^^ +LL | foo::<()>(); //~ ERROR not satisfied + | ^^^^^^^^^ the trait `Trait fn(std::cell::Cell<&'b u32>)>` is not implemented for `()` | - = note: Due to a where-clause on `foo`, - = note: `()` must implement `Trait fn(std::cell::Cell<&'b u32>)>` - = note: but `()` only implements `Trait)>` for some lifetime `'0` + = help: the following implementations were found: + <() as Trait)>> +note: required by `foo` + --> $DIR/hrtb-exists-forall-trait-invariant.rs:10:1 + | +LL | / fn foo() +LL | | where +LL | | T: Trait fn(Cell<&'b u32>)>, +LL | | { +LL | | } + | |_^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index 0d7b5cbf82348..77c1789852e52 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -1,12 +1,19 @@ -error[E0308]: mismatched types +error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 | LL | want_bar_for_any_ccx(b); //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` | - = note: expected type `for<'ccx> Bar<'ccx>` - found type `Bar<'static>` + = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound +note: required by `want_bar_for_any_ccx` + --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:31:1 + | +LL | / fn want_bar_for_any_ccx(b: &B) +LL | | where B : for<'ccx> Bar<'ccx> +LL | | { +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs index 3d2d403462d8b..48ebe5017aa62 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs @@ -15,7 +15,7 @@ fn want_foo_for_some_tcx<'x,F>(f: &'x F) where F : Foo<'x> { want_foo_for_some_tcx(f); - want_foo_for_any_tcx(f); //~ ERROR E0308 + want_foo_for_any_tcx(f); //~ ERROR not satisfied } fn want_foo_for_any_tcx(f: &F) @@ -32,7 +32,7 @@ fn want_bar_for_some_ccx<'x,B>(b: &B) want_foo_for_any_tcx(b); want_bar_for_some_ccx(b); - want_bar_for_any_ccx(b); //~ ERROR E0308 + want_bar_for_any_ccx(b); //~ ERROR not satisfied } fn want_bar_for_any_ccx(b: &B) diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr index 31dbeec2a551b..5914cb3eaa494 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -1,21 +1,40 @@ -error[E0308]: mismatched types +error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5 | -LL | want_foo_for_any_tcx(f); //~ ERROR E0308 - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other +LL | want_foo_for_any_tcx(f); //~ ERROR not satisfied + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` | - = note: expected type `for<'tcx> Foo<'tcx>` - found type `Foo<'x>` + = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound +note: required by `want_foo_for_any_tcx` + --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 + | +LL | / fn want_foo_for_any_tcx(f: &F) +LL | | where F : for<'tcx> Foo<'tcx> +LL | | { +LL | | want_foo_for_some_tcx(f); +LL | | want_foo_for_any_tcx(f); +LL | | } + | |_^ -error[E0308]: mismatched types +error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:35:5 | -LL | want_bar_for_any_ccx(b); //~ ERROR E0308 - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other +LL | want_bar_for_any_ccx(b); //~ ERROR not satisfied + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | + = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound +note: required by `want_bar_for_any_ccx` + --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 | - = note: expected type `for<'ccx> Bar<'ccx>` - found type `Bar<'x>` +LL | / fn want_bar_for_any_ccx(b: &B) +LL | | where B : for<'ccx> Bar<'ccx> +LL | | { +LL | | want_foo_for_some_tcx(b); +... | +LL | | want_bar_for_any_ccx(b); +LL | | } + | |_^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 094c449802415..fe2bc1f222504 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,22 +1,37 @@ -error: implementation of `Foo` is not general enough +error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied --> $DIR/hrtb-just-for-static.rs:24:5 | LL | want_hrtb::() //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` | - = note: Due to a where-clause on `want_hrtb`, - = note: `StaticInt` must implement `Foo<&'0 isize>` for any lifetime `'0` - = note: but `StaticInt` only implements `Foo<&'1 isize>` for some lifetime `'1` + = help: the following implementations were found: + > +note: required by `want_hrtb` + --> $DIR/hrtb-just-for-static.rs:8:1 + | +LL | / fn want_hrtb() +LL | | where T : for<'a> Foo<&'a isize> +LL | | { +LL | | } + | |_^ -error: implementation of `Foo` is not general enough +error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied --> $DIR/hrtb-just-for-static.rs:30:5 | LL | want_hrtb::<&'a u32>() //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32` + | + = help: the following implementations were found: + <&'a u32 as Foo<&'a isize>> +note: required by `want_hrtb` + --> $DIR/hrtb-just-for-static.rs:8:1 | - = note: Due to a where-clause on `want_hrtb`, - = note: `&'a u32` must implement `Foo<&'0 isize>` for any lifetime `'0` - = note: but `&'1 u32` only implements `Foo<&'1 isize>` for the lifetime `'1` +LL | / fn want_hrtb() +LL | | where T : for<'a> Foo<&'a isize> +LL | | { +LL | | } + | |_^ error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr new file mode 100644 index 0000000000000..b308291d5c0eb --- /dev/null +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied + --> $DIR/issue-46989.rs:40:5 + | +LL | assert_foo::(); + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` + | + = help: the following implementations were found: + +note: required by `assert_foo` + --> $DIR/issue-46989.rs:37:1 + | +LL | fn assert_foo() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/issue-58451.rs b/src/test/ui/hrtb/issue-58451.rs index 7ca6914d2ea96..229e505767879 100644 --- a/src/test/ui/hrtb/issue-58451.rs +++ b/src/test/ui/hrtb/issue-58451.rs @@ -9,5 +9,5 @@ where {} fn main() { - f(&[f()]); + f(&[f()]); //~ ERROR this function takes 1 parameter } diff --git a/src/test/ui/hrtb/issue-58451.stderr b/src/test/ui/hrtb/issue-58451.stderr new file mode 100644 index 0000000000000..79c24855dc96c --- /dev/null +++ b/src/test/ui/hrtb/issue-58451.stderr @@ -0,0 +1,16 @@ +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/issue-58451.rs:12:9 + | +LL | / fn f(i: I) +LL | | where +LL | | I: IntoIterator, +LL | | I::Item: for<'a> Into<&'a ()>, +LL | | {} + | |__- defined here +... +LL | f(&[f()]); //~ ERROR this function takes 1 parameter + | ^^^ expected 1 parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index d7966cea52bb0..ce0c44c147563 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/issue-40000.rs:6:9 | LL | foo(bar); //~ ERROR E0308 - | ^^^ one type is more general than the other + | ^^^ expected concrete lifetime, found bound lifetime parameter | - = note: expected type `dyn for<'r> std::ops::Fn(&'r i32)` - found type `dyn std::ops::Fn(&i32)` + = note: expected type `std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r i32) + 'static)>` + found type `std::boxed::Box` error: aborting due to previous error diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs index 324dc86bd92b8..0ce87bf6ffe64 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr.rs @@ -4,13 +4,14 @@ // longer get an error, because we recognize these two types as // equivalent! // -// compile-pass +// Whoops -- now that we reinstituted the leak-check, we get an error +// again. fn foo( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { - let z = match 22 { + let z = match 22 { //~ ERROR match arms have incompatible types 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr new file mode 100644 index 0000000000000..28a366bca014c --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr.stderr @@ -0,0 +1,17 @@ +error[E0308]: match arms have incompatible types + --> $DIR/old-lub-glb-hr.rs:14:13 + | +LL | let z = match 22 { //~ ERROR match arms have incompatible types + | _____________^ +LL | | 0 => x, +LL | | _ => y, + | | - match arm with an incompatible type +LL | | }; + | |_____^ expected bound lifetime parameter, found concrete lifetime + | + = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)` + found type `for<'a> fn(&'a u8, &'a u8)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 9be7a813603d4..3e95a7111e0cd 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -1,5 +1,9 @@ // Test that we give a note when the old LUB/GLB algorithm would have // succeeded but the new code (which is stricter) gives an error. +// +// compile-pass +// +// TODO -- why does this test pass? trait Foo { } @@ -7,7 +11,7 @@ fn foo( x: &for<'a, 'b> Foo<&'a u8, &'b u8>, y: &for<'a> Foo<&'a u8, &'a u8>, ) { - let z = match 22 { //~ ERROR E0308 + let z = match 22 { 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr deleted file mode 100644 index 17d3648156b51..0000000000000 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/old-lub-glb-object.rs:10:13 - | -LL | let z = match 22 { //~ ERROR E0308 - | _____________^ -LL | | 0 => x, -LL | | _ => y, -LL | | }; - | |_____^ one type is more general than the other - | - = note: expected type `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` - found type `dyn for<'a> Foo<&'a u8, &'a u8>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index 437150666be0c..521bd3695dfe5 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -7,6 +7,6 @@ fn main() { fn baz(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { - baz(f); //~ ERROR mismatched types - //~| ERROR mismatched types + baz(f); //~ ERROR type mismatch + //~| ERROR type mismatch } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index a6628006587c1..5dd6887005e83 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -22,25 +22,34 @@ LL | a.iter().map(|_: (u16, u16)| 45); //~ ERROR type mismatch | | | expected signature of `fn(&(u32, u32)) -> _` -error[E0308]: mismatched types +error[E0631]: type mismatch in function arguments --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | baz(f); //~ ERROR mismatched types - | ^^^ one type is more general than the other +LL | baz(f); //~ ERROR type mismatch + | ^^^ + | | + | expected signature of `for<'r> fn(*mut &'r u32) -> _` + | found signature of `fn(*mut &'a u32) -> _` | - = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` - found type `std::ops::Fn<(*mut &'a u32,)>` +note: required by `baz` + --> $DIR/closure-arg-type-mismatch.rs:8:1 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types +error[E0271]: type mismatch resolving `for<'r> >::Output == ()` --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | baz(f); //~ ERROR mismatched types - | ^^^ one type is more general than the other +LL | baz(f); //~ ERROR type mismatch + | ^^^ expected bound lifetime parameter, found concrete lifetime + | +note: required by `baz` + --> $DIR/closure-arg-type-mismatch.rs:8:1 | - = note: expected type `std::ops::FnOnce<(*mut &u32,)>` - found type `std::ops::FnOnce<(*mut &'a u32,)>` +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors -Some errors occurred: E0308, E0631. -For more information about an error, try `rustc --explain E0308`. +Some errors occurred: E0271, E0631. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index 152a525493732..40a4641fe7196 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -5,5 +5,6 @@ impl Foo for T {} fn baz(_: T) {} fn main() { - baz(|_| ()); //~ ERROR E0308 + baz(|_| ()); //~ ERROR type mismatch + //~^ ERROR type mismatch } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 0d87bc228755f..e55047e96c297 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,12 +1,32 @@ -error[E0308]: mismatched types +error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` --> $DIR/closure-mismatch.rs:8:5 | -LL | baz(|_| ()); //~ ERROR E0308 - | ^^^ one type is more general than the other +LL | baz(|_| ()); //~ ERROR type mismatch + | ^^^ expected bound lifetime parameter, found concrete lifetime | - = note: expected type `for<'r> std::ops::Fn<(&'r (),)>` - found type `std::ops::Fn<(&(),)>` + = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` +note: required by `baz` + --> $DIR/closure-mismatch.rs:5:1 + | +LL | fn baz(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); //~ ERROR type mismatch + | ^^^ ------ found signature of `fn(_) -> _` + | | + | expected signature of `for<'r> fn(&'r ()) -> _` + | + = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` +note: required by `baz` + --> $DIR/closure-mismatch.rs:5:1 + | +LL | fn baz(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors occurred: E0271, E0631. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs index 9035e3380b0c5..9edfebcd49471 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.rs +++ b/src/test/ui/mismatched_types/issue-36053-2.rs @@ -7,4 +7,5 @@ fn main() { once::<&str>("str").fuse().filter(|a: &str| true).count(); //~^ ERROR no method named `count` //~| ERROR type mismatch in closure arguments + //~| ERROR type mismatch in closure arguments } diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index e53e8c520e0c4..c5c67e6bd9bd9 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -16,7 +16,15 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | | | expected signature of `for<'r> fn(&'r &str) -> _` -error: aborting due to 2 previous errors +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-36053-2.rs:7:32 + | +LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); + | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` + | | + | expected signature of `fn(&&str) -> _` + +error: aborting due to 3 previous errors Some errors occurred: E0599, E0631. For more information about an error, try `rustc --explain E0599`. diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions-fn-subtyping-return-static-fail.rs index 242119cc201da..2dd0c9796e258 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.rs +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.rs @@ -37,7 +37,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); + want_F(bar); //~ ERROR mismatched types want_F(baz); } @@ -45,7 +45,7 @@ fn supply_F() { fn supply_G() { want_G(foo); want_G(bar); - want_G(baz); //~ ERROR + want_G(baz); //~ ERROR mismatched types } pub fn main() { diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index a9234e43191ea..66e6a615b33bc 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -1,12 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/regions-fn-subtyping-return-static-fail.rs:40:12 + | +LL | want_F(bar); //~ ERROR mismatched types + | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx + | + = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` + found type `for<'a> fn(&'a S) -> &S {bar::<'_>}` + error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | -LL | want_G(baz); //~ ERROR - | ^^^ one type is more general than the other +LL | want_G(baz); //~ ERROR mismatched types + | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx | = note: expected type `for<'cx> fn(&'cx S) -> &'static S` - found type `for<'r> fn(&'r S) -> &'r S` + found type `for<'r> fn(&'r S) -> &'r S {baz}` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 47e1d0efdc77b..5c8b3d3ba6922 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -20,10 +20,10 @@ error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types - | ^ one type is more general than the other + | ^ expected concrete lifetime, found bound lifetime parameter | = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` + found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` error: aborting due to 3 previous errors diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index 1e7b99053f77f..f36885f7aeb99 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -31,10 +31,10 @@ error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0308 - | ^ one type is more general than the other + | ^ expected concrete lifetime, found bound lifetime parameter | = note: expected type `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found type `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` + found type `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs index 9010770f1dc82..fa2cc37d05b2b 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.rs +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs @@ -5,8 +5,6 @@ // *ANY* lifetime and returns a reference with the 'static lifetime. // This can safely be considered to be an instance of `F` because all // lifetimes are sublifetimes of 'static. -// -// compile-pass #![allow(dead_code)] #![allow(unused_variables)] @@ -40,7 +38,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); + want_F(bar); //~ ERROR mismatched types want_F(baz); } diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr new file mode 100644 index 0000000000000..42a5a7c806e08 --- /dev/null +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/regions-fn-subtyping-return-static.rs:41:12 + | +LL | want_F(bar); //~ ERROR mismatched types + | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx + | + = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` + found type `for<'a> fn(&'a S) -> &S {bar::<'_>}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index a43ee7ec3ace0..99d85e9e4b5a6 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -20,10 +20,10 @@ error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0308 - | ^ one type is more general than the other + | ^ expected concrete lifetime, found bound lifetime parameter | = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` + found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` error: aborting due to 3 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs index 12626fe69cb14..a6e26614a6a50 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs @@ -11,11 +11,13 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn c() { diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index 29f276711c745..ca0298283661f 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -11,8 +11,21 @@ note: required by `call_it` LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13 + | +LL | let x = call_it(&square, 22); + | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` +note: required by `call_it` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1 + | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:17:13 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13 | LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` @@ -25,18 +38,31 @@ LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:22:13 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13 + | +LL | let y = call_it_mut(&mut square, 22); + | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` +note: required by `call_it_mut` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1 + | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:13 | LL | let z = call_it_once(square, 22); | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | - = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` note: required by `call_it_once` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:1 | LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs index 7c3152c87c461..dd3b1afc39f31 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs @@ -11,11 +11,13 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn c() { diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index e382457860579..0abc58aeebfe5 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -11,8 +11,21 @@ note: required by `call_it` LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-abi.rs:12:13 + | +LL | let x = call_it(&square, 22); + | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` +note: required by `call_it` + --> $DIR/unboxed-closures-wrong-abi.rs:7:1 + | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:17:13 + --> $DIR/unboxed-closures-wrong-abi.rs:18:13 | LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` @@ -25,18 +38,31 @@ LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:22:13 + --> $DIR/unboxed-closures-wrong-abi.rs:18:13 + | +LL | let y = call_it_mut(&mut square, 22); + | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` +note: required by `call_it_mut` + --> $DIR/unboxed-closures-wrong-abi.rs:8:1 + | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-abi.rs:24:13 | LL | let z = call_it_once(square, 22); | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | - = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` note: required by `call_it_once` --> $DIR/unboxed-closures-wrong-abi.rs:9:1 | LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs index 61d46869cbbf2..c689d79266187 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -12,11 +12,13 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn c() { diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index da511f091bf6a..19b87ad171a51 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -11,8 +11,21 @@ note: required by `call_it` LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13 + | +LL | let x = call_it(&square, 22); + | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` +note: required by `call_it` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1 + | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:18:13 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13 | LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` @@ -25,18 +38,31 @@ LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:23:13 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13 + | +LL | let y = call_it_mut(&mut square, 22); + | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` +note: required by `call_it_mut` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1 + | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:13 | LL | let z = call_it_once(square, 22); | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | - = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` note: required by `call_it_once` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:1 | LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 0ce38e69f6b0f..31174fd4cf163 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -18,5 +18,5 @@ fn foo(x: &T) {} fn main() { - foo(&X); //~ ERROR implementation of `Bar` is not general enough + foo(&X); //~ ERROR trait bound } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index afc80bf4d8ee6..bbcb61a856d8d 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,12 +1,19 @@ -error: implementation of `Bar` is not general enough +error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied --> $DIR/where-for-self-2.rs:21:5 | -LL | foo(&X); //~ ERROR implementation of `Bar` is not general enough - | ^^^ +LL | foo(&X); //~ ERROR trait bound + | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` | - = note: Due to a where-clause on `foo`, - = note: `&'0 _` must implement `Bar` for any lifetime `'0` - = note: but `&'1 u32` only implements `Bar` for the lifetime `'1` + = help: the following implementations were found: + <&'static u32 as Bar> +note: required by `foo` + --> $DIR/where-for-self-2.rs:16:1 + | +LL | / fn foo(x: &T) +LL | | where for<'a> &'a T: Bar +LL | | {} + | |__^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. From 551aafc407e5240cb9d14a612c1e9a1d11d53775 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 21 Feb 2019 12:14:30 -0500 Subject: [PATCH 09/13] partially revert 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc This preserves the error you currently get on stable for the old-lub-glb-object.rs test. --- src/librustc/traits/select.rs | 20 ++++++++++++++++++- src/test/ui/lub-glb/old-lub-glb-object.rs | 6 +----- src/test/ui/lub-glb/old-lub-glb-object.stderr | 17 ++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/lub-glb/old-lub-glb-object.stderr diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 20d95de60b312..1c84603e9da07 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3254,9 +3254,27 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { tcx.mk_existential_predicates(iter) }); let source_trait = tcx.mk_dynamic(existential_predicates, r_b); + + // Require that the traits involved in this upcast are **equal**; + // only the **lifetime bound** is changed. + // + // FIXME: This condition is arguably too strong -- it + // would suffice for the source trait to be a + // *subtype* of the target trait. In particular + // changing from something like `for<'a, 'b> Foo<'a, + // 'b>` to `for<'a> Foo<'a, 'a>` should be + // permitted. And, indeed, in the in commit + // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this + // condition was loosened. However, when the leak check was added + // back, using subtype here actually guies the coercion code in + // such a way that it accepts `old-lub-glb-object.rs`. This is probably + // a good thing, but I've modified this to `.eq` because I want + // to continue rejecting that test (as we have done for quite some time) + // before we are firmly comfortable with what our behavior + // should be there. -nikomatsakis let InferOk { obligations, .. } = self.infcx .at(&obligation.cause, obligation.param_env) - .sup(target, source_trait) + .eq(target, source_trait) // FIXME -- see below .map_err(|_| Unimplemented)?; nested.extend(obligations); diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 3e95a7111e0cd..f45696bcaad70 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -1,9 +1,5 @@ // Test that we give a note when the old LUB/GLB algorithm would have // succeeded but the new code (which is stricter) gives an error. -// -// compile-pass -// -// TODO -- why does this test pass? trait Foo { } @@ -11,7 +7,7 @@ fn foo( x: &for<'a, 'b> Foo<&'a u8, &'b u8>, y: &for<'a> Foo<&'a u8, &'a u8>, ) { - let z = match 22 { + let z = match 22 { //~ ERROR match arms have incompatible types 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr new file mode 100644 index 0000000000000..a31cd6f7a1900 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -0,0 +1,17 @@ +error[E0308]: match arms have incompatible types + --> $DIR/old-lub-glb-object.rs:10:13 + | +LL | let z = match 22 { //~ ERROR match arms have incompatible types + | _____________^ +LL | | 0 => x, +LL | | _ => y, + | | - match arm with an incompatible type +LL | | }; + | |_____^ expected bound lifetime parameter 'a, found concrete lifetime + | + = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found type `&dyn for<'a> Foo<&'a u8, &'a u8>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 600ca1ecb09a3811d083366c418169d9f07a6668 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 22 Feb 2019 04:11:23 +0000 Subject: [PATCH 10/13] improve Pin documentation Incorporates a bunch of the documentation-related comments that came up when discussing `Pin` stabilization. --- src/libcore/marker.rs | 27 ++-- src/libcore/pin.rs | 336 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 312 insertions(+), 51 deletions(-) diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 65752ba032104..4fd386c16d96d 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -597,34 +597,43 @@ unsafe impl Freeze for &mut T {} /// Types which can be safely moved after being pinned. /// -/// Since Rust itself has no notion of immovable types, and will consider moves to always be safe, +/// Since Rust itself has no notion of immovable types, and considers moves +/// (e.g. through assignment or [`mem::replace`]) to always be safe, /// this trait cannot prevent types from moving by itself. /// -/// Instead it can be used to prevent moves through the type system, -/// by controlling the behavior of pointers wrapped in the [`Pin`] wrapper, +/// Instead it is used to prevent moves through the type system, +/// by controlling the behavior of pointers `P` wrapped in the [`Pin

`] wrapper, /// which "pin" the type in place by not allowing it to be moved out of them. /// See the [`pin module`] documentation for more information on pinning. /// /// Implementing this trait lifts the restrictions of pinning off a type, -/// which then allows it to move out with functions such as [`replace`]. +/// which then allows it to move out with functions such as [`mem::replace`]. +/// +/// `Unpin` has no consequence at all for non-pinned data. In particular, +/// [`mem::replace`] happily moves `!Unpin` data (it works for any `&mut T`, not +/// just when `T: Unpin`). However, you cannot use +/// [`mem::replace`] on data wrapped inside a [`Pin

`] because you cannot get the +/// `&mut T` you need for that, and *that* is what makes this system work. /// /// So this, for example, can only be done on types implementing `Unpin`: /// /// ```rust -/// use std::mem::replace; +/// use std::mem; /// use std::pin::Pin; /// /// let mut string = "this".to_string(); /// let mut pinned_string = Pin::new(&mut string); /// -/// // dereferencing the pointer mutably is only possible because String implements Unpin -/// replace(&mut *pinned_string, "other".to_string()); +/// // We need a mutable reference to call `mem::replace`. +/// // We can obtain such a reference by (implicitly) invoking `Pin::deref_mut`, +/// // but that is only possible because `String` implements `Unpin`. +/// mem::replace(&mut *pinned_string, "other".to_string()); /// ``` /// /// This trait is automatically implemented for almost every type. /// -/// [`replace`]: ../../std/mem/fn.replace.html -/// [`Pin`]: ../pin/struct.Pin.html +/// [`mem::replace`]: ../../std/mem/fn.replace.html +/// [`Pin

`]: ../pin/struct.Pin.html /// [`pin module`]: ../../std/pin/index.html #[stable(feature = "pin", since = "1.33.0")] pub auto trait Unpin {} diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 762e07549a52a..b68b2f39d6bd9 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -2,45 +2,63 @@ //! //! It is sometimes useful to have objects that are guaranteed to not move, //! in the sense that their placement in memory does not change, and can thus be relied upon. -//! //! A prime example of such a scenario would be building self-referential structs, //! since moving an object with pointers to itself will invalidate them, //! which could cause undefined behavior. //! +//! A [`Pin

`] ensures that the pointee of any pointer type `P` has a stable location in memory, +//! meaning it cannot be moved elsewhere and its memory cannot be deallocated +//! until it gets dropped. We say that the pointee is "pinned". +//! //! By default, all types in Rust are movable. Rust allows passing all types by-value, -//! and common smart-pointer types such as `Box`, `Rc`, and `&mut` allow replacing and -//! moving the values they contain. In order to prevent objects from moving, they must -//! be pinned by wrapping a pointer to the data in the [`Pin`] type. -//! Doing this prohibits moving the value behind the pointer. -//! For example, `Pin>` functions much like a regular `Box`, -//! but doesn't allow moving `T`. The pointer value itself (the `Box`) can still be moved, -//! but the value behind it cannot. -//! -//! Since data can be moved out of `&mut` and `Box` with functions such as [`swap`], -//! changing the location of the underlying data, [`Pin`] prohibits accessing the -//! underlying pointer type (the `&mut` or `Box`) directly, and provides its own set of -//! APIs for accessing and using the value. [`Pin`] also guarantees that no other -//! functions will move the pointed-to value. This allows for the creation of -//! self-references and other special behaviors that are only possible for unmovable -//! values. +//! and common smart-pointer types such as `Box` and `&mut T` allow replacing and +//! moving the values they contain: you can move out of a `Box`, or you can use [`mem::swap`]. +//! [`Pin

`] wraps a pointer type `P`, so `Pin>` functions much like a regular `Box`: +//! when a `Pin>` gets dropped, so do its contents, and the memory gets deallocated. +//! Similarily, `Pin<&mut T>` is a lot like `&mut T`. However, [`Pin

`] does not let clients +//! actually obtain a `Box` or `&mut T` to pinned data, which implies that you cannot use +//! operations such as [`mem::swap`]: +//! ``` +//! use std::pin::Pin; +//! fn swap_pins(x: Pin<&mut T>, y: Pin<&mut T>) { +//! // `mem::swap` needs `&mut T`, but we cannot get it. +//! // We are stuck, we cannot swap the contents of these references. +//! // We could use `Pin::get_unchecked_mut`, but that is unsafe for a reason: +//! // we are not allowed to use it for moving things out of the `Pin`. +//! } +//! ``` //! -//! However, these restrictions are usually not necessary. Many types are always freely -//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the effect -//! of [`Pin`]. For `T: Unpin`, `Pin>` and `Box` function identically, as do -//! `Pin<&mut T>` and `&mut T`. +//! It is worth reiterating that [`Pin

`] does *not* change the fact that a Rust compiler +//! considers all types movable. [`mem::swap`] remains callable for any `T`. Instead, `Pin

` +//! prevents certain *values* (pointed to by pointers wrapped in `Pin

`) from being +//! moved by making it impossible to call methods that require `&mut T` on them +//! (like [`mem::swap`]). //! -//! Note that pinning and `Unpin` only affect the pointed-to type. For example, whether -//! or not `Box` is `Unpin` has no affect on the behavior of `Pin>`. Similarly, -//! `Pin>` and `Pin<&mut T>` are always `Unpin` themselves, even though the -//! `T` underneath them isn't, because the pointers in `Pin>` and `Pin<&mut _>` -//! are always freely movable, even if the data they point to isn't. +//! [`Pin

`] can be used to wrap any pointer type `P`, and as such it interacts with +//! [`Deref`] and [`DerefMut`]. A `Pin

` where `P: Deref` should be considered +//! as a "`P`-style pointer" to a pinned `P::Target` -- so, a `Pin>` is +//! an owned pointer to a pinned `T`, and a `Pin>` is a reference-counted +//! pointer to a pinned `T`. +//! For correctness, [`Pin

`] relies on the [`Deref`] and [`DerefMut`] implementations +//! to not move out of their `self` parameter, and to only ever return a pointer +//! to pinned data when they are called on a pinned pointer. //! -//! [`Pin`]: struct.Pin.html -//! [`Unpin`]: ../../std/marker/trait.Unpin.html -//! [`swap`]: ../../std/mem/fn.swap.html -//! [`Box`]: ../../std/boxed/struct.Box.html +//! # `Unpin` +//! +//! However, these restrictions are usually not necessary. Many types are always freely +//! movable, even when pinned, because they do not rely on having a stable address. +//! This includes all the basic types (like `bool`, `i32`, references) +//! as well as types consisting solely of these types. +//! Types that do not care about pinning implement the [`Unpin`] auto-trait, which +//! cancels the effect of [`Pin

`]. For `T: Unpin`, `Pin>` and `Box` function +//! identically, as do `Pin<&mut T>` and `&mut T`. +//! +//! Note that pinning and `Unpin` only affect the pointed-to type `P::Target`, not the pointer +//! type `P` itself that got wrapped in `Pin

`. For example, whether or not `Box` is +//! `Unpin` has no effect on the behavior of `Pin>` (here, `T` is the +//! pointed-to type). //! -//! # Examples +//! # Example: self-referential struct //! //! ```rust //! use std::pin::Pin; @@ -94,6 +112,150 @@ //! // let new_unmoved = Unmovable::new("world".to_string()); //! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); //! ``` +//! +//! # Example: intrusive doubly-linked list +//! +//! In an intrusive doubly-linked list, the collection does not actually allocate +//! the memory for the elements itself. Allocation is controlled by the clients, +//! and elements can live on a stack frame that lives shorter than the collection does. +//! +//! To make this work, every element has pointers to its predecessor and successor in +//! the list. Elements can only be added when they are pinned, because moving the elements +//! around would invalidate the pointers. Moreover, the `Drop` implementation of a linked +//! list element will patch the pointers of its predecessor and successor to remove itself +//! from the list. +//! +//! Crucially, we have to be able to rely on `drop` being called. If an element +//! could be deallocated or otherwise invalidated without calling `drop`, the pointers into it +//! from its neighbouring elements would become invalid, which would break the data structure. +//! +//! Therefore, pinning also comes with a `drop`-related guarantee. +//! +//! # `Drop` guarantee +//! +//! The purpose of pinning is to be able to rely on the placement of some data in memory. +//! To make this work, not just moving the data is restricted; deallocating, repurposing, or +//! otherwise invalidating the memory used to store the data is restricted, too. +//! Concretely, for pinned data you have to maintain the invariant +//! that *its memory will not get invalidated from the moment it gets pinned until +//! when `drop` is called*. Memory can be invalidated by deallocation, but also by +//! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements +//! off of a vector. +//! +//! This is exactly the kind of guarantee that the intrusive linked list from the previous +//! section needs to function correctly. +//! +//! Notice that this guarantee does *not* mean that memory does not leak! It is still +//! completely okay not to ever call `drop` on a pinned element (e.g., you can still +//! call [`mem::forget`] on a `Pin>`). In the example of the doubly-linked +//! list, that element would just stay in the list. However you may not free or reuse the storage +//! *without calling `drop`*. +//! +//! # `Drop` implementation +//! +//! If your type uses pinning (such as the two examples above), you have to be careful +//! when implementing `Drop`. The `drop` function takes `&mut self`, but this +//! is called *even if your type was previously pinned*! It is as if the +//! compiler automatically called `get_unchecked_mut`. +//! +//! This can never cause a problem in safe code because implementing a type that relies on pinning +//! requires unsafe code, but be aware that deciding to make use of pinning +//! in your type (for example by implementing some operation on `Pin<&[mut] Self>`) +//! has consequences for your `Drop` implementation as well: if an element +//! of your type could have been pinned, you must treat Drop as implicitly taking +//! `Pin<&mut Self>`. +//! +//! In particular, if your type is `#[repr(packed)]`, the compiler will automatically +//! move fields around to be able to drop them. As a consequence, you cannot use +//! pinning with a `#[repr(packed)]` type. +//! +//! # Projections and Structural Pinning +//! +//! One interesting question arises when considering the interaction of pinning and +//! the fields of a struct. When can a struct have a "pinning projection", i.e., +//! an operation with type `fn(Pin<&[mut] Struct>) -> Pin<&[mut] Field>`? +//! In a similar vein, when can a generic wrapper type (such as `Vec`, `Box`, or `RefCell`) +//! have an operation with type `fn(Pin<&[mut] Wrapper>) -> Pin<&[mut] T>`? +//! +//! Having a pinning projection for some field means that pinning is "structural": +//! when the wrapper is pinned, the field must be considered pinned, too. +//! After all, the pinning projection lets us get a `Pin<&[mut] Field>`. +//! +//! However, structural pinning comes with a few extra requirements, so not all +//! wrappers can be structural and hence not all wrappers can offer pinning projections: +//! +//! 1. The wrapper must only be [`Unpin`] if all the structural fields are +//! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of +//! the wrapper it is your responsibility *not* to add something like +//! `impl Unpin for Wrapper`. (Notice that adding a projection operation +//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break +//! the principle that you only have to worry about any of this if you use `unsafe`.) +//! 2. The destructor of the wrapper must not move structural fields out of its argument. This +//! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes +//! `&mut self`, but the wrapper (and hence its fields) might have been pinned before. +//! You have to guarantee that you do not move a field inside your `Drop` implementation. +//! In particular, as explained previously, this means that your wrapper type must *not* +//! be `#[repr(packed)]`. +//! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]: +//! once your wrapper is pinned, the memory that contains the +//! content is not overwritten or deallocated without calling the content's destructors. +//! This can be tricky, as witnessed by `VecDeque`: the destructor of `VecDeque` can fail +//! to call `drop` on all elements if one of the destructors panics. This violates the +//! `Drop` guarantee, because it can lead to elements being deallocated without +//! their destructor being called. (`VecDeque` has no pinning projections, so this +//! does not cause unsoundness.) +//! 4. You must not offer any other operations that could lead to data being moved out of +//! the fields when your type is pinned. For example, if the wrapper contains an +//! `Option` and there is a `take`-like operation with type +//! `fn(Pin<&mut Wrapper>) -> Option`, +//! that operation can be used to move a `T` out of a pinned `Wrapper` -- which means +//! pinning cannot be structural. +//! +//! For a more complex example of moving data out of a pinned type, imagine if `RefCell` +//! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`. +//! Then we could do the following: +//! ```compile_fail +//! fn exploit_ref_cell(rc: Pin<&mut RefCell) { +//! { let p = rc.as_mut().get_pin_mut(); } // Here we get pinned access to the `T`. +//! let rc_shr: &RefCell = rc.into_ref().get_ref(); +//! let b = rc_shr.borrow_mut(); +//! let content = &mut *b; // And here we have `&mut T` to the same data. +//! } +//! ``` +//! This is catastrophic, it means we can first pin the content of the `RefCell` +//! (using `RefCell::get_pin_mut`) and then move that content using the mutable +//! reference we got later. +//! +//! For a type like `Vec`, both possibilites (structural pinning or not) make sense, +//! and the choice is up to the author. A `Vec` with structural pinning could +//! have `get_pin`/`get_pin_mut` projections. However, it could *not* allow calling +//! `pop` on a pinned `Vec` because that would move the (structurally pinned) contents! +//! Nor could it allow `push`, which might reallocate and thus also move the contents. +//! A `Vec` without structural pinning could `impl Unpin for Vec`, because the contents +//! are never pinned and the `Vec` itself is fine with being moved as well. +//! +//! In the standard library, pointer types generally do not have structural pinning, +//! and thus they do not offer pinning projections. This is why `Box: Unpin` holds for all `T`. +//! It makes sense to do this for pointer types, because moving the `Box` +//! does not actually move the `T`: the `Box` can be freely movable (aka `Unpin`) even if the `T` +//! is not. In fact, even `Pin>` and `Pin<&mut T>` are always `Unpin` themselves, +//! for the same reason: their contents (the `T`) are pinned, but the pointers themselves +//! can be moved without moving the pinned data. For both `Box` and `Pin>`, +//! whether the content is pinned is entirely independent of whether the pointer is +//! pinned, meaning pinning is *not* structural. +//! +//! [`Pin

`]: struct.Pin.html +//! [`Unpin`]: ../../std/marker/trait.Unpin.html +//! [`Deref`]: ../../std/ops/trait.Deref.html +//! [`DerefMut`]: ../../std/ops/trait.DerefMut.html +//! [`mem::swap`]: ../../std/mem/fn.swap.html +//! [`mem::forget`]: ../../std/mem/fn.forget.html +//! [`Box`]: ../../std/boxed/struct.Box.html +//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len +//! [`None`]: ../../std/option/enum.Option.html#variant.None +//! [`Some(v)`]: ../../std/option/enum.Option.html#variant.Some +//! [drop-impl]: #drop-implementation +//! [drop-guarantee]: #drop-guarantee #![stable(feature = "pin", since = "1.33.0")] @@ -126,8 +288,13 @@ impl Pin

where P::Target: Unpin, { - /// Construct a new `Pin` around a pointer to some data of a type that - /// implements `Unpin`. + /// Construct a new `Pin

` around a pointer to some data of a type that + /// implements [`Unpin`]. + /// + /// Unlike `Pin::new_unchecked`, this method is safe because the pointer + /// `P` dereferences to an [`Unpin`] type, which cancels the pinning guarantees. + /// + /// [`Unpin`]: ../../std/marker/trait.Unpin.html #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn new(pointer: P) -> Pin

{ @@ -138,25 +305,83 @@ where } impl Pin

{ - /// Construct a new `Pin` around a reference to some data of a type that + /// Construct a new `Pin

` around a reference to some data of a type that /// may or may not implement `Unpin`. /// + /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used + /// instead. + /// /// # Safety /// /// This constructor is unsafe because we cannot guarantee that the data - /// pointed to by `pointer` is pinned. If the constructed `Pin

` does - /// not guarantee that the data `P` points to is pinned, constructing a - /// `Pin

` is undefined behavior. + /// pointed to by `pointer` is pinned, meaning that the data will not be moved or + /// its storage invalidated until it gets dropped. If the constructed `Pin

` does + /// not guarantee that the data `P` points to is pinned, that is a violation of + /// the API contract and may lead to undefined behavior in later (safe) operations. /// - /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used - /// instead. + /// By using this method, you are making a promise about the `P::Deref` and + /// `P::DerefMut` implementations, if they exist. Most importantly, they + /// must not move out of their `self` arguments: `Pin::as_mut` and `Pin::as_ref` + /// will call `DerefMut::deref_mut` and `Deref::deref` *on the pinned pointer* + /// and expect these methods to uphold the pinning invariants. + /// Moreover, by calling this method you promise that the reference `P` + /// dereferences to will not be moved out of again; in particular, it + /// must not be possible to obtain a `&mut P::Target` and then + /// move out of that reference (using, for example [`mem::swap`]). + /// + /// For example, calling `Pin::new_unchecked` on an `&'a mut T` is unsafe because + /// while you are able to pin it for the given lifetime `'a`, you have no control + /// over whether it is kept pinned once `'a` ends: + /// ``` + /// use std::mem; + /// use std::pin::Pin; + /// + /// fn move_pinned_ref(mut a: T, mut b: T) { + /// unsafe { + /// let p: Pin<&mut T> = Pin::new_unchecked(&mut a); + /// // This should mean the pointee `a` can never move again. + /// } + /// mem::swap(&mut a, &mut b); + /// // The address of `a` changed to `b`'s stack slot, so `a` got moved even + /// // though we have previously pinned it! We have violated the pinning API contract. + /// } + /// ``` + /// A value, once pinned, must remain pinned forever (unless its type implements `Unpin`). + /// + /// Similarily, calling `Pin::new_unchecked` on an `Rc` is unsafe because there could be + /// aliases to the same data that are not subject to the pinning restrictions: + /// ``` + /// use std::rc::Rc; + /// use std::pin::Pin; + /// + /// fn move_pinned_rc(mut x: Rc) { + /// let pinned = unsafe { Pin::new_unchecked(x.clone()) }; + /// { + /// let p: Pin<&T> = pinned.as_ref(); + /// // This should mean the pointee can never move again. + /// } + /// drop(pinned); + /// let content = Rc::get_mut(&mut x).unwrap(); + /// // Now, if `x` was the only reference, we have a mutable reference to + /// // data that we pinned above, which we could use to move it as we have + /// // seen in the previous example. We have violated the pinning API contract. + /// } + /// ``` + /// + /// [`mem::swap`]: ../../std/mem/fn.swap.html #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub unsafe fn new_unchecked(pointer: P) -> Pin

{ Pin { pointer } } - /// Get a pinned shared reference from this pinned pointer. + /// Gets a pinned shared reference from this pinned pointer. + /// + /// This is a generic method to go from `&Pin>` to `Pin<&T>`. + /// It is safe because, as part of the contract of `Pin::new_unchecked`, + /// the pointee cannot move after `Pin>` got created. + /// "Malicious" implementations of `Pointer::Deref` are likewise + /// ruled out by the contract of `Pin::new_unchecked`. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_ref(self: &Pin

) -> Pin<&P::Target> { @@ -165,14 +390,23 @@ impl Pin

{ } impl Pin

{ - /// Get a pinned mutable reference from this pinned pointer. + /// Gets a pinned mutable reference from this pinned pointer. + /// + /// This is a generic method to go from `&mut Pin>` to `Pin<&mut T>`. + /// It is safe because, as part of the contract of `Pin::new_unchecked`, + /// the pointee cannot move after `Pin>` got created. + /// "Malicious" implementations of `Pointer::DerefMut` are likewise + /// ruled out by the contract of `Pin::new_unchecked`. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_mut(self: &mut Pin

) -> Pin<&mut P::Target> { unsafe { Pin::new_unchecked(&mut *self.pointer) } } - /// Assign a new value to the memory behind the pinned reference. + /// Assigns a new value to the memory behind the pinned reference. + /// + /// This overwrites pinned data, but that is okay: its destructor gets + /// run before being overwritten, so no pinning guarantee is violated. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn set(self: &mut Pin

, value: P::Target) @@ -184,10 +418,12 @@ impl Pin

{ } impl<'a, T: ?Sized> Pin<&'a T> { - /// Construct a new pin by mapping the interior value. + /// Constructs a new pin by mapping the interior value. /// /// For example, if you wanted to get a `Pin` of a field of something, /// you could use this to get access to that field in one line of code. + /// However, there are several gotchas with these "pinning projections"; + /// see the [`pin` module] documentation for further details on that topic. /// /// # Safety /// @@ -195,6 +431,8 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. + /// + /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked(self: Pin<&'a T>, func: F) -> Pin<&'a U> where F: FnOnce(&T) -> &U, @@ -206,11 +444,21 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// Get a shared reference out of a pin. /// + /// This is safe because it is not possible to move out of a shared reference. + /// It may seem like there is an issue here with interior mutability: in fact, + /// it *is* possible to move a `T` out of a `&RefCell`. However, this is + /// not a problem as long as there does not also exist a `Pin<&T>` pointing + /// to the same data, and `RefCell` does not let you create a pinned reference + /// to its contents. See the discussion on ["pinning projections"] for further + /// details. + /// /// Note: `Pin` also implements `Deref` to the target, which can be used /// to access the inner value. However, `Deref` only provides a reference /// that lives for as long as the borrow of the `Pin`, not the lifetime of /// the `Pin` itself. This method allows turning the `Pin` into a reference /// with the same lifetime as the original `Pin`. + /// + /// ["pinning projections"]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn get_ref(self: Pin<&'a T>) -> &'a T { @@ -263,6 +511,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// /// For example, if you wanted to get a `Pin` of a field of something, /// you could use this to get access to that field in one line of code. + /// However, there are several gotchas with these "pinning projections"; + /// see the [`pin` module] documentation for further details on that topic. /// /// # Safety /// @@ -270,6 +520,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. + /// + /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked_mut(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where F: FnOnce(&mut T) -> &mut U, From fdd5467bccd5a6b9d251f714b199e041e8dd0ee8 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Wed, 6 Feb 2019 15:42:21 +0100 Subject: [PATCH 11/13] Updated RELEASES.md for 1.33.0 Cherry-picked (and squashed) from #58227. --- RELEASES.md | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 83c44774da283..841467b69c986 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,151 @@ +Version 1.33.0 (2019-02-28) +========================== + +Language +-------- +- [You can now use the `cfg(target_vendor)` attribute.][57465] E.g. + `#[cfg(target_vendor="linux")] fn main() { println!("Hello Linux!"); }` +- [Integer patterns such as in a match expression can now be exhaustive.][56362] + E.g. You can have match statement on a `u8` that covers `0..=255` and + you would no longer be required to have a `_ => unreachable!()` case. +- [You can now have multiple patterns in `if let` and `while let` + expressions.][57532] You can do this with the same syntax as a `match` + expression. E.g. + ```rust + enum Creature { + Crab(String), + Lobster(String), + Person(String), + } + + fn main() { + let state = Creature::Crab("Ferris"); + + if let Creature::Crab(name) | Creature::Person(name) = state { + println!("This creature's name is: {}", name); + } + } + ``` +- [You can now have irrefutable `if let` and `while let` patterns.][57535] Using + this feature will by default produce a warning as this behaviour can be + unintuitive. E.g. `if let _ = 5 {}` +- [You can now use `let` bindings, assignments, expression statements, + and irrefutable pattern destructuring in const functions.][57175] +- [You can now call unsafe const functions.][57067] E.g. + ```rust + const unsafe fn foo() -> i32 { 5 } + const fn bar() -> i32 { + unsafe { foo() } + } + ``` +- [You can now specify multiple attributes in a `cfg_attr` attribute.][57332] + E.g. `#[cfg_attr(all(), must_use, optimize)]` +- [You can now specify a specific alignment with the `#[repr(packed)]` + attribute.][57049] E.g. `#[repr(packed(2))] struct Foo(i16, i32);` is a struct + with an alignment of 2 bytes and a size of 6 bytes. +- [You can now import an item from a module as an `_`.][56303] This allows you to + import a trait's impls, and not have the name in the namespace. E.g. + ```rust + use std::io::Read as _; + + // Allowed as there is only one `Read` in the module. + pub trait Read {} + ``` +- [`extern` functions will now abort by default when panicking.][55982] + This was previously undefined behaviour. + +Compiler +-------- +- [You can now set a linker flavor for `rustc` with the `-Clinker-flavor` + command line argument.][56351] +- [The mininum required LLVM version has been bumped to 6.0.][56642] +- [Added support for the PowerPC64 architecture on FreeBSD.][57615] +- [The `x86_64-fortanix-unknown-sgx` target support has been upgraded to + tier 2 support.][57130] Visit the [platform support][platform-support] page for + information on Rust's platform support. +- [Added support for the `thumbv7neon-linux-androideabi` and + `thumbv7neon-unknown-linux-gnueabihf` targets.][56947] +- [Added support for the `x86_64-unknown-uefi` target.][56769] + +Libraries +--------- +- [The methods `overflowing_{add, sub, mul, shl, shr}` are now `const` + functions for all numeric types.][57566] +- [The methods `rotate_left`, `rotate_right`, and `wrapping_{add, sub, mul, shl, shr}` + are now `const` functions for all numeric types.][57105] +- [The methods `is_positive` and `is_negative` are now `const` functions for + all signed numeric types.][57105] +- [The `get` method for all `NonZero` types is now `const`.][57167] +- [The methods `count_ones`, `count_zeros`, `leading_zeros`, `trailing_zeros`, + `swap_bytes`, `from_be`, `from_le`, `to_be`, `to_le` are now `const` for all + numeric types.][57234] +- [`Ipv4Addr::new` is now a `const` function][57234] + +Stabilized APIs +--------------- +- [`unix::FileExt::read_exact_at`] +- [`unix::FileExt::write_all_at`] +- [`Option::transpose`] +- [`Result::transpose`] +- [`convert::identity`] +- [`pin::Pin`] +- [`marker::Unpin`] +- [`marker::PhantomPinned`] +- [`Vec::resize_with`] +- [`VecDeque::resize_with`] +- [`Duration::as_millis`] +- [`Duration::as_micros`] +- [`Duration::as_nanos`] + + +Cargo +----- +- [Cargo should now rebuild a crate if a file was modified during the initial + build.][cargo/6484] + +Compatibility Notes +------------------- +- The methods `str::{trim_left, trim_right, trim_left_matches, trim_right_matches}` + are now deprecated in the standard library, and their usage will now produce a warning. + Please use the `str::{trim_start, trim_end, trim_start_matches, trim_end_matches}` + methods instead. + +[57615]: https://github.com/rust-lang/rust/pull/57615/ +[57465]: https://github.com/rust-lang/rust/pull/57465/ +[57532]: https://github.com/rust-lang/rust/pull/57532/ +[57535]: https://github.com/rust-lang/rust/pull/57535/ +[57566]: https://github.com/rust-lang/rust/pull/57566/ +[57130]: https://github.com/rust-lang/rust/pull/57130/ +[57167]: https://github.com/rust-lang/rust/pull/57167/ +[57175]: https://github.com/rust-lang/rust/pull/57175/ +[57234]: https://github.com/rust-lang/rust/pull/57234/ +[57332]: https://github.com/rust-lang/rust/pull/57332/ +[56947]: https://github.com/rust-lang/rust/pull/56947/ +[57049]: https://github.com/rust-lang/rust/pull/57049/ +[57067]: https://github.com/rust-lang/rust/pull/57067/ +[56769]: https://github.com/rust-lang/rust/pull/56769/ +[56642]: https://github.com/rust-lang/rust/pull/56642/ +[56303]: https://github.com/rust-lang/rust/pull/56303/ +[56351]: https://github.com/rust-lang/rust/pull/56351/ +[55982]: https://github.com/rust-lang/rust/pull/55982/ +[56362]: https://github.com/rust-lang/rust/pull/56362 +[57105]: https://github.com/rust-lang/rust/pull/57105 +[cargo/6484]: https://github.com/rust-lang/cargo/pull/6484/ +[`unix::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.read_exact_at +[`unix::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at +[`Option::transpose`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.transpose +[`Result::transpose`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose +[`convert::identity`]: https://doc.rust-lang.org/std/convert/fn.identity.html +[`pin::Pin`]: https://doc.rust-lang.org/std/pin/struct.Pin.html +[`marker::Unpin`]: https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html +[`marker::PhantomPinned`]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomPinned.html +[`Vec::resize_with`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.resize_with +[`VecDeque::resize_with`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.resize_with +[`Duration::as_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_millis +[`Duration::as_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_micros +[`Duration::as_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_nanos +[platform-support]: https://forge.rust-lang.org/platform-support.html + Version 1.32.0 (2019-01-17) ========================== From a63575c3abe1386277048c9c0fc3909f892750da Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Jan 2019 12:05:00 +0100 Subject: [PATCH 12/13] Fix invalid background color --- src/librustdoc/html/static/themes/dark.css | 4 ---- src/librustdoc/html/static/themes/light.css | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 52a30967a2310..6935ecde791f8 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -410,10 +410,6 @@ kbd { color: #ccc; } -.impl-items code { - background-color: rgba(0, 0, 0, 0); -} - #sidebar-toggle { background-color: #565656; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index d20fea666e61d..306e8dc15d893 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -405,10 +405,6 @@ kbd { color: #999; } -.impl-items code { - background-color: rgba(0, 0, 0, 0); -} - #sidebar-toggle { background-color: #F1F1F1; } From 5c6eb4e844abedcb179f390c62a8a30fc3df5e97 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 17 Jan 2019 21:28:23 +0100 Subject: [PATCH 13/13] Fix non-clickable urls --- src/librustdoc/html/static/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 8a8b7adcf7d4a..36765496ff4e9 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -391,10 +391,6 @@ h4 > code, h3 > code, .invisible > code { display: block; } -.in-band, code { - z-index: -5; -} - .invisible { width: 100%; display: inline-block;