Skip to content

Commit 28df997

Browse files
committed
Show suggestion for <SelfTy as Trait>::assoc_fn in more cases and fmt code
1 parent b309646 commit 28df997

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};
@@ -2369,12 +2369,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
23692369
&& let [
23702370
..,
23712371
trait_path_segment @ hir::PathSegment {
2372-
res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id),
2372+
res: Res::Def(DefKind::Trait, trait_id),
23732373
..
23742374
},
23752375
hir::PathSegment {
23762376
ident: assoc_item_name,
2377-
res: rustc_hir::def::Res::Def(_, item_id),
2377+
res: Res::Def(_, item_id),
23782378
..
23792379
}
23802380
] = path.segments
@@ -2385,45 +2385,68 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
23852385
let (verb, noun) = match self.tcx.associated_item(item_id).kind {
23862386
ty::AssocKind::Const => ("refer to the", "constant"),
23872387
ty::AssocKind::Fn => ("call", "function"),
2388-
ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here
2388+
// This is already covered by E0223, but this following single match
2389+
// arm doesn't hurt here.
2390+
ty::AssocKind::Type => ("refer to the", "type"),
23892391
};
23902392

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

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

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

24092422
let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
24102423

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