From 4208c53ed695ddb822b6510e3faa0a46e591060e Mon Sep 17 00:00:00 2001 From: Ellen Date: Thu, 5 May 2022 12:41:43 +0100 Subject: [PATCH] exit out of `compare_number_of_generics` early --- .../rustc_typeck/src/check/compare_method.rs | 30 ++++++++++++++ .../mismatched_ty_const_in_trait_impl.rs | 4 +- .../mismatched_ty_const_in_trait_impl.stderr | 41 +++++++------------ .../const_params_have_right_type.rs | 2 +- .../const_params_have_right_type.stderr | 2 +- 5 files changed, 48 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index c42280a8208..c810be16bf8 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -579,6 +579,27 @@ fn compare_self_type<'tcx>( Ok(()) } +/// Checks that the number of generics on a given assoc item in a trait impl is the same +/// as the number of generics on the respective assoc item in the trait definition. +/// +/// For example this code emits the errors in the following code: +/// ``` +/// trait Trait { +/// fn foo(); +/// type Assoc; +/// } +/// +/// impl Trait for () { +/// fn foo() {} +/// //~^ error +/// type Assoc = u32; +/// //~^ error +/// } +/// ``` +/// +/// Notably this does not error on `foo` implemented as `foo` or +/// `foo` implemented as `foo`. This is handled in +/// [`compare_generic_param_kinds`]. This function also does not handle lifetime parameters fn compare_number_of_generics<'tcx>( tcx: TyCtxt<'tcx>, impl_: &ty::AssocItem, @@ -589,6 +610,15 @@ fn compare_number_of_generics<'tcx>( let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts(); let impl_own_counts = tcx.generics_of(impl_.def_id).own_counts(); + // This avoids us erroring on `foo` implemented as `foo` as this is implemented + // in `compare_generic_param_kinds` which will give a nicer error message than something like: + // "expected 1 type parameter, found 0 type parameters" + if (trait_own_counts.types + trait_own_counts.consts) + == (impl_own_counts.types + impl_own_counts.consts) + { + return Ok(()); + } + let matchings = [ ("type", trait_own_counts.types, impl_own_counts.types), ("const", trait_own_counts.consts, impl_own_counts.consts), diff --git a/src/test/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs b/src/test/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs index 0c6669fa9b6..fd57060d5e7 100644 --- a/src/test/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs +++ b/src/test/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs @@ -3,7 +3,7 @@ trait Trait { } impl Trait for () { fn foo() {} - //~^ error: method `foo` has an incompatble generic parameter for trait + //~^ error: method `foo` has an incompatible generic parameter for trait } trait Other { @@ -19,7 +19,7 @@ trait Uwu { } impl Uwu for () { fn baz() {} - //~^ error: method `baz` has an incompatible generic parameter for trait + //~^ error: method `baz` has an incompatible const parameter type for trait } fn main() {} diff --git a/src/test/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr b/src/test/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr index d400c216590..cea8f4e50b0 100644 --- a/src/test/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr +++ b/src/test/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr @@ -1,38 +1,26 @@ -error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter +error[E0053]: method `foo` has an incompatible generic parameter for trait --> $DIR/mismatched_ty_const_in_trait_impl.rs:5:12 | -LL | fn foo() {} - | - expected 1 type parameter -... LL | fn foo() {} - | ^^^^^^^^^^^^ found 0 type parameters - -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters - --> $DIR/mismatched_ty_const_in_trait_impl.rs:5:12 + | ^^^^^^^^^^^^ + | +note: the trait impl specifies `M` is a const parameter of type `u64`, but the declaration in trait `Trait::foo` requires it is a type parameter + --> $DIR/mismatched_ty_const_in_trait_impl.rs:2:12 | LL | fn foo() {} - | - expected 0 const parameters -... -LL | fn foo() {} - | ^^^^^^^^^^^^ found 1 const parameter + | ^ -error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters +error[E0053]: method `bar` has an incompatible generic parameter for trait --> $DIR/mismatched_ty_const_in_trait_impl.rs:13:12 | -LL | fn bar() {} - | ----------- expected 0 type parameters -... LL | fn bar() {} - | ^ found 1 type parameter - -error[E0049]: method `bar` has 0 const parameters but its trait declaration has 1 const parameter - --> $DIR/mismatched_ty_const_in_trait_impl.rs:13:12 + | ^ + | +note: the trait impl specifies `T` is a type parameter, but the declaration in trait `Other::bar` requires it is a const parameter of type `u8` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:10:12 | LL | fn bar() {} - | ----------- expected 1 const parameter -... -LL | fn bar() {} - | ^ found 0 const parameters + | ^^^^^^^^^^^ error[E0053]: method `baz` has an incompatible const parameter type for trait --> $DIR/mismatched_ty_const_in_trait_impl.rs:21:12 @@ -46,7 +34,6 @@ note: the const parameter `N` has type `i32`, but the declaration in trait `Uwu: LL | fn baz() {} | ^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0049, E0053. -For more information about an error, try `rustc --explain E0049`. +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/generic-associated-types/const_params_have_right_type.rs b/src/test/ui/generic-associated-types/const_params_have_right_type.rs index 675132587bf..138d332eed4 100644 --- a/src/test/ui/generic-associated-types/const_params_have_right_type.rs +++ b/src/test/ui/generic-associated-types/const_params_have_right_type.rs @@ -6,7 +6,7 @@ trait Trait { impl Trait for () { type Foo = u32; - //~^ error: associated type `Foo` has an incompatible const parameter type + //~^ error: type `Foo` has an incompatible const parameter type } fn main() {} diff --git a/src/test/ui/generic-associated-types/const_params_have_right_type.stderr b/src/test/ui/generic-associated-types/const_params_have_right_type.stderr index 62353180c67..4ec6c19f54b 100644 --- a/src/test/ui/generic-associated-types/const_params_have_right_type.stderr +++ b/src/test/ui/generic-associated-types/const_params_have_right_type.stderr @@ -1,4 +1,4 @@ -error[E0053]: associated type `Foo` has an incompatible const parameter type for trait +error[E0053]: type `Foo` has an incompatible const parameter type for trait --> $DIR/const_params_have_right_type.rs:8:14 | LL | type Foo = u32;