]> git.lizzy.rs Git - rust.git/commitdiff
Point to type argument span when used as trait
authorEsteban Küber <esteban@kuber.com.ar>
Thu, 27 Oct 2016 03:51:49 +0000 (20:51 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Tue, 8 Nov 2016 22:17:18 +0000 (14:17 -0800)
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
```

src/librustc_resolve/lib.rs
src/libsyntax/ast.rs
src/test/compile-fail/issue-3907.rs
src/test/compile-fail/issue-5035.rs
src/test/ui/codemap_tests/two_files.stderr
src/test/ui/span/issue-35987.rs [new file with mode: 0644]
src/test/ui/span/issue-35987.stderr [new file with mode: 0644]

index 7091d7d2a632171f89eefbfd665dd702c2c11456..061708127a3d15a771d91688d8ffa6c50625f517 100644 (file)
@@ -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
@@ -225,13 +225,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) => {
@@ -566,7 +566,7 @@ fn visit_ty(&mut self, ty: &Ty) {
         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
@@ -1703,7 +1703,7 @@ fn resolve_item(&mut self, item: &Item) {
             }
 
             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,
@@ -1893,7 +1893,8 @@ fn resolve_function(&mut self,
     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 {
@@ -1906,8 +1907,16 @@ fn resolve_trait_reference(&mut self,
             }
 
             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 {
@@ -1952,7 +1961,11 @@ fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
         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;
@@ -1960,7 +1973,8 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
         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()));
@@ -2048,7 +2062,7 @@ fn resolve_implementation(&mut self,
                         }
                     });
                 });
-            });
+            }, Some(&generics));
         });
     }
 
@@ -2492,7 +2506,7 @@ fn resolve_possibly_assoc_item(&mut self,
                 }
                 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();
index 30fc4c3dd8045137865da8d779cff1fb65335ba3..cc39e81fdaeeba39c0991bcfd718833861c2f05b 100644 (file)
@@ -399,6 +399,14 @@ pub fn is_type_parameterized(&self) -> bool {
     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 {
index 93556577ad345c66381d3452cb146cf4ea17e577..86906ed9af2063117182176dc1f828bff541cca6 100644 (file)
@@ -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() { }
 }
index 7a36012925eed415f3c836f067946553e1bd9f33..8ebcba47134001d32600e1bbac93ed552f91802b 100644 (file)
@@ -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]
index d58e7148f6104025a40004e386bb4f72c77c90d9..d05e6eb2bbe4da144b184bf1a3d8ddf5b8250ca7 100644 (file)
@@ -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 (file)
index 0000000..8ff5f3b
--- /dev/null
@@ -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 (file)
index 0000000..2370b3d
--- /dev/null
@@ -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
+