Skip to content

Commit 053c905

Browse files
committed
Show suggestion for <SelfTy as Trait>::assoc_fn in more cases and fmt code
1 parent acaad3c commit 053c905

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
@@ -23,7 +23,7 @@ use rustc_errors::{
2323
MultiSpan, Style,
2424
};
2525
use rustc_hir as hir;
26-
use rustc_hir::def::Namespace;
26+
use rustc_hir::def::{DefKind, Namespace, Res};
2727
use rustc_hir::def_id::{DefId, LocalDefId};
2828
use rustc_hir::intravisit::Visitor;
2929
use rustc_hir::{GenericParam, Item, Node};
@@ -2367,12 +2367,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
23672367
&& let [
23682368
..,
23692369
trait_path_segment @ hir::PathSegment {
2370-
res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id),
2370+
res: Res::Def(DefKind::Trait, trait_id),
23712371
..
23722372
},
23732373
hir::PathSegment {
23742374
ident: assoc_item_name,
2375-
res: rustc_hir::def::Res::Def(_, item_id),
2375+
res: Res::Def(_, item_id),
23762376
..
23772377
}
23782378
] = path.segments
@@ -2383,45 +2383,68 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
23832383
let (verb, noun) = match self.tcx.associated_item(item_id).kind {
23842384
ty::AssocKind::Const => ("refer to the", "constant"),
23852385
ty::AssocKind::Fn => ("call", "function"),
2386-
ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here
2386+
// This is already covered by E0223, but this following single match
2387+
// arm doesn't hurt here.
2388+
ty::AssocKind::Type => ("refer to the", "type"),
23872389
};
23882390

23892391
// Replace the more general E0283 with a more specific error
23902392
err.cancel();
23912393
err = self.tcx.sess.struct_span_err_with_code(
23922394
span,
23932395
format!(
2394-
"cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type",
2396+
"cannot {verb} associated {noun} on trait without specifying the \
2397+
corresponding `impl` type",
23952398
),
23962399
rustc_errors::error_code!(E0790),
23972400
);
23982401

23992402
if let Some(local_def_id) = data.trait_ref.def_id.as_local()
2400-
&& 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)
2401-
&& let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) {
2402-
err.span_label(method_ref.span, format!("`{trait_name}::{assoc_item_name}` defined here"));
2403+
&& let Some(hir::Node::Item(hir::Item {
2404+
ident: trait_name,
2405+
kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs),
2406+
..
2407+
})) = self.tcx.hir().find_by_def_id(local_def_id)
2408+
&& let Some(method_ref) = trait_item_refs
2409+
.iter()
2410+
.find(|item_ref| item_ref.ident == *assoc_item_name)
2411+
{
2412+
err.span_label(
2413+
method_ref.span,
2414+
format!("`{trait_name}::{assoc_item_name}` defined here"),
2415+
);
24032416
}
24042417

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

24072420
let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
24082421

2409-
if trait_impls.blanket_impls().is_empty()
2410-
&& let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
2422+
if let Some(impl_def_id) =
2423+
trait_impls.non_blanket_impls().values().flatten().next()
24112424
{
2412-
let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
2425+
let non_blanket_impl_count =
2426+
trait_impls.non_blanket_impls().values().flatten().count();
24132427
// If there is only one implementation of the trait, suggest using it.
24142428
// Otherwise, use a placeholder comment for the implementation.
2415-
let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
2416-
"use the fully-qualified path to the only available implementation",
2417-
format!("<{} as ", self.tcx.type_of(impl_def_id).instantiate_identity())
2418-
)} else {
2419-
("use a fully-qualified path to a specific available implementation",
2420-
"</* self type */ as ".to_string()
2421-
)};
2429+
let (message, self_type) = if non_blanket_impl_count == 1 {
2430+
(
2431+
"use the fully-qualified path to the only available \
2432+
implementation",
2433+
format!(
2434+
"{}",
2435+
self.tcx.type_of(impl_def_id).instantiate_identity()
2436+
),
2437+
)
2438+
} else {
2439+
(
2440+
"use a fully-qualified path to a specific available \
2441+
implementation",
2442+
"/* self type */".to_string(),
2443+
)
2444+
};
24222445
let mut suggestions = vec![(
24232446
path.span.shrink_to_lo(),
2424-
impl_suggestion
2447+
format!("<{self_type} as "),
24252448
)];
24262449
if let Some(generic_arg) = trait_path_segment.args {
24272450
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)