Rollup merge of #128527 - estebank:ambiguity-suggestion, r=Nadrieril

More information for fully-qualified suggestion when there are multiple impls

```
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
  --> $DIR/E0283.rs:30:21
   |
LL |     fn create() -> u32;
   |     ------------------- `Coroutine::create` defined here
...
LL |     let cont: u32 = Coroutine::create();
   |                     ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
   |
help: use a fully-qualified path to a specific available implementation
   |
LL |     let cont: u32 = <Impl as Coroutine>::create();
   |                     ++++++++          +
LL |     let cont: u32 = <AnotherImpl as Coroutine>::create();
   |                     +++++++++++++++          +
```
This commit is contained in:
Guillaume Gomez 2024-08-07 15:59:36 +02:00 committed by GitHub
commit 493233ce29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 27 deletions

View File

@ -388,39 +388,67 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
trait_impls.non_blanket_impls().values().flatten().count(); trait_impls.non_blanket_impls().values().flatten().count();
// If there is only one implementation of the trait, suggest using it. // If there is only one implementation of the trait, suggest using it.
// Otherwise, use a placeholder comment for the implementation. // Otherwise, use a placeholder comment for the implementation.
let (message, self_type) = if non_blanket_impl_count == 1 { let (message, self_types) = if non_blanket_impl_count == 1 {
( (
"use the fully-qualified path to the only available \ "use the fully-qualified path to the only available \
implementation", implementation",
format!( vec![format!(
"{}", "{}",
self.tcx.type_of(impl_def_id).instantiate_identity() self.tcx.type_of(impl_def_id).instantiate_identity()
), )],
)
} else if non_blanket_impl_count < 20 {
(
"use a fully-qualified path to one of the available \
implementations",
trait_impls
.non_blanket_impls()
.values()
.flatten()
.map(|id| {
format!(
"{}",
self.tcx.type_of(id).instantiate_identity()
)
})
.collect::<Vec<String>>(),
) )
} else { } else {
( (
"use a fully-qualified path to a specific available \ "use a fully-qualified path to a specific available \
implementation", implementation",
"/* self type */".to_string(), vec!["/* self type */".to_string()],
) )
}; };
let mut suggestions = let suggestions: Vec<_> = self_types
vec![(path.span.shrink_to_lo(), format!("<{self_type} as "))]; .into_iter()
.map(|self_type| {
let mut suggestions = vec![(
path.span.shrink_to_lo(),
format!("<{self_type} as "),
)];
if let Some(generic_arg) = trait_path_segment.args { if let Some(generic_arg) = trait_path_segment.args {
let between_span = let between_span = trait_path_segment
trait_path_segment.ident.span.between(generic_arg.span_ext); .ident
.span
.between(generic_arg.span_ext);
// get rid of :: between Trait and <type> // get rid of :: between Trait and <type>
// must be '::' between them, otherwise the parser won't accept the code // must be '::' between them, otherwise the parser won't accept the code
suggestions.push((between_span, "".to_string())); suggestions.push((between_span, "".to_string()));
suggestions suggestions.push((
.push((generic_arg.span_ext.shrink_to_hi(), ">".to_string())); generic_arg.span_ext.shrink_to_hi(),
">".to_string(),
));
} else { } else {
suggestions.push(( suggestions.push((
trait_path_segment.ident.span.shrink_to_hi(), trait_path_segment.ident.span.shrink_to_hi(),
">".to_string(), ">".to_string(),
)); ));
} }
err.multipart_suggestion( suggestions
})
.collect();
err.multipart_suggestions(
message, message,
suggestions, suggestions,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,

View File

@ -7,10 +7,12 @@ LL | fn create() -> u32;
LL | let cont: u32 = Coroutine::create(); LL | let cont: u32 = Coroutine::create();
| ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
| |
help: use a fully-qualified path to a specific available implementation help: use a fully-qualified path to one of the available implementations
| |
LL | let cont: u32 = </* self type */ as Coroutine>::create(); LL | let cont: u32 = <Impl as Coroutine>::create();
| +++++++++++++++++++ + | ++++++++ +
LL | let cont: u32 = <AnotherImpl as Coroutine>::create();
| +++++++++++++++ +
error[E0283]: type annotations needed error[E0283]: type annotations needed
--> $DIR/E0283.rs:35:24 --> $DIR/E0283.rs:35:24

View File

@ -63,10 +63,12 @@ LL | fn my_fn();
LL | MyTrait2::my_fn(); LL | MyTrait2::my_fn();
| ^^^^^^^^^^^^^^^^^ cannot call associated function of trait | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
| |
help: use a fully-qualified path to a specific available implementation help: use a fully-qualified path to one of the available implementations
| |
LL | </* self type */ as MyTrait2>::my_fn(); LL | <Impl1 as MyTrait2>::my_fn();
| +++++++++++++++++++ + | +++++++++ +
LL | <Impl2 as MyTrait2>::my_fn();
| +++++++++ +
error: aborting due to 5 previous errors error: aborting due to 5 previous errors