Skip to content

Commit 7313c10

Browse files
committed
Show suggestion for <SelfTy as Trait>::assoc_fn in more cases and fmt code
1 parent 91b9ffe commit 7313c10

File tree

3 files changed

+53
-20
lines changed

3 files changed

+53
-20
lines changed

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::iter;
2727

2828
pub enum TypeAnnotationNeeded {
2929
/// ```compile_fail,E0282
30-
/// let x = "hello".chars().rev().collect();
30+
/// let x;
3131
/// ```
3232
E0282,
3333
/// An implementation cannot be chosen unambiguously because of lack of information.

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_errors::{
2525
MultiSpan, Style,
2626
};
2727
use rustc_hir as hir;
28-
use rustc_hir::def::Namespace;
28+
use rustc_hir::def::{DefKind, Namespace, Res};
2929
use rustc_hir::def_id::{DefId, LocalDefId};
3030
use rustc_hir::intravisit::Visitor;
3131
use rustc_hir::{GenericParam, Item, Node};
@@ -2453,12 +2453,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
24532453
&& let [
24542454
..,
24552455
trait_path_segment @ hir::PathSegment {
2456-
res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id),
2456+
res: Res::Def(DefKind::Trait, trait_id),
24572457
..
24582458
},
24592459
hir::PathSegment {
24602460
ident: assoc_item_name,
2461-
res: rustc_hir::def::Res::Def(_, item_id),
2461+
res: Res::Def(_, item_id),
24622462
..
24632463
}
24642464
] = path.segments
@@ -2469,45 +2469,68 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
24692469
let (verb, noun) = match self.tcx.associated_item(item_id).kind {
24702470
ty::AssocKind::Const => ("refer to the", "constant"),
24712471
ty::AssocKind::Fn => ("call", "function"),
2472-
ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here
2472+
// This is already covered by E0223, but this following single match
2473+
// arm doesn't hurt here.
2474+
ty::AssocKind::Type => ("refer to the", "type"),
24732475
};
24742476

24752477
// Replace the more general E0283 with a more specific error
24762478
err.cancel();
24772479
err = self.tcx.sess.struct_span_err_with_code(
24782480
span,
24792481
format!(
2480-
"cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type",
2482+
"cannot {verb} associated {noun} on trait without specifying the \
2483+
corresponding `impl` type",
24812484
),
24822485
rustc_errors::error_code!(E0790),
24832486
);
24842487

24852488
if let Some(local_def_id) = data.trait_ref.def_id.as_local()
2486-
&& let Some(hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. })) = self.tcx.hir().find_by_def_id(local_def_id)
2487-
&& let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) {
2488-
err.span_label(method_ref.span, format!("`{trait_name}::{assoc_item_name}` defined here"));
2489+
&& let Some(hir::Node::Item(hir::Item {
2490+
ident: trait_name,
2491+
kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs),
2492+
..
2493+
})) = self.tcx.hir().find_by_def_id(local_def_id)
2494+
&& let Some(method_ref) = trait_item_refs
2495+
.iter()
2496+
.find(|item_ref| item_ref.ident == *assoc_item_name)
2497+
{
2498+
err.span_label(
2499+
method_ref.span,
2500+
format!("`{trait_name}::{assoc_item_name}` defined here"),
2501+
);
24892502
}
24902503

24912504
err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
24922505

24932506
let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
24942507

2495-
if trait_impls.blanket_impls().is_empty()
2496-
&& let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
2508+
if let Some(impl_def_id) =
2509+
trait_impls.non_blanket_impls().values().flatten().next()
24972510
{
2498-
let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
2511+
let non_blanket_impl_count =
2512+
trait_impls.non_blanket_impls().values().flatten().count();
24992513
// If there is only one implementation of the trait, suggest using it.
25002514
// Otherwise, use a placeholder comment for the implementation.
2501-
let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
2502-
"use the fully-qualified path to the only available implementation",
2503-
format!("<{} as ", self.tcx.type_of(impl_def_id).instantiate_identity())
2504-
)} else {
2505-
("use a fully-qualified path to a specific available implementation",
2506-
"</* self type */ as ".to_string()
2507-
)};
2515+
let (message, self_type) = if non_blanket_impl_count == 1 {
2516+
(
2517+
"use the fully-qualified path to the only available \
2518+
implementation",
2519+
format!(
2520+
"{}",
2521+
self.tcx.type_of(impl_def_id).instantiate_identity()
2522+
),
2523+
)
2524+
} else {
2525+
(
2526+
"use a fully-qualified path to a specific available \
2527+
implementation",
2528+
"/* self type */".to_string(),
2529+
)
2530+
};
25082531
let mut suggestions = vec![(
25092532
path.span.shrink_to_lo(),
2510-
impl_suggestion
2533+
format!("<{self_type} as "),
25112534
)];
25122535
if let Some(generic_arg) = trait_path_segment.args {
25132536
let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);

tests/ui/impl-trait/cross-return-site-inference.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,22 @@ error[E0790]: cannot call associated function on trait without specifying the co
1414
|
1515
LL | return Err(From::from("foo"));
1616
| ^^^^^^^^^^ cannot call associated function of trait
17+
|
18+
help: use a fully-qualified path to a specific available implementation
19+
|
20+
LL | return Err(</* self type */ as From>::from("foo"));
21+
| +++++++++++++++++++ +
1722

1823
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
1924
--> $DIR/cross-return-site-inference.rs:44:9
2025
|
2126
LL | Err(From::from("foo"))
2227
| ^^^^^^^^^^ cannot call associated function of trait
28+
|
29+
help: use a fully-qualified path to a specific available implementation
30+
|
31+
LL | Err(</* self type */ as From>::from("foo"))
32+
| +++++++++++++++++++ +
2333

2434
error: aborting due to 3 previous errors
2535

0 commit comments

Comments
 (0)