diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index c97a6a1a6587a..3257625ac013a 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -147,6 +147,14 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> // 'static. fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {} + fn projection_equate(&mut self, _projection_ty: ty::ProjectionTy<'tcx>, _ty: Ty<'tcx>) { + unreachable!() + } + + fn defer_projection_equality(&self) -> bool { + false + } + fn normalization() -> NormalizationStrategy { NormalizationStrategy::Eager } diff --git a/compiler/rustc_error_codes/src/error_codes/E0275.md b/compiler/rustc_error_codes/src/error_codes/E0275.md index 2d12fcea4cafc..bd06b373c1501 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0275.md +++ b/compiler/rustc_error_codes/src/error_codes/E0275.md @@ -8,6 +8,12 @@ trait Foo {} struct Bar(T); impl Foo for T where Bar: Foo {} + +fn takes_foo() {} + +fn calls_takes_foo() { + takes_foo::<()>(); +} ``` This error occurs when there was a recursive trait requirement that overflowed diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 00e238648712f..e86136c589ff5 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -40,6 +40,7 @@ pub struct At<'a, 'tcx> { /// matching from matching anything against opaque /// types. pub define_opaque_types: bool, + pub defer_projection_equality: bool, } pub struct Trace<'a, 'tcx> { @@ -55,7 +56,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> At<'a, 'tcx> { - At { infcx: self, cause, param_env, define_opaque_types: true } + At { + infcx: self, + cause, + param_env, + define_opaque_types: true, + defer_projection_equality: true, + } } /// Forks the inference context, creating a new inference context with the same inference @@ -101,6 +108,10 @@ impl<'a, 'tcx> At<'a, 'tcx> { Self { define_opaque_types, ..self } } + pub fn defer_projection_equality(self, defer_projection_equality: bool) -> Self { + Self { defer_projection_equality, ..self } + } + /// Hacky routine for equating two impl headers in coherence. pub fn eq_impl_headers( self, @@ -252,7 +263,12 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields( + trace, + at.param_env, + at.define_opaque_types, + at.defer_projection_equality, + ); fields .sub(a_is_expected) .relate(a, b) @@ -269,7 +285,12 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields( + trace, + at.param_env, + at.define_opaque_types, + at.defer_projection_equality, + ); fields .equate(a_is_expected) .relate(a, b) @@ -284,7 +305,12 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields( + trace, + at.param_env, + at.define_opaque_types, + at.defer_projection_equality, + ); fields .lub(a_is_expected) .relate(a, b) @@ -299,7 +325,12 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields( + trace, + at.param_env, + at.define_opaque_types, + at.defer_projection_equality, + ); fields .glb(a_is_expected) .relate(a, b) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 56e8348987951..181d54cad89a0 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -733,6 +733,23 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { span_bug!(self.cause.span(), "generic_const_exprs: unreachable `const_equate`"); } + fn projection_equate(&mut self, projection_ty: ty::ProjectionTy<'tcx>, ty: Ty<'tcx>) { + self.obligations.push(Obligation { + cause: self.cause.clone(), + param_env: self.param_env, + predicate: ty::Binder::dummy(ty::PredicateKind::Projection(ty::ProjectionPredicate { + projection_ty, + term: ty::Term::from(ty), + })) + .to_predicate(self.infcx.tcx), + recursion_depth: 0, + }) + } + + fn defer_projection_equality(&self) -> bool { + true + } + fn normalization() -> NormalizationStrategy { NormalizationStrategy::Eager } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index c406df9e41116..f3b3a630cd70d 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -54,6 +54,7 @@ pub struct CombineFields<'infcx, 'tcx> { /// matching from matching anything against opaque /// types. pub define_opaque_types: bool, + pub defer_projection_equality: bool, } #[derive(Copy, Clone, Debug)] @@ -457,6 +458,19 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { ty::Binder::dummy(predicate).to_predicate(self.tcx()), )); } + + pub fn add_projection_equate_obligation( + &mut self, + projection_ty: ty::ProjectionTy<'tcx>, + ty: Ty<'tcx>, + ) { + self.obligations.push(Obligation::new( + self.trace.cause.clone(), + self.param_env, + ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, term: ty::Term::from(ty) }) + .to_predicate(self.tcx()), + )); + } } struct Generalizer<'cx, 'tcx> { @@ -759,6 +773,18 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { _ => relate::super_relate_consts(self, c, c), } } + + fn projection_equate_obligation( + &mut self, + _projection_ty: ty::ProjectionTy<'tcx>, + _ty: Ty<'tcx>, + ) { + bug!("`TypeGeneralizer` shouldn't equate projections with other kinds of types"); + } + + fn defer_projection_equality(&self) -> bool { + false + } } pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> { @@ -982,4 +1008,16 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { _ => relate::super_relate_consts(self, c, c), } } + + fn projection_equate_obligation( + &mut self, + _projection_ty: ty::ProjectionTy<'tcx>, + _ty: Ty<'tcx>, + ) { + bug!("`ConstInferUnifier` shouldn't equate projections with other kinds of types"); + } + + fn defer_projection_equality(&self) -> bool { + bug!("`ConstInferUnifier` shouldn't equate projections with other kinds of types"); + } } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 3b1798ca73746..d83d0c18b2348 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -160,6 +160,18 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { } Ok(a) } + + fn projection_equate_obligation( + &mut self, + projection_ty: ty::ProjectionTy<'tcx>, + ty: Ty<'tcx>, + ) { + self.fields.add_projection_equate_obligation(projection_ty, ty); + } + + fn defer_projection_equality(&self) -> bool { + self.fields.defer_projection_equality + } } impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 546ab82bc238a..723c84fdbb3fb 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2777,6 +2777,18 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> { // relation Ok(a) } + + fn projection_equate_obligation( + &mut self, + _projection_ty: ty::ProjectionTy<'tcx>, + _ty: Ty<'tcx>, + ) { + unreachable!() + } + + fn defer_projection_equality(&self) -> bool { + false + } } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 1570a08f3ca8b..cecbfb109774e 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -110,6 +110,18 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> { Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?)) } } + + fn projection_equate_obligation( + &mut self, + projection_ty: ty::ProjectionTy<'tcx>, + ty: Ty<'tcx>, + ) { + self.fields.add_projection_equate_obligation(projection_ty, ty); + } + + fn defer_projection_equality(&self) -> bool { + self.fields.defer_projection_equality + } } impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index 9f96d52c85034..fdaf41f8c89db 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -110,6 +110,18 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> { Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?)) } } + + fn projection_equate_obligation( + &mut self, + projection_ty: ty::ProjectionTy<'tcx>, + ty: Ty<'tcx>, + ) { + self.fields.add_projection_equate_obligation(projection_ty, ty); + } + + fn defer_projection_equality(&self) -> bool { + self.fields.defer_projection_equality + } } impl<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 3abed12217ccd..7af701905112e 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -784,6 +784,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, define_opaque_types: bool, + defer_projection_equality: bool, ) -> CombineFields<'a, 'tcx> { CombineFields { infcx: self, @@ -792,6 +793,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { param_env, obligations: PredicateObligations::new(), define_opaque_types, + defer_projection_equality, } } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index bb6f6ae60e26a..9d3badb21b043 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -91,6 +91,11 @@ pub trait TypeRelatingDelegate<'tcx> { ); fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>); + + fn projection_equate(&mut self, projection_ty: ty::ProjectionTy<'tcx>, ty: Ty<'tcx>); + + fn defer_projection_equality(&self) -> bool; + fn register_opaque_type( &mut self, a: Ty<'tcx>, @@ -273,38 +278,6 @@ where self.delegate.push_outlives(sup, sub, info); } - /// Relate a projection type and some value type lazily. This will always - /// succeed, but we push an additional `ProjectionEq` goal depending - /// on the value type: - /// - if the value type is any type `T` which is not a projection, we push - /// `ProjectionEq(projection = T)`. - /// - if the value type is another projection `other_projection`, we create - /// a new inference variable `?U` and push the two goals - /// `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`. - fn relate_projection_ty( - &mut self, - projection_ty: ty::ProjectionTy<'tcx>, - value_ty: Ty<'tcx>, - ) -> Ty<'tcx> { - use rustc_span::DUMMY_SP; - - match *value_ty.kind() { - ty::Projection(other_projection_ty) => { - let var = self.infcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span: DUMMY_SP, - }); - // FIXME(lazy-normalization): This will always ICE, because the recursive - // call will end up in the _ arm below. - self.relate_projection_ty(projection_ty, var); - self.relate_projection_ty(other_projection_ty, var); - var - } - - _ => bug!("should never be invoked with eager normalization"), - } - } - /// Relate a type inference variable with a value type. This works /// by creating a "generalization" G of the value where all the /// lifetimes are replaced with fresh inference values. This @@ -344,7 +317,9 @@ where } ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => { - return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid))); + let ty_var = self.infcx.tcx.mk_ty_var(vid); + self.projection_equate_obligation(projection_ty, ty_var); + return Ok(ty_var); } _ => (), @@ -608,18 +583,6 @@ where self.relate_opaques(a, b) } - (&ty::Projection(projection_ty), _) - if D::normalization() == NormalizationStrategy::Lazy => - { - Ok(self.relate_projection_ty(projection_ty, b)) - } - - (_, &ty::Projection(projection_ty)) - if D::normalization() == NormalizationStrategy::Lazy => - { - Ok(self.relate_projection_ty(projection_ty, a)) - } - _ => { debug!(?a, ?b, ?self.ambient_variance); @@ -792,6 +755,18 @@ where Ok(a) } + + fn projection_equate_obligation( + &mut self, + projection_ty: ty::ProjectionTy<'tcx>, + value_ty: Ty<'tcx>, + ) { + self.delegate.projection_equate(projection_ty, value_ty); + } + + fn defer_projection_equality(&self) -> bool { + self.delegate.defer_projection_equality() + } } impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D> @@ -1085,4 +1060,16 @@ where self.first_free_index.shift_out(1); Ok(a.rebind(result)) } + + fn projection_equate_obligation( + &mut self, + _projection_ty: ty::ProjectionTy<'tcx>, + _ty: Ty<'tcx>, + ) { + bug!("`TypeGeneralizer` shouldn't equate projections with other kinds of types"); + } + + fn defer_projection_equality(&self) -> bool { + false + } } diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index a5c21f0fb9b50..723ee8cd1b4e3 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -211,4 +211,17 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { self.pattern_depth.shift_out(1); result } + + fn projection_equate_obligation( + &mut self, + _projection_ty: ty::ProjectionTy<'tcx>, + _ty: Ty<'tcx>, + ) { + unreachable!() + } + + fn defer_projection_equality(&self) -> bool { + // FIXME(projection_equality): ??? + false + } } diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index b7eab5d43285b..699edd32458a7 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -212,6 +212,18 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { self.fields.higher_ranked_sub(a, b, self.a_is_expected)?; Ok(a) } + + fn projection_equate_obligation( + &mut self, + projection_ty: ty::ProjectionTy<'tcx>, + ty: Ty<'tcx>, + ) { + self.fields.add_projection_equate_obligation(projection_ty, ty); + } + + fn defer_projection_equality(&self) -> bool { + self.fields.defer_projection_equality + } } impl<'tcx> ConstEquateRelation<'tcx> for Sub<'_, '_, 'tcx> { diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index e6aab30a150de..bc3de5f2be71d 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -121,4 +121,15 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { { Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) } + + fn projection_equate_obligation( + &mut self, + _projection_ty: ty::ProjectionTy<'tcx>, + _ty: Ty<'tcx>, + ) { + } + + fn defer_projection_equality(&self) -> bool { + true + } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 0d97d4acdfc78..a111bc4229339 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -5,7 +5,7 @@ //! subtyping, type equality, etc. use crate::ty::error::{ExpectedFound, TypeError}; -use crate::ty::{self, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use crate::ty::{GenericArg, GenericArgKind, SubstsRef}; use rustc_hir as ast; use rustc_hir::def_id::DefId; @@ -99,6 +99,10 @@ pub trait TypeRelation<'tcx>: Sized { ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>; + + fn projection_equate_obligation(&mut self, projection_ty: ty::ProjectionTy<'tcx>, ty: Ty<'tcx>); + + fn defer_projection_equality(&self) -> bool; } pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy { @@ -270,6 +274,7 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { a: ty::ProjectionTy<'tcx>, b: ty::ProjectionTy<'tcx>, ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> { + // FIXME(projection_equality) defer to `R::relate_tys()` to ensure lazyness if a.item_def_id != b.item_def_id { Err(TypeError::ProjectionMismatched(expected_found( relation, @@ -552,9 +557,24 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(tcx.mk_fn_ptr(fty)) } - // these two are already handled downstream in case of lazy normalization - (&ty::Projection(a_data), &ty::Projection(b_data)) => { - let projection_ty = relation.relate(a_data, b_data)?; + // FIXME(BoxyUwU): remove this opaque R projection arm + (ty::Projection(_), ty::Opaque(_, _)) | (ty::Opaque(_, _), ty::Projection(_)) => { + Err(TypeError::Sorts(expected_found(relation, a, b))) + } + (&ty::Projection(proj_a), _) + if proj_a.has_infer_types_or_consts() && relation.defer_projection_equality() => + { + relation.projection_equate_obligation(proj_a, b); + Ok(b) + } + (_, &ty::Projection(proj_b)) + if proj_b.has_infer_types_or_consts() && relation.defer_projection_equality() => + { + relation.projection_equate_obligation(proj_b, a); + Ok(a) + } + (&ty::Projection(proj_a), &ty::Projection(proj_b)) => { + let projection_ty = relation.relate(proj_a, proj_b)?; Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs)) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6f41cbeb7af2a..df37269deb3b6 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -29,6 +29,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::traits::select::OverflowError; +use rustc_middle::ty::error::ExpectedFound; +use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable}; use rustc_middle::ty::DefIdTree; @@ -255,6 +257,116 @@ fn project_and_unify_type<'cx, 'tcx>( }; debug!(?normalized, ?obligations, "project_and_unify_type result"); let actual = obligation.predicate.term; + + if let Some(ty) = normalized.ty() { + if let &ty::Projection(projection) = ty.kind() { + match opt_normalize_projection_type( + selcx, + obligation.param_env, + projection, + obligation.cause.clone(), + obligation.recursion_depth, + &mut obligations, + ) { + Ok(Some(_)) => (), + Ok(None) => { + debug!("failed normalization of: {:?}", projection); + return ProjectAndUnifyResult::FailedNormalization; + } + Err(InProgress) => unreachable!(), + } + + let actual = actual.ty().unwrap(); + let done = match actual.kind() { + &ty::Projection(other) => { + let flipped_projection_eq = InferOk { + obligations: vec![Obligation::new( + obligation.cause.clone(), + obligation.param_env, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: other, + term: ty::Term::from(ty), + }) + .to_predicate(selcx.tcx()), + )], + value: (), + }; + + match opt_normalize_projection_type( + selcx, + obligation.param_env, + other, + obligation.cause.clone(), + obligation.recursion_depth, + &mut obligations, + ) { + Ok(Some(normed_other)) => match normed_other.ty().unwrap().kind() { + &ty::Projection(normed_other) => { + match opt_normalize_projection_type( + selcx, + obligation.param_env, + normed_other, + obligation.cause.clone(), + obligation.recursion_depth, + &mut obligations, + ) { + Ok(Some(_)) => { + // For an example where this is neccessary see src/test/ui/impl-trait/nested-return-type2.rs + // This allows users to omit re-mentioning all bounds on an associated type and just use an + // `impl Trait` for the assoc type to add more bounds. + let InferOk { + value: s_opaque_infer_actual, + obligations: new, + } = selcx.infcx().replace_opaque_types_with_inference_vars( + actual, + obligation.cause.body_id, + obligation.cause.span, + obligation.param_env, + ); + obligations.extend(new); + + let s_opaque_infer_actual = + match s_opaque_infer_actual.kind() { + &ty::Projection(actual) => actual, + _ => unreachable!(), + }; + + infcx + .at(&obligation.cause, obligation.param_env) + .trace(ty, actual) + .eq(projection, s_opaque_infer_actual) + } + Ok(None) => Ok(flipped_projection_eq), + Err(InProgress) => unreachable!(), + } + } + ty::Infer(_) => { + infcx.at(&obligation.cause, obligation.param_env).eq(ty, actual) + } + _ => Err(TypeError::Sorts(ExpectedFound::new(false, ty, actual))), + }, + Ok(None) => Ok(flipped_projection_eq), + Err(InProgress) => return ProjectAndUnifyResult::Recursive, + } + } + ty::Infer(_) => infcx.at(&obligation.cause, obligation.param_env).eq(ty, actual), + _ => Err(TypeError::Sorts(ExpectedFound::new(false, ty, actual))), + }; + return match done { + Ok(InferOk { obligations: inferred_obligations, value: () }) => { + obligations.extend(inferred_obligations); + ProjectAndUnifyResult::Holds(obligations) + } + Err(err) => { + debug!("equating types encountered error {:?}", err); + ProjectAndUnifyResult::MismatchedProjectionTypes(MismatchedProjectionTypes { + err, + }) + } + }; + } + } + // For an example where this is neccessary see src/test/ui/impl-trait/nested-return-type2.rs // This allows users to omit re-mentioning all bounds on an associated type and just use an // `impl Trait` for the assoc type to add more bounds. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 451427a69807d..b7420d93627f4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -157,17 +157,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Winnow, but record the exact outcome of evaluation, which // is needed for specialization. Propagate overflow if it occurs. + let mut eval_cand = |c| match self.evaluate_candidate(stack, &c) { + Ok(eval) if eval.may_apply() => { + Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval })) + } + Ok(_) => Ok(None), + Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)), + Err(OverflowError::ErrorReporting) => Err(ErrorReporting), + Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))), + }; + + // this is very not perf and should be fixed xd + let drop_impl_candidates = candidates + .iter() + .filter(|c| matches!(c, SelectionCandidate::ParamCandidate(_))) + .cloned() + .map(&mut eval_cand) + .flat_map(Result::transpose) + .try_fold(false, |should_drop, param_candidate| { + let cand = ¶m_candidate?.candidate; + Ok::<_, SelectionError<'_>>( + should_drop || !(cand.is_global() && !cand.has_late_bound_regions()), + ) + })?; let mut candidates = candidates .into_iter() - .map(|c| match self.evaluate_candidate(stack, &c) { - Ok(eval) if eval.may_apply() => { - Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval })) - } - Ok(_) => Ok(None), - Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)), - Err(OverflowError::ErrorReporting) => Err(ErrorReporting), - Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))), - }) + .filter(|c| !matches!(c, SelectionCandidate::ImplCandidate(_) if drop_impl_candidates)) + .map(&mut eval_cand) .flat_map(Result::transpose) .collect::, _>>()?; diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index ab143c059820d..42594ccc92c83 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -326,4 +326,20 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> { Ok(a) } + + fn projection_equate_obligation( + &mut self, + _projection_ty: ty::ProjectionTy<'tcx>, + _ty: Ty<'tcx>, + ) { + bug!( + "`SimpleEqRelation` is only used for drop impl where clauses which shouldn't contain infer vars" + ); + } + + fn defer_projection_equality(&self) -> bool { + bug!( + "`SimpleEqRelation` is only used for drop impl where clauses which shouldn't contain infer vars" + ); + } } diff --git a/src/test/ui/associated-types/hr-associated-type-bound-object.stderr b/src/test/ui/associated-types/hr-associated-type-bound-object.stderr index 6d19186bde49a..45dd179860348 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-object.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-object.stderr @@ -12,6 +12,10 @@ LL | trait X<'a> LL | where LL | for<'b> >::U: Clone, | ^^^^^ required by this bound in `X` +help: consider further restricting the associated type + | +LL | fn f<'a, T: X<'a> + ?Sized>(x: &>::U) where for<'b> >::U: Clone { + | ++++++++++++++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-90318.rs b/src/test/ui/const-generics/issues/issue-90318.rs index d6c48e63bb3ce..049fe34837d28 100644 --- a/src/test/ui/const-generics/issues/issue-90318.rs +++ b/src/test/ui/const-generics/issues/issue-90318.rs @@ -12,14 +12,14 @@ impl True for If {} fn consume(_val: T) where If<{ TypeId::of::() != TypeId::of::<()>() }>: True, - //~^ ERROR: can't compare + //~^ ERROR: can't compare `TypeId` with `_` in const contexts { } fn test() where If<{ TypeId::of::() != TypeId::of::<()>() }>: True, - //~^ ERROR: can't compare + //~^ ERROR: can't compare `TypeId` with `_` in const contexts { } diff --git a/src/test/ui/error-codes/E0275.rs b/src/test/ui/error-codes/E0275.rs index 28a9676f03e39..9189960783b6b 100644 --- a/src/test/ui/error-codes/E0275.rs +++ b/src/test/ui/error-codes/E0275.rs @@ -2,7 +2,10 @@ trait Foo {} struct Bar(T); -impl Foo for T where Bar: Foo {} //~ ERROR E0275 +impl Foo for T where Bar: Foo {} + +fn takes_foo() {} fn main() { + takes_foo::<()>(); //~ ERROR E0275 } diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index 87cfaa489c6aa..e1be10b815c63 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -1,17 +1,22 @@ -error[E0275]: overflow evaluating the requirement `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` - --> $DIR/E0275.rs:5:33 +error[E0275]: overflow evaluating the requirement `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` + --> $DIR/E0275.rs:10:5 | -LL | impl Foo for T where Bar: Foo {} - | ^^^ +LL | takes_foo::<()>(); + | ^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) -note: required for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo` +note: required for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo` --> $DIR/E0275.rs:5:9 | LL | impl Foo for T where Bar: Foo {} | ^^^ ^ = note: 127 redundant requirements hidden - = note: required for `Bar` to implement `Foo` + = note: required for `()` to implement `Foo` +note: required by a bound in `takes_foo` + --> $DIR/E0275.rs:7:17 + | +LL | fn takes_foo() {} + | ^^^ required by this bound in `takes_foo` error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr index c5fd58096b7fd..8a584fec17961 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr @@ -1,22 +1,14 @@ -error[E0631]: type mismatch in function arguments - --> $DIR/issue-88382.rs:26:40 +error[E0282]: type annotations needed + --> $DIR/issue-88382.rs:28:40 | LL | do_something(SomeImplementation(), test); - | ------------ ^^^^ expected due to this - | | - | required by a bound introduced by this call -... -LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} - | ------------------------------------------------- found signature defined here + | ^^^^ cannot infer type of the type parameter `I` declared on the function `test` | - = note: expected function signature `for<'r> fn(&'r mut std::iter::Empty) -> _` - found function signature `for<'a, 'r> fn(&'r mut <_ as Iterable>::Iterator<'a>) -> _` -note: required by a bound in `do_something` - --> $DIR/issue-88382.rs:20:48 +help: consider specifying the generic argument | -LL | fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` +LL | do_something(SomeImplementation(), test::); + | +++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0631`. +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.rs b/src/test/ui/generic-associated-types/bugs/issue-88460.rs index 224e696ad2c9c..3d2b225f0cd01 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.rs @@ -1,7 +1,4 @@ -// check-fail -// known-bug: #88460 - -// This should pass, but has a missed normalization due to HRTB. +// check-pass pub trait Marker {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr deleted file mode 100644 index 6612c4b49446f..0000000000000 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied - --> $DIR/issue-88460.rs:28:10 - | -LL | test(Foo); - | ---- ^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` - | | - | required by a bound introduced by this call - | - = help: the trait `Marker` is implemented for `()` -note: required by a bound in `test` - --> $DIR/issue-88460.rs:15:27 - | -LL | fn test(value: T) - | ---- required by a bound in this -... -LL | for<'a> T::Assoc<'a>: Marker, - | ^^^^^^ required by this bound in `test` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-93340.rs b/src/test/ui/generic-associated-types/issue-93340.rs index 4662fda537b5f..d60e4e41175ab 100644 --- a/src/test/ui/generic-associated-types/issue-93340.rs +++ b/src/test/ui/generic-associated-types/issue-93340.rs @@ -10,9 +10,10 @@ fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefT todo!() } -fn build_expression( -) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { - cmp_eq +fn build_expression() +-> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { + // FIXME(BoxyUwU) + cmp_eq:: } fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-96230.rs b/src/test/ui/generic-associated-types/issue-96230.rs new file mode 100644 index 0000000000000..6f252ec7c7bd0 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-96230.rs @@ -0,0 +1,42 @@ +// check-pass +#![feature(generic_associated_types)] + +use std::fmt::Debug; + +trait Classic { + type Assoc; +} + +trait Gat { + type Assoc<'a>; +} + +struct Foo; + +impl Classic for Foo { + type Assoc = (); +} + +impl Gat for Foo { + type Assoc<'i> = (); +} + +fn classic_debug(_: T) +where + T::Assoc: Debug, +{ +} + +fn gat_debug(_: T) +where + for<'a> T::Assoc<'a>: Debug, +{ +} + +fn main() { + classic_debug::(Foo); + classic_debug(Foo); + + gat_debug::(Foo); + gat_debug(Foo); +} diff --git a/src/test/ui/higher-rank-trait-bounds/inference_var_doesnt_break_selection.rs b/src/test/ui/higher-rank-trait-bounds/inference_var_doesnt_break_selection.rs new file mode 100644 index 0000000000000..cd8e7a9c430c1 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/inference_var_doesnt_break_selection.rs @@ -0,0 +1,29 @@ +// check-pass +trait Foo {} +impl Foo for bool {} +impl Foo for (bool, bool) {} + +trait Bar<'a> { + type Assoc; +} +impl<'a> Bar<'a> for u8 { + type Assoc = bool; +} +impl<'a, T: Bar<'a>, U: Bar<'a>> Bar<'a> for (T, U) { + type Assoc = (T::Assoc, U::Assoc); +} + +fn calls() { + has_bound((1_u8, 1_u8)); +} + +fn has_bound(_: T) +where + for<'a> T: Bar<'a>, + for<'a> >::Assoc: Foo, +{ +} + +fn main() { + calls() +} diff --git a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs index e70f6fc3430f6..756f4d415b47e 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs +++ b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs @@ -37,8 +37,8 @@ trait Ty<'a> { fn main() { let v = Unit2.m( L { - //~^ ERROR to be a closure that returns `Unit3`, but it returns `Unit4` - //~| ERROR type mismatch + //~^ ERROR expected + //~^^ ERROR expected f: |x| { drop(x); Unit4 diff --git a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr index ab5598e364fc4..efb34a1dfc035 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` +error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]` to be a closure that returns `Unit3`, but it returns `Unit4` --> $DIR/issue-62203-hrtb-ice.rs:39:9 | LL | let v = Unit2.m( @@ -10,25 +10,21 @@ LL | | f: |x| { ... | LL | | }, LL | | }, - | |_________^ type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` + | |_________^ expected struct `Unit3`, found struct `Unit4` | -note: expected this to be `<_ as Ty<'_>>::V` - --> $DIR/issue-62203-hrtb-ice.rs:21:14 +note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>` to implement `for<'r> T0<'r, (&'r u8,)>` + --> $DIR/issue-62203-hrtb-ice.rs:17:16 | -LL | type O = T::Output; - | ^^^^^^^^^ - = note: expected associated type `<_ as Ty<'_>>::V` - found struct `Unit4` - = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` or calling a method that returns `<_ as Ty<'_>>::V` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +LL | impl<'a, A, T> T0<'a, A> for L + | ^^^^^^^^^ ^^^^ note: required by a bound in `T1::m` - --> $DIR/issue-62203-hrtb-ice.rs:27:51 + --> $DIR/issue-62203-hrtb-ice.rs:27:12 | LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 | - required by a bound in this LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]` to be a closure that returns `Unit3`, but it returns `Unit4` --> $DIR/issue-62203-hrtb-ice.rs:39:9 @@ -50,13 +46,13 @@ note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>` to i LL | impl<'a, A, T> T0<'a, A> for L | ^^^^^^^^^ ^^^^ note: required by a bound in `T1::m` - --> $DIR/issue-62203-hrtb-ice.rs:27:12 + --> $DIR/issue-62203-hrtb-ice.rs:27:51 | LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 | - required by a bound in this LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` error: aborting due to 2 previous errors 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 index d84e30f4984ea..827442585803b 100644 --- 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 @@ -23,7 +23,7 @@ impl WithDefault for () { //f(()); // Going through another generic function works fine. call(f, ()); - //~^ expected a + //~^ type annotations needed } } 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 index b30dd36d2ad6a..b754d528d7ed1 100644 --- 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 @@ -1,19 +1,14 @@ -error[E0277]: expected a `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F` - --> $DIR/issue-62529-3.rs:25:14 +error[E0282]: type annotations needed + --> $DIR/issue-62529-3.rs:25:9 | LL | call(f, ()); - | ---- ^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F` - | | - | required by a bound introduced by this call + | ^^^^ cannot infer type of the type parameter `T` declared on the function `call` | - = note: expected a closure with arguments `((),)` - found a closure with arguments `(<_ as ATC<'a>>::Type,)` -note: required by a bound in `call` - --> $DIR/issue-62529-3.rs:9:36 +help: consider specifying the generic arguments | -LL | fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(>::Type)>( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call` +LL | call::(f, ()); + | ++++++++ 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 E0282`. diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.rs b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs new file mode 100644 index 0000000000000..aaa6064d8d5a7 --- /dev/null +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs @@ -0,0 +1,50 @@ +trait T0<'a, A> { + type O; +} + +struct L { + f: T, +} + +// explicitly named variants of what one would normally denote by the +// unit type `()`. Why do this? So that we can differentiate them in +// the diagnostic output. +struct Unit1; +struct Unit2; +struct Unit3; +struct Unit4; + +impl<'a, A, T> T0<'a, A> for L +where + T: FnMut(A) -> Unit3, +{ + type O = T::Output; +} + +trait T1: for<'r> Ty<'r> { + fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 + where + F: for<'r> T0<'r, (>::V,), O = >::V>, + { + unimplemented!(); + } +} + +trait Ty<'a> { + type V; +} + +fn main() { + let v = Unit2.m( + L { + //~^ ERROR: expected + //~^^ ERROR: expected + f : |x| { drop(x); Unit4 } + }); +} + +impl<'a> Ty<'a> for Unit2 { + type V = &'a u8; +} + +impl T1 for Unit2 {} diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr new file mode 100644 index 0000000000000..9de85fb419ab2 --- /dev/null +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -0,0 +1,55 @@ +error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]` to be a closure that returns `Unit3`, but it returns `Unit4` + --> $DIR/issue-62203-hrtb-ice.rs:39:9 + | +LL | let v = Unit2.m( + | - required by a bound introduced by this call +LL | / L { +LL | | +LL | | +LL | | f : |x| { drop(x); Unit4 } +LL | | }); + | |_________^ expected struct `Unit3`, found struct `Unit4` + | +note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]>` to implement `for<'r> T0<'r, (&'r u8,)>` + --> $DIR/issue-62203-hrtb-ice.rs:17:16 + | +LL | impl<'a, A, T> T0<'a, A> for L + | ^^^^^^^^^ ^^^^ +note: required by a bound in `T1::m` + --> $DIR/issue-62203-hrtb-ice.rs:27:12 + | +LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 + | - required by a bound in this +LL | where +LL | F: for<'r> T0<'r, (>::V,), O = >::V>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` + +error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]` to be a closure that returns `Unit3`, but it returns `Unit4` + --> $DIR/issue-62203-hrtb-ice.rs:39:9 + | +LL | let v = Unit2.m( + | - required by a bound introduced by this call +LL | / L { +LL | | +LL | | +LL | | f : |x| { drop(x); Unit4 } +LL | | }); + | |_________^ expected struct `Unit3`, found struct `Unit4` + | +note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]>` to implement `for<'r> T0<'r, (&'r u8,)>` + --> $DIR/issue-62203-hrtb-ice.rs:17:16 + | +LL | impl<'a, A, T> T0<'a, A> for L + | ^^^^^^^^^ ^^^^ +note: required by a bound in `T1::m` + --> $DIR/issue-62203-hrtb-ice.rs:27:51 + | +LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 + | - required by a bound in this +LL | where +LL | F: for<'r> T0<'r, (>::V,), O = >::V>, + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/issues/issue-20413.rs b/src/test/ui/issues/issue-20413.rs index 138a235e675e3..33bcbcb4f3aea 100644 --- a/src/test/ui/issues/issue-20413.rs +++ b/src/test/ui/issues/issue-20413.rs @@ -6,7 +6,6 @@ struct NoData; //~^ ERROR: parameter `T` is never used impl Foo for T where NoData: Foo { - //~^ ERROR: overflow evaluating the requirement fn answer(self) { let val: NoData = NoData; } @@ -25,14 +24,12 @@ struct AlmostNoData(Option); struct EvenLessData(Option); impl Bar for T where EvenLessData: Baz { -//~^ ERROR: overflow evaluating the requirement fn answer(self) { let val: EvenLessData = EvenLessData(None); } } impl Baz for T where AlmostNoData: Bar { -//~^ ERROR: overflow evaluating the requirement fn answer(self) { let val: NoData = AlmostNoData(None); } diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 2db60b641eea5..3c0d47936ca88 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -7,62 +7,6 @@ LL | struct NoData; = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: usize` instead -error[E0275]: overflow evaluating the requirement `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` - --> $DIR/issue-20413.rs:8:36 - | -LL | impl Foo for T where NoData: Foo { - | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo` - --> $DIR/issue-20413.rs:8:9 - | -LL | impl Foo for T where NoData: Foo { - | ^^^ ^ - = note: 127 redundant requirements hidden - = note: required for `NoData` to implement `Foo` - -error[E0275]: overflow evaluating the requirement `EvenLessData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz` - --> $DIR/issue-20413.rs:27:42 - | -LL | impl Bar for T where EvenLessData: Baz { - | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `AlmostNoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Bar` - --> $DIR/issue-20413.rs:27:9 - | -LL | impl Bar for T where EvenLessData: Baz { - | ^^^ ^ -note: required for `EvenLessData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Baz` - --> $DIR/issue-20413.rs:34:9 - | -LL | impl Baz for T where AlmostNoData: Bar { - | ^^^ ^ - = note: 126 redundant requirements hidden - = note: required for `EvenLessData` to implement `Baz` - -error[E0275]: overflow evaluating the requirement `AlmostNoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar` - --> $DIR/issue-20413.rs:34:42 - | -LL | impl Baz for T where AlmostNoData: Bar { - | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `EvenLessData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Baz` - --> $DIR/issue-20413.rs:34:9 - | -LL | impl Baz for T where AlmostNoData: Bar { - | ^^^ ^ -note: required for `AlmostNoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Bar` - --> $DIR/issue-20413.rs:27:9 - | -LL | impl Bar for T where EvenLessData: Baz { - | ^^^ ^ - = note: 126 redundant requirements hidden - = note: required for `AlmostNoData` to implement `Bar` - -error: aborting due to 4 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0275, E0392. -For more information about an error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0392`.