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.
This commit is contained in:
Eduard-Mihai Burtescu 2016-11-09 20:51:16 +02:00 committed by GitHub
commit bd9969fb11
7 changed files with 69 additions and 14 deletions

View 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
@ -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();

View File

@ -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 {

View 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() { }
}

View 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]

View 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

View File

@ -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!();
}
}

View File

@ -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