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:
commit
493233ce29
@ -388,39 +388,67 @@ pub(super) fn maybe_report_ambiguity(
|
|||||||
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()
|
||||||
if let Some(generic_arg) = trait_path_segment.args {
|
.map(|self_type| {
|
||||||
let between_span =
|
let mut suggestions = vec![(
|
||||||
trait_path_segment.ident.span.between(generic_arg.span_ext);
|
path.span.shrink_to_lo(),
|
||||||
// get rid of :: between Trait and <type>
|
format!("<{self_type} as "),
|
||||||
// must be '::' between them, otherwise the parser won't accept the code
|
)];
|
||||||
suggestions.push((between_span, "".to_string()));
|
if let Some(generic_arg) = trait_path_segment.args {
|
||||||
suggestions
|
let between_span = trait_path_segment
|
||||||
.push((generic_arg.span_ext.shrink_to_hi(), ">".to_string()));
|
.ident
|
||||||
} else {
|
.span
|
||||||
suggestions.push((
|
.between(generic_arg.span_ext);
|
||||||
trait_path_segment.ident.span.shrink_to_hi(),
|
// get rid of :: between Trait and <type>
|
||||||
">".to_string(),
|
// must be '::' between them, otherwise the parser won't accept the code
|
||||||
));
|
suggestions.push((between_span, "".to_string()));
|
||||||
}
|
suggestions.push((
|
||||||
err.multipart_suggestion(
|
generic_arg.span_ext.shrink_to_hi(),
|
||||||
|
">".to_string(),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
suggestions.push((
|
||||||
|
trait_path_segment.ident.span.shrink_to_hi(),
|
||||||
|
">".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
suggestions
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
err.multipart_suggestions(
|
||||||
message,
|
message,
|
||||||
suggestions,
|
suggestions,
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user