Skip to content

Generic associated consts: Check regions earlier when comparing impl with trait item def #123898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1723,6 +1723,7 @@ pub(super) fn compare_impl_const_raw(

compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
}

Expand Down Expand Up @@ -1763,8 +1764,6 @@ fn compare_const_predicate_entailment<'tcx>(
let impl_ct_predicates = tcx.predicates_of(impl_ct.def_id);
let trait_ct_predicates = tcx.predicates_of(trait_ct.def_id);

check_region_bounds_on_impl_item(tcx, impl_ct, trait_ct, false)?;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On lifetime param mismatches, we ICE'd in tcx.type_of(trait_ct.def_id).instantiate(tcx, trait_to_impl_args) a few lines further up for obvious reasons. That's on me, I messed that up in the initial GCI PR.


// The predicates declared by the impl definition, the trait and the
// associated const in the trait are assumed.
let impl_predicates = tcx.predicates_of(impl_ct_predicates.parent.unwrap());
Expand Down Expand Up @@ -1866,6 +1865,7 @@ pub(super) fn compare_impl_ty<'tcx>(
let _: Result<(), ErrorGuaranteed> = try {
compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?;
};
Expand All @@ -1886,8 +1886,6 @@ fn compare_type_predicate_entailment<'tcx>(
let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);

check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was no need to move this one out of compare_type_predicate_entailment except consistency with both compare_{method,const}_predicate_entailment which is reason enough imo.


let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_args);
if impl_ty_own_bounds.len() == 0 {
// Nothing to check.
Expand Down
11 changes: 7 additions & 4 deletions tests/ui/generic-const-items/compare-impl-item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ trait Trait<P> {
const B<const K: u64, const Q: u64>: u64;
const C<T>: T;
const D<const N: usize>: usize;
const E<'a>: &'a ();

const E: usize;
const F<T: PartialEq>: ();
const F: usize;
const G<T: PartialEq>: ();
}

impl<P> Trait<P> for () {
Expand All @@ -20,11 +21,13 @@ impl<P> Trait<P> for () {
//~^ ERROR const `C` has 0 type parameters but its trait declaration has 1 type parameter
const D<const N: u16>: u16 = N;
//~^ ERROR const `D` has an incompatible generic parameter for trait `Trait`
const E: &'static () = &();
//~^ ERROR lifetime parameters or bounds on const `E` do not match the trait declaration

const E: usize = 1024
const F: usize = 1024
where
P: Copy; //~ ERROR impl has stricter requirements than trait
const F<T: Eq>: () = (); //~ ERROR impl has stricter requirements than trait
const G<T: Eq>: () = (); //~ ERROR impl has stricter requirements than trait
}

fn main() {}
35 changes: 22 additions & 13 deletions tests/ui/generic-const-items/compare-impl-item.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0049]: const `A` has 1 type parameter but its trait declaration has 0 type parameters
--> $DIR/compare-impl-item.rs:15:13
--> $DIR/compare-impl-item.rs:16:13
|
LL | const A: ();
| - expected 0 type parameters
Expand All @@ -8,7 +8,7 @@ LL | const A<T>: () = ();
| ^ found 1 type parameter

error[E0049]: const `B` has 1 const parameter but its trait declaration has 2 const parameters
--> $DIR/compare-impl-item.rs:17:13
--> $DIR/compare-impl-item.rs:18:13
|
LL | const B<const K: u64, const Q: u64>: u64;
| ------------ ------------
Expand All @@ -19,7 +19,7 @@ LL | const B<const K: u64>: u64 = 0;
| ^^^^^^^^^^^^ found 1 const parameter

error[E0049]: const `C` has 0 type parameters but its trait declaration has 1 type parameter
--> $DIR/compare-impl-item.rs:19:13
--> $DIR/compare-impl-item.rs:20:13
|
LL | const C<T>: T;
| - expected 1 type parameter
Expand All @@ -28,7 +28,7 @@ LL | const C<'a>: &'a str = "";
| ^^ found 0 type parameters

error[E0053]: const `D` has an incompatible generic parameter for trait `Trait`
--> $DIR/compare-impl-item.rs:21:13
--> $DIR/compare-impl-item.rs:22:13
|
LL | trait Trait<P> {
| -----
Expand All @@ -42,25 +42,34 @@ LL | impl<P> Trait<P> for () {
LL | const D<const N: u16>: u16 = N;
| ^^^^^^^^^^^^ found const parameter of type `u16`

error[E0195]: lifetime parameters or bounds on const `E` do not match the trait declaration
--> $DIR/compare-impl-item.rs:24:12
|
LL | const E<'a>: &'a ();
| ---- lifetimes in impl do not match this const in trait
...
LL | const E: &'static () = &();
| ^ lifetimes do not match const in trait

error[E0276]: impl has stricter requirements than trait
--> $DIR/compare-impl-item.rs:26:12
--> $DIR/compare-impl-item.rs:29:12
|
LL | const E: usize;
| -------------- definition of `E` from trait
LL | const F: usize;
| -------------- definition of `F` from trait
...
LL | P: Copy;
| ^^^^ impl has extra requirement `P: Copy`

error[E0276]: impl has stricter requirements than trait
--> $DIR/compare-impl-item.rs:27:16
--> $DIR/compare-impl-item.rs:30:16
|
LL | const F<T: PartialEq>: ();
| ------------------------- definition of `F` from trait
LL | const G<T: PartialEq>: ();
| ------------------------- definition of `G` from trait
...
LL | const F<T: Eq>: () = ();
LL | const G<T: Eq>: () = ();
| ^^ impl has extra requirement `T: Eq`

error: aborting due to 6 previous errors
error: aborting due to 7 previous errors

Some errors have detailed explanations: E0049, E0053, E0276.
Some errors have detailed explanations: E0049, E0053, E0195, E0276.
For more information about an error, try `rustc --explain E0049`.
Loading