Rollup merge of #128377 - veera-sivarajan:fix-128249, r=davidtwco

Fix ICE Caused by Incorrectly Delaying E0107

Fixes  #128249

For the following code:
```rust
trait Foo<T> {}
impl Foo<T: Default> for u8 {}
```
#126054 added some logic to delay emitting E0107 as the names of associated type `T` in the impl header and generic parameter `T` in `trait Foo` match.

But it failed to ensure whether such unexpected associated type bounds are coming from a impl block header. This caused an ICE as the compiler was delaying E0107 for code like:
```rust
trait Trait<Type> {
    type Type;

    fn method(&self) -> impl Trait<Type: '_>;
}
```
because it assumed the associated type bound `Type: '_` is for the generic parameter `Type` in `trait Trait` since the names are same.

This PR adds a check to ensure that E0107 is delayed only in the context of impl block header.
This commit is contained in:
Matthias Krüger 2024-08-06 20:23:39 +02:00 committed by GitHub
commit 333c63b9fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 98 additions and 14 deletions

View File

@ -3700,6 +3700,11 @@ pub fn def_id(self) -> OwnerId {
}
}
/// Check if node is an impl block.
pub fn is_impl_block(&self) -> bool {
matches!(self, OwnerNode::Item(Item { kind: ItemKind::Impl(_), .. }))
}
expect_methods_self! {
expect_item, &'hir Item<'hir>, OwnerNode::Item(n), n;
expect_foreign_item, &'hir ForeignItem<'hir>, OwnerNode::ForeignItem(n), n;

View File

@ -552,21 +552,34 @@ pub(crate) fn check_generic_arg_count(
synth_provided,
}
} else {
let num_missing_args = expected_max - provided;
// Check if associated type bounds are incorrectly written in impl block header like:
// ```
// trait Foo<T> {}
// impl Foo<T: Default> for u8 {}
// ```
let parent_is_impl_block = cx
.tcx()
.hir()
.parent_owner_iter(seg.hir_id)
.next()
.is_some_and(|(_, owner_node)| owner_node.is_impl_block());
if parent_is_impl_block {
let constraint_names: Vec<_> =
gen_args.constraints.iter().map(|b| b.ident.name).collect();
let param_names: Vec<_> = gen_params
.own_params
.iter()
.filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
.map(|param| param.name)
.collect();
if constraint_names == param_names {
// We set this to true and delay emitting `WrongNumberOfGenericArgs`
// to provide a succinct error for cases like issue #113073
all_params_are_binded = true;
};
}
let constraint_names: Vec<_> =
gen_args.constraints.iter().map(|b| b.ident.name).collect();
let param_names: Vec<_> = gen_params
.own_params
.iter()
.filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
.map(|param| param.name)
.collect();
if constraint_names == param_names {
// We set this to true and delay emitting `WrongNumberOfGenericArgs`
// to provide a succinct error for cases like issue #113073
all_params_are_binded = true;
};
let num_missing_args = expected_max - provided;
GenericArgsInfo::MissingTypesOrConsts {
num_missing_args,

View File

@ -0,0 +1,15 @@
trait Trait<Type> {
type Type;
fn one(&self, val: impl Trait<Type: Default>);
//~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
fn two<T: Trait<Type: Default>>(&self) -> T;
//~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
fn three<T>(&self) -> T where
T: Trait<Type: Default>,;
//~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
}
fn main() {}

View File

@ -0,0 +1,51 @@
error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/name-same-as-generic-type-issue-128249.rs:4:30
|
LL | fn one(&self, val: impl Trait<Type: Default>);
| ^^^^^ expected 1 generic argument
|
note: trait defined here, with 1 generic parameter: `Type`
--> $DIR/name-same-as-generic-type-issue-128249.rs:1:7
|
LL | trait Trait<Type> {
| ^^^^^ ----
help: add missing generic argument
|
LL | fn one(&self, val: impl Trait<Type, Type: Default>);
| +++++
error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/name-same-as-generic-type-issue-128249.rs:7:15
|
LL | fn two<T: Trait<Type: Default>>(&self) -> T;
| ^^^^^ expected 1 generic argument
|
note: trait defined here, with 1 generic parameter: `Type`
--> $DIR/name-same-as-generic-type-issue-128249.rs:1:7
|
LL | trait Trait<Type> {
| ^^^^^ ----
help: add missing generic argument
|
LL | fn two<T: Trait<Type, Type: Default>>(&self) -> T;
| +++++
error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/name-same-as-generic-type-issue-128249.rs:11:12
|
LL | T: Trait<Type: Default>,;
| ^^^^^ expected 1 generic argument
|
note: trait defined here, with 1 generic parameter: `Type`
--> $DIR/name-same-as-generic-type-issue-128249.rs:1:7
|
LL | trait Trait<Type> {
| ^^^^^ ----
help: add missing generic argument
|
LL | T: Trait<Type, Type: Default>,;
| +++++
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0107`.