1
Fork 0

Avoid guessing unknown trait impl in suggestions

When a trait is used without specifying the implementation (e.g. calling
a non-member associated function without fully-qualified syntax) and
there are multiple implementations available, use a placeholder comment
for the implementation type in the suggestion instead of picking a
random implementation.

Example:

```
fn main() {
    let _ = Default::default();
}
```

Previous output:

```
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
 --> test.rs:2:13
  |
2 |     let _ = Default::default();
  |             ^^^^^^^^^^^^^^^^ cannot call associated function of trait
  |
help: use a fully-qualified path to a specific available implementation (273 found)
  |
2 |     let _ = <FileTimes as Default>::default();
  |             +++++++++++++        +
```

New output:

```
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
 --> test.rs:2:13
  |
2 |     let _ = Default::default();
  |             ^^^^^^^^^^^^^^^^ cannot call associated function of trait
  |
help: use a fully-qualified path to a specific available implementation (273 found)
  |
2 |     let _ = </* self type */ as Default>::default();
  |             +++++++++++++++++++        +
```
This commit is contained in:
Alexander Zhang 2023-06-22 16:37:52 -07:00
parent 04075b3202
commit 48167bd4bd
3 changed files with 14 additions and 10 deletions

View file

@ -2382,17 +2382,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&& let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next() && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
{ {
let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count(); let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
let message = if non_blanket_impl_count == 1 { // If there is only one implementation of the trait, suggest using it.
"use the fully-qualified path to the only available implementation".to_string() // Otherwise, use a placeholder comment for the implementation.
} else { let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
"use the fully-qualified path to the only available implementation".to_string(),
format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity())
)} else {(
format!( format!(
"use a fully-qualified path to a specific available implementation ({} found)", "use a fully-qualified path to a specific available implementation ({} found)",
non_blanket_impl_count non_blanket_impl_count
) ),
}; "</* self type */ as ".to_string()
)};
let mut suggestions = vec![( let mut suggestions = vec![(
path.span.shrink_to_lo(), path.span.shrink_to_lo(),
format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity()) impl_suggestion
)]; )];
if let Some(generic_arg) = trait_path_segment.args { if let Some(generic_arg) = trait_path_segment.args {
let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext); let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);

View file

@ -9,8 +9,8 @@ LL | let cont: u32 = Generator::create();
| |
help: use a fully-qualified path to a specific available implementation (2 found) help: use a fully-qualified path to a specific available implementation (2 found)
| |
LL | let cont: u32 = <Impl as Generator>::create(); LL | let cont: u32 = </* self type */ as Generator>::create();
| ++++++++ + | +++++++++++++++++++ +
error[E0283]: type annotations needed error[E0283]: type annotations needed
--> $DIR/E0283.rs:35:24 --> $DIR/E0283.rs:35:24

View file

@ -65,8 +65,8 @@ LL | MyTrait2::my_fn();
| |
help: use a fully-qualified path to a specific available implementation (2 found) help: use a fully-qualified path to a specific available implementation (2 found)
| |
LL | <Impl1 as MyTrait2>::my_fn(); LL | </* self type */ as MyTrait2>::my_fn();
| +++++++++ + | +++++++++++++++++++ +
error: aborting due to 5 previous errors error: aborting due to 5 previous errors