about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-11-11 17:36:16 +0000
committerMichael Goulet <michael@errs.io>2022-11-22 01:36:41 +0000
commit94e047ba3bff6a789f51f89b2e6fd880102744ad (patch)
tree20a3a8ed54006265b2fff951324c3becdfb52f01
parent28a53cdb4695b71cb9ee39959df88542056479cd (diff)
downloadrust-94e047ba3bff6a789f51f89b2e6fd880102744ad.tar.gz
rust-94e047ba3bff6a789f51f89b2e6fd880102744ad.zip
Check generics parity between impl and trait before collecting RPITITs
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs14
-rw-r--r--src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs18
-rw-r--r--src/test/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr21
3 files changed, 50 insertions, 3 deletions
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<Span>,
 ) -> 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<T>() -> 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<T>() -> 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<T>() -> 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`.