From 94e047ba3bff6a789f51f89b2e6fd880102744ad Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 11 Nov 2022 17:36:16 +0000 Subject: [PATCH] Check generics parity between impl and trait before collecting RPITITs --- .../src/check/compare_method.rs | 14 ++++++++++--- .../in-trait/trait-more-generics-than-impl.rs | 18 ++++++++++++++++ .../trait-more-generics-than-impl.stderr | 21 +++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs create mode 100644 src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index e68df228c6b..110ecd2f56b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -51,7 +51,7 @@ pub(crate) fn compare_impl_method<'tcx>( return; } - if let Err(_) = compare_number_of_generics(tcx, impl_m, impl_m_span, trait_m, trait_item_span) { + if let Err(_) = compare_number_of_generics(tcx, impl_m, trait_m, trait_item_span) { return; } @@ -352,6 +352,10 @@ pub fn collect_trait_impl_trait_tys<'tcx>( let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap(); let param_env = tcx.param_env(def_id); + // First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later. + compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id))?; + compare_generic_param_kinds(tcx, impl_m, trait_m)?; + let trait_to_impl_substs = impl_trait_ref.substs; let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); @@ -376,6 +380,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( let infcx = &tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(infcx); + // Normalize the impl signature with fresh variables for lifetime inference. let norm_cause = ObligationCause::misc(return_span, impl_m_hir_id); let impl_sig = ocx.normalize( norm_cause.clone(), @@ -388,6 +393,10 @@ pub fn collect_trait_impl_trait_tys<'tcx>( ); let impl_return_ty = impl_sig.output(); + // Normalize the trait signature with liberated bound vars, passing it through + // the ImplTraitInTraitCollector, which gathers all of the RPITITs and replaces + // them with inference variables. + // We will use these inference variables to collect the hidden types of RPITITs. let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id); let unnormalized_trait_sig = tcx .liberate_late_bound_regions( @@ -922,7 +931,6 @@ fn compare_self_type<'tcx>( fn compare_number_of_generics<'tcx>( tcx: TyCtxt<'tcx>, impl_: &ty::AssocItem, - _impl_span: Span, trait_: &ty::AssocItem, trait_span: Option, ) -> Result<(), ErrorGuaranteed> { @@ -1489,7 +1497,7 @@ pub(crate) fn compare_ty_impl<'tcx>( debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref); let _: Result<(), ErrorGuaranteed> = (|| { - compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?; + compare_number_of_generics(tcx, impl_ty, trait_ty, trait_item_span)?; compare_generic_param_kinds(tcx, impl_ty, trait_ty)?; diff --git a/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs b/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs new file mode 100644 index 00000000000..608006203d9 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs @@ -0,0 +1,18 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct S; + +trait Foo { + fn bar() -> impl Sized; +} + +impl Foo for S { + fn bar() -> impl Sized {} + //~^ ERROR method `bar` has 0 type parameters but its trait declaration has 1 type parameter + //~| ERROR method `bar` has 0 type parameters but its trait declaration has 1 type parameter +} + +fn main() { + S::bar(); +} diff --git a/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr b/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr new file mode 100644 index 00000000000..acde1f7654b --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr @@ -0,0 +1,21 @@ +error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/trait-more-generics-than-impl.rs:11:11 + | +LL | fn bar() -> impl Sized; + | - expected 1 type parameter +... +LL | fn bar() -> impl Sized {} + | ^ found 0 type parameters + +error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/trait-more-generics-than-impl.rs:11:11 + | +LL | fn bar() -> impl Sized; + | - expected 1 type parameter +... +LL | fn bar() -> impl Sized {} + | ^ found 0 type parameters + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0049`.