about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2016-11-09 20:51:16 +0200
committerGitHub <noreply@github.com>2016-11-09 20:51:16 +0200
commitbd9969fb1138d3a0aef0e860173a5f221a74e7ab (patch)
treebe8c2ef9dc91f2a1232f8df2fa84ea272148720d
parent7f2853fda3773d4f9ec28484ba3592d5e825ca59 (diff)
parent3edb4fc56345ba2d33a04e952e1d402b08bc676c (diff)
downloadrust-bd9969fb1138d3a0aef0e860173a5f221a74e7ab.tar.gz
rust-bd9969fb1138d3a0aef0e860173a5f221a74e7ab.zip
Rollup merge of #37428 - estebank:generic-type-error-span, r=sanxiyn
Point to type argument span when used as trait

Given the following code:

``` rust
struct Foo<T: Clone>(T);

use std::ops::Add;

impl<T: Clone, Add> Add for Foo<T> {
  type Output = usize;

  fn add(self, rhs: Self) -> Self::Output {
    unimplemented!();
  }
}
```

present the following output:

``` nocode
error[E0404]: `Add` is not a trait
 --> file3.rs:5:21
  |
5 | impl<T: Clone, Add> Add for Okok<T> {
  |                ---  ^^^ expected trait, found type parameter
  |                |
  |                type parameter defined here
```

Fixes #35987.
-rw-r--r--src/librustc_resolve/lib.rs36
-rw-r--r--src/libsyntax/ast.rs8
-rw-r--r--src/test/compile-fail/issue-3907.rs2
-rw-r--r--src/test/compile-fail/issue-5035.rs2
-rw-r--r--src/test/ui/codemap_tests/two_files.stderr2
-rw-r--r--src/test/ui/span/issue-35987.rs21
-rw-r--r--src/test/ui/span/issue-35987.stderr12
7 files changed, 69 insertions, 14 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index df4c05fcf5d..0c7c1a55a61 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -108,7 +108,7 @@ enum ResolutionError<'a> {
     /// error E0403: the name is already used for a type parameter in this type parameter list
     NameAlreadyUsedInTypeParameterList(Name, &'a Span),
     /// error E0404: is not a trait
-    IsNotATrait(&'a str),
+    IsNotATrait(&'a str, &'a str),
     /// error E0405: use of undeclared trait name
     UndeclaredTraitName(&'a str, SuggestedCandidates),
     /// error E0407: method is not a member of trait
@@ -223,13 +223,13 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
              err
 
         }
-        ResolutionError::IsNotATrait(name) => {
+        ResolutionError::IsNotATrait(name, kind_name) => {
             let mut err = struct_span_err!(resolver.session,
                                            span,
                                            E0404,
                                            "`{}` is not a trait",
                                            name);
-            err.span_label(span, &format!("not a trait"));
+            err.span_label(span, &format!("expected trait, found {}", kind_name));
             err
         }
         ResolutionError::UndeclaredTraitName(name, candidates) => {
@@ -555,7 +555,7 @@ impl<'a> Visitor for Resolver<'a> {
         self.resolve_type(ty);
     }
     fn visit_poly_trait_ref(&mut self, tref: &ast::PolyTraitRef, m: &ast::TraitBoundModifier) {
-        match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) {
+        match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0, None) {
             Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
             Err(_) => {
                 // error already reported
@@ -1699,7 +1699,7 @@ impl<'a> Resolver<'a> {
             }
 
             ItemKind::DefaultImpl(_, ref trait_ref) => {
-                self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
+                self.with_optional_trait_ref(Some(trait_ref), |_, _| {}, None);
             }
             ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
                 self.resolve_implementation(generics,
@@ -1889,7 +1889,8 @@ impl<'a> Resolver<'a> {
     fn resolve_trait_reference(&mut self,
                                id: NodeId,
                                trait_path: &Path,
-                               path_depth: usize)
+                               path_depth: usize,
+                               generics: Option<&Generics>)
                                -> Result<PathResolution, ()> {
         self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| {
             match path_res.base_def {
@@ -1902,8 +1903,16 @@ impl<'a> Resolver<'a> {
             }
 
             let mut err = resolve_struct_error(self, trait_path.span, {
-                ResolutionError::IsNotATrait(&path_names_to_string(trait_path, path_depth))
+                ResolutionError::IsNotATrait(&path_names_to_string(trait_path, path_depth),
+                                             path_res.base_def.kind_name())
             });
+            if let Some(generics) = generics {
+                if let Some(span) = generics.span_for_name(
+                    &path_names_to_string(trait_path, path_depth)) {
+
+                    err.span_label(span, &"type parameter defined here");
+                }
+            }
 
             // If it's a typedef, give a note
             if let Def::TyAlias(..) = path_res.base_def {
@@ -1948,7 +1957,11 @@ impl<'a> Resolver<'a> {
         result
     }
 
-    fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
+    fn with_optional_trait_ref<T, F>(&mut self,
+                                     opt_trait_ref: Option<&TraitRef>,
+                                     f: F,
+                                     generics: Option<&Generics>)
+        -> T
         where F: FnOnce(&mut Resolver, Option<DefId>) -> T
     {
         let mut new_val = None;
@@ -1956,7 +1969,8 @@ impl<'a> Resolver<'a> {
         if let Some(trait_ref) = opt_trait_ref {
             if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id,
                                                                &trait_ref.path,
-                                                               0) {
+                                                               0,
+                                                               generics) {
                 assert!(path_res.depth == 0);
                 self.record_def(trait_ref.ref_id, path_res);
                 new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
@@ -2044,7 +2058,7 @@ impl<'a> Resolver<'a> {
                         }
                     });
                 });
-            });
+            }, Some(&generics));
         });
     }
 
@@ -2494,7 +2508,7 @@ impl<'a> Resolver<'a> {
                 }
                 max_assoc_types = path.segments.len() - qself.position;
                 // Make sure the trait is valid.
-                let _ = self.resolve_trait_reference(id, path, max_assoc_types);
+                let _ = self.resolve_trait_reference(id, path, max_assoc_types, None);
             }
             None => {
                 max_assoc_types = path.segments.len();
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index f7581924eb1..9751ad6aa43 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -399,6 +399,14 @@ impl Generics {
     pub fn is_parameterized(&self) -> bool {
         self.is_lt_parameterized() || self.is_type_parameterized()
     }
+    pub fn span_for_name(&self, name: &str) -> Option<Span> {
+        for t in &self.ty_params {
+            if t.ident.name.as_str() == name {
+                return Some(t.span);
+            }
+        }
+        None
+    }
 }
 
 impl Default for Generics {
diff --git a/src/test/compile-fail/issue-3907.rs b/src/test/compile-fail/issue-3907.rs
index 93556577ad3..86906ed9af2 100644
--- a/src/test/compile-fail/issue-3907.rs
+++ b/src/test/compile-fail/issue-3907.rs
@@ -18,7 +18,7 @@ struct S {
 }
 
 impl Foo for S { //~ ERROR: `Foo` is not a trait
-                 //~| NOTE: not a trait
+                 //~| NOTE: expected trait, found type alias
                  //~| NOTE: type aliases cannot be used for traits
     fn bar() { }
 }
diff --git a/src/test/compile-fail/issue-5035.rs b/src/test/compile-fail/issue-5035.rs
index 7a36012925e..8ebcba47134 100644
--- a/src/test/compile-fail/issue-5035.rs
+++ b/src/test/compile-fail/issue-5035.rs
@@ -11,7 +11,7 @@
 trait I {}
 type K = I;
 impl K for isize {} //~ ERROR: `K` is not a trait
-                    //~| NOTE: not a trait
+                    //~| NOTE: expected trait, found type alias
                     //~| NOTE: aliases cannot be used for traits
 
 use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr
index d58e7148f61..d05e6eb2bbe 100644
--- a/src/test/ui/codemap_tests/two_files.stderr
+++ b/src/test/ui/codemap_tests/two_files.stderr
@@ -2,7 +2,7 @@ error[E0404]: `Bar` is not a trait
   --> $DIR/two_files.rs:15:6
    |
 15 | impl Bar for Baz { }
-   |      ^^^ not a trait
+   |      ^^^ expected trait, found type alias
    |
    = note: type aliases cannot be used for traits
 
diff --git a/src/test/ui/span/issue-35987.rs b/src/test/ui/span/issue-35987.rs
new file mode 100644
index 00000000000..8ff5f3b8398
--- /dev/null
+++ b/src/test/ui/span/issue-35987.rs
@@ -0,0 +1,21 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo<T: Clone>(T);
+
+use std::ops::Add;
+
+impl<T: Clone, Add> Add for Foo<T> {
+    type Output = usize;
+
+    fn add(self, rhs: Self) -> Self::Output {
+        unimplemented!();
+    }
+}
diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr
new file mode 100644
index 00000000000..2370b3d6c61
--- /dev/null
+++ b/src/test/ui/span/issue-35987.stderr
@@ -0,0 +1,12 @@
+error[E0404]: `Add` is not a trait
+  --> $DIR/issue-35987.rs:15:21
+   |
+15 | impl<T: Clone, Add> Add for Foo<T> {
+   |                ---  ^^^ expected trait, found type parameter
+   |                |
+   |                type parameter defined here
+
+error: main function not found
+
+error: cannot continue compilation due to previous error
+