Skip to content

Commit

Permalink
Rollup merge of #109957 - fmease:fix-109905, r=petrochenkov
Browse files Browse the repository at this point in the history
diagnostics: account for self type when looking for source of unsolved type variable

Fixes #109905.

When searching for the source of an unsolved infer var inside of a list of generic args, we look through the `tcx.generics_of(…).own_substs(…)` which *skips* the self type if present. However, the computed `argument_index` is later[^1] used to index into `tcx.generics_of(…).params` which may still contain the self type. In such case, we are off by one when indexing into the parameters.

From now on, we account for this immediately after calling `own_substs` which keeps things local.

This also fixes the wrong output in the preexisting UI test `inference/need_type_info/concrete-impl.rs` which was overlooked. It used to claim that the *type of type parameter `Self`* couldn't be inferred in `<Struct as Ambiguous<_>>::method()` which of course isn't true: `Self` equals `Struct` here, `A` couldn't be inferred.

`@rustbot` label A-diagnostics

[^1]: https://github.com/rust-lang/rust/blob/f98a2718141593fbb8dbad10acc537786d748156/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs#L471
  • Loading branch information
matthiaskrgr authored Apr 6, 2023
2 parents b7e6973 + b904ce9 commit e63586f
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1191,11 +1191,14 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
have_turbofish,
} = args;
let generics = tcx.generics_of(generics_def_id);
if let Some(argument_index) = generics
if let Some(mut argument_index) = generics
.own_substs(substs)
.iter()
.position(|&arg| self.generic_arg_contains_target(arg))
{
if generics.parent.is_none() && generics.has_self {
argument_index += 1;
}
let substs = self.infcx.resolve_vars_if_possible(substs);
let generic_args = &generics.own_substs_no_defaults(tcx, substs)
[generics.own_counts().lifetimes..];
Expand Down
3 changes: 3 additions & 0 deletions tests/ui/inference/need_type_info/concrete-impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ struct Two;
struct Struct;

impl Ambiguous<One> for Struct {}
//~^ NOTE multiple `impl`s satisfying `Struct: Ambiguous<_>` found
impl Ambiguous<Two> for Struct {}

fn main() {
<Struct as Ambiguous<_>>::method();
//~^ ERROR type annotations needed
//~| NOTE cannot infer type of the type parameter `A`
//~| ERROR type annotations needed
//~| NOTE infer type of the type parameter `A`
}
9 changes: 5 additions & 4 deletions tests/ui/inference/need_type_info/concrete-impl.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
error[E0282]: type annotations needed
--> $DIR/concrete-impl.rs:13:5
--> $DIR/concrete-impl.rs:14:5
|
LL | <Struct as Ambiguous<_>>::method();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous`

error[E0283]: type annotations needed
--> $DIR/concrete-impl.rs:13:5
--> $DIR/concrete-impl.rs:14:5
|
LL | <Struct as Ambiguous<_>>::method();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous`
|
note: multiple `impl`s satisfying `Struct: Ambiguous<_>` found
--> $DIR/concrete-impl.rs:9:1
|
LL | impl Ambiguous<One> for Struct {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | impl Ambiguous<Two> for Struct {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
25 changes: 25 additions & 0 deletions tests/ui/inference/need_type_info/issue-109905.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Test that we show the correct type parameter that couldn't be inferred and that we don't
// end up stating nonsense like "type parameter `'a`" which we used to do.

trait Trait<'a, T> {
fn m(self);
}

impl<'a, A> Trait<'a, A> for () {
fn m(self) {}
}

fn qualified() {
<() as Trait<'static, _>>::m(());
//~^ ERROR type annotations needed
//~| NOTE cannot infer type of the type parameter `T`

}

fn unqualified() {
Trait::<'static, _>::m(());
//~^ ERROR type annotations needed
//~| NOTE cannot infer type of the type parameter `T`
}

fn main() {}
15 changes: 15 additions & 0 deletions tests/ui/inference/need_type_info/issue-109905.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0282]: type annotations needed
--> $DIR/issue-109905.rs:13:5
|
LL | <() as Trait<'static, _>>::m(());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait`

error[E0282]: type annotations needed
--> $DIR/issue-109905.rs:20:5
|
LL | Trait::<'static, _>::m(());
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0282`.

0 comments on commit e63586f

Please sign in to comment.