diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2016-11-09 20:51:16 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-09 20:51:16 +0200 |
| commit | bd9969fb1138d3a0aef0e860173a5f221a74e7ab (patch) | |
| tree | be8c2ef9dc91f2a1232f8df2fa84ea272148720d | |
| parent | 7f2853fda3773d4f9ec28484ba3592d5e825ca59 (diff) | |
| parent | 3edb4fc56345ba2d33a04e952e1d402b08bc676c (diff) | |
| download | rust-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.rs | 36 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 8 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-3907.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-5035.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/codemap_tests/two_files.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/span/issue-35987.rs | 21 | ||||
| -rw-r--r-- | src/test/ui/span/issue-35987.stderr | 12 |
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 + |
