Skip to content

Commit bd9969f

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#35987.
2 parents 7f2853f + 3edb4fc commit bd9969f

File tree

7 files changed

+69
-14
lines changed

7 files changed

+69
-14
lines changed

src/librustc_resolve/lib.rs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ enum ResolutionError<'a> {
108108
/// error E0403: the name is already used for a type parameter in this type parameter list
109109
NameAlreadyUsedInTypeParameterList(Name, &'a Span),
110110
/// error E0404: is not a trait
111-
IsNotATrait(&'a str),
111+
IsNotATrait(&'a str, &'a str),
112112
/// error E0405: use of undeclared trait name
113113
UndeclaredTraitName(&'a str, SuggestedCandidates),
114114
/// 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>,
223223
err
224224

225225
}
226-
ResolutionError::IsNotATrait(name) => {
226+
ResolutionError::IsNotATrait(name, kind_name) => {
227227
let mut err = struct_span_err!(resolver.session,
228228
span,
229229
E0404,
230230
"`{}` is not a trait",
231231
name);
232-
err.span_label(span, &format!("not a trait"));
232+
err.span_label(span, &format!("expected trait, found {}", kind_name));
233233
err
234234
}
235235
ResolutionError::UndeclaredTraitName(name, candidates) => {
@@ -555,7 +555,7 @@ impl<'a> Visitor for Resolver<'a> {
555555
self.resolve_type(ty);
556556
}
557557
fn visit_poly_trait_ref(&mut self, tref: &ast::PolyTraitRef, m: &ast::TraitBoundModifier) {
558-
match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) {
558+
match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0, None) {
559559
Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
560560
Err(_) => {
561561
// error already reported
@@ -1699,7 +1699,7 @@ impl<'a> Resolver<'a> {
16991699
}
17001700

17011701
ItemKind::DefaultImpl(_, ref trait_ref) => {
1702-
self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
1702+
self.with_optional_trait_ref(Some(trait_ref), |_, _| {}, None);
17031703
}
17041704
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
17051705
self.resolve_implementation(generics,
@@ -1889,7 +1889,8 @@ impl<'a> Resolver<'a> {
18891889
fn resolve_trait_reference(&mut self,
18901890
id: NodeId,
18911891
trait_path: &Path,
1892-
path_depth: usize)
1892+
path_depth: usize,
1893+
generics: Option<&Generics>)
18931894
-> Result<PathResolution, ()> {
18941895
self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| {
18951896
match path_res.base_def {
@@ -1902,8 +1903,16 @@ impl<'a> Resolver<'a> {
19021903
}
19031904

19041905
let mut err = resolve_struct_error(self, trait_path.span, {
1905-
ResolutionError::IsNotATrait(&path_names_to_string(trait_path, path_depth))
1906+
ResolutionError::IsNotATrait(&path_names_to_string(trait_path, path_depth),
1907+
path_res.base_def.kind_name())
19061908
});
1909+
if let Some(generics) = generics {
1910+
if let Some(span) = generics.span_for_name(
1911+
&path_names_to_string(trait_path, path_depth)) {
1912+
1913+
err.span_label(span, &"type parameter defined here");
1914+
}
1915+
}
19071916

19081917
// If it's a typedef, give a note
19091918
if let Def::TyAlias(..) = path_res.base_def {
@@ -1948,15 +1957,20 @@ impl<'a> Resolver<'a> {
19481957
result
19491958
}
19501959

1951-
fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
1960+
fn with_optional_trait_ref<T, F>(&mut self,
1961+
opt_trait_ref: Option<&TraitRef>,
1962+
f: F,
1963+
generics: Option<&Generics>)
1964+
-> T
19521965
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
19531966
{
19541967
let mut new_val = None;
19551968
let mut new_id = None;
19561969
if let Some(trait_ref) = opt_trait_ref {
19571970
if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id,
19581971
&trait_ref.path,
1959-
0) {
1972+
0,
1973+
generics) {
19601974
assert!(path_res.depth == 0);
19611975
self.record_def(trait_ref.ref_id, path_res);
19621976
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
@@ -2044,7 +2058,7 @@ impl<'a> Resolver<'a> {
20442058
}
20452059
});
20462060
});
2047-
});
2061+
}, Some(&generics));
20482062
});
20492063
}
20502064

@@ -2494,7 +2508,7 @@ impl<'a> Resolver<'a> {
24942508
}
24952509
max_assoc_types = path.segments.len() - qself.position;
24962510
// Make sure the trait is valid.
2497-
let _ = self.resolve_trait_reference(id, path, max_assoc_types);
2511+
let _ = self.resolve_trait_reference(id, path, max_assoc_types, None);
24982512
}
24992513
None => {
25002514
max_assoc_types = path.segments.len();

src/libsyntax/ast.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,14 @@ impl Generics {
399399
pub fn is_parameterized(&self) -> bool {
400400
self.is_lt_parameterized() || self.is_type_parameterized()
401401
}
402+
pub fn span_for_name(&self, name: &str) -> Option<Span> {
403+
for t in &self.ty_params {
404+
if t.ident.name.as_str() == name {
405+
return Some(t.span);
406+
}
407+
}
408+
None
409+
}
402410
}
403411

404412
impl Default for Generics {

src/test/compile-fail/issue-3907.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct S {
1818
}
1919

2020
impl Foo for S { //~ ERROR: `Foo` is not a trait
21-
//~| NOTE: not a trait
21+
//~| NOTE: expected trait, found type alias
2222
//~| NOTE: type aliases cannot be used for traits
2323
fn bar() { }
2424
}

src/test/compile-fail/issue-5035.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
trait I {}
1212
type K = I;
1313
impl K for isize {} //~ ERROR: `K` is not a trait
14-
//~| NOTE: not a trait
14+
//~| NOTE: expected trait, found type alias
1515
//~| NOTE: aliases cannot be used for traits
1616

1717
use ImportError; //~ ERROR unresolved import `ImportError` [E0432]

src/test/ui/codemap_tests/two_files.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0404]: `Bar` is not a trait
22
--> $DIR/two_files.rs:15:6
33
|
44
15 | impl Bar for Baz { }
5-
| ^^^ not a trait
5+
| ^^^ expected trait, found type alias
66
|
77
= note: type aliases cannot be used for traits
88

src/test/ui/span/issue-35987.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Foo<T: Clone>(T);
12+
13+
use std::ops::Add;
14+
15+
impl<T: Clone, Add> Add for Foo<T> {
16+
type Output = usize;
17+
18+
fn add(self, rhs: Self) -> Self::Output {
19+
unimplemented!();
20+
}
21+
}

src/test/ui/span/issue-35987.stderr

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0404]: `Add` is not a trait
2+
--> $DIR/issue-35987.rs:15:21
3+
|
4+
15 | impl<T: Clone, Add> Add for Foo<T> {
5+
| --- ^^^ expected trait, found type parameter
6+
| |
7+
| type parameter defined here
8+
9+
error: main function not found
10+
11+
error: cannot continue compilation due to previous error
12+

0 commit comments

Comments
 (0)