Skip to content

Commit

Permalink
Suggest correct code when encountering an incorrect trait bound refer…
Browse files Browse the repository at this point in the history
…encing the current trait
  • Loading branch information
ohadravid committed Nov 2, 2019
1 parent 87cbf0a commit 5558fe8
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 3 deletions.
18 changes: 17 additions & 1 deletion src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -1759,17 +1761,31 @@ 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);

// If the trait in segment is the same as the trait defining the item,
// use the `<Self as ..>` syntax in the error.
debug!("qpath_to_ty: self.item_def_id()={:?}", self.item_def_id());

let type_name = if self.item_def_id() == Some(trait_def_id) {
"Self"
} else {
"Type"
};

self.report_ambiguous_associated_type(
span,
"Type",
type_name,
&path_str,
item_segment.ident.name,
);
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ trait Grab {
//~^ ERROR ambiguous associated type
}

trait Bar {}

trait Foo where Foo::Assoc: Bar {
//~^ ERROR ambiguous associated type
type Assoc;
}

type X = std::ops::Deref::Target;
//~^ ERROR ambiguous associated type

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:17: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:22:10
|
LL | type X = std::ops::Deref::Target;
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as std::ops::Deref>::Target`
Expand All @@ -16,6 +22,6 @@ error[E0223]: ambiguous associated type
LL | fn grab(&self) -> Grab::Value;
| ^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Grab>::Value`

error: aborting due to 3 previous errors
error: aborting due to 4 previous errors

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

0 comments on commit 5558fe8

Please sign in to comment.