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 ```
This commit is contained in:
parent
b5f6d7ec2d
commit
3edb4fc563
7 changed files with 69 additions and 14 deletions
|
@ -108,7 +108,7 @@ enum ResolutionError<'a> {
|
||||||
/// error E0403: the name is already used for a type parameter in this type parameter list
|
/// error E0403: the name is already used for a type parameter in this type parameter list
|
||||||
NameAlreadyUsedInTypeParameterList(Name, &'a Span),
|
NameAlreadyUsedInTypeParameterList(Name, &'a Span),
|
||||||
/// error E0404: is not a trait
|
/// error E0404: is not a trait
|
||||||
IsNotATrait(&'a str),
|
IsNotATrait(&'a str, &'a str),
|
||||||
/// error E0405: use of undeclared trait name
|
/// error E0405: use of undeclared trait name
|
||||||
UndeclaredTraitName(&'a str, SuggestedCandidates),
|
UndeclaredTraitName(&'a str, SuggestedCandidates),
|
||||||
/// error E0407: method is not a member of trait
|
/// 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
|
err
|
||||||
|
|
||||||
}
|
}
|
||||||
ResolutionError::IsNotATrait(name) => {
|
ResolutionError::IsNotATrait(name, kind_name) => {
|
||||||
let mut err = struct_span_err!(resolver.session,
|
let mut err = struct_span_err!(resolver.session,
|
||||||
span,
|
span,
|
||||||
E0404,
|
E0404,
|
||||||
"`{}` is not a trait",
|
"`{}` is not a trait",
|
||||||
name);
|
name);
|
||||||
err.span_label(span, &format!("not a trait"));
|
err.span_label(span, &format!("expected trait, found {}", kind_name));
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
ResolutionError::UndeclaredTraitName(name, candidates) => {
|
ResolutionError::UndeclaredTraitName(name, candidates) => {
|
||||||
|
@ -566,7 +566,7 @@ impl<'a> Visitor for Resolver<'a> {
|
||||||
self.resolve_type(ty);
|
self.resolve_type(ty);
|
||||||
}
|
}
|
||||||
fn visit_poly_trait_ref(&mut self, tref: &ast::PolyTraitRef, m: &ast::TraitBoundModifier) {
|
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),
|
Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// error already reported
|
// error already reported
|
||||||
|
@ -1703,7 +1703,7 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::DefaultImpl(_, ref trait_ref) => {
|
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) =>
|
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
|
||||||
self.resolve_implementation(generics,
|
self.resolve_implementation(generics,
|
||||||
|
@ -1893,7 +1893,8 @@ impl<'a> Resolver<'a> {
|
||||||
fn resolve_trait_reference(&mut self,
|
fn resolve_trait_reference(&mut self,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
trait_path: &Path,
|
trait_path: &Path,
|
||||||
path_depth: usize)
|
path_depth: usize,
|
||||||
|
generics: Option<&Generics>)
|
||||||
-> Result<PathResolution, ()> {
|
-> Result<PathResolution, ()> {
|
||||||
self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| {
|
self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| {
|
||||||
match path_res.base_def {
|
match path_res.base_def {
|
||||||
|
@ -1906,8 +1907,16 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut err = resolve_struct_error(self, trait_path.span, {
|
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 it's a typedef, give a note
|
||||||
if let Def::TyAlias(..) = path_res.base_def {
|
if let Def::TyAlias(..) = path_res.base_def {
|
||||||
|
@ -1952,7 +1961,11 @@ impl<'a> Resolver<'a> {
|
||||||
result
|
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
|
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
|
||||||
{
|
{
|
||||||
let mut new_val = None;
|
let mut new_val = None;
|
||||||
|
@ -1960,7 +1973,8 @@ impl<'a> Resolver<'a> {
|
||||||
if let Some(trait_ref) = opt_trait_ref {
|
if let Some(trait_ref) = opt_trait_ref {
|
||||||
if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id,
|
if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id,
|
||||||
&trait_ref.path,
|
&trait_ref.path,
|
||||||
0) {
|
0,
|
||||||
|
generics) {
|
||||||
assert!(path_res.depth == 0);
|
assert!(path_res.depth == 0);
|
||||||
self.record_def(trait_ref.ref_id, path_res);
|
self.record_def(trait_ref.ref_id, path_res);
|
||||||
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
|
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
|
||||||
|
@ -2048,7 +2062,7 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}, Some(&generics));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2492,7 +2506,7 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
max_assoc_types = path.segments.len() - qself.position;
|
max_assoc_types = path.segments.len() - qself.position;
|
||||||
// Make sure the trait is valid.
|
// 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 => {
|
None => {
|
||||||
max_assoc_types = path.segments.len();
|
max_assoc_types = path.segments.len();
|
||||||
|
|
|
@ -399,6 +399,14 @@ impl Generics {
|
||||||
pub fn is_parameterized(&self) -> bool {
|
pub fn is_parameterized(&self) -> bool {
|
||||||
self.is_lt_parameterized() || self.is_type_parameterized()
|
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 {
|
impl Default for Generics {
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct S {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo for S { //~ ERROR: `Foo` is not a trait
|
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
|
//~| NOTE: type aliases cannot be used for traits
|
||||||
fn bar() { }
|
fn bar() { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
trait I {}
|
trait I {}
|
||||||
type K = I;
|
type K = I;
|
||||||
impl K for isize {} //~ ERROR: `K` is not a trait
|
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
|
//~| NOTE: aliases cannot be used for traits
|
||||||
|
|
||||||
use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
|
use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0404]: `Bar` is not a trait
|
||||||
--> $DIR/two_files.rs:15:6
|
--> $DIR/two_files.rs:15:6
|
||||||
|
|
|
|
||||||
15 | impl Bar for Baz { }
|
15 | impl Bar for Baz { }
|
||||||
| ^^^ not a trait
|
| ^^^ expected trait, found type alias
|
||||||
|
|
|
|
||||||
= note: type aliases cannot be used for traits
|
= note: type aliases cannot be used for traits
|
||||||
|
|
||||||
|
|
21
src/test/ui/span/issue-35987.rs
Normal file
21
src/test/ui/span/issue-35987.rs
Normal 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!();
|
||||||
|
}
|
||||||
|
}
|
12
src/test/ui/span/issue-35987.stderr
Normal file
12
src/test/ui/span/issue-35987.stderr
Normal 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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue