Rollup merge of #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 #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
This commit is contained in:
commit
1d5cb17ebe
5 changed files with 60 additions and 4 deletions
|
@ -43,6 +43,8 @@ pub struct PathSeg(pub DefId, pub usize);
|
|||
pub trait AstConv<'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
|
||||
|
||||
fn item_def_id(&self) -> Option<DefId>;
|
||||
|
||||
/// Returns predicates in scope of the form `X: Foo`, where `X` is
|
||||
/// a type parameter `X` with the given id `def_id`. This is a
|
||||
/// subset of the full set of predicates.
|
||||
|
@ -1759,17 +1761,41 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
-> Ty<'tcx>
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
||||
let trait_def_id = tcx.parent(item_def_id).unwrap();
|
||||
|
||||
debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
|
||||
|
||||
self.prohibit_generics(slice::from_ref(item_segment));
|
||||
|
||||
let self_ty = if let Some(ty) = opt_self_ty {
|
||||
ty
|
||||
} else {
|
||||
let path_str = tcx.def_path_str(trait_def_id);
|
||||
|
||||
let def_id = self.item_def_id();
|
||||
|
||||
debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
|
||||
|
||||
let parent_def_id = def_id.and_then(|def_id| tcx.hir().as_local_hir_id(def_id))
|
||||
.map(|hir_id| tcx.hir().get_parent_did(hir_id));
|
||||
|
||||
debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
|
||||
|
||||
// If the trait in segment is the same as the trait defining the item,
|
||||
// use the `<Self as ..>` syntax in the error.
|
||||
let is_part_of_self_trait_constraints = def_id == Some(trait_def_id);
|
||||
let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
|
||||
|
||||
let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
|
||||
"Self"
|
||||
} else {
|
||||
"Type"
|
||||
};
|
||||
|
||||
self.report_ambiguous_associated_type(
|
||||
span,
|
||||
"Type",
|
||||
type_name,
|
||||
&path_str,
|
||||
item_segment.ident.name,
|
||||
);
|
||||
|
|
|
@ -2279,6 +2279,10 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
|||
self.tcx
|
||||
}
|
||||
|
||||
fn item_def_id(&self) -> Option<DefId> {
|
||||
None
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
|
||||
|
|
|
@ -182,6 +182,10 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
|
|||
self.tcx
|
||||
}
|
||||
|
||||
fn item_def_id(&self) -> Option<DefId> {
|
||||
Some(self.item_def_id)
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
|
||||
self.tcx
|
||||
.at(span)
|
||||
|
|
|
@ -10,6 +10,16 @@ trait Grab {
|
|||
type Value;
|
||||
fn grab(&self) -> Grab::Value;
|
||||
//~^ ERROR ambiguous associated type
|
||||
|
||||
fn get(&self) -> Get::Value;
|
||||
//~^ ERROR ambiguous associated type
|
||||
}
|
||||
|
||||
trait Bar {}
|
||||
|
||||
trait Foo where Foo::Assoc: Bar {
|
||||
//~^ ERROR ambiguous associated type
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
type X = std::ops::Deref::Target;
|
||||
|
|
|
@ -5,7 +5,13 @@ LL | fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
|
|||
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value`
|
||||
|
||||
error[E0223]: ambiguous associated type
|
||||
--> $DIR/associated-types-in-ambiguous-context.rs:15:10
|
||||
--> $DIR/associated-types-in-ambiguous-context.rs:20:17
|
||||
|
|
||||
LL | trait Foo where Foo::Assoc: Bar {
|
||||
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Foo>::Assoc`
|
||||
|
||||
error[E0223]: ambiguous associated type
|
||||
--> $DIR/associated-types-in-ambiguous-context.rs:25:10
|
||||
|
|
||||
LL | type X = std::ops::Deref::Target;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as std::ops::Deref>::Target`
|
||||
|
@ -14,8 +20,14 @@ error[E0223]: ambiguous associated type
|
|||
--> $DIR/associated-types-in-ambiguous-context.rs:11:23
|
||||
|
|
||||
LL | fn grab(&self) -> Grab::Value;
|
||||
| ^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Grab>::Value`
|
||||
| ^^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Grab>::Value`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0223]: ambiguous associated type
|
||||
--> $DIR/associated-types-in-ambiguous-context.rs:14:22
|
||||
|
|
||||
LL | fn get(&self) -> Get::Value;
|
||||
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0223`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue