From 8d7707f3c4f72e6eb334d897354beca692b265d1 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Mon, 3 May 2021 09:25:32 -0400 Subject: [PATCH 1/5] Normalize associated types with bound vars --- compiler/rustc_middle/src/ty/layout.rs | 3 +- .../borrow_check/type_check/input_output.rs | 31 ++++- .../src/borrow_check/type_check/mod.rs | 1 + .../src/traits/project.rs | 71 +++++------ .../src/traits/query/normalize.rs | 114 +++++++++++++----- compiler/rustc_typeck/src/check/coercion.rs | 5 +- .../ui/associated-type-bounds/issue-83017.rs | 4 +- .../associated-type-bounds/issue-83017.stderr | 33 ----- .../higher-ranked-projection.bad.stderr | 4 +- .../hr-associated-type-bound-1.rs | 2 +- .../hr-associated-type-bound-1.stderr | 6 +- .../hr-associated-type-bound-2.rs | 5 +- .../hr-associated-type-bound-2.stderr | 43 +++++-- .../hr-associated-type-bound-param-1.rs | 2 +- .../hr-associated-type-bound-param-1.stderr | 6 +- .../hr-associated-type-bound-param-2.rs | 6 +- .../hr-associated-type-bound-param-2.stderr | 18 +-- .../hr-associated-type-bound-param-3.rs | 2 +- .../hr-associated-type-bound-param-3.stderr | 6 +- .../hr-associated-type-bound-param-4.rs | 2 +- .../hr-associated-type-bound-param-4.stderr | 6 +- .../hr-associated-type-bound-param-5.rs | 6 +- .../hr-associated-type-bound-param-5.stderr | 50 +------- .../hr-associated-type-bound-param-6.rs | 1 - .../hr-associated-type-bound-param-6.stderr | 27 +---- .../hr-associated-type-projection-1.rs | 3 +- .../hr-associated-type-projection-1.stderr | 34 ++---- src/test/ui/closures/issue-41366.rs | 4 +- src/test/ui/closures/issue-41366.stderr | 32 ----- .../normalize-under-binder/issue-62529-1.rs | 88 ++++++++++++++ .../issue-62529-1.stderr | 67 ++++++++++ .../normalize-under-binder/issue-62529-2.rs | 33 +++++ .../normalize-under-binder/issue-62529-3.rs | 32 +++++ .../issue-62529-3.stderr | 15 +++ .../normalize-under-binder/issue-62529-4.rs | 39 ++++++ .../normalize-under-binder/issue-62529-5.rs | 27 +++++ .../normalize-under-binder/issue-62529-6.rs | 77 ++++++++++++ .../normalize-under-binder/issue-70120.rs | 29 +++++ .../normalize-under-binder/issue-70120.stderr | 20 +++ src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 6 +- .../bound-normalization-fail.stderr | 4 +- src/test/ui/issues/issue-35570.rs | 3 +- src/test/ui/issues/issue-35570.stderr | 9 ++ src/test/ui/issues/issue-43623.rs | 3 +- src/test/ui/issues/issue-43623.stderr | 21 ---- src/test/ui/issues/issue-44005.rs | 9 +- src/test/ui/issues/issue-44005.stderr | 20 +++ src/test/ui/issues/issue-57843.nll.stderr | 11 -- src/test/ui/issues/issue-60218.stderr | 4 +- .../issue-67039-unsound-pin-partialeq.stderr | 4 +- .../issue-75361-mismatched-impl.stderr | 4 +- ...ions-implied-bounds-projection-gap-hr-1.rs | 2 +- ...-implied-bounds-projection-gap-hr-1.stderr | 20 ++- 53 files changed, 716 insertions(+), 358 deletions(-) delete mode 100644 src/test/ui/associated-type-bounds/issue-83017.stderr delete mode 100644 src/test/ui/closures/issue-41366.stderr create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr create mode 100644 src/test/ui/issues/issue-35570.stderr delete mode 100644 src/test/ui/issues/issue-43623.stderr create mode 100644 src/test/ui/issues/issue-44005.stderr delete mode 100644 src/test/ui/issues/issue-57843.nll.stderr diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 80c99872dd766..5342535ddfe7f 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2474,10 +2474,9 @@ impl<'tcx> ty::Instance<'tcx> { // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping // track of a polymorphization `ParamEnv` to allow normalizing later. let mut sig = match *ty.kind() { - ty::FnDef(def_id, substs) if tcx.sess.opts.debugging_opts.polymorphize => tcx + ty::FnDef(def_id, substs) => tcx .normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id)) .subst(tcx, substs), - ty::FnDef(def_id, substs) => tcx.fn_sig(def_id).subst(tcx, substs), _ => unreachable!(), }; diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs index f8989a7d9df1c..ba35813555811 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs @@ -9,7 +9,9 @@ use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::*; -use rustc_middle::ty::Ty; +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::{self, Ty}; +use rustc_trait_selection::traits::query::normalize::AtExt; use rustc_index::vec::Idx; use rustc_span::Span; @@ -80,6 +82,33 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let local = Local::new(argument_index + 1); let mir_input_ty = body.local_decls[local].ty; + // FIXME(jackh726): This is a hack. It's somewhat like + // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd + // like to normalize *before* inserting into `local_decls`, but I + // couldn't figure out where the heck that was. + let mir_input_ty = match self + .infcx + .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) + .normalize(mir_input_ty) + { + Ok(n) => { + debug!("equate_inputs_and_outputs: {:?}", n); + if n.obligations.iter().all(|o| { + matches!( + o.predicate.kind().skip_binder(), + ty::PredicateKind::RegionOutlives(_) + ) + }) { + n.value + } else { + mir_input_ty + } + } + Err(_) => { + debug!("equate_inputs_and_outputs: NoSolution"); + mir_input_ty + } + }; let mir_input_span = body.local_decls[local].source_info.span; self.equate_normalized_input_or_output( normalized_input_ty, diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 35bb6ef6c2d6e..999b25319bf8d 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1053,6 +1053,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); for user_annotation in self.user_type_annotations { let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation; + let inferred_ty = self.normalize(inferred_ty, Locations::All(span)); let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty); match annotation { UserType::Ty(mut ty) => { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 19e3c1afb9fb6..df1dca9831ab1 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -362,25 +362,25 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { if !needs_normalization(&ty, self.param_env.reveal()) { return ty; } - // We don't want to normalize associated types that occur inside of region - // binders, because they may contain bound regions, and we can't cope with that. - // - // Example: - // - // for<'a> fn(>::A) - // - // Instead of normalizing `>::A` here, we'll - // normalize it when we instantiate those bound regions (which - // should occur eventually). - - let ty = ty.super_fold_with(self); + + // N.b. while we want to call `super_fold_with(self)` on `ty` before + // normalization, we wait until we know whether we need to normalize the + // current type. If we do, then we only fold the ty *after* replacing bound + // vars with placeholders. This means that nested types don't need to replace + // bound vars at the current binder level or above. A key assumption here is + // that folding the type can't introduce new bound vars. + match *ty.kind() { - ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { + ty::Opaque(def_id, substs) => { // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { - Reveal::UserFacing => ty, + Reveal::UserFacing => ty.super_fold_with(self), Reveal::All => { + // N.b. there is an assumption here all this code can handle + // escaping bound vars. + + let substs = substs.super_fold_with(self); let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { let obligation = Obligation::with_depth( @@ -403,18 +403,13 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } ty::Projection(data) if !data.has_escaping_bound_vars() => { - // This is kind of hacky -- we need to be able to - // handle normalization within binders because - // otherwise we wind up a need to normalize when doing - // trait matching (since you can have a trait - // obligation like `for<'a> T::B: Fn(&'a i32)`), but - // we can't normalize with bound regions in scope. So - // far now we just ignore binders but only normalize - // if all bound regions are gone (and then we still - // have to renormalize whenever we instantiate a - // binder). It would be better to normalize in a - // binding-aware fashion. + // This branch is *mostly* just an optimization: when we don't + // have escaping bound vars, we don't need to replace them with + // placeholders (see branch below). *Also*, we know that we can + // register an obligation to *later* project, since we know + // there won't be bound vars there. + let data = data.super_fold_with(self); let normalized_ty = normalize_projection_type( self.selcx, self.param_env, @@ -433,22 +428,19 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { normalized_ty } - ty::Projection(data) if !data.trait_ref(self.tcx()).has_escaping_bound_vars() => { - // Okay, so you thought the previous branch was hacky. Well, to - // extend upon this, when the *trait ref* doesn't have escaping - // bound vars, but the associated item *does* (can only occur - // with GATs), then we might still be able to project the type. - // For this, we temporarily replace the bound vars with - // placeholders. Note though, that in the case that we still - // can't project for whatever reason (e.g. self type isn't - // known enough), we *can't* register an obligation and return - // an inference variable (since then that obligation would have - // bound vars and that's a can of worms). Instead, we just - // give up and fall back to pretending like we never tried! + ty::Projection(data) => { + // If there are escaping bound vars, we temporarily replace the + // bound vars with placeholders. Note though, that in the cas + // that we still can't project for whatever reason (e.g. self + // type isn't known enough), we *can't* register an obligation + // and return an inference variable (since then that obligation + // would have bound vars and that's a can of worms). Instead, + // we just give up and fall back to pretending like we never tried! let infcx = self.selcx.infcx(); let (data, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); + let data = data.super_fold_with(self); let normalized_ty = opt_normalize_projection_type( self.selcx, self.param_env, @@ -459,7 +451,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { ) .ok() .flatten() - .unwrap_or_else(|| ty); + .unwrap_or_else(|| ty.super_fold_with(self)); let normalized_ty = PlaceholderReplacer::replace_placeholders( infcx, @@ -479,7 +471,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { normalized_ty } - _ => ty, + _ => ty.super_fold_with(self), } } @@ -908,6 +900,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // an impl, where-clause etc) and hence we must // re-normalize it + let projected_ty = selcx.infcx().resolve_vars_if_possible(projected_ty); debug!(?projected_ty, ?depth, ?projected_obligations); let result = if projected_ty.has_projections() { diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 3f6efa03b3a28..8f8de24981b8e 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -14,7 +14,9 @@ use rustc_infer::traits::Normalized; use rustc_middle::mir; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; + +use std::ops::ControlFlow; use super::NoSolution; @@ -65,6 +67,14 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { universes: vec![], }; + if value.has_escaping_bound_vars() { + let mut max_visitor = + MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 }; + value.visit_with(&mut max_visitor); + if max_visitor.escaping > 0 { + normalizer.universes.extend((0..max_visitor.escaping).map(|_| None)); + } + } let result = value.fold_with(&mut normalizer); info!( "normalize::<{}>: result={:?} with {} obligations", @@ -85,6 +95,58 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { } } +/// Visitor to find the maximum escaping bound var +struct MaxEscapingBoundVarVisitor { + // The index which would count as escaping + outer_index: ty::DebruijnIndex, + escaping: usize, +} + +impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor { + fn visit_binder>( + &mut self, + t: &ty::Binder<'tcx, T>, + ) -> ControlFlow { + self.outer_index.shift_in(1); + let result = t.super_visit_with(self); + self.outer_index.shift_out(1); + result + } + + #[inline] + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if t.outer_exclusive_binder() > self.outer_index { + self.escaping = self + .escaping + .max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize()); + } + ControlFlow::CONTINUE + } + + #[inline] + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + match *r { + ty::ReLateBound(debruijn, _) if debruijn > self.outer_index => { + self.escaping = + self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize()); + } + _ => {} + } + ControlFlow::CONTINUE + } + + fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow { + match ct.val { + ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => { + self.escaping = + self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize()); + ControlFlow::CONTINUE + } + _ => ct.super_visit_with(self), + } + } +} + struct QueryNormalizer<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, cause: &'cx ObligationCause<'tcx>, @@ -121,14 +183,25 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { return ty; } - let ty = ty.super_fold_with(self); + // N.b. while we want to call `super_fold_with(self)` on `ty` before + // normalization, we wait until we know whether we need to normalize the + // current type. If we do, then we only fold the ty *after* replacing bound + // vars with placeholders. This means that nested types don't need to replace + // bound vars at the current binder level or above. A key assumption here is + // that folding the type can't introduce new bound vars. + + // Wrap this in a closure so we don't accidentally return from the outer function let res = (|| match *ty.kind() { - ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { + ty::Opaque(def_id, substs) => { // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { - Reveal::UserFacing => ty, + Reveal::UserFacing => ty.super_fold_with(self), Reveal::All => { + // N.b. there is an assumption here all this code can handle + // escaping bound vars. + + let substs = substs.super_fold_with(self); let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { let obligation = Obligation::with_depth( @@ -161,19 +234,11 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } ty::Projection(data) if !data.has_escaping_bound_vars() => { - // This is kind of hacky -- we need to be able to - // handle normalization within binders because - // otherwise we wind up a need to normalize when doing - // trait matching (since you can have a trait - // obligation like `for<'a> T::B: Fn(&'a i32)`), but - // we can't normalize with bound regions in scope. So - // far now we just ignore binders but only normalize - // if all bound regions are gone (and then we still - // have to renormalize whenever we instantiate a - // binder). It would be better to normalize in a - // binding-aware fashion. + // This branch is just an optimization: when we don't have escaping bound vars, + // we don't need to replace them with placeholders (see branch below). let tcx = self.infcx.tcx; + let data = data.super_fold_with(self); let mut orig_values = OriginalQueryValues::default(); // HACK(matthewjasper) `'static` is special-cased in selection, @@ -217,22 +282,9 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } } } - ty::Projection(data) if !data.trait_ref(self.infcx.tcx).has_escaping_bound_vars() => { - // See note in `rustc_trait_selection::traits::project` - - // One other point mentioning: In `traits::project`, if a - // projection can't be normalized, we return an inference variable - // and register an obligation to later resolve that. Here, the query - // will just return ambiguity. In both cases, the effect is the same: we only want - // to return `ty` because there are bound vars that we aren't yet handling in a more - // complete way. - // `BoundVarReplacer` can't handle escaping bound vars. Ideally, we want this before even calling - // `QueryNormalizer`, but some const-generics tests pass escaping bound vars. - // Also, use `ty` so we get that sweet `outer_exclusive_binder` optimization - assert!(!ty.has_vars_bound_at_or_above(ty::DebruijnIndex::from_usize( - self.universes.len() - ))); + ty::Projection(data) => { + // See note in `rustc_trait_selection::traits::project` let tcx = self.infcx.tcx; let infcx = self.infcx; @@ -292,7 +344,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { ) } - _ => ty, + _ => ty.super_fold_with(self), })(); self.cache.insert(ty, res); res diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 17a81486048ed..3bfab9d513f37 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -796,6 +796,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { //! into a closure or a `proc`. let b = self.shallow_resolve(b); + let InferOk { value: b, mut obligations } = + self.normalize_associated_types_in_as_infer_ok(self.cause.span, b); debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b); match b.kind() { @@ -815,8 +817,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } } - let InferOk { value: a_sig, mut obligations } = + let InferOk { value: a_sig, obligations: o1 } = self.normalize_associated_types_in_as_infer_ok(self.cause.span, a_sig); + obligations.extend(o1); let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig); let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn( diff --git a/src/test/ui/associated-type-bounds/issue-83017.rs b/src/test/ui/associated-type-bounds/issue-83017.rs index 8f0a9ea3566fb..a02208661f1f7 100644 --- a/src/test/ui/associated-type-bounds/issue-83017.rs +++ b/src/test/ui/associated-type-bounds/issue-83017.rs @@ -1,3 +1,5 @@ +// check-pass + #![feature(associated_type_bounds)] trait TraitA<'a> { @@ -34,6 +36,4 @@ where fn main() { foo::(); - //~^ ERROR: the trait bound `for<'a, 'b> >::AsA: TraitB<'a, 'b>` is not satisfied - //~| ERROR: the trait bound `for<'a, 'b, 'c> <>::AsA as TraitB<'a, 'b>>::AsB: TraitC<'a, 'b, 'c>` is not satisfied } diff --git a/src/test/ui/associated-type-bounds/issue-83017.stderr b/src/test/ui/associated-type-bounds/issue-83017.stderr deleted file mode 100644 index af86990ac66aa..0000000000000 --- a/src/test/ui/associated-type-bounds/issue-83017.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0277]: the trait bound `for<'a, 'b> >::AsA: TraitB<'a, 'b>` is not satisfied - --> $DIR/issue-83017.rs:36:5 - | -LL | foo::(); - | ^^^^^^^^ the trait `for<'a, 'b> TraitB<'a, 'b>` is not implemented for `>::AsA` - | -note: required by a bound in `foo` - --> $DIR/issue-83017.rs:31:32 - | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | for<'a> T: TraitA<'a, AsA: for<'b> TraitB<'a, 'b, AsB: for<'c> TraitC<'a, 'b, 'c>>>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` - -error[E0277]: the trait bound `for<'a, 'b, 'c> <>::AsA as TraitB<'a, 'b>>::AsB: TraitC<'a, 'b, 'c>` is not satisfied - --> $DIR/issue-83017.rs:36:5 - | -LL | foo::(); - | ^^^^^^^^ the trait `for<'a, 'b, 'c> TraitC<'a, 'b, 'c>` is not implemented for `<>::AsA as TraitB<'a, 'b>>::AsB` - | -note: required by a bound in `foo` - --> $DIR/issue-83017.rs:31:60 - | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | for<'a> T: TraitA<'a, AsA: for<'b> TraitB<'a, 'b, AsB: for<'c> TraitC<'a, 'b, 'c>>>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. 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 e2847b6b72b86..1ac72e4b90c75 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(()); | ^^^ lifetime mismatch | - = note: expected type `&'a ()` - found type `&()` + = note: expected reference `&'a ()` + found type `&()` note: the lifetime requirement is introduced here --> $DIR/higher-ranked-projection.rs:15:33 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-1.rs b/src/test/ui/associated-types/hr-associated-type-bound-1.rs index cdf32dd82a6a9..db414164e1663 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-1.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-1.rs @@ -10,7 +10,7 @@ where impl X<'_> for i32 { type U = str; - //~^ ERROR the trait bound `for<'b> >::U: Clone` + //~^ ERROR the trait bound `str: Clone` } fn main() { diff --git a/src/test/ui/associated-types/hr-associated-type-bound-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr index 0bcc9be5c43ce..4eed5c9a0083c 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr @@ -1,11 +1,9 @@ -error[E0277]: the trait bound `for<'b> >::U: Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-1.rs:12:14 | LL | type U = str; - | ^^^ the trait `for<'b> Clone` is not implemented for `>::U` + | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <&T as Clone> note: required by a bound in `X` --> $DIR/hr-associated-type-bound-1.rs:3:33 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-2.rs index 78ee28b17d4b3..2eb956c8dbb08 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-2.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.rs @@ -8,14 +8,13 @@ where } } -impl X<'_> for u32 +impl X<'_> for u32 //~ overflow evaluating the requirement `for<'b> u32: X<'b>` where for<'b> >::U: Clone, { - type U = str; + type U = str; //~ overflow evaluating the requirement `for<'b> u32: X<'b>` } fn main() { 1u32.f("abc"); - //~^ ERROR the method } diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr index 043d1ac76de9a..079989f2331af 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr @@ -1,13 +1,38 @@ -error[E0599]: the method `f` exists for type `u32`, but its trait bounds were not satisfied - --> $DIR/hr-associated-type-bound-2.rs:19:10 +error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>` + --> $DIR/hr-associated-type-bound-2.rs:11:1 | -LL | 1u32.f("abc"); - | ^ method cannot be called on `u32` due to unsatisfied trait bounds +LL | / impl X<'_> for u32 +LL | | where +LL | | for<'b> >::U: Clone, +LL | | { +LL | | type U = str; +LL | | } + | |_^ | - = note: the following trait bounds were not satisfied: - `>::U: Clone` - which is required by `u32: X` + = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`hr_associated_type_bound_2`) +note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32` + --> $DIR/hr-associated-type-bound-2.rs:11:6 + | +LL | impl X<'_> for u32 + | ^^^^^ ^^^ + = note: 128 redundant requirements hidden + = note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32` + +error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>` + --> $DIR/hr-associated-type-bound-2.rs:15:5 + | +LL | type U = str; + | ^^^^^^^^^^^^^ + | + = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`hr_associated_type_bound_2`) +note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32` + --> $DIR/hr-associated-type-bound-2.rs:11:6 + | +LL | impl X<'_> for u32 + | ^^^^^ ^^^ + = note: 128 redundant requirements hidden + = note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs index 0a81f373ad4c5..bbeeb145d1fe2 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs @@ -12,7 +12,7 @@ where impl<'a> Y<'a, u8> for u8 { type V = str; - //~^ ERROR the trait bound `for<'b> >::V: Clone` is not satisfied + //~^ ERROR the trait bound `str: Clone` is not satisfied } fn main() { diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr index e16931ee09fc6..99f95c200511a 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr @@ -1,11 +1,9 @@ -error[E0277]: the trait bound `for<'b> >::V: Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-1.rs:14:14 | LL | type V = str; - | ^^^ the trait `for<'b> Clone` is not implemented for `>::V` + | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <&T as Clone> note: required by a bound in `Y` --> $DIR/hr-associated-type-bound-param-1.rs:4:36 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs index a04144ba06b65..5193400882d12 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs @@ -2,8 +2,8 @@ trait Z<'a, T: ?Sized> where T: Z<'a, u16>, - //~^ the trait bound `for<'b> >::W: Clone` is not satisfied - //~| the trait bound `for<'b> >::W: Clone` is not satisfied + //~^ the trait bound `str: Clone` is not satisfied + //~| the trait bound `str: Clone` is not satisfied for<'b> >::W: Clone, { type W: ?Sized; @@ -14,7 +14,7 @@ where impl<'a> Z<'a, u16> for u16 { type W = str; - //~^ ERROR the trait bound `for<'b> >::W: Clone + //~^ ERROR the trait bound `str: Clone } fn main() { diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr index 0c9f2a3978cd1..730229b5208da 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -1,11 +1,9 @@ -error[E0277]: the trait bound `for<'b> >::W: Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-2.rs:4:8 | LL | T: Z<'a, u16>, - | ^^^^^^^^^^ the trait `for<'b> Clone` is not implemented for `>::W` + | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <&T as Clone> note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:7:35 | @@ -15,14 +13,12 @@ LL | trait Z<'a, T: ?Sized> LL | for<'b> >::W: Clone, | ^^^^^ required by this bound in `Z` -error[E0277]: the trait bound `for<'b> >::W: Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-2.rs:4:8 | LL | T: Z<'a, u16>, - | ^^^^^^^^^^ the trait `for<'b> Clone` is not implemented for `>::W` + | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <&T as Clone> note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:7:35 | @@ -32,14 +28,12 @@ LL | trait Z<'a, T: ?Sized> LL | for<'b> >::W: Clone, | ^^^^^ required by this bound in `Z` -error[E0277]: the trait bound `for<'b> >::W: Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-2.rs:16:14 | LL | type W = str; - | ^^^ the trait `for<'b> Clone` is not implemented for `>::W` + | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <&T as Clone> note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:7:35 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs index 1af63bf9070a1..fda7d8111856d 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs @@ -11,7 +11,7 @@ where impl X<'_, (T,)> for (S,) { type U = str; - //~^ ERROR the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: Clone` is not satisfied + //~^ ERROR the trait bound `str: Clone` is not satisfied } pub fn main() { diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr index b1bc1dfbb1127..9935445c30658 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr @@ -1,11 +1,9 @@ -error[E0277]: the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-3.rs:13:14 | LL | type U = str; - | ^^^ the trait `for<'b> Clone` is not implemented for `<(T,) as X<'b, (T,)>>::U` + | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <&T as Clone> note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-3.rs:4:33 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs index 6f06b925bd2e8..20c8157ed9749 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs @@ -11,7 +11,7 @@ where impl X<'_, T> for (S,) { type U = str; - //~^ ERROR the trait bound `for<'b> <(T,) as X<'b, T>>::U: Clone` is not satisfied + //~^ ERROR the trait bound `str: Clone` is not satisfied } pub fn main() { diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr index 0bd404f8a41b2..c26324ee62554 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr @@ -1,11 +1,9 @@ -error[E0277]: the trait bound `for<'b> <(T,) as X<'b, T>>::U: Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-4.rs:13:14 | LL | type U = str; - | ^^^ the trait `for<'b> Clone` is not implemented for `<(T,) as X<'b, T>>::U` + | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <&T as Clone> note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-4.rs:4:36 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs index fc3a85171e273..920aa83528070 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs @@ -25,14 +25,12 @@ where impl X<'_, Vec> for S { type U = str; - //~^ ERROR the trait bound `for<'b> as X<'b, Box>>::U: Clone` is not satisfied - //~| ERROR the trait bound `for<'b> as X<'b, Vec>>::U: Clone` is not satisfied + //~^ ERROR the trait bound `str: Clone` is not satisfied } impl X<'_, Box> for S { type U = str; - //~^ ERROR the trait bound `for<'b> as X<'b, Box>>::U: Clone` is not satisfied - //~| ERROR the trait bound `for<'b> as X<'b, Vec>>::U: Clone` is not satisfied + //~^ ERROR the trait bound `str: Clone` is not satisfied } pub fn main() { diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr index 59c0a7268cc83..63cd89316b38c 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr @@ -1,11 +1,9 @@ -error[E0277]: the trait bound `for<'b> as X<'b, Box>>::U: Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-5.rs:27:14 | LL | type U = str; - | ^^^ the trait `for<'b> Clone` is not implemented for ` as X<'b, Box>>::U` + | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <&T as Clone> note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-5.rs:18:45 | @@ -15,31 +13,12 @@ LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> LL | for<'b> >::U: Clone, | ^^^^^ required by this bound in `X` -error[E0277]: the trait bound `for<'b> as X<'b, Vec>>::U: Clone` is not satisfied - --> $DIR/hr-associated-type-bound-param-5.rs:27:14 - | -LL | type U = str; - | ^^^ the trait `for<'b> Clone` is not implemented for ` as X<'b, Vec>>::U` - | - = help: the following implementations were found: - <&T as Clone> -note: required by a bound in `X` - --> $DIR/hr-associated-type-bound-param-5.rs:16:33 - | -LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> - | - required by a bound in this -LL | where -LL | for<'b> >::U: Clone, - | ^^^^^ required by this bound in `X` - -error[E0277]: the trait bound `for<'b> as X<'b, Vec>>::U: Clone` is not satisfied - --> $DIR/hr-associated-type-bound-param-5.rs:33:14 +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:32:14 | LL | type U = str; - | ^^^ the trait `for<'b> Clone` is not implemented for ` as X<'b, Vec>>::U` + | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <&T as Clone> note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-5.rs:18:45 | @@ -49,23 +28,6 @@ LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> LL | for<'b> >::U: Clone, | ^^^^^ required by this bound in `X` -error[E0277]: the trait bound `for<'b> as X<'b, Box>>::U: Clone` is not satisfied - --> $DIR/hr-associated-type-bound-param-5.rs:33:14 - | -LL | type U = str; - | ^^^ the trait `for<'b> Clone` is not implemented for ` as X<'b, Box>>::U` - | - = help: the following implementations were found: - <&T as Clone> -note: required by a bound in `X` - --> $DIR/hr-associated-type-bound-param-5.rs:16:33 - | -LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> - | - required by a bound in this -LL | where -LL | for<'b> >::U: Clone, - | ^^^^^ required by this bound in `X` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-6.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-6.rs index 04b88c7f4fcb4..482047b095925 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-6.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-6.rs @@ -12,7 +12,6 @@ where impl X<'_, T> for (S,) { //~^ ERROR the trait bound `for<'b> T: X<'b, T>` is not satisfied type U = str; - //~^ ERROR the trait bound `for<'b> >::U: Clone` is not satisfied } pub fn main() { diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr index bce5737af1bb6..bd6e627a3d0d5 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr @@ -1,39 +1,14 @@ -error[E0277]: the trait bound `for<'b> >::U: Clone` is not satisfied - --> $DIR/hr-associated-type-bound-param-6.rs:14:14 - | -LL | type U = str; - | ^^^ the trait `for<'b> Clone` is not implemented for `>::U` - | - = help: the following implementations were found: - <&T as Clone> -note: required by a bound in `X` - --> $DIR/hr-associated-type-bound-param-6.rs:4:33 - | -LL | trait X<'a, T> - | - required by a bound in this -... -LL | for<'b> >::U: Clone, - | ^^^^^ required by this bound in `X` - error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied --> $DIR/hr-associated-type-bound-param-6.rs:12:12 | LL | impl X<'_, T> for (S,) { | ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` | -note: required by a bound in `X` - --> $DIR/hr-associated-type-bound-param-6.rs:3:16 - | -LL | trait X<'a, T> - | - required by a bound in this -LL | where -LL | for<'b> T: X<'b, T>, - | ^^^^^^^^ required by this bound in `X` help: consider restricting type parameter `T` | LL | impl X<'b, T>> X<'_, T> for (S,) { | ++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.rs b/src/test/ui/associated-types/hr-associated-type-projection-1.rs index bad736b64c038..951dd9e97d268 100644 --- a/src/test/ui/associated-types/hr-associated-type-projection-1.rs +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.rs @@ -11,9 +11,8 @@ where } impl UnsafeCopy<'_, T> for T { - //~^ ERROR the trait bound `for<'b> >::Item: Deref` is not satisfied + //~^ type mismatch resolving `::Target == T` type Item = T; - //~^ ERROR the trait bound `for<'b> >::Item: Deref } pub fn main() { diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr index 20d7a206754ea..9c29e969de8da 100644 --- a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr @@ -1,32 +1,16 @@ -error[E0277]: the trait bound `for<'b> >::Item: Deref` is not satisfied - --> $DIR/hr-associated-type-projection-1.rs:15:17 - | -LL | type Item = T; - | ^ the trait `for<'b> Deref` is not implemented for `>::Item` - | - = help: the following implementations were found: - <&T as Deref> - <&mut T as Deref> -note: required by a bound in `UnsafeCopy` - --> $DIR/hr-associated-type-projection-1.rs:3:48 - | -LL | trait UnsafeCopy<'a, T: Copy> - | ---------- required by a bound in this -LL | where -LL | for<'b> >::Item: std::ops::Deref, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UnsafeCopy` - -error[E0277]: the trait bound `for<'b> >::Item: Deref` is not satisfied +error[E0271]: type mismatch resolving `::Target == T` --> $DIR/hr-associated-type-projection-1.rs:13:33 | LL | impl UnsafeCopy<'_, T> for T { - | ^^^^^^^^^^^^^^^^^ the trait `for<'b> Deref` is not implemented for `>::Item` + | - this type parameter ^^^^^^^^^^^^^^^^^ expected associated type, found type parameter `T` | -help: consider further restricting the associated type + = note: expected associated type `::Target` + found type parameter `T` +help: consider further restricting this bound | -LL | impl UnsafeCopy<'_, T> for T where for<'b> >::Item: Deref { - | +++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | impl> UnsafeCopy<'_, T> for T { + | +++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs index 909c33f642d31..acc1c6ae1225d 100644 --- a/src/test/ui/closures/issue-41366.rs +++ b/src/test/ui/closures/issue-41366.rs @@ -1,3 +1,5 @@ +// check-pass + trait T<'x> { type V; } @@ -8,6 +10,4 @@ impl<'g> T<'g> for u32 { fn main() { (&|_| ()) as &dyn for<'x> Fn(>::V); - //~^ ERROR: type mismatch in closure arguments - //~| ERROR: size for values of type `>::V` cannot be known at compilation time } diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr deleted file mode 100644 index 06477efac264e..0000000000000 --- a/src/test/ui/closures/issue-41366.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-41366.rs:10:5 - | -LL | (&|_| ()) as &dyn for<'x> Fn(>::V); - | ^^------^ - | | | - | | found signature of `fn(u16) -> _` - | expected signature of `for<'x> fn(>::V) -> _` - | - = note: required for the cast to the object type `dyn for<'x> Fn(>::V)` - -error[E0277]: the size for values of type `>::V` cannot be known at compilation time - --> $DIR/issue-41366.rs:10:8 - | -LL | (&|_| ()) as &dyn for<'x> Fn(>::V); - | ^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `>::V` - = help: unsized fn params are gated as an unstable feature -help: consider further restricting the associated type - | -LL | fn main() where >::V: Sized { - | ++++++++++++++++++++++++++++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | (&|&_| ()) as &dyn for<'x> Fn(>::V); - | + - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0631. -For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs new file mode 100644 index 0000000000000..24ac566f9df0c --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs @@ -0,0 +1,88 @@ +// FamilyType (GAT workaround) +pub trait FamilyLt<'a> { + type Out; +} + +struct RefMutFamily(std::marker::PhantomData, ()); +impl<'a, T: 'a> FamilyLt<'a> for RefMutFamily { + type Out = &'a mut T; +} + +pub trait Execute { + type E: Inject; + fn execute(self, value: <::I as FamilyLt>::Out); +} + +pub trait Inject +where + Self: Sized, +{ + type I: for<'a> FamilyLt<'a>; + fn inject(_: &()) -> ::Out; +} + +impl Inject for RefMutFamily { + type I = Self; + fn inject(_: &()) -> ::Out { + unimplemented!() + } +} + +// This struct is only used to give a hint to the compiler about the type `Q` +struct Annotate(std::marker::PhantomData); +impl Annotate { + fn new() -> Self { + Self(std::marker::PhantomData) + } +} + +// This function annotate a closure so it can have Higher-Rank Lifetime Bounds +// +// See 'annotate' workaround: https://github.com/rust-lang/rust/issues/58052 +fn annotate(_q: Annotate, func: F) -> impl Execute + 'static +where + F: for<'r> FnOnce(<::I as FamilyLt<'r>>::Out) + 'static, + Q: Inject + 'static, +{ + let wrapper: Wrapper = Wrapper(std::marker::PhantomData, func); + wrapper +} + +struct Wrapper(std::marker::PhantomData, F); +impl Execute for Wrapper + where + Q: Inject, + F: for<'r> FnOnce(<::I as FamilyLt<'r>>::Out), +{ + type E = Q; + + fn execute(self, value: <::I as FamilyLt>::Out) { + (self.1)(value) + } +} + +struct Task { + _processor: Box, +} + +// This function consume the closure +fn task

(processor: P) -> Task +where P: Execute + 'static { + Task { + _processor: Box::new(move || { + let q = P::E::inject(&()); + processor.execute(q); + }) + } +} + +fn main() { + task(annotate( //~ type mismatch + //~^ the size + //~^^ the trait bound + Annotate::>::new(), + |value: &mut usize| { + *value = 2; + } + )); +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr new file mode 100644 index 0000000000000..8311c147ee3bd --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr @@ -0,0 +1,67 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-62529-1.rs:80:10 + | +LL | task(annotate( + | ^^^^^^^^ expected signature of `for<'r> fn( as FamilyLt<'r>>::Out) -> _` +... +LL | |value: &mut usize| { + | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _` + | +note: required by a bound in `annotate` + --> $DIR/issue-62529-1.rs:44:8 + | +LL | fn annotate(_q: Annotate, func: F) -> impl Execute + 'static + | -------- required by a bound in this +LL | where +LL | F: for<'r> FnOnce(<::I as FamilyLt<'r>>::Out) + 'static, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `annotate` + +error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time + --> $DIR/issue-62529-1.rs:80:10 + | +LL | task(annotate( + | __________^ +LL | | +LL | | +LL | | Annotate::>::new(), +... | +LL | | } +LL | | )); + | |_____^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl Execute` +note: required by a bound in `task` + --> $DIR/issue-62529-1.rs:69:9 + | +LL | fn task

(processor: P) -> Task + | ^ required by this bound in `task` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn task(processor: P) -> Task + | ++++++++ + +error[E0277]: the trait bound `impl Execute: Execute` is not satisfied + --> $DIR/issue-62529-1.rs:80:10 + | +LL | task(annotate( + | __________^ +LL | | +LL | | +LL | | Annotate::>::new(), +... | +LL | | } +LL | | )); + | |_____^ the trait `Execute` is not implemented for `impl Execute` + | +note: required by a bound in `task` + --> $DIR/issue-62529-1.rs:70:10 + | +LL | fn task

(processor: P) -> Task + | ---- required by a bound in this +LL | where P: Execute + 'static { + | ^^^^^^^ required by this bound in `task` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0631. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs new file mode 100644 index 0000000000000..002054732919e --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs @@ -0,0 +1,33 @@ +// check-pass + +use std::marker::PhantomData; + +trait Lt<'a> { + type T; +} +struct Id(PhantomData); +impl<'a,T> Lt<'a> for Id { + type T = T; +} + +struct Ref(PhantomData) where T: ?Sized; +impl<'a,T> Lt<'a> for Ref +where T: 'a + Lt<'a> + ?Sized +{ + type T = &'a T; +} +struct Mut(PhantomData) where T: ?Sized; +impl<'a,T> Lt<'a> for Mut +where T: 'a + Lt<'a> + ?Sized +{ + type T = &'a mut T; +} + +struct C(for<'a> fn(>::T) -> O) where I: for<'a> Lt<'a>; + + +fn main() { + let c = C::,_>(|()| 3); + c.0(()); + +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs new file mode 100644 index 0000000000000..d84e30f4984ea --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs @@ -0,0 +1,32 @@ +trait ATC<'a> { + type Type: Sized; +} + +trait WithDefault: for<'a> ATC<'a> { + fn with_default Fn(>::Type)>(f: F); +} + +fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(>::Type)>( + f: F, + x: >::Type, +) { + f(x); +} + +impl<'a> ATC<'a> for () { + type Type = Self; +} + +impl WithDefault for () { + fn with_default Fn(>::Type)>(f: F) { + // Errors with a bogus type mismatch. + //f(()); + // Going through another generic function works fine. + call(f, ()); + //~^ expected a + } +} + +fn main() { + // <()>::with_default(|_| {}); +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr new file mode 100644 index 0000000000000..b110734642177 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -0,0 +1,15 @@ +error[E0277]: expected a `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F` + --> $DIR/issue-62529-3.rs:25:9 + | +LL | call(f, ()); + | ^^^^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F` + | +note: required by a bound in `call` + --> $DIR/issue-62529-3.rs:9:36 + | +LL | fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(>::Type)>( + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs new file mode 100644 index 0000000000000..8c2a59868ca5e --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs @@ -0,0 +1,39 @@ +// check-pass + +use std::marker::PhantomData; +use std::mem; + +trait Container<'a> { + type Root: 'a; +} + +type RootOf<'a, T> = >::Root; + +struct Test<'a, T> where T: Container<'a> { + pub root: T::Root, + marker: PhantomData<&'a mut &'a mut ()>, +} + +impl<'a, 'b> Container<'b> for &'a str { + type Root = &'b str; +} + +impl<'a, T> Test<'a, T> where T: for<'b> Container<'b> { + fn new(root: RootOf<'a, T>) -> Test<'a, T> { + Test { + root: root, + marker: PhantomData + } + } + + fn with_mut(&mut self, f: F) -> R where + F: for<'b> FnOnce(&'b mut RootOf<'b, T>) -> R { + f(unsafe { mem::transmute(&mut self.root) }) + } +} + +fn main() { + let val = "root"; + let mut test: Test<&str> = Test::new(val); + test.with_mut(|_| { }); +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs new file mode 100644 index 0000000000000..03f257a029c17 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs @@ -0,0 +1,27 @@ +// check-pass + +pub struct Struct {} + +pub trait Trait<'a> { + type Assoc; + + fn method() -> Self::Assoc; +} + +impl<'a> Trait<'a> for Struct { + type Assoc = (); + + fn method() -> Self::Assoc {} +} + +pub fn function(f: F) +where + F: for<'a> FnOnce(>::Assoc), + T: for<'b> Trait<'b>, +{ + f(T::method()); +} + +fn main() { + function::<_, Struct>(|_| {}); +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs new file mode 100644 index 0000000000000..74a4785e478b8 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs @@ -0,0 +1,77 @@ +// check-pass + +use std::cell::RefMut; + +fn main() { + StateMachine2::Init.resume(); +} + +enum StateMachine2<'a> { + Init, + #[allow(dead_code)] // match required for ICE + AfterTwoYields { + p: Backed<'a, *mut String>, + }, +} + +impl<'a> StateMachine2<'a> { + fn take(&self) -> Self { + StateMachine2::Init + } +} + +impl<'a> StateMachine2<'a> { + fn resume(&mut self) -> () { + use StateMachine2::*; + match self.take() { + AfterTwoYields { p } => { + p.with(|_| {}); + } + _ => panic!("Resume after completed."), + } + } +} + +unsafe trait Unpack<'a> { + type Unpacked: 'a; + + fn unpack(&self) -> Self::Unpacked { + unsafe { std::mem::transmute_copy(&self) } + } +} + +unsafe trait Pack { + type Packed; + + fn pack(&self) -> Self::Packed { + unsafe { std::mem::transmute_copy(&self) } + } +} + +unsafe impl<'a> Unpack<'a> for String { + type Unpacked = String; +} + +unsafe impl Pack for String { + type Packed = String; +} + +unsafe impl<'a> Unpack<'a> for *mut String { + type Unpacked = &'a mut String; +} + +unsafe impl<'a> Pack for &'a mut String { + type Packed = *mut String; +} + +struct Backed<'a, U>(RefMut<'a, Option>, U); + +impl<'a, 'b, U: Unpack<'b>> Backed<'a, U> { + fn with(self, f: F) -> Backed<'a, ()> + where + F: for<'f> FnOnce(>::Unpacked) -> (), + { + let result = f(self.1.unpack()); + Backed(self.0, result) + } +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs new file mode 100644 index 0000000000000..87d1a250f7ae6 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs @@ -0,0 +1,29 @@ +pub trait MyTrait<'a> { + type Output: 'a; + fn gimme_value(&self) -> Self::Output; +} + +pub struct MyStruct; + +impl<'a> MyTrait<'a> for MyStruct { + type Output = &'a usize; + fn gimme_value(&self) -> Self::Output { + unimplemented!() + } +} + +fn meow(t: T, f: F) +where + T: for<'any> MyTrait<'any>, + F: for<'any2> Fn(>::Output), +{ + let v = t.gimme_value(); + f(v); +} + +fn main() { + let struc = MyStruct; + meow(struc, |foo| { //~ type mismatch + println!("{:?}", foo); + }) +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr new file mode 100644 index 0000000000000..efc956888ee5a --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr @@ -0,0 +1,20 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-70120.rs:26:5 + | +LL | meow(struc, |foo| { + | ^^^^ ----- found signature of `for<'r> fn(&'r usize) -> _` + | | + | expected signature of `for<'any2> fn(>::Output) -> _` + | +note: required by a bound in `meow` + --> $DIR/issue-70120.rs:18:8 + | +LL | fn meow(t: T, f: F) + | ---- required by a bound in this +... +LL | F: for<'any2> Fn(>::Output), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `meow` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 7b81beeed4167..97f53bc70e44e 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `for<'r> as T0<'r, (>::V,)>>::O == <_ as Ty<'r>>::V` +error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` --> $DIR/issue-62203-hrtb-ice.rs:38:19 | LL | let v = Unit2.m( @@ -9,13 +9,13 @@ LL | let v = Unit2.m( = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&u8,),)>>::Output == Unit3` +error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&'r u8,),)>>::Output == Unit3` --> $DIR/issue-62203-hrtb-ice.rs:38:19 | LL | let v = Unit2.m( | ^ expected struct `Unit4`, found struct `Unit3` | -note: required because of the requirements on the impl of `for<'r> T0<'r, (>::V,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>` +note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>` --> $DIR/issue-62203-hrtb-ice.rs:17:16 | LL | impl<'a, A, T> T0<'a, A> for L diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index bf04a8c987393..3c720f50d48b2 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -5,7 +5,7 @@ LL | fn foo_fail() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` | = note: expected associated type `::Assoc` - found type `()` + found unit type `()` help: consider constraining the associated type `::Assoc` to `()` | LL | fn foo_fail>() -> impl FooLike { @@ -24,7 +24,7 @@ LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` | = note: expected associated type `>::Assoc` - found type `()` + found unit type `()` help: consider constraining the associated type `>::Assoc` to `()` | LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { diff --git a/src/test/ui/issues/issue-35570.rs b/src/test/ui/issues/issue-35570.rs index fafef79ea5b86..42cef9a47f279 100644 --- a/src/test/ui/issues/issue-35570.rs +++ b/src/test/ui/issues/issue-35570.rs @@ -1,5 +1,3 @@ -// check-pass - use std::mem; trait Trait1 {} @@ -8,6 +6,7 @@ trait Trait2<'a> { } fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { +//~^ the trait bound `for<'a> (): Trait2<'a>` is not satisfied let _e: (usize, usize) = unsafe{mem::transmute(param)}; } diff --git a/src/test/ui/issues/issue-35570.stderr b/src/test/ui/issues/issue-35570.stderr new file mode 100644 index 0000000000000..dda6145e65ada --- /dev/null +++ b/src/test/ui/issues/issue-35570.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied + --> $DIR/issue-35570.rs:8:4 + | +LL | fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { + | ^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-43623.rs b/src/test/ui/issues/issue-43623.rs index 99cae46fd9cf2..cedcf7c361c3b 100644 --- a/src/test/ui/issues/issue-43623.rs +++ b/src/test/ui/issues/issue-43623.rs @@ -1,3 +1,5 @@ +// check-pass + pub trait Trait<'a> { type Assoc; } @@ -14,7 +16,6 @@ where F: for<'b> FnMut(>::Assoc), { break_me::; - //~^ ERROR: type mismatch in function arguments } fn main() {} diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr deleted file mode 100644 index b99f367d73365..0000000000000 --- a/src/test/ui/issues/issue-43623.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0631]: type mismatch in function arguments - --> $DIR/issue-43623.rs:16:5 - | -LL | break_me::; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | expected signature of `for<'b> fn(>::Assoc) -> _` - | found signature of `fn(()) -> _` - | -note: required by a bound in `break_me` - --> $DIR/issue-43623.rs:14:16 - | -LL | pub fn break_me(f: F) - | -------- required by a bound in this -... -LL | F: for<'b> FnMut(>::Assoc), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `break_me` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/issues/issue-44005.rs b/src/test/ui/issues/issue-44005.rs index 041fcdbf823bf..ab3b92142c8c9 100644 --- a/src/test/ui/issues/issue-44005.rs +++ b/src/test/ui/issues/issue-44005.rs @@ -1,4 +1,3 @@ -// build-pass pub trait Foo<'a> { type Bar; fn foo(&'a self) -> Self::Bar; @@ -12,8 +11,9 @@ impl<'a, 'b, T: 'a> Foo<'a> for &'b T { } pub fn uncallable(x: T, f: F) - where T: for<'a> Foo<'a>, - F: for<'a> Fn(>::Bar) +where + T: for<'a> Foo<'a>, + F: for<'a> Fn(>::Bar), { f(x.foo()); } @@ -24,6 +24,7 @@ pub fn catalyst(x: &i32) { pub fn broken(x: &i32, f: F) { uncallable(x, |y| f(y)); + //~^ type mismatch } -fn main() { } +fn main() {} diff --git a/src/test/ui/issues/issue-44005.stderr b/src/test/ui/issues/issue-44005.stderr new file mode 100644 index 0000000000000..307e444e69635 --- /dev/null +++ b/src/test/ui/issues/issue-44005.stderr @@ -0,0 +1,20 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-44005.rs:26:5 + | +LL | uncallable(x, |y| f(y)); + | ^^^^^^^^^^ -------- found signature of `for<'r> fn(&'r i32) -> _` + | | + | expected signature of `for<'a> fn(<&i32 as Foo<'a>>::Bar) -> _` + | +note: required by a bound in `uncallable` + --> $DIR/issue-44005.rs:16:8 + | +LL | pub fn uncallable(x: T, f: F) + | ---------- required by a bound in this +... +LL | F: for<'a> Fn(>::Bar), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/issues/issue-57843.nll.stderr b/src/test/ui/issues/issue-57843.nll.stderr deleted file mode 100644 index 2ab49ec61cf59..0000000000000 --- a/src/test/ui/issues/issue-57843.nll.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57843.rs:25:9 - | -LL | Foo(Box::new(|_| ())); - | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 bool)` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2` - -error: aborting due to previous error - diff --git a/src/test/ui/issues/issue-60218.stderr b/src/test/ui/issues/issue-60218.stderr index a16363d7c8730..ac33cfd040243 100644 --- a/src/test/ui/issues/issue-60218.stderr +++ b/src/test/ui/issues/issue-60218.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `for<'t> ::IntoIter, _> as Iterator>::Item: Foo` is not satisfied +error[E0277]: the trait bound `&u32: Foo` is not satisfied --> $DIR/issue-60218.rs:18:5 | LL | trigger_error(vec![], |x: &u32| x) - | ^^^^^^^^^^^^^ the trait `for<'t> Foo` is not implemented for `::IntoIter, _> as Iterator>::Item` + | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32` | note: required by a bound in `trigger_error` --> $DIR/issue-60218.rs:13:72 diff --git a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr index 036a9300a174d..733456a1a8bd1 100644 --- a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr +++ b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving ` as Deref>::Target == Rc LL | let _ = Pin::new(Apple) == Rc::pin(Apple); | ^^ expected struct `Apple`, found struct `Rc` | - = note: expected type `Apple` - found struct `Rc` + = note: expected struct `Apple` + found struct `Rc` = note: required because of the requirements on the impl of `PartialEq>>` for `Pin` error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr index a64cb82305a48..9867addaf38e7 100644 --- a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr +++ b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr @@ -2,10 +2,10 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/issue-75361-mismatched-impl.rs:18:3 | LL | fn adjacent_edges(&self) -> Box>; - | --------------------------------------------------------------------- expected `fn(&T) -> Box<(dyn MyTrait + 'static)>` + | --------------------------------------------------------------------- expected `fn(&T) -> Box<(dyn MyTrait + 'static)>` ... LL | fn adjacent_edges(&self) -> Box + '_> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&T) -> Box>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&T) -> Box>` | = note: expected `fn(&T) -> Box<(dyn MyTrait + 'static)>` found `fn(&T) -> Box>` diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs index a4272802af54d..c1dab6086ef3a 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs @@ -19,7 +19,7 @@ trait Trait2<'a, 'b> { // since for it to be WF, we would need to know that `'y: 'x`, but we // do not infer that. fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) - //~^ ERROR reference has a longer lifetime than the data it references + //~^ the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied { } diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index 6470ebf541b5b..44ef13c740c06 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -1,20 +1,14 @@ -error[E0491]: in type `&'x (dyn for<'z> Trait1<>::Foo> + 'x)`, reference has a longer lifetime than the data it references - --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:25 +error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied + --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:4 | LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` | -note: the pointer is valid for the lifetime `'x` as defined on the function body at 21:11 - --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:11 +help: consider restricting type parameter `T` | -LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) - | ^^ -note: but the referenced data is only valid for the lifetime `'y` as defined on the function body at 21:15 - --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:15 - | -LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) - | ^^ +LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) + | ++++++++++++++++++++++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0491`. +For more information about this error, try `rustc --explain E0277`. From 07ee86a6fd6ddf0750bf1f1e13b608e92a4e694f Mon Sep 17 00:00:00 2001 From: jackh726 Date: Fri, 23 Jul 2021 00:10:56 -0400 Subject: [PATCH 2/5] Normalize only after failure --- .../borrow_check/type_check/input_output.rs | 76 ++++++++++--------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs index ba35813555811..1e0a2b0c42177 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs @@ -82,33 +82,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let local = Local::new(argument_index + 1); let mir_input_ty = body.local_decls[local].ty; - // FIXME(jackh726): This is a hack. It's somewhat like - // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd - // like to normalize *before* inserting into `local_decls`, but I - // couldn't figure out where the heck that was. - let mir_input_ty = match self - .infcx - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) - .normalize(mir_input_ty) - { - Ok(n) => { - debug!("equate_inputs_and_outputs: {:?}", n); - if n.obligations.iter().all(|o| { - matches!( - o.predicate.kind().skip_binder(), - ty::PredicateKind::RegionOutlives(_) - ) - }) { - n.value - } else { - mir_input_ty - } - } - Err(_) => { - debug!("equate_inputs_and_outputs: NoSolution"); - mir_input_ty - } - }; let mir_input_span = body.local_decls[local].source_info.span; self.equate_normalized_input_or_output( normalized_input_ty, @@ -191,17 +164,48 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) { debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b); - if let Err(terr) = + if let Err(_) = self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation) { - span_mirbug!( - self, - Location::START, - "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`", - a, - b, - terr - ); + // FIXME(jackh726): This is a hack. It's somewhat like + // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd + // like to normalize *before* inserting into `local_decls`, but I + // couldn't figure out where the heck that was. + let b = match self + .infcx + .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) + .normalize(b) + { + Ok(n) => { + debug!("equate_inputs_and_outputs: {:?}", n); + if n.obligations.iter().all(|o| { + matches!( + o.predicate.kind().skip_binder(), + ty::PredicateKind::RegionOutlives(_) + ) + }) { + n.value + } else { + b + } + } + Err(_) => { + debug!("equate_inputs_and_outputs: NoSolution"); + b + } + }; + if let Err(terr) = + self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation) + { + span_mirbug!( + self, + Location::START, + "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`", + a, + b, + terr + ); + } } } } From 9891e470b10566bc77db56712afcc740ec27a184 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Fri, 23 Jul 2021 14:26:02 -0400 Subject: [PATCH 3/5] Also ignore typeoutlives predicates --- .../borrow_check/type_check/input_output.rs | 1 + .../normalization-generality-2.rs | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/test/ui/associated-types/normalization-generality-2.rs diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs index 1e0a2b0c42177..c815ed0d1cb49 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs @@ -182,6 +182,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { matches!( o.predicate.kind().skip_binder(), ty::PredicateKind::RegionOutlives(_) + | ty::PredicateKind::TypeOutlives(_) ) }) { n.value diff --git a/src/test/ui/associated-types/normalization-generality-2.rs b/src/test/ui/associated-types/normalization-generality-2.rs new file mode 100644 index 0000000000000..d8790bb2d12fc --- /dev/null +++ b/src/test/ui/associated-types/normalization-generality-2.rs @@ -0,0 +1,30 @@ +// build-pass + +// Ensures that we don't regress on "implementation is not general enough" when +// normalizating under binders. Unlike `normalization-generality.rs`, this also produces +// type outlives predicates that we must ignore. + +pub unsafe trait Yokeable<'a> { + type Output: 'a; +} +pub struct Yoke Yokeable<'a>> { + _marker: std::marker::PhantomData, +} +impl Yokeable<'a>> Yoke { + pub fn project

( + &self, + _f: for<'a> fn(&>::Output, &'a ()) ->

>::Output, + ) -> Yoke

+ where + P: for<'a> Yokeable<'a>, + { + unimplemented!() + } +} +pub fn slice(y: Yoke<&'static str>) -> Yoke<&'static [u8]> { + y.project(move |yk, _| yk.as_bytes()) +} +unsafe impl<'a, T: 'static + ?Sized> Yokeable<'a> for &'static T { + type Output = &'a T; +} +fn main() {} From af14db14f4aae4cac306f2c38b83311e7cb3c3f0 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Tue, 24 Aug 2021 22:26:48 -0400 Subject: [PATCH 4/5] Review comments --- .../borrow_check/type_check/input_output.rs | 4 +- .../src/traits/project.rs | 54 +++++++++++++------ .../src/traits/query/normalize.rs | 51 ++++++++++-------- 3 files changed, 68 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs index c815ed0d1cb49..ba9b6926526be 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs @@ -169,8 +169,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { { // FIXME(jackh726): This is a hack. It's somewhat like // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd - // like to normalize *before* inserting into `local_decls`, but I - // couldn't figure out where the heck that was. + // like to normalize *before* inserting into `local_decls`, but + // doing so ends up causing some other trouble. let b = match self .infcx .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index df1dca9831ab1..91b9ad0af356c 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -363,12 +363,28 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { return ty; } - // N.b. while we want to call `super_fold_with(self)` on `ty` before - // normalization, we wait until we know whether we need to normalize the - // current type. If we do, then we only fold the ty *after* replacing bound - // vars with placeholders. This means that nested types don't need to replace - // bound vars at the current binder level or above. A key assumption here is - // that folding the type can't introduce new bound vars. + // We try to be a little clever here as a performance optimization in + // cases where there are nested projections under binders. + // For example: + // ``` + // for<'a> fn(::One<'a, Box::Two<'a>>>>) + // ``` + // We normalize the substs on the projection before the projecting, but + // if we're naive, we'll + // replace bound vars on inner, project inner, replace placeholders on inner, + // replace bound vars on outer, project outer, replace placeholders on outer + // + // However, if we're a bit more clever, we can replace the bound vars + // on the entire type before normalizing nested projections, meaning we + // replace bound vars on outer, project inner, + // project outer, replace placeholders on outer + // + // This is possible because the inner `'a` will already be a placeholder + // when we need to normalize the inner projection + // + // On the other hand, this does add a bit of complexity, since we only + // replace bound vars if the current type is a `Projection` and we need + // to make sure we don't forget to fold the substs regardless. match *ty.kind() { ty::Opaque(def_id, substs) => { @@ -380,7 +396,6 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { // N.b. there is an assumption here all this code can handle // escaping bound vars. - let substs = substs.super_fold_with(self); let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { let obligation = Obligation::with_depth( @@ -392,6 +407,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { self.selcx.infcx().report_overflow_error(&obligation, true); } + let substs = substs.super_fold_with(self); let generic_ty = self.tcx().type_of(def_id); let concrete_ty = generic_ty.subst(self.tcx(), substs); self.depth += 1; @@ -430,12 +446,16 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { ty::Projection(data) => { // If there are escaping bound vars, we temporarily replace the - // bound vars with placeholders. Note though, that in the cas + // bound vars with placeholders. Note though, that in the case // that we still can't project for whatever reason (e.g. self // type isn't known enough), we *can't* register an obligation // and return an inference variable (since then that obligation // would have bound vars and that's a can of worms). Instead, // we just give up and fall back to pretending like we never tried! + // + // Note: this isn't necessarily the final approach here; we may + // want to figure out how to register obligations with escaping vars + // or handle this some other way. let infcx = self.selcx.infcx(); let (data, mapped_regions, mapped_types, mapped_consts) = @@ -451,16 +471,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { ) .ok() .flatten() + .map(|normalized_ty| { + PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + normalized_ty, + ) + }) .unwrap_or_else(|| ty.super_fold_with(self)); - let normalized_ty = PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - normalized_ty, - ); debug!( ?self.depth, ?ty, diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 8f8de24981b8e..21e1bd8f46467 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -67,6 +67,16 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { universes: vec![], }; + // This is actually a consequence by the way `normalize_erasing_regions` works currently. + // Because it needs to call the `normalize_generic_arg_after_erasing_regions`, it folds + // through tys and consts in a `TypeFoldable`. Importantly, it skips binders, leaving us + // with trying to normalize with escaping bound vars. + // + // Here, we just add the universes that we *would* have created had we passed through the binders. + // + // We *could* replace escaping bound vars eagerly here, but it doesn't seem really necessary. + // The rest of the code is already set up to be lazy about replacing bound vars, + // and only when we actually have to normalize. if value.has_escaping_bound_vars() { let mut max_visitor = MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 }; @@ -183,12 +193,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { return ty; } - // N.b. while we want to call `super_fold_with(self)` on `ty` before - // normalization, we wait until we know whether we need to normalize the - // current type. If we do, then we only fold the ty *after* replacing bound - // vars with placeholders. This means that nested types don't need to replace - // bound vars at the current binder level or above. A key assumption here is - // that folding the type can't introduce new bound vars. + // See note in `rustc_trait_selection::traits::project` about why we + // wait to fold the substs. // Wrap this in a closure so we don't accidentally return from the outer function let res = (|| match *ty.kind() { @@ -253,7 +259,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { // We don't expect ambiguity. if result.is_ambiguous() { self.error = true; - return ty; + return ty.super_fold_with(self); } match self.infcx.instantiate_query_response_and_region_obligations( @@ -271,14 +277,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { Err(_) => { self.error = true; - ty + ty.super_fold_with(self) } } } Err(NoSolution) => { self.error = true; - ty + ty.super_fold_with(self) } } } @@ -304,12 +310,12 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - let normalized_ty = match tcx.normalize_projection_ty(c_data) { + match tcx.normalize_projection_ty(c_data) { Ok(result) => { // We don't expect ambiguity. if result.is_ambiguous() { self.error = true; - return ty; + return ty.super_fold_with(self); } match self.infcx.instantiate_query_response_and_region_obligations( self.cause, @@ -321,27 +327,26 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); self.obligations.extend(obligations); - result.normalized_ty + crate::traits::project::PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + result.normalized_ty, + ) } Err(_) => { self.error = true; - ty + ty.super_fold_with(self) } } } Err(NoSolution) => { self.error = true; - ty + ty.super_fold_with(self) } - }; - crate::traits::project::PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - normalized_ty, - ) + } } _ => ty.super_fold_with(self), From 994a6bb667d8a0ae7bbc777f4d33994692dd7266 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Wed, 25 Aug 2021 16:06:52 -0400 Subject: [PATCH 5/5] Bless NLL compare mode --- .../associated-types/higher-ranked-projection.bad.nll.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr index 59e27cd2e7dd6..e3bd0c2276e48 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | foo(()); | ^^^^^^^ one type is more general than the other | - = note: expected type `&'a ()` - found reference `&()` + = note: expected reference `&'a ()` + found reference `&()` error: aborting due to previous error