Skip to content

Commit 1d5cb17

Browse files
authored
Rollup merge of rust-lang#66042 - ohadravid:suggest-correct-code-when-ref-current-trait, r=estebank
Suggest correct code when encountering an incorrect trait bound referencing the current trait Fixes rust-lang#65985 and also improves the suggestion for code like this: ``` trait Grab { type Value; fn grab(&self) -> Grab::Value; } ``` To suggest `<Self as Grab>::Value`. I wasn't sure which of the syntax versions is better (`<Self as ..>::` vs `Self::`), so I used the former simply because it was less change to the existing code. r? @estebank
2 parents d32a262 + 8c90934 commit 1d5cb17

File tree

5 files changed

+60
-4
lines changed

5 files changed

+60
-4
lines changed

src/librustc_typeck/astconv.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ pub struct PathSeg(pub DefId, pub usize);
4343
pub trait AstConv<'tcx> {
4444
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
4545

46+
fn item_def_id(&self) -> Option<DefId>;
47+
4648
/// Returns predicates in scope of the form `X: Foo`, where `X` is
4749
/// a type parameter `X` with the given id `def_id`. This is a
4850
/// subset of the full set of predicates.
@@ -1759,17 +1761,41 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
17591761
-> Ty<'tcx>
17601762
{
17611763
let tcx = self.tcx();
1764+
17621765
let trait_def_id = tcx.parent(item_def_id).unwrap();
17631766

1767+
debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
1768+
17641769
self.prohibit_generics(slice::from_ref(item_segment));
17651770

17661771
let self_ty = if let Some(ty) = opt_self_ty {
17671772
ty
17681773
} else {
17691774
let path_str = tcx.def_path_str(trait_def_id);
1775+
1776+
let def_id = self.item_def_id();
1777+
1778+
debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
1779+
1780+
let parent_def_id = def_id.and_then(|def_id| tcx.hir().as_local_hir_id(def_id))
1781+
.map(|hir_id| tcx.hir().get_parent_did(hir_id));
1782+
1783+
debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
1784+
1785+
// If the trait in segment is the same as the trait defining the item,
1786+
// use the `<Self as ..>` syntax in the error.
1787+
let is_part_of_self_trait_constraints = def_id == Some(trait_def_id);
1788+
let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
1789+
1790+
let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
1791+
"Self"
1792+
} else {
1793+
"Type"
1794+
};
1795+
17701796
self.report_ambiguous_associated_type(
17711797
span,
1772-
"Type",
1798+
type_name,
17731799
&path_str,
17741800
item_segment.ident.name,
17751801
);

src/librustc_typeck/check/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2279,6 +2279,10 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
22792279
self.tcx
22802280
}
22812281

2282+
fn item_def_id(&self) -> Option<DefId> {
2283+
None
2284+
}
2285+
22822286
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
22832287
let tcx = self.tcx;
22842288
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();

src/librustc_typeck/collect.rs

+4
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
182182
self.tcx
183183
}
184184

185+
fn item_def_id(&self) -> Option<DefId> {
186+
Some(self.item_def_id)
187+
}
188+
185189
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
186190
self.tcx
187191
.at(span)

src/test/ui/associated-types/associated-types-in-ambiguous-context.rs

+10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ trait Grab {
1010
type Value;
1111
fn grab(&self) -> Grab::Value;
1212
//~^ ERROR ambiguous associated type
13+
14+
fn get(&self) -> Get::Value;
15+
//~^ ERROR ambiguous associated type
16+
}
17+
18+
trait Bar {}
19+
20+
trait Foo where Foo::Assoc: Bar {
21+
//~^ ERROR ambiguous associated type
22+
type Assoc;
1323
}
1424

1525
type X = std::ops::Deref::Target;

src/test/ui/associated-types/associated-types-in-ambiguous-context.stderr

+15-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ LL | fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
55
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value`
66

77
error[E0223]: ambiguous associated type
8-
--> $DIR/associated-types-in-ambiguous-context.rs:15:10
8+
--> $DIR/associated-types-in-ambiguous-context.rs:20:17
9+
|
10+
LL | trait Foo where Foo::Assoc: Bar {
11+
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Foo>::Assoc`
12+
13+
error[E0223]: ambiguous associated type
14+
--> $DIR/associated-types-in-ambiguous-context.rs:25:10
915
|
1016
LL | type X = std::ops::Deref::Target;
1117
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as std::ops::Deref>::Target`
@@ -14,8 +20,14 @@ error[E0223]: ambiguous associated type
1420
--> $DIR/associated-types-in-ambiguous-context.rs:11:23
1521
|
1622
LL | fn grab(&self) -> Grab::Value;
17-
| ^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Grab>::Value`
23+
| ^^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Grab>::Value`
24+
25+
error[E0223]: ambiguous associated type
26+
--> $DIR/associated-types-in-ambiguous-context.rs:14:22
27+
|
28+
LL | fn get(&self) -> Get::Value;
29+
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value`
1830

19-
error: aborting due to 3 previous errors
31+
error: aborting due to 5 previous errors
2032

2133
For more information about this error, try `rustc --explain E0223`.

0 commit comments

Comments
 (0)