Show candidates for names not in scope
This commit adds functionality that allows the name resolution pass to search for entities (traits/types/enums/structs) by name, in order to show recommendations along with the errors. For now, only E0405 and E0412 have suggestions attached, as per the request in bug #21221, but it's likely other errors can also benefit from the ability to generate suggestions.
This commit is contained in:
parent
e18f7a1c5a
commit
88af8fa0b1
32 changed files with 521 additions and 85 deletions
|
|
@ -461,12 +461,12 @@ impl Foo for Bar { // ok!
|
|||
"##,
|
||||
|
||||
E0405: r##"
|
||||
An unknown trait was implemented. Example of erroneous code:
|
||||
The code refers to a trait that is not in scope. Example of erroneous code:
|
||||
|
||||
```compile_fail
|
||||
struct Foo;
|
||||
|
||||
impl SomeTrait for Foo {} // error: use of undeclared trait name `SomeTrait`
|
||||
impl SomeTrait for Foo {} // error: trait `SomeTrait` is not in scope
|
||||
```
|
||||
|
||||
Please verify that the name of the trait wasn't misspelled and ensure that it
|
||||
|
|
@ -599,20 +599,20 @@ trait Baz : Foo + Foo2 {
|
|||
"##,
|
||||
|
||||
E0412: r##"
|
||||
An undeclared type name was used. Example of erroneous codes:
|
||||
The type name used is not in scope. Example of erroneous codes:
|
||||
|
||||
```compile_fail
|
||||
impl Something {} // error: use of undeclared type name `Something`
|
||||
impl Something {} // error: type name `Something` is not in scope
|
||||
|
||||
// or:
|
||||
|
||||
trait Foo {
|
||||
fn bar(N); // error: use of undeclared type name `N`
|
||||
fn bar(N); // error: type name `N` is not in scope
|
||||
}
|
||||
|
||||
// or:
|
||||
|
||||
fn foo(x: T) {} // error: use of undeclared type name `T`
|
||||
fn foo(x: T) {} // type name `T` is not in scope
|
||||
```
|
||||
|
||||
To fix this error, please verify you didn't misspell the type name, you did
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ use rustc_front::hir::{ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStatic, It
|
|||
use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
|
||||
use rustc_front::hir::Local;
|
||||
use rustc_front::hir::{Pat, PatKind, Path, PrimTy};
|
||||
use rustc_front::hir::{PathSegment, PathParameters};
|
||||
use rustc_front::hir::HirVec;
|
||||
use rustc_front::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt};
|
||||
use rustc_front::hir::{TyRptr, TyStr, TyUint, TyPath, TyPtr};
|
||||
use rustc_front::util::walk_pat;
|
||||
|
|
@ -117,6 +119,12 @@ enum SuggestionType {
|
|||
NotFound,
|
||||
}
|
||||
|
||||
/// Candidates for a name resolution failure
|
||||
pub struct SuggestedCandidates {
|
||||
name: String,
|
||||
candidates: Vec<Path>,
|
||||
}
|
||||
|
||||
pub enum ResolutionError<'a> {
|
||||
/// error E0401: can't use type parameters from outer function
|
||||
TypeParametersFromOuterFunction,
|
||||
|
|
@ -127,7 +135,7 @@ pub enum ResolutionError<'a> {
|
|||
/// error E0404: is not a trait
|
||||
IsNotATrait(&'a str),
|
||||
/// error E0405: use of undeclared trait name
|
||||
UndeclaredTraitName(&'a str),
|
||||
UndeclaredTraitName(&'a str, SuggestedCandidates),
|
||||
/// error E0406: undeclared associated type
|
||||
UndeclaredAssociatedType,
|
||||
/// error E0407: method is not a member of trait
|
||||
|
|
@ -145,7 +153,7 @@ pub enum ResolutionError<'a> {
|
|||
/// error E0411: use of `Self` outside of an impl or trait
|
||||
SelfUsedOutsideImplOrTrait,
|
||||
/// error E0412: use of undeclared
|
||||
UseOfUndeclared(&'a str, &'a str),
|
||||
UseOfUndeclared(&'a str, &'a str, SuggestedCandidates),
|
||||
/// error E0413: declaration shadows an enum variant or unit-like struct in scope
|
||||
DeclarationShadowsEnumVariantOrUnitLikeStruct(Name),
|
||||
/// error E0414: only irrefutable patterns allowed here
|
||||
|
|
@ -248,12 +256,14 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
|
|||
ResolutionError::IsNotATrait(name) => {
|
||||
struct_span_err!(resolver.session, span, E0404, "`{}` is not a trait", name)
|
||||
}
|
||||
ResolutionError::UndeclaredTraitName(name) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0405,
|
||||
"use of undeclared trait name `{}`",
|
||||
name)
|
||||
ResolutionError::UndeclaredTraitName(name, candidates) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0405,
|
||||
"trait `{}` is not in scope",
|
||||
name);
|
||||
show_candidates(&mut err, span, &candidates);
|
||||
err
|
||||
}
|
||||
ResolutionError::UndeclaredAssociatedType => {
|
||||
struct_span_err!(resolver.session, span, E0406, "undeclared associated type")
|
||||
|
|
@ -313,13 +323,15 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
|
|||
E0411,
|
||||
"use of `Self` outside of an impl or trait")
|
||||
}
|
||||
ResolutionError::UseOfUndeclared(kind, name) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0412,
|
||||
"use of undeclared {} `{}`",
|
||||
kind,
|
||||
name)
|
||||
ResolutionError::UseOfUndeclared(kind, name, candidates) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0412,
|
||||
"{} `{}` is undefined or not in scope",
|
||||
kind,
|
||||
name);
|
||||
show_candidates(&mut err, span, &candidates);
|
||||
err
|
||||
}
|
||||
ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => {
|
||||
struct_span_err!(resolver.session,
|
||||
|
|
@ -839,6 +851,7 @@ pub struct ModuleS<'a> {
|
|||
pub type Module<'a> = &'a ModuleS<'a>;
|
||||
|
||||
impl<'a> ModuleS<'a> {
|
||||
|
||||
fn new(parent_link: ParentLink<'a>, def: Option<Def>, external: bool, is_public: bool) -> Self {
|
||||
ModuleS {
|
||||
parent_link: parent_link,
|
||||
|
|
@ -1969,10 +1982,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
Err(())
|
||||
}
|
||||
} else {
|
||||
resolve_error(self,
|
||||
trait_path.span,
|
||||
ResolutionError::UndeclaredTraitName(&path_names_to_string(trait_path,
|
||||
path_depth)));
|
||||
|
||||
// find possible candidates
|
||||
let trait_name = trait_path.segments.last().unwrap().identifier.name;
|
||||
let candidates =
|
||||
self.lookup_candidates(
|
||||
trait_name,
|
||||
TypeNS,
|
||||
|def| match def {
|
||||
Def::Trait(_) => true,
|
||||
_ => false,
|
||||
},
|
||||
);
|
||||
|
||||
// create error object
|
||||
let name = &path_names_to_string(trait_path, path_depth);
|
||||
let error =
|
||||
ResolutionError::UndeclaredTraitName(
|
||||
name,
|
||||
candidates,
|
||||
);
|
||||
|
||||
resolve_error(self, trait_path.span, error);
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
|
@ -2296,13 +2327,33 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
ty.span,
|
||||
ResolutionError::SelfUsedOutsideImplOrTrait);
|
||||
} else {
|
||||
resolve_error(self,
|
||||
ty.span,
|
||||
ResolutionError::UseOfUndeclared(
|
||||
kind,
|
||||
&path_names_to_string(path,
|
||||
0))
|
||||
);
|
||||
let segment = path.segments.last();
|
||||
let segment = segment.expect("missing name in path");
|
||||
let type_name = segment.identifier.name;
|
||||
|
||||
let candidates =
|
||||
self.lookup_candidates(
|
||||
type_name,
|
||||
TypeNS,
|
||||
|def| match def {
|
||||
Def::Trait(_) |
|
||||
Def::Enum(_) |
|
||||
Def::Struct(_) |
|
||||
Def::TyAlias(_) => true,
|
||||
_ => false,
|
||||
},
|
||||
);
|
||||
|
||||
// create error object
|
||||
let name = &path_names_to_string(path, 0);
|
||||
let error =
|
||||
ResolutionError::UseOfUndeclared(
|
||||
kind,
|
||||
name,
|
||||
candidates,
|
||||
);
|
||||
|
||||
resolve_error(self, ty.span, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3457,6 +3508,99 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
found_traits
|
||||
}
|
||||
|
||||
/// When name resolution fails, this method can be used to look up candidate
|
||||
/// entities with the expected name. It allows filtering them using the
|
||||
/// supplied predicate (which should be used to only accept the types of
|
||||
/// definitions expected e.g. traits). The lookup spans across all crates.
|
||||
///
|
||||
/// NOTE: The method does not look into imports, but this is not a problem,
|
||||
/// since we report the definitions (thus, the de-aliased imports).
|
||||
fn lookup_candidates<FilterFn>(&mut self,
|
||||
lookup_name: Name,
|
||||
namespace: Namespace,
|
||||
filter_fn: FilterFn) -> SuggestedCandidates
|
||||
where FilterFn: Fn(Def) -> bool {
|
||||
|
||||
let mut lookup_results = Vec::new();
|
||||
let mut worklist = Vec::new();
|
||||
worklist.push((self.graph_root, Vec::new(), false));
|
||||
|
||||
while let Some((in_module,
|
||||
path_segments,
|
||||
in_module_is_extern)) = worklist.pop() {
|
||||
build_reduced_graph::populate_module_if_necessary(self, &in_module);
|
||||
|
||||
in_module.for_each_child(|name, ns, name_binding| {
|
||||
|
||||
// avoid imports entirely
|
||||
if name_binding.is_import() { return; }
|
||||
|
||||
// collect results based on the filter function
|
||||
if let Some(def) = name_binding.def() {
|
||||
if name == lookup_name && ns == namespace && filter_fn(def) {
|
||||
// create the path
|
||||
let ident = hir::Ident::from_name(name);
|
||||
let params = PathParameters::none();
|
||||
let segment = PathSegment {
|
||||
identifier: ident,
|
||||
parameters: params,
|
||||
};
|
||||
let span = name_binding.span.unwrap_or(syntax::codemap::DUMMY_SP);
|
||||
let mut segms = path_segments.clone();
|
||||
segms.push(segment);
|
||||
let segms = HirVec::from_vec(segms);
|
||||
let path = Path {
|
||||
span: span,
|
||||
global: true,
|
||||
segments: segms,
|
||||
};
|
||||
// the entity is accessible in the following cases:
|
||||
// 1. if it's defined in the same crate, it's always
|
||||
// accessible (since private entities can be made public)
|
||||
// 2. if it's defined in another crate, it's accessible
|
||||
// only if both the module is public and the entity is
|
||||
// declared as public (due to pruning, we don't explore
|
||||
// outside crate private modules => no need to check this)
|
||||
if !in_module_is_extern || name_binding.is_public() {
|
||||
lookup_results.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collect submodules to explore
|
||||
if let Some(module) = name_binding.module() {
|
||||
// form the path
|
||||
let path_segments = match module.parent_link {
|
||||
NoParentLink => path_segments.clone(),
|
||||
ModuleParentLink(_, name) => {
|
||||
let mut paths = path_segments.clone();
|
||||
let ident = hir::Ident::from_name(name);
|
||||
let params = PathParameters::none();
|
||||
let segm = PathSegment {
|
||||
identifier: ident,
|
||||
parameters: params,
|
||||
};
|
||||
paths.push(segm);
|
||||
paths
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if !in_module_is_extern || name_binding.is_public() {
|
||||
// add the module to the lookup
|
||||
let is_extern = in_module_is_extern || module.is_extern_crate;
|
||||
worklist.push((module, path_segments, is_extern));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
SuggestedCandidates {
|
||||
name: lookup_name.as_str().to_string(),
|
||||
candidates: lookup_results,
|
||||
}
|
||||
}
|
||||
|
||||
fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
|
||||
debug!("(recording def) recording {:?} for {}", resolution, node_id);
|
||||
assert!(match resolution.last_private {
|
||||
|
|
@ -3512,6 +3656,67 @@ fn path_names_to_string(path: &Path, depth: usize) -> String {
|
|||
names_to_string(&names[..])
|
||||
}
|
||||
|
||||
/// When an entity with a given name is not available in scope, we search for
|
||||
/// entities with that name in all crates. This method allows outputting the
|
||||
/// results of this search in a programmer-friendly way
|
||||
fn show_candidates(session: &mut DiagnosticBuilder,
|
||||
span: syntax::codemap::Span,
|
||||
candidates: &SuggestedCandidates) {
|
||||
|
||||
let paths = &candidates.candidates;
|
||||
|
||||
if paths.len() > 0 {
|
||||
// don't show more than MAX_CANDIDATES results, so
|
||||
// we're consistent with the trait suggestions
|
||||
const MAX_CANDIDATES: usize = 5;
|
||||
|
||||
// we want consistent results across executions, but candidates are produced
|
||||
// by iterating through a hash map, so make sure they are ordered:
|
||||
let mut path_strings: Vec<_> = paths.into_iter()
|
||||
.map(|p| path_names_to_string(&p, 0))
|
||||
.collect();
|
||||
path_strings.sort();
|
||||
|
||||
// behave differently based on how many candidates we have:
|
||||
if !paths.is_empty() {
|
||||
if paths.len() == 1 {
|
||||
session.fileline_help(
|
||||
span,
|
||||
&format!("you can to import it into scope: `use {};`.",
|
||||
&path_strings[0]),
|
||||
);
|
||||
} else {
|
||||
session.fileline_help(span, "you can import several candidates \
|
||||
into scope (`use ...;`):");
|
||||
let count = path_strings.len() as isize - MAX_CANDIDATES as isize + 1;
|
||||
|
||||
for (idx, path_string) in path_strings.iter().enumerate() {
|
||||
if idx == MAX_CANDIDATES - 1 && count > 1 {
|
||||
session.fileline_help(
|
||||
span,
|
||||
&format!(" and {} other candidates", count).to_string(),
|
||||
);
|
||||
break;
|
||||
} else {
|
||||
session.fileline_help(
|
||||
span,
|
||||
&format!(" `{}`", path_string).to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// nothing found:
|
||||
session.fileline_help(
|
||||
span,
|
||||
&format!("no candidates by the name of `{}` found in your \
|
||||
project; maybe you misspelled the name or forgot to import \
|
||||
an external crate?", candidates.name.to_string()),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/// A somewhat inefficient routine to obtain the name of a module.
|
||||
fn module_to_string<'a>(module: Module<'a>) -> String {
|
||||
let mut names = Vec::new();
|
||||
|
|
|
|||
29
src/test/auxiliary/issue-21221-3.rs
Normal file
29
src/test/auxiliary/issue-21221-3.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// 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.
|
||||
|
||||
// testing whether the lookup mechanism picks up types
|
||||
// defined in the outside crate
|
||||
|
||||
#![crate_type="lib"]
|
||||
|
||||
pub mod outer {
|
||||
// should suggest this
|
||||
pub trait OuterTrait {}
|
||||
|
||||
// should not suggest this since the module is private
|
||||
mod private_module {
|
||||
pub trait OuterTrait {}
|
||||
}
|
||||
|
||||
// should not suggest since the trait is private
|
||||
pub mod public_module {
|
||||
trait OuterTrait {}
|
||||
}
|
||||
}
|
||||
22
src/test/auxiliary/issue-21221-4.rs
Normal file
22
src/test/auxiliary/issue-21221-4.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// 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.
|
||||
|
||||
// testing whether the lookup mechanism picks up types
|
||||
// defined in the outside crate
|
||||
|
||||
#![crate_type="lib"]
|
||||
|
||||
mod foo {
|
||||
// should not be suggested => foo is private
|
||||
pub trait T {}
|
||||
}
|
||||
|
||||
// should be suggested
|
||||
pub use foo::T;
|
||||
|
|
@ -17,7 +17,7 @@ pub trait Foo {
|
|||
}
|
||||
|
||||
fn foo2<I: Foo>(x: I) {
|
||||
let _: A = x.boo(); //~ERROR use of undeclared
|
||||
let _: A = x.boo(); //~ERROR undefined or not in scope
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@
|
|||
|
||||
fn foo<T>() {
|
||||
fn bar(b: T) { } //~ ERROR can't use type parameters from outer
|
||||
//~^ ERROR use of undeclared type name
|
||||
//~^ ERROR type name `T` is undefined or not in scope
|
||||
}
|
||||
fn main() { }
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ extern "rust-intrinsic" {
|
|||
|
||||
// Unresolved bounds should still error.
|
||||
fn align_of<T: NoSuchTrait>() -> usize;
|
||||
//~^ ERROR use of undeclared trait name `NoSuchTrait`
|
||||
//~^ ERROR trait `NoSuchTrait` is not in scope
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ fn main() {
|
|||
C; //~ ERROR: unresolved
|
||||
import(); //~ ERROR: unresolved
|
||||
|
||||
foo::<A>(); //~ ERROR: undeclared
|
||||
foo::<C>(); //~ ERROR: undeclared
|
||||
foo::<D>(); //~ ERROR: undeclared
|
||||
foo::<A>(); //~ ERROR: not in scope
|
||||
foo::<C>(); //~ ERROR: not in scope
|
||||
foo::<D>(); //~ ERROR: not in scope
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ enum Bar<T> { What } //~ ERROR parameter `T` is never used
|
|||
fn foo<T>() {
|
||||
static a: Bar<T> = Bar::What;
|
||||
//~^ ERROR cannot use an outer type parameter in this context
|
||||
//~| ERROR use of undeclared type name `T`
|
||||
//~| ERROR type name `T` is undefined or not in scope
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
impl Undefined {}
|
||||
//~^ ERROR use of undeclared type name `Undefined`
|
||||
//~^ ERROR type name `Undefined` is undefined or not in scope
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ static Y: u8 = 1;
|
|||
fn foo() {}
|
||||
|
||||
impl X {}
|
||||
//~^ ERROR use of undeclared type name `X`
|
||||
//~^ ERROR type name `X` is undefined or not in scope
|
||||
impl Y {}
|
||||
//~^ ERROR use of undeclared type name `Y`
|
||||
//~^ ERROR type name `Y` is undefined or not in scope
|
||||
impl foo {}
|
||||
//~^ ERROR use of undeclared type name `foo`
|
||||
//~^ ERROR type name `foo` is undefined or not in scope
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ trait From<Src> {
|
|||
trait To: Sized {
|
||||
fn to<Dst: From<Self>>(self) ->
|
||||
<Dst as From<Self>>::Dst
|
||||
//~^ ERROR use of undeclared associated type `From::Dst`
|
||||
//~^ ERROR associated type `From::Dst` is undefined or not in scope
|
||||
{
|
||||
From::from(self)
|
||||
}
|
||||
|
|
|
|||
94
src/test/compile-fail/issue-21221-1.rs
Normal file
94
src/test/compile-fail/issue-21221-1.rs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
// 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.
|
||||
|
||||
mod mul1 {
|
||||
pub trait Mul {}
|
||||
}
|
||||
|
||||
mod mul2 {
|
||||
pub trait Mul {}
|
||||
}
|
||||
|
||||
mod mul3 {
|
||||
enum Mul {
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
}
|
||||
|
||||
mod mul4 {
|
||||
type Mul = String;
|
||||
}
|
||||
|
||||
mod mul5 {
|
||||
struct Mul{
|
||||
left_term: u32,
|
||||
right_term: u32
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo;
|
||||
|
||||
// When we comment the next line:
|
||||
//use mul1::Mul;
|
||||
|
||||
// BEFORE, we got the following error for the `impl` below:
|
||||
// error: use of undeclared trait name `Mul` [E0405]
|
||||
// AFTER, we get this message:
|
||||
// error: trait `Mul` is not in scope.
|
||||
// help: ...
|
||||
// help: you can import several candidates into scope (`use ...;`):
|
||||
// help: `mul1::Mul`
|
||||
// help: `mul2::Mul`
|
||||
// help: `std::ops::Mul`
|
||||
|
||||
impl Mul for Foo {
|
||||
//~^ ERROR trait `Mul` is not in scope
|
||||
//~| HELP `mul1::Mul`
|
||||
//~| HELP `mul2::Mul`
|
||||
//~| HELP `std::ops::Mul`
|
||||
}
|
||||
|
||||
// BEFORE, we got:
|
||||
// error: use of undeclared type name `Mul` [E0412]
|
||||
// AFTER, we get:
|
||||
// error: type name `Mul` is not in scope. Maybe you meant:
|
||||
// help: ...
|
||||
// help: you can import several candidates into scope (`use ...;`):
|
||||
// help: `mul1::Mul`
|
||||
// help: `mul2::Mul`
|
||||
// help: `mul3::Mul`
|
||||
// help: `mul4::Mul`
|
||||
// help: and 2 other candidates
|
||||
fn getMul() -> Mul {
|
||||
//~^ ERROR type name `Mul` is undefined or not in scope
|
||||
//~| HELP `mul1::Mul`
|
||||
//~| HELP `mul2::Mul`
|
||||
//~| HELP `mul3::Mul`
|
||||
//~| HELP `mul4::Mul`
|
||||
//~| HELP and 2 other candidates
|
||||
}
|
||||
|
||||
// Let's also test what happens if the trait doesn't exist:
|
||||
impl ThisTraitReallyDoesntExistInAnyModuleReally for Foo {
|
||||
//~^ ERROR trait `ThisTraitReallyDoesntExistInAnyModuleReally` is not in scope
|
||||
}
|
||||
|
||||
// Let's also test what happens if there's just one alternative:
|
||||
impl Div for Foo {
|
||||
//~^ ERROR trait `Div` is not in scope
|
||||
//~| HELP `use std::ops::Div;`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo();
|
||||
println!("Hello, {:?}!", foo);
|
||||
}
|
||||
30
src/test/compile-fail/issue-21221-2.rs
Normal file
30
src/test/compile-fail/issue-21221-2.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// 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.
|
||||
|
||||
pub mod foo {
|
||||
pub mod bar {
|
||||
// note: trait T is not public, but being in the current
|
||||
// crate, it's fine to show it, since the programmer can
|
||||
// decide to make it public based on the suggestion ...
|
||||
trait T {}
|
||||
}
|
||||
// imports should be ignored:
|
||||
use self::bar::T;
|
||||
}
|
||||
|
||||
pub mod baz {
|
||||
pub use foo;
|
||||
pub use std::ops::{Mul as T};
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
impl T for Foo { }
|
||||
//~^ ERROR trait `T` is not in scope
|
||||
//~| HELP you can to import it into scope: `use foo::bar::T;`.
|
||||
30
src/test/compile-fail/issue-21221-3.rs
Normal file
30
src/test/compile-fail/issue-21221-3.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// 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.
|
||||
|
||||
// testing whether the lookup mechanism picks up types
|
||||
// defined in the outside crate
|
||||
|
||||
// aux-build:issue-21221-3.rs
|
||||
|
||||
extern crate issue_21221_3;
|
||||
|
||||
struct Foo;
|
||||
|
||||
// NOTE: This shows only traits accessible from the current
|
||||
// crate, thus the two private entities:
|
||||
// `issue_21221_3::outer::private_module::OuterTrait` and
|
||||
// `issue_21221_3::outer::public_module::OuterTrait`
|
||||
// are hidden from the view.
|
||||
impl OuterTrait for Foo {}
|
||||
//~^ ERROR trait `OuterTrait` is not in scope
|
||||
//~| HELP you can to import it into scope: `use issue_21221_3::outer::OuterTrait;`.
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
26
src/test/compile-fail/issue-21221-4.rs
Normal file
26
src/test/compile-fail/issue-21221-4.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// 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.
|
||||
|
||||
// testing whether the lookup mechanism picks up types
|
||||
// defined in the outside crate
|
||||
|
||||
// aux-build:issue-21221-4.rs
|
||||
|
||||
extern crate issue_21221_4;
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl T for Foo {}
|
||||
//~^ ERROR trait `T` is not in scope
|
||||
//~| HELP you can to import it into scope: `use issue_21221_4::T;`.
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
trait A {
|
||||
type Output;
|
||||
fn a(&self) -> <Self as A>::X;
|
||||
//~^ ERROR: use of undeclared associated type `A::X`
|
||||
//~^ ERROR: associated type `A::X` is undefined or not in scope
|
||||
}
|
||||
|
||||
impl A for u32 {
|
||||
|
|
|
|||
|
|
@ -14,5 +14,5 @@ trait Trait {
|
|||
|
||||
fn main() {
|
||||
<<i32 as Copy>::foobar as Trait>::foo();
|
||||
//~^ ERROR use of undeclared associated type `Copy::foobar`
|
||||
//~^ ERROR associated type `Copy::foobar` is undefined or not in scope
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ fn siphash<T>() {
|
|||
trait t {
|
||||
fn g(&self, x: T) -> T; //~ ERROR can't use type parameters from outer function; try using
|
||||
//~^ ERROR can't use type parameters from outer function; try using
|
||||
//~^^ ERROR use of undeclared type name `T`
|
||||
//~^^^ ERROR use of undeclared type name `T`
|
||||
//~^^ ERROR type name `T` is undefined or not in scope
|
||||
//~^^^ ERROR type name `T` is undefined or not in scope
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
fn foo<T>() {
|
||||
struct foo {
|
||||
x: T, //~ ERROR can't use type parameters from outer function;
|
||||
//~^ ERROR use of undeclared type name
|
||||
//~^ ERROR type name `T` is undefined or not in scope
|
||||
}
|
||||
|
||||
impl<T> Drop for foo<T> {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ mod a {
|
|||
pub mod sub {
|
||||
use a::b::*;
|
||||
fn sub() -> bar { 1 }
|
||||
//~^ ERROR: undeclared type name
|
||||
//~^ ERROR: type name `bar` is undefined or not in scope
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
fn f<Z>() -> bool {
|
||||
enum E { V(Z) }
|
||||
//~^ ERROR can't use type parameters from outer function
|
||||
//~^^ ERROR use of undeclared type name `Z`
|
||||
//~^^ ERROR type name `Z` is undefined or not in scope
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
fn f<T>() -> bool {
|
||||
struct S(T); //~ ERROR use of undeclared type name `T`
|
||||
struct S(T); //~ ERROR type name `T` is undefined or not in scope
|
||||
//~^ ERROR can't use type parameters from outer function; try using
|
||||
|
||||
true
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct Foo {
|
|||
x: isize
|
||||
}
|
||||
|
||||
impl Fo { //~ ERROR use of undeclared type name `Fo`
|
||||
impl Fo { //~ ERROR type name `Fo` is undefined or not in scope
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
impl B { //~ ERROR use of undeclared type name `B`
|
||||
impl B { //~ ERROR type name `B` is undefined or not in scope
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@
|
|||
mod foo {
|
||||
mod baz {
|
||||
struct Test;
|
||||
impl Add for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Clone for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Iterator for Test {} //~ ERROR: use of undeclared trait
|
||||
impl ToString for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Writer for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Add for Test {} //~ ERROR: not in scope
|
||||
impl Clone for Test {} //~ ERROR: not in scope
|
||||
impl Iterator for Test {} //~ ERROR: not in scope
|
||||
impl ToString for Test {} //~ ERROR: not in scope
|
||||
impl Writer for Test {} //~ ERROR: not in scope
|
||||
|
||||
fn foo() {
|
||||
drop(2) //~ ERROR: unresolved name
|
||||
|
|
@ -30,11 +30,11 @@ mod foo {
|
|||
}
|
||||
|
||||
struct Test;
|
||||
impl Add for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Clone for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Iterator for Test {} //~ ERROR: use of undeclared trait
|
||||
impl ToString for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Writer for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Add for Test {} //~ ERROR: not in scope
|
||||
impl Clone for Test {} //~ ERROR: not in scope
|
||||
impl Iterator for Test {} //~ ERROR: not in scope
|
||||
impl ToString for Test {} //~ ERROR: not in scope
|
||||
impl Writer for Test {} //~ ERROR: not in scope
|
||||
|
||||
fn foo() {
|
||||
drop(2) //~ ERROR: unresolved name
|
||||
|
|
@ -45,11 +45,11 @@ fn qux() {
|
|||
#[no_implicit_prelude]
|
||||
mod qux_inner {
|
||||
struct Test;
|
||||
impl Add for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Clone for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Iterator for Test {} //~ ERROR: use of undeclared trait
|
||||
impl ToString for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Writer for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Add for Test {} //~ ERROR: not in scope
|
||||
impl Clone for Test {} //~ ERROR: not in scope
|
||||
impl Iterator for Test {} //~ ERROR: not in scope
|
||||
impl ToString for Test {} //~ ERROR: not in scope
|
||||
impl Writer for Test {} //~ ERROR: not in scope
|
||||
|
||||
fn foo() {
|
||||
drop(2) //~ ERROR: unresolved name
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@
|
|||
// fail with the same error message).
|
||||
|
||||
struct Test;
|
||||
impl Add for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Clone for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Iterator for Test {} //~ ERROR: use of undeclared trait
|
||||
impl ToString for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Writer for Test {} //~ ERROR: use of undeclared trait
|
||||
impl Add for Test {} //~ ERROR: not in scope
|
||||
impl Clone for Test {} //~ ERROR: not in scope
|
||||
impl Iterator for Test {} //~ ERROR: not in scope
|
||||
impl ToString for Test {} //~ ERROR: not in scope
|
||||
impl Writer for Test {} //~ ERROR: not in scope
|
||||
|
||||
fn main() {
|
||||
drop(2) //~ ERROR: unresolved name
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ pub mod foo2 {
|
|||
fn test_glob2() {
|
||||
use foo2::*;
|
||||
|
||||
let _x: Box<Bar>; //~ ERROR use of undeclared type name `Bar`
|
||||
let _x: Box<Bar>; //~ ERROR type name `Bar` is undefined or not in scope
|
||||
}
|
||||
|
||||
// neither public
|
||||
|
|
@ -58,7 +58,7 @@ fn test_glob3() {
|
|||
use foo3::*;
|
||||
|
||||
Bar(); //~ ERROR unresolved name `Bar`
|
||||
let _x: Box<Bar>; //~ ERROR use of undeclared type name `Bar`
|
||||
let _x: Box<Bar>; //~ ERROR type name `Bar` is undefined or not in scope
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ trait TraitA<A> {
|
|||
//~^ ERROR parameter `B` is never used
|
||||
Variance(A)
|
||||
//~^ ERROR can't use type parameters from outer function
|
||||
//~^^ ERROR use of undeclared type name `A`
|
||||
//~^^ ERROR type name `A` is undefined or not in scope
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ trait TraitB<A> {
|
|||
fn outer(self) {
|
||||
struct Foo<B>(A);
|
||||
//~^ ERROR can't use type parameters from outer function
|
||||
//~^^ ERROR use of undeclared type name `A`
|
||||
//~^^ ERROR type name `A` is undefined or not in scope
|
||||
//~^^^ ERROR parameter `B` is never used
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ trait TraitC<A> {
|
|||
fn outer(self) {
|
||||
struct Foo<B> { a: A }
|
||||
//~^ ERROR can't use type parameters from outer function
|
||||
//~^^ ERROR use of undeclared type name `A`
|
||||
//~^^ ERROR type name `A` is undefined or not in scope
|
||||
//~^^^ ERROR parameter `B` is never used
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ trait TraitD<A> {
|
|||
fn outer(self) {
|
||||
fn foo<B>(a: A) { }
|
||||
//~^ ERROR can't use type parameters from outer function
|
||||
//~^^ ERROR use of undeclared type name `A`
|
||||
//~^^ ERROR type name `A` is undefined or not in scope
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@
|
|||
|
||||
|
||||
trait NewTrait : SomeNonExistentTrait {}
|
||||
//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
|
||||
//~^ ERROR trait `SomeNonExistentTrait` is not in scope
|
||||
|
||||
impl SomeNonExistentTrait for isize {}
|
||||
//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
|
||||
//~^ ERROR trait `SomeNonExistentTrait` is not in scope
|
||||
|
||||
fn f<T:SomeNonExistentTrait>() {}
|
||||
//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
|
||||
//~^ ERROR trait `SomeNonExistentTrait` is not in scope
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ mod a {
|
|||
trait A {
|
||||
}
|
||||
|
||||
impl A for a { //~ ERROR use of undeclared type name `a`
|
||||
impl A for a { //~ ERROR type name `a` is undefined or not in scope
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR undeclared trait name `Nonexist`
|
||||
fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR trait `Nonexist` is not in scope
|
||||
|
||||
type Typedef = isize;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue