about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOhad Ravid <ohad.rv@gmail.com>2019-11-01 13:50:36 +0100
committerOhad Ravid <ohad.rv@gmail.com>2019-11-02 10:26:17 +0100
commit5558fe8a9207b000b1cab9f3d521b06b144d6f8f (patch)
tree77fdc8f2c0fb4cfa8d7aa24baab877c32b8ee8bd
parent87cbf0a547aaf9e8a7fc708851ecf4bc2adab5fd (diff)
downloadrust-5558fe8a9207b000b1cab9f3d521b06b144d6f8f.tar.gz
rust-5558fe8a9207b000b1cab9f3d521b06b144d6f8f.zip
Suggest correct code when encountering an incorrect trait bound referencing the current trait
-rw-r--r--src/librustc_typeck/astconv.rs18
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/librustc_typeck/collect.rs4
-rw-r--r--src/test/ui/associated-types/associated-types-in-ambiguous-context.rs7
-rw-r--r--src/test/ui/associated-types/associated-types-in-ambiguous-context.stderr10
5 files changed, 40 insertions, 3 deletions
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index aa05a08686a..8bcf51eb9e3 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -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,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,
             );
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f7132cd868a..a2af29aef09 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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();
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 001d98aece2..7ef842cb757 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -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)
diff --git a/src/test/ui/associated-types/associated-types-in-ambiguous-context.rs b/src/test/ui/associated-types/associated-types-in-ambiguous-context.rs
index 1b1ea9d52a9..202eecfa7b7 100644
--- a/src/test/ui/associated-types/associated-types-in-ambiguous-context.rs
+++ b/src/test/ui/associated-types/associated-types-in-ambiguous-context.rs
@@ -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
 
diff --git a/src/test/ui/associated-types/associated-types-in-ambiguous-context.stderr b/src/test/ui/associated-types/associated-types-in-ambiguous-context.stderr
index 83667b54807..db6dec6e899 100644
--- a/src/test/ui/associated-types/associated-types-in-ambiguous-context.stderr
+++ b/src/test/ui/associated-types/associated-types-in-ambiguous-context.stderr
@@ -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`
@@ -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`.