Auto merge of #62684 - petrochenkov:scopevisit, r=davidtwco
resolve: Improve candidate search for unresolved macro suggestions Use same scope visiting machinery for both collecting suggestion candidates and actually resolving the names. The PR is better read in per-commit fashion with whitespace changes ignored (the first commit in particular moves some code around). This should be the last pre-requisite for https://github.com/rust-lang/rust/pull/62086. r? @davidtwco
This commit is contained in:
commit
fe499a7b34
66 changed files with 1170 additions and 1271 deletions
|
@ -398,4 +398,12 @@ impl<Id> Res<Id> {
|
|||
Res::Err => Res::Err,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn macro_kind(self) -> Option<MacroKind> {
|
||||
match self {
|
||||
Res::Def(DefKind::Macro(kind), _) => Some(kind),
|
||||
Res::NonMacroAttr(..) => Some(MacroKind::Attr),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
//! Here we build the "reduced graph": the graph of the module tree without
|
||||
//! any imports resolved.
|
||||
|
||||
use crate::macros::{InvocationData, ParentScope, LegacyScope};
|
||||
use crate::macros::{InvocationData, LegacyScope};
|
||||
use crate::resolve_imports::ImportDirective;
|
||||
use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
|
||||
use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
|
||||
use crate::{ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
|
||||
use crate::{ModuleOrUniformRoot, ParentScope, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
|
||||
use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
|
||||
use crate::{resolve_error, resolve_struct_error, ResolutionError, Determinacy};
|
||||
|
||||
|
|
|
@ -2,21 +2,84 @@ use std::cmp::Reverse;
|
|||
|
||||
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
||||
use log::debug;
|
||||
use rustc::hir::def::{self, DefKind, CtorKind, Namespace::*};
|
||||
use rustc::hir::def::{self, DefKind, CtorKind, NonMacroAttrKind};
|
||||
use rustc::hir::def::Namespace::{self, *};
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
|
||||
use rustc::hir::PrimTy;
|
||||
use rustc::session::{Session, config::nightly_options};
|
||||
use syntax::ast::{self, Expr, ExprKind, Ident};
|
||||
use rustc::ty::{self, DefIdTree};
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use syntax::ast::{self, Expr, ExprKind, Ident, NodeId, Path, Ty, TyKind};
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax::feature_gate::BUILTIN_ATTRIBUTES;
|
||||
use syntax::symbol::{Symbol, kw};
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax_pos::{BytePos, Span};
|
||||
|
||||
use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
|
||||
use crate::{is_self_type, is_self_value, path_names_to_string, KNOWN_TOOLS};
|
||||
use crate::{CrateLint, LegacyScope, Module, ModuleKind, ModuleOrUniformRoot};
|
||||
use crate::{PathResult, PathSource, ParentScope, Resolver, RibKind, Scope, ScopeSet, Segment};
|
||||
|
||||
type Res = def::Res<ast::NodeId>;
|
||||
|
||||
use crate::macros::ParentScope;
|
||||
use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
|
||||
use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_names_to_string};
|
||||
use crate::{AssocSuggestion, CrateLint, ImportSuggestion, ModuleOrUniformRoot, PathResult,
|
||||
PathSource, Resolver, Segment, Suggestion};
|
||||
/// A vector of spans and replacements, a message and applicability.
|
||||
crate type Suggestion = (Vec<(Span, String)>, String, Applicability);
|
||||
|
||||
/// A field or associated item from self type suggested in case of resolution failure.
|
||||
enum AssocSuggestion {
|
||||
Field,
|
||||
MethodWithSelf,
|
||||
AssocItem,
|
||||
}
|
||||
|
||||
struct TypoSuggestion {
|
||||
candidate: Symbol,
|
||||
|
||||
/// The kind of the binding ("crate", "module", etc.)
|
||||
kind: &'static str,
|
||||
|
||||
/// An appropriate article to refer to the binding ("a", "an", etc.)
|
||||
article: &'static str,
|
||||
}
|
||||
|
||||
impl TypoSuggestion {
|
||||
fn from_res(candidate: Symbol, res: Res) -> TypoSuggestion {
|
||||
TypoSuggestion { candidate, kind: res.descr(), article: res.article() }
|
||||
}
|
||||
}
|
||||
|
||||
/// A free importable items suggested in case of resolution failure.
|
||||
crate struct ImportSuggestion {
|
||||
did: Option<DefId>,
|
||||
pub path: Path,
|
||||
}
|
||||
|
||||
fn add_typo_suggestion(
|
||||
err: &mut DiagnosticBuilder<'_>, suggestion: Option<TypoSuggestion>, span: Span
|
||||
) -> bool {
|
||||
if let Some(suggestion) = suggestion {
|
||||
let msg = format!("{} {} with a similar name exists", suggestion.article, suggestion.kind);
|
||||
err.span_suggestion(
|
||||
span, &msg, suggestion.candidate.to_string(), Applicability::MaybeIncorrect
|
||||
);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn add_module_candidates(
|
||||
module: Module<'_>, names: &mut Vec<TypoSuggestion>, filter_fn: &impl Fn(Res) -> bool
|
||||
) {
|
||||
for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
|
||||
if let Some(binding) = resolution.borrow().binding {
|
||||
let res = binding.res();
|
||||
if filter_fn(res) {
|
||||
names.push(TypoSuggestion::from_res(ident.name, res));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
/// Handles error reporting for `smart_resolve_path_fragment` function.
|
||||
|
@ -204,24 +267,10 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut levenshtein_worked = false;
|
||||
|
||||
// Try Levenshtein algorithm.
|
||||
let suggestion = self.lookup_typo_candidate(path, ns, is_expected, span);
|
||||
if let Some(suggestion) = suggestion {
|
||||
let msg = format!(
|
||||
"{} {} with a similar name exists",
|
||||
suggestion.article, suggestion.kind
|
||||
);
|
||||
err.span_suggestion(
|
||||
ident_span,
|
||||
&msg,
|
||||
suggestion.candidate.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
||||
levenshtein_worked = true;
|
||||
}
|
||||
let levenshtein_worked = add_typo_suggestion(
|
||||
&mut err, self.lookup_typo_candidate(path, ns, is_expected, span), ident_span
|
||||
);
|
||||
|
||||
// Try context-dependent help if relaxed lookup didn't work.
|
||||
if let Some(res) = res {
|
||||
|
@ -365,7 +414,7 @@ impl<'a> Resolver<'a> {
|
|||
};
|
||||
|
||||
match (res, source) {
|
||||
(Res::Def(DefKind::Macro(..), _), _) => {
|
||||
(Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use `!` to invoke the macro",
|
||||
|
@ -439,6 +488,513 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn lookup_assoc_candidate<FilterFn>(&mut self,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
filter_fn: FilterFn)
|
||||
-> Option<AssocSuggestion>
|
||||
where FilterFn: Fn(Res) -> bool
|
||||
{
|
||||
fn extract_node_id(t: &Ty) -> Option<NodeId> {
|
||||
match t.node {
|
||||
TyKind::Path(None, _) => Some(t.id),
|
||||
TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty),
|
||||
// This doesn't handle the remaining `Ty` variants as they are not
|
||||
// that commonly the self_type, it might be interesting to provide
|
||||
// support for those in future.
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Fields are generally expected in the same contexts as locals.
|
||||
if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) {
|
||||
if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
|
||||
// Look for a field with the same name in the current self_type.
|
||||
if let Some(resolution) = self.partial_res_map.get(&node_id) {
|
||||
match resolution.base_res() {
|
||||
Res::Def(DefKind::Struct, did) | Res::Def(DefKind::Union, did)
|
||||
if resolution.unresolved_segments() == 0 => {
|
||||
if let Some(field_names) = self.field_names.get(&did) {
|
||||
if field_names.iter().any(|&field_name| ident.name == field_name) {
|
||||
return Some(AssocSuggestion::Field);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for assoc_type_ident in &self.current_trait_assoc_types {
|
||||
if *assoc_type_ident == ident {
|
||||
return Some(AssocSuggestion::AssocItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Look for associated items in the current trait.
|
||||
if let Some((module, _)) = self.current_trait_ref {
|
||||
if let Ok(binding) = self.resolve_ident_in_module(
|
||||
ModuleOrUniformRoot::Module(module),
|
||||
ident,
|
||||
ns,
|
||||
None,
|
||||
false,
|
||||
module.span,
|
||||
) {
|
||||
let res = binding.res();
|
||||
if filter_fn(res) {
|
||||
return Some(if self.has_self.contains(&res.def_id()) {
|
||||
AssocSuggestion::MethodWithSelf
|
||||
} else {
|
||||
AssocSuggestion::AssocItem
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Lookup typo candidate in scope for a macro or import.
|
||||
fn early_lookup_typo_candidate(
|
||||
&mut self,
|
||||
scope_set: ScopeSet,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
ident: Ident,
|
||||
filter_fn: &impl Fn(Res) -> bool,
|
||||
) -> Option<TypoSuggestion> {
|
||||
let mut suggestions = Vec::new();
|
||||
self.visit_scopes(scope_set, parent_scope, ident, |this, scope, _| {
|
||||
match scope {
|
||||
Scope::DeriveHelpers => {
|
||||
let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
|
||||
if filter_fn(res) {
|
||||
for derive in &parent_scope.derives {
|
||||
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
||||
if let Ok((Some(ext), _)) = this.resolve_macro_path(
|
||||
derive, Some(MacroKind::Derive), &parent_scope, false, false
|
||||
) {
|
||||
suggestions.extend(ext.helper_attrs.iter().map(|name| {
|
||||
TypoSuggestion::from_res(*name, res)
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Scope::MacroRules(legacy_scope) => {
|
||||
if let LegacyScope::Binding(legacy_binding) = legacy_scope {
|
||||
let res = legacy_binding.binding.res();
|
||||
if filter_fn(res) {
|
||||
suggestions.push(
|
||||
TypoSuggestion::from_res(legacy_binding.ident.name, res)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Scope::CrateRoot => {
|
||||
let root_ident = Ident::new(kw::PathRoot, ident.span);
|
||||
let root_module = this.resolve_crate_root(root_ident);
|
||||
add_module_candidates(root_module, &mut suggestions, filter_fn);
|
||||
}
|
||||
Scope::Module(module) => {
|
||||
add_module_candidates(module, &mut suggestions, filter_fn);
|
||||
}
|
||||
Scope::MacroUsePrelude => {
|
||||
suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
|
||||
let res = binding.res();
|
||||
if filter_fn(res) {
|
||||
Some(TypoSuggestion::from_res(*name, res))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}));
|
||||
}
|
||||
Scope::BuiltinMacros => {
|
||||
suggestions.extend(this.builtin_macros.iter().filter_map(|(name, binding)| {
|
||||
let res = binding.res();
|
||||
if filter_fn(res) {
|
||||
Some(TypoSuggestion::from_res(*name, res))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}));
|
||||
}
|
||||
Scope::BuiltinAttrs => {
|
||||
let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
|
||||
if filter_fn(res) {
|
||||
suggestions.extend(BUILTIN_ATTRIBUTES.iter().map(|(name, ..)| {
|
||||
TypoSuggestion::from_res(*name, res)
|
||||
}));
|
||||
}
|
||||
}
|
||||
Scope::LegacyPluginHelpers => {
|
||||
let res = Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper);
|
||||
if filter_fn(res) {
|
||||
let plugin_attributes = this.session.plugin_attributes.borrow();
|
||||
suggestions.extend(plugin_attributes.iter().map(|(name, _)| {
|
||||
TypoSuggestion::from_res(*name, res)
|
||||
}));
|
||||
}
|
||||
}
|
||||
Scope::ExternPrelude => {
|
||||
suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
|
||||
let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX));
|
||||
if filter_fn(res) {
|
||||
Some(TypoSuggestion::from_res(ident.name, res))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}));
|
||||
}
|
||||
Scope::ToolPrelude => {
|
||||
let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
|
||||
suggestions.extend(KNOWN_TOOLS.iter().map(|name| {
|
||||
TypoSuggestion::from_res(*name, res)
|
||||
}));
|
||||
}
|
||||
Scope::StdLibPrelude => {
|
||||
if let Some(prelude) = this.prelude {
|
||||
add_module_candidates(prelude, &mut suggestions, filter_fn);
|
||||
}
|
||||
}
|
||||
Scope::BuiltinTypes => {
|
||||
let primitive_types = &this.primitive_type_table.primitive_types;
|
||||
suggestions.extend(
|
||||
primitive_types.iter().flat_map(|(name, prim_ty)| {
|
||||
let res = Res::PrimTy(*prim_ty);
|
||||
if filter_fn(res) {
|
||||
Some(TypoSuggestion::from_res(*name, res))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
None::<()>
|
||||
});
|
||||
|
||||
// Make sure error reporting is deterministic.
|
||||
suggestions.sort_by_cached_key(|suggestion| suggestion.candidate.as_str());
|
||||
|
||||
match find_best_match_for_name(
|
||||
suggestions.iter().map(|suggestion| &suggestion.candidate),
|
||||
&ident.as_str(),
|
||||
None,
|
||||
) {
|
||||
Some(found) if found != ident.name => suggestions
|
||||
.into_iter()
|
||||
.find(|suggestion| suggestion.candidate == found),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_typo_candidate(
|
||||
&mut self,
|
||||
path: &[Segment],
|
||||
ns: Namespace,
|
||||
filter_fn: &impl Fn(Res) -> bool,
|
||||
span: Span,
|
||||
) -> Option<TypoSuggestion> {
|
||||
let mut names = Vec::new();
|
||||
if path.len() == 1 {
|
||||
// Search in lexical scope.
|
||||
// Walk backwards up the ribs in scope and collect candidates.
|
||||
for rib in self.ribs[ns].iter().rev() {
|
||||
// Locals and type parameters
|
||||
for (ident, &res) in &rib.bindings {
|
||||
if filter_fn(res) {
|
||||
names.push(TypoSuggestion::from_res(ident.name, res));
|
||||
}
|
||||
}
|
||||
// Items in scope
|
||||
if let RibKind::ModuleRibKind(module) = rib.kind {
|
||||
// Items from this module
|
||||
add_module_candidates(module, &mut names, &filter_fn);
|
||||
|
||||
if let ModuleKind::Block(..) = module.kind {
|
||||
// We can see through blocks
|
||||
} else {
|
||||
// Items from the prelude
|
||||
if !module.no_implicit_prelude {
|
||||
names.extend(self.extern_prelude.clone().iter().flat_map(|(ident, _)| {
|
||||
self.crate_loader
|
||||
.maybe_process_path_extern(ident.name, ident.span)
|
||||
.and_then(|crate_id| {
|
||||
let crate_mod = Res::Def(
|
||||
DefKind::Mod,
|
||||
DefId {
|
||||
krate: crate_id,
|
||||
index: CRATE_DEF_INDEX,
|
||||
},
|
||||
);
|
||||
|
||||
if filter_fn(crate_mod) {
|
||||
Some(TypoSuggestion {
|
||||
candidate: ident.name,
|
||||
article: "a",
|
||||
kind: "crate",
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}));
|
||||
|
||||
if let Some(prelude) = self.prelude {
|
||||
add_module_candidates(prelude, &mut names, &filter_fn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add primitive types to the mix
|
||||
if filter_fn(Res::PrimTy(PrimTy::Bool)) {
|
||||
names.extend(
|
||||
self.primitive_type_table.primitive_types.iter().map(|(name, prim_ty)| {
|
||||
TypoSuggestion::from_res(*name, Res::PrimTy(*prim_ty))
|
||||
})
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Search in module.
|
||||
let mod_path = &path[..path.len() - 1];
|
||||
if let PathResult::Module(module) = self.resolve_path_without_parent_scope(
|
||||
mod_path, Some(TypeNS), false, span, CrateLint::No
|
||||
) {
|
||||
if let ModuleOrUniformRoot::Module(module) = module {
|
||||
add_module_candidates(module, &mut names, &filter_fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let name = path[path.len() - 1].ident.name;
|
||||
// Make sure error reporting is deterministic.
|
||||
names.sort_by_cached_key(|suggestion| suggestion.candidate.as_str());
|
||||
|
||||
match find_best_match_for_name(
|
||||
names.iter().map(|suggestion| &suggestion.candidate),
|
||||
&name.as_str(),
|
||||
None,
|
||||
) {
|
||||
Some(found) if found != name => names
|
||||
.into_iter()
|
||||
.find(|suggestion| suggestion.candidate == found),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_import_candidates_from_module<FilterFn>(&mut self,
|
||||
lookup_ident: Ident,
|
||||
namespace: Namespace,
|
||||
start_module: Module<'a>,
|
||||
crate_name: Ident,
|
||||
filter_fn: FilterFn)
|
||||
-> Vec<ImportSuggestion>
|
||||
where FilterFn: Fn(Res) -> bool
|
||||
{
|
||||
let mut candidates = Vec::new();
|
||||
let mut seen_modules = FxHashSet::default();
|
||||
let not_local_module = crate_name.name != kw::Crate;
|
||||
let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), not_local_module)];
|
||||
|
||||
while let Some((in_module,
|
||||
path_segments,
|
||||
in_module_is_extern)) = worklist.pop() {
|
||||
self.populate_module_if_necessary(in_module);
|
||||
|
||||
// We have to visit module children in deterministic order to avoid
|
||||
// instabilities in reported imports (#43552).
|
||||
in_module.for_each_child_stable(|ident, ns, name_binding| {
|
||||
// avoid imports entirely
|
||||
if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
|
||||
// avoid non-importable candidates as well
|
||||
if !name_binding.is_importable() { return; }
|
||||
|
||||
// collect results based on the filter function
|
||||
if ident.name == lookup_ident.name && ns == namespace {
|
||||
let res = name_binding.res();
|
||||
if filter_fn(res) {
|
||||
// create the path
|
||||
let mut segms = path_segments.clone();
|
||||
if lookup_ident.span.rust_2018() {
|
||||
// crate-local absolute paths start with `crate::` in edition 2018
|
||||
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
|
||||
segms.insert(
|
||||
0, ast::PathSegment::from_ident(crate_name)
|
||||
);
|
||||
}
|
||||
|
||||
segms.push(ast::PathSegment::from_ident(ident));
|
||||
let path = Path {
|
||||
span: name_binding.span,
|
||||
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.vis == ty::Visibility::Public {
|
||||
let did = match res {
|
||||
Res::Def(DefKind::Ctor(..), did) => self.parent(did),
|
||||
_ => res.opt_def_id(),
|
||||
};
|
||||
candidates.push(ImportSuggestion { did, path });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collect submodules to explore
|
||||
if let Some(module) = name_binding.module() {
|
||||
// form the path
|
||||
let mut path_segments = path_segments.clone();
|
||||
path_segments.push(ast::PathSegment::from_ident(ident));
|
||||
|
||||
let is_extern_crate_that_also_appears_in_prelude =
|
||||
name_binding.is_extern_crate() &&
|
||||
lookup_ident.span.rust_2018();
|
||||
|
||||
let is_visible_to_user =
|
||||
!in_module_is_extern || name_binding.vis == ty::Visibility::Public;
|
||||
|
||||
if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user {
|
||||
// add the module to the lookup
|
||||
let is_extern = in_module_is_extern || name_binding.is_extern_crate();
|
||||
if seen_modules.insert(module.def_id().unwrap()) {
|
||||
worklist.push((module, path_segments, is_extern));
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
candidates
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// N.B., the method does not look into imports, but this is not a problem,
|
||||
/// since we report the definitions (thus, the de-aliased imports).
|
||||
crate fn lookup_import_candidates<FilterFn>(
|
||||
&mut self, lookup_ident: Ident, namespace: Namespace, filter_fn: FilterFn
|
||||
) -> Vec<ImportSuggestion>
|
||||
where FilterFn: Fn(Res) -> bool
|
||||
{
|
||||
let mut suggestions = self.lookup_import_candidates_from_module(
|
||||
lookup_ident, namespace, self.graph_root, Ident::with_empty_ctxt(kw::Crate), &filter_fn
|
||||
);
|
||||
|
||||
if lookup_ident.span.rust_2018() {
|
||||
let extern_prelude_names = self.extern_prelude.clone();
|
||||
for (ident, _) in extern_prelude_names.into_iter() {
|
||||
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
|
||||
ident.span) {
|
||||
let crate_root = self.get_module(DefId {
|
||||
krate: crate_id,
|
||||
index: CRATE_DEF_INDEX,
|
||||
});
|
||||
self.populate_module_if_necessary(&crate_root);
|
||||
|
||||
suggestions.extend(self.lookup_import_candidates_from_module(
|
||||
lookup_ident, namespace, crate_root, ident, &filter_fn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suggestions
|
||||
}
|
||||
|
||||
fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {
|
||||
let mut result = None;
|
||||
let mut seen_modules = FxHashSet::default();
|
||||
let mut worklist = vec![(self.graph_root, Vec::new())];
|
||||
|
||||
while let Some((in_module, path_segments)) = worklist.pop() {
|
||||
// abort if the module is already found
|
||||
if result.is_some() { break; }
|
||||
|
||||
self.populate_module_if_necessary(in_module);
|
||||
|
||||
in_module.for_each_child_stable(|ident, _, name_binding| {
|
||||
// abort if the module is already found or if name_binding is private external
|
||||
if result.is_some() || !name_binding.vis.is_visible_locally() {
|
||||
return
|
||||
}
|
||||
if let Some(module) = name_binding.module() {
|
||||
// form the path
|
||||
let mut path_segments = path_segments.clone();
|
||||
path_segments.push(ast::PathSegment::from_ident(ident));
|
||||
let module_def_id = module.def_id().unwrap();
|
||||
if module_def_id == def_id {
|
||||
let path = Path {
|
||||
span: name_binding.span,
|
||||
segments: path_segments,
|
||||
};
|
||||
result = Some((module, ImportSuggestion { did: Some(def_id), path }));
|
||||
} else {
|
||||
// add the module to the lookup
|
||||
if seen_modules.insert(module_def_id) {
|
||||
worklist.push((module, path_segments));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn collect_enum_variants(&mut self, def_id: DefId) -> Option<Vec<Path>> {
|
||||
self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| {
|
||||
self.populate_module_if_necessary(enum_module);
|
||||
|
||||
let mut variants = Vec::new();
|
||||
enum_module.for_each_child_stable(|ident, _, name_binding| {
|
||||
if let Res::Def(DefKind::Variant, _) = name_binding.res() {
|
||||
let mut segms = enum_import_suggestion.path.segments.clone();
|
||||
segms.push(ast::PathSegment::from_ident(ident));
|
||||
variants.push(Path {
|
||||
span: name_binding.span,
|
||||
segments: segms,
|
||||
});
|
||||
}
|
||||
});
|
||||
variants
|
||||
})
|
||||
}
|
||||
|
||||
crate fn unresolved_macro_suggestions(
|
||||
&mut self,
|
||||
err: &mut DiagnosticBuilder<'a>,
|
||||
macro_kind: MacroKind,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
ident: Ident,
|
||||
) {
|
||||
let is_expected = &|res: Res| res.macro_kind() == Some(macro_kind);
|
||||
let suggestion = self.early_lookup_typo_candidate(
|
||||
ScopeSet::Macro(macro_kind), &parent_scope, ident, is_expected
|
||||
);
|
||||
add_typo_suggestion(err, suggestion, ident.span);
|
||||
|
||||
if macro_kind == MacroKind::Derive &&
|
||||
(ident.as_str() == "Send" || ident.as_str() == "Sync") {
|
||||
let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
|
||||
err.span_note(ident.span, &msg);
|
||||
}
|
||||
if self.macro_names.contains(&ident.modern()) {
|
||||
err.help("have you added the `#[macro_use]` on the module/import?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
|
@ -871,3 +1427,70 @@ fn find_span_immediately_after_crate_name(
|
|||
|
||||
(next_left_bracket == after_second_colon, from_second_colon)
|
||||
}
|
||||
|
||||
/// Gets the stringified path for an enum from an `ImportSuggestion` for an enum variant.
|
||||
fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, String) {
|
||||
let variant_path = &suggestion.path;
|
||||
let variant_path_string = path_names_to_string(variant_path);
|
||||
|
||||
let path_len = suggestion.path.segments.len();
|
||||
let enum_path = ast::Path {
|
||||
span: suggestion.path.span,
|
||||
segments: suggestion.path.segments[0..path_len - 1].to_vec(),
|
||||
};
|
||||
let enum_path_string = path_names_to_string(&enum_path);
|
||||
|
||||
(variant_path_string, enum_path_string)
|
||||
}
|
||||
|
||||
/// 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
|
||||
crate fn show_candidates(
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
// This is `None` if all placement locations are inside expansions
|
||||
span: Option<Span>,
|
||||
candidates: &[ImportSuggestion],
|
||||
better: bool,
|
||||
found_use: bool,
|
||||
) {
|
||||
// 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<_> =
|
||||
candidates.into_iter().map(|c| path_names_to_string(&c.path)).collect();
|
||||
path_strings.sort();
|
||||
|
||||
let better = if better { "better " } else { "" };
|
||||
let msg_diff = match path_strings.len() {
|
||||
1 => " is found in another module, you can import it",
|
||||
_ => "s are found in other modules, you can import them",
|
||||
};
|
||||
let msg = format!("possible {}candidate{} into scope", better, msg_diff);
|
||||
|
||||
if let Some(span) = span {
|
||||
for candidate in &mut path_strings {
|
||||
// produce an additional newline to separate the new use statement
|
||||
// from the directly following item.
|
||||
let additional_newline = if found_use {
|
||||
""
|
||||
} else {
|
||||
"\n"
|
||||
};
|
||||
*candidate = format!("use {};\n{}", candidate, additional_newline);
|
||||
}
|
||||
|
||||
err.span_suggestions(
|
||||
span,
|
||||
&msg,
|
||||
path_strings.into_iter(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
} else {
|
||||
let mut msg = msg;
|
||||
msg.push(':');
|
||||
for candidate in path_strings {
|
||||
msg.push('\n');
|
||||
msg.push_str(&candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ use rustc::hir::def::{
|
|||
use rustc::hir::def::Namespace::*;
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
|
||||
use rustc::hir::{TraitCandidate, TraitMap, GlobMap};
|
||||
use rustc::ty::{self, DefIdTree};
|
||||
use rustc::ty;
|
||||
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
|
||||
use rustc::{bug, span_bug};
|
||||
|
||||
|
@ -69,9 +69,10 @@ use rustc_data_structures::ptr_key::PtrKey;
|
|||
use rustc_data_structures::sync::Lrc;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use diagnostics::{Suggestion, ImportSuggestion};
|
||||
use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
|
||||
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
|
||||
use macros::{InvocationData, LegacyBinding, ParentScope};
|
||||
use macros::{InvocationData, LegacyBinding, LegacyScope};
|
||||
|
||||
type Res = def::Res<NodeId>;
|
||||
|
||||
|
@ -84,9 +85,7 @@ mod check_unused;
|
|||
mod build_reduced_graph;
|
||||
mod resolve_imports;
|
||||
|
||||
fn is_known_tool(name: Name) -> bool {
|
||||
["clippy", "rustfmt"].contains(&&*name.as_str())
|
||||
}
|
||||
const KNOWN_TOOLS: &[Name] = &[sym::clippy, sym::rustfmt];
|
||||
|
||||
enum Weak {
|
||||
Yes,
|
||||
|
@ -105,6 +104,29 @@ impl Determinacy {
|
|||
}
|
||||
}
|
||||
|
||||
/// A specific scope in which a name can be looked up.
|
||||
/// This enum is currently used only for early resolution (imports and macros),
|
||||
/// but not for late resolution yet.
|
||||
#[derive(Clone, Copy)]
|
||||
enum Scope<'a> {
|
||||
DeriveHelpers,
|
||||
MacroRules(LegacyScope<'a>),
|
||||
CrateRoot,
|
||||
Module(Module<'a>),
|
||||
MacroUsePrelude,
|
||||
BuiltinMacros,
|
||||
BuiltinAttrs,
|
||||
LegacyPluginHelpers,
|
||||
ExternPrelude,
|
||||
ToolPrelude,
|
||||
StdLibPrelude,
|
||||
BuiltinTypes,
|
||||
}
|
||||
|
||||
/// Names from different contexts may want to visit different subsets of all specific scopes
|
||||
/// with different restrictions when looking up the resolution.
|
||||
/// This enum is currently used only for early resolution (imports and macros),
|
||||
/// but not for late resolution yet.
|
||||
enum ScopeSet {
|
||||
Import(Namespace),
|
||||
AbsolutePath(Namespace),
|
||||
|
@ -112,17 +134,16 @@ enum ScopeSet {
|
|||
Module,
|
||||
}
|
||||
|
||||
/// A free importable items suggested in case of resolution failure.
|
||||
struct ImportSuggestion {
|
||||
did: Option<DefId>,
|
||||
path: Path,
|
||||
}
|
||||
|
||||
/// A field or associated item from self type suggested in case of resolution failure.
|
||||
enum AssocSuggestion {
|
||||
Field,
|
||||
MethodWithSelf,
|
||||
AssocItem,
|
||||
/// Everything you need to know about a name's location to resolve it.
|
||||
/// Serves as a starting point for the scope visitor.
|
||||
/// This struct is currently used only for early resolution (imports and macros),
|
||||
/// but not for late resolution yet.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParentScope<'a> {
|
||||
module: Module<'a>,
|
||||
expansion: Mark,
|
||||
legacy: LegacyScope<'a>,
|
||||
derives: Vec<ast::Path>,
|
||||
}
|
||||
|
||||
#[derive(Eq)]
|
||||
|
@ -132,16 +153,6 @@ struct BindingError {
|
|||
target: BTreeSet<Span>,
|
||||
}
|
||||
|
||||
struct TypoSuggestion {
|
||||
candidate: Symbol,
|
||||
|
||||
/// The kind of the binding ("crate", "module", etc.)
|
||||
kind: &'static str,
|
||||
|
||||
/// An appropriate article to refer to the binding ("a", "an", etc.)
|
||||
article: &'static str,
|
||||
}
|
||||
|
||||
impl PartialOrd for BindingError {
|
||||
fn partial_cmp(&self, other: &BindingError) -> Option<cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
|
@ -160,9 +171,6 @@ impl Ord for BindingError {
|
|||
}
|
||||
}
|
||||
|
||||
/// A vector of spans and replacements, a message and applicability.
|
||||
type Suggestion = (Vec<(Span, String)>, String, Applicability);
|
||||
|
||||
enum ResolutionError<'a> {
|
||||
/// Error E0401: can't use type or const parameters from outer function.
|
||||
GenericParamsFromOuterFunction(Res),
|
||||
|
@ -1488,11 +1496,7 @@ impl<'a> NameBinding<'a> {
|
|||
}
|
||||
|
||||
fn macro_kind(&self) -> Option<MacroKind> {
|
||||
match self.res() {
|
||||
Res::Def(DefKind::Macro(kind), _) => Some(kind),
|
||||
Res::NonMacroAttr(..) => Some(MacroKind::Attr),
|
||||
_ => None,
|
||||
}
|
||||
self.res().macro_kind()
|
||||
}
|
||||
|
||||
fn descr(&self) -> &'static str {
|
||||
|
@ -2134,6 +2138,149 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A generic scope visitor.
|
||||
/// Visits scopes in order to resolve some identifier in them or perform other actions.
|
||||
/// If the callback returns `Some` result, we stop visiting scopes and return it.
|
||||
fn visit_scopes<T>(
|
||||
&mut self,
|
||||
scope_set: ScopeSet,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
ident: Ident,
|
||||
mut visitor: impl FnMut(&mut Self, Scope<'a>, Ident) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
// General principles:
|
||||
// 1. Not controlled (user-defined) names should have higher priority than controlled names
|
||||
// built into the language or standard library. This way we can add new names into the
|
||||
// language or standard library without breaking user code.
|
||||
// 2. "Closed set" below means new names cannot appear after the current resolution attempt.
|
||||
// Places to search (in order of decreasing priority):
|
||||
// (Type NS)
|
||||
// 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
|
||||
// (open set, not controlled).
|
||||
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled).
|
||||
// 3. Extern prelude (open, the open part is from macro expansions, not controlled).
|
||||
// 4. Tool modules (closed, controlled right now, but not in the future).
|
||||
// 5. Standard library prelude (de-facto closed, controlled).
|
||||
// 6. Language prelude (closed, controlled).
|
||||
// (Value NS)
|
||||
// 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet
|
||||
// (open set, not controlled).
|
||||
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled).
|
||||
// 3. Standard library prelude (de-facto closed, controlled).
|
||||
// (Macro NS)
|
||||
// 1-3. Derive helpers (open, not controlled). All ambiguities with other names
|
||||
// are currently reported as errors. They should be higher in priority than preludes
|
||||
// and probably even names in modules according to the "general principles" above. They
|
||||
// also should be subject to restricted shadowing because are effectively produced by
|
||||
// derives (you need to resolve the derive first to add helpers into scope), but they
|
||||
// should be available before the derive is expanded for compatibility.
|
||||
// It's mess in general, so we are being conservative for now.
|
||||
// 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher
|
||||
// priority than prelude macros, but create ambiguities with macros in modules.
|
||||
// 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled). Have higher priority than prelude macros, but create
|
||||
// ambiguities with `macro_rules`.
|
||||
// 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
|
||||
// 4a. User-defined prelude from macro-use
|
||||
// (open, the open part is from macro expansions, not controlled).
|
||||
// 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
|
||||
// 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
|
||||
// 6. Language prelude: builtin attributes (closed, controlled).
|
||||
// 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
|
||||
// but introduced by legacy plugins using `register_attribute`. Priority is somewhere
|
||||
// in prelude, not sure where exactly (creates ambiguities with any other prelude names).
|
||||
|
||||
let rust_2015 = ident.span.rust_2015();
|
||||
let (ns, is_absolute_path) = match scope_set {
|
||||
ScopeSet::Import(ns) => (ns, false),
|
||||
ScopeSet::AbsolutePath(ns) => (ns, true),
|
||||
ScopeSet::Macro(_) => (MacroNS, false),
|
||||
ScopeSet::Module => (TypeNS, false),
|
||||
};
|
||||
let mut scope = match ns {
|
||||
_ if is_absolute_path => Scope::CrateRoot,
|
||||
TypeNS | ValueNS => Scope::Module(parent_scope.module),
|
||||
MacroNS => Scope::DeriveHelpers,
|
||||
};
|
||||
let mut ident = ident.modern();
|
||||
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
|
||||
|
||||
loop {
|
||||
let visit = match scope {
|
||||
Scope::DeriveHelpers => true,
|
||||
Scope::MacroRules(..) => true,
|
||||
Scope::CrateRoot => true,
|
||||
Scope::Module(..) => true,
|
||||
Scope::MacroUsePrelude => use_prelude || rust_2015,
|
||||
Scope::BuiltinMacros => true,
|
||||
Scope::BuiltinAttrs => true,
|
||||
Scope::LegacyPluginHelpers => use_prelude || rust_2015,
|
||||
Scope::ExternPrelude => use_prelude || is_absolute_path,
|
||||
Scope::ToolPrelude => use_prelude,
|
||||
Scope::StdLibPrelude => use_prelude,
|
||||
Scope::BuiltinTypes => true,
|
||||
};
|
||||
|
||||
if visit {
|
||||
if let break_result @ Some(..) = visitor(self, scope, ident) {
|
||||
return break_result;
|
||||
}
|
||||
}
|
||||
|
||||
scope = match scope {
|
||||
Scope::DeriveHelpers =>
|
||||
Scope::MacroRules(parent_scope.legacy),
|
||||
Scope::MacroRules(legacy_scope) => match legacy_scope {
|
||||
LegacyScope::Binding(binding) => Scope::MacroRules(
|
||||
binding.parent_legacy_scope
|
||||
),
|
||||
LegacyScope::Invocation(invoc) => Scope::MacroRules(
|
||||
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope)
|
||||
),
|
||||
LegacyScope::Empty => Scope::Module(parent_scope.module),
|
||||
}
|
||||
Scope::CrateRoot => match ns {
|
||||
TypeNS => {
|
||||
ident.span.adjust(Mark::root());
|
||||
Scope::ExternPrelude
|
||||
}
|
||||
ValueNS | MacroNS => break,
|
||||
}
|
||||
Scope::Module(module) => {
|
||||
use_prelude = !module.no_implicit_prelude;
|
||||
match self.hygienic_lexical_parent(module, &mut ident.span) {
|
||||
Some(parent_module) => Scope::Module(parent_module),
|
||||
None => {
|
||||
ident.span.adjust(Mark::root());
|
||||
match ns {
|
||||
TypeNS => Scope::ExternPrelude,
|
||||
ValueNS => Scope::StdLibPrelude,
|
||||
MacroNS => Scope::MacroUsePrelude,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Scope::MacroUsePrelude => Scope::StdLibPrelude,
|
||||
Scope::BuiltinMacros => Scope::BuiltinAttrs,
|
||||
Scope::BuiltinAttrs => Scope::LegacyPluginHelpers,
|
||||
Scope::LegacyPluginHelpers => break, // nowhere else to search
|
||||
Scope::ExternPrelude if is_absolute_path => break,
|
||||
Scope::ExternPrelude => Scope::ToolPrelude,
|
||||
Scope::ToolPrelude => Scope::StdLibPrelude,
|
||||
Scope::StdLibPrelude => match ns {
|
||||
TypeNS => Scope::BuiltinTypes,
|
||||
ValueNS => break, // nowhere else to search
|
||||
MacroNS => Scope::BuiltinMacros,
|
||||
}
|
||||
Scope::BuiltinTypes => break, // nowhere else to search
|
||||
};
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
|
||||
/// More specifically, we proceed up the hierarchy of scopes and return the binding for
|
||||
/// `ident` in the first scope that defines it (or None if no scopes define it).
|
||||
|
@ -2258,7 +2405,7 @@ impl<'a> Resolver<'a> {
|
|||
return Some(LexicalScopeBinding::Item(binding));
|
||||
}
|
||||
}
|
||||
if ns == TypeNS && is_known_tool(ident.name) {
|
||||
if ns == TypeNS && KNOWN_TOOLS.contains(&ident.name) {
|
||||
let binding = (Res::ToolMod, ty::Visibility::Public,
|
||||
DUMMY_SP, Mark::root()).to_name_binding(self.arenas);
|
||||
return Some(LexicalScopeBinding::Item(binding));
|
||||
|
@ -3517,9 +3664,7 @@ impl<'a> Resolver<'a> {
|
|||
crate_lint: CrateLint,
|
||||
) -> Option<PartialRes> {
|
||||
let mut fin_res = None;
|
||||
// FIXME: can't resolve paths in macro namespace yet, macros are
|
||||
// processed by the little special hack below.
|
||||
for (i, ns) in [primary_ns, TypeNS, ValueNS, /*MacroNS*/].iter().cloned().enumerate() {
|
||||
for (i, ns) in [primary_ns, TypeNS, ValueNS].iter().cloned().enumerate() {
|
||||
if i == 0 || ns != primary_ns {
|
||||
match self.resolve_qpath(id, qself, path, ns, span, global_by_default, crate_lint) {
|
||||
// If defer_to_typeck, then resolution > no resolution,
|
||||
|
@ -3528,21 +3673,23 @@ impl<'a> Resolver<'a> {
|
|||
defer_to_typeck =>
|
||||
return Some(partial_res),
|
||||
partial_res => if fin_res.is_none() { fin_res = partial_res },
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if primary_ns != MacroNS &&
|
||||
(self.macro_names.contains(&path[0].ident.modern()) ||
|
||||
self.builtin_macros.get(&path[0].ident.name).cloned()
|
||||
.and_then(NameBinding::macro_kind) == Some(MacroKind::Bang) ||
|
||||
self.macro_use_prelude.get(&path[0].ident.name).cloned()
|
||||
.and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) {
|
||||
// Return some dummy definition, it's enough for error reporting.
|
||||
return Some(PartialRes::new(Res::Def(
|
||||
DefKind::Macro(MacroKind::Bang),
|
||||
DefId::local(CRATE_DEF_INDEX),
|
||||
)));
|
||||
|
||||
// `MacroNS`
|
||||
assert!(primary_ns != MacroNS);
|
||||
if qself.is_none() {
|
||||
let path_seg = |seg: &Segment| ast::PathSegment::from_ident(seg.ident);
|
||||
let path = Path { segments: path.iter().map(path_seg).collect(), span };
|
||||
let parent_scope =
|
||||
ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
|
||||
if let Ok((_, res)) =
|
||||
self.resolve_macro_path(&path, None, &parent_scope, false, false) {
|
||||
return Some(PartialRes::new(res));
|
||||
}
|
||||
}
|
||||
|
||||
fin_res
|
||||
}
|
||||
|
||||
|
@ -4124,195 +4271,6 @@ impl<'a> Resolver<'a> {
|
|||
res
|
||||
}
|
||||
|
||||
fn lookup_assoc_candidate<FilterFn: Fn(Res) -> bool>(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
filter_fn: FilterFn,
|
||||
) -> Option<AssocSuggestion> {
|
||||
fn extract_node_id(t: &Ty) -> Option<NodeId> {
|
||||
match t.node {
|
||||
TyKind::Path(None, _) => Some(t.id),
|
||||
TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty),
|
||||
// This doesn't handle the remaining `Ty` variants as they are not
|
||||
// that commonly the self_type, it might be interesting to provide
|
||||
// support for those in future.
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Fields are generally expected in the same contexts as locals.
|
||||
if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) {
|
||||
if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
|
||||
// Look for a field with the same name in the current self_type.
|
||||
if let Some(resolution) = self.partial_res_map.get(&node_id) {
|
||||
match resolution.base_res() {
|
||||
Res::Def(DefKind::Struct, did) | Res::Def(DefKind::Union, did)
|
||||
if resolution.unresolved_segments() == 0 => {
|
||||
if let Some(field_names) = self.field_names.get(&did) {
|
||||
if field_names.iter().any(|&field_name| ident.name == field_name) {
|
||||
return Some(AssocSuggestion::Field);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for assoc_type_ident in &self.current_trait_assoc_types {
|
||||
if *assoc_type_ident == ident {
|
||||
return Some(AssocSuggestion::AssocItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Look for associated items in the current trait.
|
||||
if let Some((module, _)) = self.current_trait_ref {
|
||||
if let Ok(binding) = self.resolve_ident_in_module(
|
||||
ModuleOrUniformRoot::Module(module),
|
||||
ident,
|
||||
ns,
|
||||
None,
|
||||
false,
|
||||
module.span,
|
||||
) {
|
||||
let res = binding.res();
|
||||
if filter_fn(res) {
|
||||
debug!("extract_node_id res not filtered");
|
||||
return Some(if self.has_self.contains(&res.def_id()) {
|
||||
AssocSuggestion::MethodWithSelf
|
||||
} else {
|
||||
AssocSuggestion::AssocItem
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn lookup_typo_candidate<FilterFn>(
|
||||
&mut self,
|
||||
path: &[Segment],
|
||||
ns: Namespace,
|
||||
filter_fn: FilterFn,
|
||||
span: Span,
|
||||
) -> Option<TypoSuggestion>
|
||||
where
|
||||
FilterFn: Fn(Res) -> bool,
|
||||
{
|
||||
let add_module_candidates = |module: Module<'_>, names: &mut Vec<TypoSuggestion>| {
|
||||
for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
|
||||
if let Some(binding) = resolution.borrow().binding {
|
||||
if filter_fn(binding.res()) {
|
||||
names.push(TypoSuggestion {
|
||||
candidate: ident.name,
|
||||
article: binding.res().article(),
|
||||
kind: binding.res().descr(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut names = Vec::new();
|
||||
if path.len() == 1 {
|
||||
// Search in lexical scope.
|
||||
// Walk backwards up the ribs in scope and collect candidates.
|
||||
for rib in self.ribs[ns].iter().rev() {
|
||||
// Locals and type parameters
|
||||
for (ident, &res) in &rib.bindings {
|
||||
if filter_fn(res) {
|
||||
names.push(TypoSuggestion {
|
||||
candidate: ident.name,
|
||||
article: res.article(),
|
||||
kind: res.descr(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Items in scope
|
||||
if let ModuleRibKind(module) = rib.kind {
|
||||
// Items from this module
|
||||
add_module_candidates(module, &mut names);
|
||||
|
||||
if let ModuleKind::Block(..) = module.kind {
|
||||
// We can see through blocks
|
||||
} else {
|
||||
// Items from the prelude
|
||||
if !module.no_implicit_prelude {
|
||||
names.extend(self.extern_prelude.clone().iter().flat_map(|(ident, _)| {
|
||||
self.crate_loader
|
||||
.maybe_process_path_extern(ident.name, ident.span)
|
||||
.and_then(|crate_id| {
|
||||
let crate_mod = Res::Def(
|
||||
DefKind::Mod,
|
||||
DefId {
|
||||
krate: crate_id,
|
||||
index: CRATE_DEF_INDEX,
|
||||
},
|
||||
);
|
||||
|
||||
if filter_fn(crate_mod) {
|
||||
Some(TypoSuggestion {
|
||||
candidate: ident.name,
|
||||
article: "a",
|
||||
kind: "crate",
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}));
|
||||
|
||||
if let Some(prelude) = self.prelude {
|
||||
add_module_candidates(prelude, &mut names);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add primitive types to the mix
|
||||
if filter_fn(Res::PrimTy(Bool)) {
|
||||
names.extend(
|
||||
self.primitive_type_table.primitive_types.iter().map(|(name, _)| {
|
||||
TypoSuggestion {
|
||||
candidate: *name,
|
||||
article: "a",
|
||||
kind: "primitive type",
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Search in module.
|
||||
let mod_path = &path[..path.len() - 1];
|
||||
if let PathResult::Module(module) = self.resolve_path_without_parent_scope(
|
||||
mod_path, Some(TypeNS), false, span, CrateLint::No
|
||||
) {
|
||||
if let ModuleOrUniformRoot::Module(module) = module {
|
||||
add_module_candidates(module, &mut names);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let name = path[path.len() - 1].ident.name;
|
||||
// Make sure error reporting is deterministic.
|
||||
names.sort_by_cached_key(|suggestion| suggestion.candidate.as_str());
|
||||
|
||||
match find_best_match_for_name(
|
||||
names.iter().map(|suggestion| &suggestion.candidate),
|
||||
&name.as_str(),
|
||||
None,
|
||||
) {
|
||||
Some(found) if found != name => names
|
||||
.into_iter()
|
||||
.find(|suggestion| suggestion.candidate == found),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_resolved_label<F>(&mut self, label: Option<Label>, id: NodeId, f: F)
|
||||
where F: FnOnce(&mut Resolver<'_>)
|
||||
{
|
||||
|
@ -4606,193 +4564,6 @@ impl<'a> Resolver<'a> {
|
|||
import_ids
|
||||
}
|
||||
|
||||
fn lookup_import_candidates_from_module<FilterFn>(&mut self,
|
||||
lookup_ident: Ident,
|
||||
namespace: Namespace,
|
||||
start_module: &'a ModuleData<'a>,
|
||||
crate_name: Ident,
|
||||
filter_fn: FilterFn)
|
||||
-> Vec<ImportSuggestion>
|
||||
where FilterFn: Fn(Res) -> bool
|
||||
{
|
||||
let mut candidates = Vec::new();
|
||||
let mut seen_modules = FxHashSet::default();
|
||||
let not_local_module = crate_name.name != kw::Crate;
|
||||
let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), not_local_module)];
|
||||
|
||||
while let Some((in_module,
|
||||
path_segments,
|
||||
in_module_is_extern)) = worklist.pop() {
|
||||
self.populate_module_if_necessary(in_module);
|
||||
|
||||
// We have to visit module children in deterministic order to avoid
|
||||
// instabilities in reported imports (#43552).
|
||||
in_module.for_each_child_stable(|ident, ns, name_binding| {
|
||||
// avoid imports entirely
|
||||
if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
|
||||
// avoid non-importable candidates as well
|
||||
if !name_binding.is_importable() { return; }
|
||||
|
||||
// collect results based on the filter function
|
||||
if ident.name == lookup_ident.name && ns == namespace {
|
||||
let res = name_binding.res();
|
||||
if filter_fn(res) {
|
||||
// create the path
|
||||
let mut segms = path_segments.clone();
|
||||
if lookup_ident.span.rust_2018() {
|
||||
// crate-local absolute paths start with `crate::` in edition 2018
|
||||
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
|
||||
segms.insert(
|
||||
0, ast::PathSegment::from_ident(crate_name)
|
||||
);
|
||||
}
|
||||
|
||||
segms.push(ast::PathSegment::from_ident(ident));
|
||||
let path = Path {
|
||||
span: name_binding.span,
|
||||
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.vis == ty::Visibility::Public {
|
||||
let did = match res {
|
||||
Res::Def(DefKind::Ctor(..), did) => self.parent(did),
|
||||
_ => res.opt_def_id(),
|
||||
};
|
||||
candidates.push(ImportSuggestion { did, path });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collect submodules to explore
|
||||
if let Some(module) = name_binding.module() {
|
||||
// form the path
|
||||
let mut path_segments = path_segments.clone();
|
||||
path_segments.push(ast::PathSegment::from_ident(ident));
|
||||
|
||||
let is_extern_crate_that_also_appears_in_prelude =
|
||||
name_binding.is_extern_crate() &&
|
||||
lookup_ident.span.rust_2018();
|
||||
|
||||
let is_visible_to_user =
|
||||
!in_module_is_extern || name_binding.vis == ty::Visibility::Public;
|
||||
|
||||
if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user {
|
||||
// add the module to the lookup
|
||||
let is_extern = in_module_is_extern || name_binding.is_extern_crate();
|
||||
if seen_modules.insert(module.def_id().unwrap()) {
|
||||
worklist.push((module, path_segments, is_extern));
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
candidates
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// N.B., 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_import_candidates<FilterFn>(&mut self,
|
||||
lookup_ident: Ident,
|
||||
namespace: Namespace,
|
||||
filter_fn: FilterFn)
|
||||
-> Vec<ImportSuggestion>
|
||||
where FilterFn: Fn(Res) -> bool
|
||||
{
|
||||
let mut suggestions = self.lookup_import_candidates_from_module(
|
||||
lookup_ident, namespace, self.graph_root, Ident::with_empty_ctxt(kw::Crate), &filter_fn
|
||||
);
|
||||
|
||||
if lookup_ident.span.rust_2018() {
|
||||
let extern_prelude_names = self.extern_prelude.clone();
|
||||
for (ident, _) in extern_prelude_names.into_iter() {
|
||||
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
|
||||
ident.span) {
|
||||
let crate_root = self.get_module(DefId {
|
||||
krate: crate_id,
|
||||
index: CRATE_DEF_INDEX,
|
||||
});
|
||||
self.populate_module_if_necessary(&crate_root);
|
||||
|
||||
suggestions.extend(self.lookup_import_candidates_from_module(
|
||||
lookup_ident, namespace, crate_root, ident, &filter_fn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suggestions
|
||||
}
|
||||
|
||||
fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {
|
||||
let mut result = None;
|
||||
let mut seen_modules = FxHashSet::default();
|
||||
let mut worklist = vec![(self.graph_root, Vec::new())];
|
||||
|
||||
while let Some((in_module, path_segments)) = worklist.pop() {
|
||||
// abort if the module is already found
|
||||
if result.is_some() { break; }
|
||||
|
||||
self.populate_module_if_necessary(in_module);
|
||||
|
||||
in_module.for_each_child_stable(|ident, _, name_binding| {
|
||||
// abort if the module is already found or if name_binding is private external
|
||||
if result.is_some() || !name_binding.vis.is_visible_locally() {
|
||||
return
|
||||
}
|
||||
if let Some(module) = name_binding.module() {
|
||||
// form the path
|
||||
let mut path_segments = path_segments.clone();
|
||||
path_segments.push(ast::PathSegment::from_ident(ident));
|
||||
let module_def_id = module.def_id().unwrap();
|
||||
if module_def_id == def_id {
|
||||
let path = Path {
|
||||
span: name_binding.span,
|
||||
segments: path_segments,
|
||||
};
|
||||
result = Some((module, ImportSuggestion { did: Some(def_id), path }));
|
||||
} else {
|
||||
// add the module to the lookup
|
||||
if seen_modules.insert(module_def_id) {
|
||||
worklist.push((module, path_segments));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn collect_enum_variants(&mut self, def_id: DefId) -> Option<Vec<Path>> {
|
||||
self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| {
|
||||
self.populate_module_if_necessary(enum_module);
|
||||
|
||||
let mut variants = Vec::new();
|
||||
enum_module.for_each_child_stable(|ident, _, name_binding| {
|
||||
if let Res::Def(DefKind::Variant, _) = name_binding.res() {
|
||||
let mut segms = enum_import_suggestion.path.segments.clone();
|
||||
segms.push(ast::PathSegment::from_ident(ident));
|
||||
variants.push(Path {
|
||||
span: name_binding.span,
|
||||
segments: segms,
|
||||
});
|
||||
}
|
||||
});
|
||||
variants
|
||||
})
|
||||
}
|
||||
|
||||
fn record_partial_res(&mut self, node_id: NodeId, resolution: PartialRes) {
|
||||
debug!("(recording res) recording {:?} for {}", resolution, node_id);
|
||||
if let Some(prev_res) = self.partial_res_map.insert(node_id, resolution) {
|
||||
|
@ -5010,7 +4781,7 @@ impl<'a> Resolver<'a> {
|
|||
for UseError { mut err, candidates, node_id, better } in self.use_injections.drain(..) {
|
||||
let (span, found_use) = UsePlacementFinder::check(krate, node_id);
|
||||
if !candidates.is_empty() {
|
||||
show_candidates(&mut err, span, &candidates, better, found_use);
|
||||
diagnostics::show_candidates(&mut err, span, &candidates, better, found_use);
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
@ -5326,72 +5097,6 @@ fn path_names_to_string(path: &Path) -> String {
|
|||
.collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
/// Gets the stringified path for an enum from an `ImportSuggestion` for an enum variant.
|
||||
fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, String) {
|
||||
let variant_path = &suggestion.path;
|
||||
let variant_path_string = path_names_to_string(variant_path);
|
||||
|
||||
let path_len = suggestion.path.segments.len();
|
||||
let enum_path = ast::Path {
|
||||
span: suggestion.path.span,
|
||||
segments: suggestion.path.segments[0..path_len - 1].to_vec(),
|
||||
};
|
||||
let enum_path_string = path_names_to_string(&enum_path);
|
||||
|
||||
(variant_path_string, enum_path_string)
|
||||
}
|
||||
|
||||
/// 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(err: &mut DiagnosticBuilder<'_>,
|
||||
// This is `None` if all placement locations are inside expansions
|
||||
span: Option<Span>,
|
||||
candidates: &[ImportSuggestion],
|
||||
better: bool,
|
||||
found_use: bool) {
|
||||
|
||||
// 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<_> =
|
||||
candidates.into_iter().map(|c| path_names_to_string(&c.path)).collect();
|
||||
path_strings.sort();
|
||||
|
||||
let better = if better { "better " } else { "" };
|
||||
let msg_diff = match path_strings.len() {
|
||||
1 => " is found in another module, you can import it",
|
||||
_ => "s are found in other modules, you can import them",
|
||||
};
|
||||
let msg = format!("possible {}candidate{} into scope", better, msg_diff);
|
||||
|
||||
if let Some(span) = span {
|
||||
for candidate in &mut path_strings {
|
||||
// produce an additional newline to separate the new use statement
|
||||
// from the directly following item.
|
||||
let additional_newline = if found_use {
|
||||
""
|
||||
} else {
|
||||
"\n"
|
||||
};
|
||||
*candidate = format!("use {};\n{}", candidate, additional_newline);
|
||||
}
|
||||
|
||||
err.span_suggestions(
|
||||
span,
|
||||
&msg,
|
||||
path_strings.into_iter(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
} else {
|
||||
let mut msg = msg;
|
||||
msg.push(':');
|
||||
for candidate in path_strings {
|
||||
msg.push('\n');
|
||||
msg.push_str(&candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A somewhat inefficient routine to obtain the name of a module.
|
||||
fn module_to_string(module: Module<'_>) -> Option<String> {
|
||||
let mut names = Vec::new();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy};
|
||||
use crate::{CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
|
||||
use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak};
|
||||
use crate::{Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
|
||||
use crate::{is_known_tool, resolve_error};
|
||||
use crate::{resolve_error, KNOWN_TOOLS};
|
||||
use crate::ModuleOrUniformRoot;
|
||||
use crate::Namespace::*;
|
||||
use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
|
||||
|
@ -13,18 +13,15 @@ use rustc::middle::stability;
|
|||
use rustc::{ty, lint, span_bug};
|
||||
use syntax::ast::{self, Ident, ItemKind};
|
||||
use syntax::attr::{self, StabilityLevel};
|
||||
use syntax::errors::DiagnosticBuilder;
|
||||
use syntax::ext::base::{self, Indeterminate};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
|
||||
use syntax::ext::hygiene::{self, Mark, ExpnInfo, ExpnKind};
|
||||
use syntax::ext::tt::macro_rules;
|
||||
use syntax::feature_gate::{feature_err, emit_feature_err, is_builtin_attr_name};
|
||||
use syntax::feature_gate::{AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES};
|
||||
use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name};
|
||||
use syntax::feature_gate::GateIssue;
|
||||
use syntax::symbol::{Symbol, kw, sym};
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use errors::Applicability;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::{mem, ptr};
|
||||
|
@ -60,10 +57,10 @@ impl<'a> InvocationData<'a> {
|
|||
/// Not modularized, can shadow previous legacy bindings, etc.
|
||||
#[derive(Debug)]
|
||||
pub struct LegacyBinding<'a> {
|
||||
binding: &'a NameBinding<'a>,
|
||||
crate binding: &'a NameBinding<'a>,
|
||||
/// Legacy scope into which the `macro_rules` item was planted.
|
||||
parent_legacy_scope: LegacyScope<'a>,
|
||||
ident: Ident,
|
||||
crate parent_legacy_scope: LegacyScope<'a>,
|
||||
crate ident: Ident,
|
||||
}
|
||||
|
||||
/// The scope introduced by a `macro_rules!` macro.
|
||||
|
@ -82,15 +79,6 @@ pub enum LegacyScope<'a> {
|
|||
Invocation(&'a InvocationData<'a>),
|
||||
}
|
||||
|
||||
/// Everything you need to resolve a macro or import path.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParentScope<'a> {
|
||||
crate module: Module<'a>,
|
||||
crate expansion: Mark,
|
||||
crate legacy: LegacyScope<'a>,
|
||||
crate derives: Vec<ast::Path>,
|
||||
}
|
||||
|
||||
// Macro namespace is separated into two sub-namespaces, one for bang macros and
|
||||
// one for attribute-like macros (attributes, derives).
|
||||
// We ignore resolutions from one sub-namespace when searching names in scope for another.
|
||||
|
@ -232,7 +220,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
};
|
||||
|
||||
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
|
||||
let (ext, res) = self.smart_resolve_macro_path(path, kind, &parent_scope, true, force)?;
|
||||
let (ext, res) = self.smart_resolve_macro_path(path, kind, &parent_scope, force)?;
|
||||
|
||||
let span = invoc.span();
|
||||
invoc.expansion_data.mark.set_expn_info(ext.expn_info(span, fast_print_path(path)));
|
||||
|
@ -281,10 +269,10 @@ impl<'a> Resolver<'a> {
|
|||
path: &ast::Path,
|
||||
kind: MacroKind,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
trace: bool,
|
||||
force: bool,
|
||||
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
|
||||
let (ext, res) = match self.resolve_macro_path(path, kind, parent_scope, trace, force) {
|
||||
let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope,
|
||||
true, force) {
|
||||
Ok((Some(ext), res)) => (ext, res),
|
||||
// Use dummy syntax extensions for unresolved macros for better recovery.
|
||||
Ok((None, res)) => (self.dummy_ext(kind), res),
|
||||
|
@ -324,23 +312,7 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Res::NonMacroAttr(attr_kind) => {
|
||||
if attr_kind == NonMacroAttrKind::Custom {
|
||||
assert!(path.segments.len() == 1);
|
||||
if !features.custom_attribute {
|
||||
let msg = format!("The attribute `{}` is currently unknown to the \
|
||||
compiler and may have meaning added to it in the \
|
||||
future", path);
|
||||
self.report_unknown_attribute(
|
||||
path.span,
|
||||
&path.segments[0].ident.as_str(),
|
||||
&msg,
|
||||
sym::custom_attribute,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Res::Err => {}
|
||||
Res::NonMacroAttr(..) | Res::Err => {}
|
||||
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
|
||||
};
|
||||
|
||||
|
@ -359,64 +331,10 @@ impl<'a> Resolver<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn report_unknown_attribute(&self, span: Span, name: &str, msg: &str, feature: Symbol) {
|
||||
let mut err = feature_err(
|
||||
&self.session.parse_sess,
|
||||
feature,
|
||||
span,
|
||||
GateIssue::Language,
|
||||
&msg,
|
||||
);
|
||||
|
||||
let features = self.session.features_untracked();
|
||||
|
||||
let attr_candidates = BUILTIN_ATTRIBUTES
|
||||
.iter()
|
||||
.filter_map(|&(name, _, _, ref gate)| {
|
||||
if name.as_str().starts_with("rustc_") && !features.rustc_attrs {
|
||||
return None;
|
||||
}
|
||||
|
||||
match gate {
|
||||
AttributeGate::Gated(Stability::Unstable, ..)
|
||||
if self.session.opts.unstable_features.is_nightly_build() =>
|
||||
{
|
||||
Some(name)
|
||||
}
|
||||
AttributeGate::Gated(Stability::Deprecated(..), ..) => Some(name),
|
||||
AttributeGate::Ungated => Some(name),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.chain(
|
||||
// Add built-in macro attributes as well.
|
||||
self.builtin_macros.iter().filter_map(|(name, binding)| {
|
||||
match binding.macro_kind() {
|
||||
Some(MacroKind::Attr) => Some(*name),
|
||||
_ => None,
|
||||
}
|
||||
}),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let lev_suggestion = find_best_match_for_name(attr_candidates.iter(), &name, None);
|
||||
|
||||
if let Some(suggestion) = lev_suggestion {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"a built-in attribute with a similar name exists",
|
||||
suggestion.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
pub fn resolve_macro_path(
|
||||
&mut self,
|
||||
path: &ast::Path,
|
||||
kind: MacroKind,
|
||||
kind: Option<MacroKind>,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
trace: bool,
|
||||
force: bool,
|
||||
|
@ -425,7 +343,7 @@ impl<'a> Resolver<'a> {
|
|||
let mut path = Segment::from_path(path);
|
||||
|
||||
// Possibly apply the macro helper hack
|
||||
if kind == MacroKind::Bang && path.len() == 1 &&
|
||||
if kind == Some(MacroKind::Bang) && path.len() == 1 &&
|
||||
path[0].ident.span.ctxt().outer_expn_info()
|
||||
.map_or(false, |info| info.local_inner_macros) {
|
||||
let root = Ident::new(kw::DollarCrate, path[0].ident.span);
|
||||
|
@ -446,6 +364,7 @@ impl<'a> Resolver<'a> {
|
|||
};
|
||||
|
||||
if trace {
|
||||
let kind = kind.expect("macro kind must be specified if tracing is enabled");
|
||||
parent_scope.module.multi_segment_macro_resolutions.borrow_mut()
|
||||
.push((path, path_span, kind, parent_scope.clone(), res.ok()));
|
||||
}
|
||||
|
@ -453,14 +372,17 @@ impl<'a> Resolver<'a> {
|
|||
self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
|
||||
res
|
||||
} else {
|
||||
// Macro without a specific kind restriction is equvalent to a macro import.
|
||||
let scope_set = kind.map_or(ScopeSet::Import(MacroNS), ScopeSet::Macro);
|
||||
let binding = self.early_resolve_ident_in_lexical_scope(
|
||||
path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
|
||||
path[0].ident, scope_set, parent_scope, false, force, path_span
|
||||
);
|
||||
if let Err(Determinacy::Undetermined) = binding {
|
||||
return Err(Determinacy::Undetermined);
|
||||
}
|
||||
|
||||
if trace {
|
||||
let kind = kind.expect("macro kind must be specified if tracing is enabled");
|
||||
parent_scope.module.single_segment_macro_resolutions.borrow_mut()
|
||||
.push((path[0].ident, kind, parent_scope.clone(), binding.ok()));
|
||||
}
|
||||
|
@ -487,65 +409,6 @@ impl<'a> Resolver<'a> {
|
|||
force: bool,
|
||||
path_span: Span,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
// General principles:
|
||||
// 1. Not controlled (user-defined) names should have higher priority than controlled names
|
||||
// built into the language or standard library. This way we can add new names into the
|
||||
// language or standard library without breaking user code.
|
||||
// 2. "Closed set" below means new names cannot appear after the current resolution attempt.
|
||||
// Places to search (in order of decreasing priority):
|
||||
// (Type NS)
|
||||
// 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
|
||||
// (open set, not controlled).
|
||||
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled).
|
||||
// 3. Extern prelude (closed, not controlled).
|
||||
// 4. Tool modules (closed, controlled right now, but not in the future).
|
||||
// 5. Standard library prelude (de-facto closed, controlled).
|
||||
// 6. Language prelude (closed, controlled).
|
||||
// (Value NS)
|
||||
// 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet
|
||||
// (open set, not controlled).
|
||||
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled).
|
||||
// 3. Standard library prelude (de-facto closed, controlled).
|
||||
// (Macro NS)
|
||||
// 1-3. Derive helpers (open, not controlled). All ambiguities with other names
|
||||
// are currently reported as errors. They should be higher in priority than preludes
|
||||
// and probably even names in modules according to the "general principles" above. They
|
||||
// also should be subject to restricted shadowing because are effectively produced by
|
||||
// derives (you need to resolve the derive first to add helpers into scope), but they
|
||||
// should be available before the derive is expanded for compatibility.
|
||||
// It's mess in general, so we are being conservative for now.
|
||||
// 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher
|
||||
// priority than prelude macros, but create ambiguities with macros in modules.
|
||||
// 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled). Have higher priority than prelude macros, but create
|
||||
// ambiguities with `macro_rules`.
|
||||
// 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
|
||||
// 4a. User-defined prelude from macro-use
|
||||
// (open, the open part is from macro expansions, not controlled).
|
||||
// 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
|
||||
// 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
|
||||
// 6. Language prelude: builtin attributes (closed, controlled).
|
||||
// 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
|
||||
// but introduced by legacy plugins using `register_attribute`. Priority is somewhere
|
||||
// in prelude, not sure where exactly (creates ambiguities with any other prelude names).
|
||||
|
||||
enum WhereToResolve<'a> {
|
||||
DeriveHelpers,
|
||||
MacroRules(LegacyScope<'a>),
|
||||
CrateRoot,
|
||||
Module(Module<'a>),
|
||||
MacroUsePrelude,
|
||||
BuiltinMacros,
|
||||
BuiltinAttrs,
|
||||
LegacyPluginHelpers,
|
||||
ExternPrelude,
|
||||
ToolPrelude,
|
||||
StdLibPrelude,
|
||||
BuiltinTypes,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
struct Flags: u8 {
|
||||
const MACRO_RULES = 1 << 0;
|
||||
|
@ -558,13 +421,19 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
|
||||
assert!(force || !record_used); // `record_used` implies `force`
|
||||
let mut ident = orig_ident.modern();
|
||||
|
||||
// Make sure `self`, `super` etc produce an error when passed to here.
|
||||
if ident.is_path_segment_keyword() {
|
||||
if orig_ident.is_path_segment_keyword() {
|
||||
return Err(Determinacy::Determined);
|
||||
}
|
||||
|
||||
let (ns, macro_kind, is_import) = match scope_set {
|
||||
ScopeSet::Import(ns) => (ns, None, true),
|
||||
ScopeSet::AbsolutePath(ns) => (ns, None, false),
|
||||
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
|
||||
ScopeSet::Module => (TypeNS, None, false),
|
||||
};
|
||||
|
||||
// This is *the* result, resolution from the scope closest to the resolved identifier.
|
||||
// However, sometimes this result is "weak" because it comes from a glob import or
|
||||
// a macro expansion, and in this case it cannot shadow names from outer scopes, e.g.
|
||||
|
@ -577,34 +446,22 @@ impl<'a> Resolver<'a> {
|
|||
// So we have to save the innermost solution and continue searching in outer scopes
|
||||
// to detect potential ambiguities.
|
||||
let mut innermost_result: Option<(&NameBinding<'_>, Flags)> = None;
|
||||
let mut determinacy = Determinacy::Determined;
|
||||
|
||||
// Go through all the scopes and try to resolve the name.
|
||||
let rust_2015 = orig_ident.span.rust_2015();
|
||||
let (ns, macro_kind, is_import, is_absolute_path) = match scope_set {
|
||||
ScopeSet::Import(ns) => (ns, None, true, false),
|
||||
ScopeSet::AbsolutePath(ns) => (ns, None, false, true),
|
||||
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false, false),
|
||||
ScopeSet::Module => (TypeNS, None, false, false),
|
||||
};
|
||||
let mut where_to_resolve = match ns {
|
||||
_ if is_absolute_path => WhereToResolve::CrateRoot,
|
||||
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
|
||||
MacroNS => WhereToResolve::DeriveHelpers,
|
||||
};
|
||||
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
|
||||
let mut determinacy = Determinacy::Determined;
|
||||
loop {
|
||||
let result = match where_to_resolve {
|
||||
WhereToResolve::DeriveHelpers => {
|
||||
let break_result =
|
||||
self.visit_scopes(scope_set, parent_scope, orig_ident, |this, scope, ident| {
|
||||
let result = match scope {
|
||||
Scope::DeriveHelpers => {
|
||||
let mut result = Err(Determinacy::Determined);
|
||||
for derive in &parent_scope.derives {
|
||||
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
||||
match self.resolve_macro_path(derive, MacroKind::Derive,
|
||||
match this.resolve_macro_path(derive, Some(MacroKind::Derive),
|
||||
&parent_scope, true, force) {
|
||||
Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
||||
ty::Visibility::Public, derive.span, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
.to_name_binding(this.arenas);
|
||||
result = Ok((binding, Flags::empty()));
|
||||
break;
|
||||
}
|
||||
|
@ -615,19 +472,19 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
result
|
||||
}
|
||||
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
|
||||
Scope::MacroRules(legacy_scope) => match legacy_scope {
|
||||
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
|
||||
Ok((legacy_binding.binding, Flags::MACRO_RULES)),
|
||||
LegacyScope::Invocation(invoc) if invoc.output_legacy_scope.get().is_none() =>
|
||||
Err(Determinacy::Undetermined),
|
||||
_ => Err(Determinacy::Determined),
|
||||
}
|
||||
WhereToResolve::CrateRoot => {
|
||||
let root_ident = Ident::new(kw::PathRoot, orig_ident.span);
|
||||
let root_module = self.resolve_crate_root(root_ident);
|
||||
let binding = self.resolve_ident_in_module_ext(
|
||||
Scope::CrateRoot => {
|
||||
let root_ident = Ident::new(kw::PathRoot, ident.span);
|
||||
let root_module = this.resolve_crate_root(root_ident);
|
||||
let binding = this.resolve_ident_in_module_ext(
|
||||
ModuleOrUniformRoot::Module(root_module),
|
||||
orig_ident,
|
||||
ident,
|
||||
ns,
|
||||
None,
|
||||
record_used,
|
||||
|
@ -636,15 +493,15 @@ impl<'a> Resolver<'a> {
|
|||
match binding {
|
||||
Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
|
||||
Err((Determinacy::Undetermined, Weak::No)) =>
|
||||
return Err(Determinacy::determined(force)),
|
||||
return Some(Err(Determinacy::determined(force))),
|
||||
Err((Determinacy::Undetermined, Weak::Yes)) =>
|
||||
Err(Determinacy::Undetermined),
|
||||
Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
|
||||
}
|
||||
}
|
||||
WhereToResolve::Module(module) => {
|
||||
let orig_current_module = mem::replace(&mut self.current_module, module);
|
||||
let binding = self.resolve_ident_in_module_unadjusted_ext(
|
||||
Scope::Module(module) => {
|
||||
let orig_current_module = mem::replace(&mut this.current_module, module);
|
||||
let binding = this.resolve_ident_in_module_unadjusted_ext(
|
||||
ModuleOrUniformRoot::Module(module),
|
||||
ident,
|
||||
ns,
|
||||
|
@ -653,10 +510,10 @@ impl<'a> Resolver<'a> {
|
|||
record_used,
|
||||
path_span,
|
||||
);
|
||||
self.current_module = orig_current_module;
|
||||
this.current_module = orig_current_module;
|
||||
match binding {
|
||||
Ok(binding) => {
|
||||
let misc_flags = if ptr::eq(module, self.graph_root) {
|
||||
let misc_flags = if ptr::eq(module, this.graph_root) {
|
||||
Flags::MISC_SUGGEST_CRATE
|
||||
} else if module.is_normal() {
|
||||
Flags::MISC_SUGGEST_SELF
|
||||
|
@ -666,107 +523,82 @@ impl<'a> Resolver<'a> {
|
|||
Ok((binding, Flags::MODULE | misc_flags))
|
||||
}
|
||||
Err((Determinacy::Undetermined, Weak::No)) =>
|
||||
return Err(Determinacy::determined(force)),
|
||||
return Some(Err(Determinacy::determined(force))),
|
||||
Err((Determinacy::Undetermined, Weak::Yes)) =>
|
||||
Err(Determinacy::Undetermined),
|
||||
Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
|
||||
}
|
||||
}
|
||||
WhereToResolve::MacroUsePrelude => {
|
||||
if use_prelude || rust_2015 {
|
||||
match self.macro_use_prelude.get(&ident.name).cloned() {
|
||||
Some(binding) =>
|
||||
Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)),
|
||||
None => Err(Determinacy::determined(
|
||||
self.graph_root.unresolved_invocations.borrow().is_empty()
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
Scope::MacroUsePrelude => match this.macro_use_prelude.get(&ident.name).cloned() {
|
||||
Some(binding) => Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)),
|
||||
None => Err(Determinacy::determined(
|
||||
this.graph_root.unresolved_invocations.borrow().is_empty()
|
||||
))
|
||||
}
|
||||
WhereToResolve::BuiltinMacros => {
|
||||
match self.builtin_macros.get(&ident.name).cloned() {
|
||||
Some(binding) => Ok((binding, Flags::PRELUDE)),
|
||||
None => Err(Determinacy::Determined),
|
||||
}
|
||||
Scope::BuiltinMacros => match this.builtin_macros.get(&ident.name).cloned() {
|
||||
Some(binding) => Ok((binding, Flags::PRELUDE)),
|
||||
None => Err(Determinacy::Determined),
|
||||
}
|
||||
WhereToResolve::BuiltinAttrs => {
|
||||
if is_builtin_attr_name(ident.name) {
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::Builtin),
|
||||
ty::Visibility::Public, DUMMY_SP, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
Scope::BuiltinAttrs => if is_builtin_attr_name(ident.name) {
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::Builtin),
|
||||
ty::Visibility::Public, DUMMY_SP, Mark::root())
|
||||
.to_name_binding(this.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
WhereToResolve::LegacyPluginHelpers => {
|
||||
if (use_prelude || rust_2015) &&
|
||||
self.session.plugin_attributes.borrow().iter()
|
||||
Scope::LegacyPluginHelpers => if this.session.plugin_attributes.borrow().iter()
|
||||
.any(|(name, _)| ident.name == *name) {
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper),
|
||||
ty::Visibility::Public, DUMMY_SP, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper),
|
||||
ty::Visibility::Public, DUMMY_SP, Mark::root())
|
||||
.to_name_binding(this.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
WhereToResolve::ExternPrelude => {
|
||||
if use_prelude || is_absolute_path {
|
||||
match self.extern_prelude_get(ident, !record_used) {
|
||||
Some(binding) => Ok((binding, Flags::PRELUDE)),
|
||||
None => Err(Determinacy::determined(
|
||||
self.graph_root.unresolved_invocations.borrow().is_empty()
|
||||
)),
|
||||
}
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
Scope::ExternPrelude => match this.extern_prelude_get(ident, !record_used) {
|
||||
Some(binding) => Ok((binding, Flags::PRELUDE)),
|
||||
None => Err(Determinacy::determined(
|
||||
this.graph_root.unresolved_invocations.borrow().is_empty()
|
||||
)),
|
||||
}
|
||||
WhereToResolve::ToolPrelude => {
|
||||
if use_prelude && is_known_tool(ident.name) {
|
||||
let binding = (Res::ToolMod, ty::Visibility::Public,
|
||||
DUMMY_SP, Mark::root()).to_name_binding(self.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
Scope::ToolPrelude => if KNOWN_TOOLS.contains(&ident.name) {
|
||||
let binding = (Res::ToolMod, ty::Visibility::Public, DUMMY_SP, Mark::root())
|
||||
.to_name_binding(this.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
WhereToResolve::StdLibPrelude => {
|
||||
Scope::StdLibPrelude => {
|
||||
let mut result = Err(Determinacy::Determined);
|
||||
if use_prelude {
|
||||
if let Some(prelude) = self.prelude {
|
||||
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(
|
||||
ModuleOrUniformRoot::Module(prelude),
|
||||
ident,
|
||||
ns,
|
||||
false,
|
||||
path_span,
|
||||
) {
|
||||
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
|
||||
}
|
||||
if let Some(prelude) = this.prelude {
|
||||
if let Ok(binding) = this.resolve_ident_in_module_unadjusted(
|
||||
ModuleOrUniformRoot::Module(prelude),
|
||||
ident,
|
||||
ns,
|
||||
false,
|
||||
path_span,
|
||||
) {
|
||||
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
WhereToResolve::BuiltinTypes => {
|
||||
match self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
|
||||
Some(prim_ty) => {
|
||||
let binding = (Res::PrimTy(prim_ty), ty::Visibility::Public,
|
||||
DUMMY_SP, Mark::root()).to_name_binding(self.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
}
|
||||
None => Err(Determinacy::Determined)
|
||||
Scope::BuiltinTypes => match this.primitive_type_table.primitive_types
|
||||
.get(&ident.name).cloned() {
|
||||
Some(prim_ty) => {
|
||||
let binding = (Res::PrimTy(prim_ty), ty::Visibility::Public,
|
||||
DUMMY_SP, Mark::root()).to_name_binding(this.arenas);
|
||||
Ok((binding, Flags::PRELUDE))
|
||||
}
|
||||
None => Err(Determinacy::Determined)
|
||||
}
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok((binding, flags)) if sub_namespace_match(binding.macro_kind(), macro_kind) => {
|
||||
if !record_used {
|
||||
return Ok(binding);
|
||||
return Some(Ok(binding));
|
||||
}
|
||||
|
||||
if let Some((innermost_binding, innermost_flags)) = innermost_result {
|
||||
|
@ -791,11 +623,11 @@ impl<'a> Resolver<'a> {
|
|||
Some(AmbiguityKind::LegacyHelperVsPrelude)
|
||||
} else if innermost_flags.contains(Flags::MACRO_RULES) &&
|
||||
flags.contains(Flags::MODULE) &&
|
||||
!self.disambiguate_legacy_vs_modern(innermost_binding,
|
||||
!this.disambiguate_legacy_vs_modern(innermost_binding,
|
||||
binding) ||
|
||||
flags.contains(Flags::MACRO_RULES) &&
|
||||
innermost_flags.contains(Flags::MODULE) &&
|
||||
!self.disambiguate_legacy_vs_modern(binding,
|
||||
!this.disambiguate_legacy_vs_modern(binding,
|
||||
innermost_binding) {
|
||||
Some(AmbiguityKind::LegacyVsModern)
|
||||
} else if innermost_binding.is_glob_import() {
|
||||
|
@ -816,7 +648,7 @@ impl<'a> Resolver<'a> {
|
|||
} else {
|
||||
AmbiguityErrorMisc::None
|
||||
};
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
this.ambiguity_errors.push(AmbiguityError {
|
||||
kind,
|
||||
ident: orig_ident,
|
||||
b1: innermost_binding,
|
||||
|
@ -824,7 +656,7 @@ impl<'a> Resolver<'a> {
|
|||
misc1: misc(innermost_flags),
|
||||
misc2: misc(flags),
|
||||
});
|
||||
return Ok(innermost_binding);
|
||||
return Some(Ok(innermost_binding));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -836,55 +668,11 @@ impl<'a> Resolver<'a> {
|
|||
Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined
|
||||
}
|
||||
|
||||
where_to_resolve = match where_to_resolve {
|
||||
WhereToResolve::DeriveHelpers =>
|
||||
WhereToResolve::MacroRules(parent_scope.legacy),
|
||||
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
|
||||
LegacyScope::Binding(binding) => WhereToResolve::MacroRules(
|
||||
binding.parent_legacy_scope
|
||||
),
|
||||
LegacyScope::Invocation(invoc) => WhereToResolve::MacroRules(
|
||||
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope)
|
||||
),
|
||||
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
|
||||
}
|
||||
WhereToResolve::CrateRoot => match ns {
|
||||
TypeNS => {
|
||||
ident.span.adjust(Mark::root());
|
||||
WhereToResolve::ExternPrelude
|
||||
}
|
||||
ValueNS | MacroNS => break,
|
||||
}
|
||||
WhereToResolve::Module(module) => {
|
||||
match self.hygienic_lexical_parent(module, &mut ident.span) {
|
||||
Some(parent_module) => WhereToResolve::Module(parent_module),
|
||||
None => {
|
||||
ident.span.adjust(Mark::root());
|
||||
use_prelude = !module.no_implicit_prelude;
|
||||
match ns {
|
||||
TypeNS => WhereToResolve::ExternPrelude,
|
||||
ValueNS => WhereToResolve::StdLibPrelude,
|
||||
MacroNS => WhereToResolve::MacroUsePrelude,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WhereToResolve::MacroUsePrelude => WhereToResolve::StdLibPrelude,
|
||||
WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
|
||||
WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
|
||||
WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
|
||||
WhereToResolve::ExternPrelude if is_absolute_path => break,
|
||||
WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
|
||||
WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
|
||||
WhereToResolve::StdLibPrelude => match ns {
|
||||
TypeNS => WhereToResolve::BuiltinTypes,
|
||||
ValueNS => break, // nowhere else to search
|
||||
MacroNS => WhereToResolve::BuiltinMacros,
|
||||
}
|
||||
WhereToResolve::BuiltinTypes => break, // nowhere else to search
|
||||
};
|
||||
None
|
||||
});
|
||||
|
||||
continue;
|
||||
if let Some(break_result) = break_result {
|
||||
return break_result;
|
||||
}
|
||||
|
||||
// The first found solution was the only one, return it.
|
||||
|
@ -893,13 +681,14 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
|
||||
let determinacy = Determinacy::determined(determinacy == Determinacy::Determined || force);
|
||||
if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) {
|
||||
if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) &&
|
||||
self.session.features_untracked().custom_attribute {
|
||||
// For single-segment attributes interpret determinate "no resolution" as a custom
|
||||
// attribute. (Lexical resolution implies the first segment and attr kind should imply
|
||||
// the last segment, so we are certainly working with a single-segment attribute here.)
|
||||
assert!(ns == MacroNS);
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::Custom),
|
||||
ty::Visibility::Public, ident.span, Mark::root())
|
||||
ty::Visibility::Public, orig_ident.span, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
Ok(binding)
|
||||
} else {
|
||||
|
@ -992,7 +781,7 @@ impl<'a> Resolver<'a> {
|
|||
let msg =
|
||||
format!("cannot find {} `{}{}` in this scope", kind.descr(), ident, bang);
|
||||
let mut err = self.session.struct_span_err(ident.span, &msg);
|
||||
self.suggest_macro_name(ident.name, kind, &mut err, ident.span);
|
||||
self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident);
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
@ -1042,64 +831,6 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn suggest_macro_name(&mut self, name: Symbol, kind: MacroKind,
|
||||
err: &mut DiagnosticBuilder<'a>, span: Span) {
|
||||
if kind == MacroKind::Derive && (name.as_str() == "Send" || name.as_str() == "Sync") {
|
||||
let msg = format!("unsafe traits like `{}` should be implemented explicitly", name);
|
||||
err.span_note(span, &msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// First check if this is a locally-defined bang macro.
|
||||
let suggestion = if let MacroKind::Bang = kind {
|
||||
find_best_match_for_name(
|
||||
self.macro_names.iter().map(|ident| &ident.name), &name.as_str(), None)
|
||||
} else {
|
||||
None
|
||||
// Then check global macros.
|
||||
}.or_else(|| {
|
||||
let names = self.builtin_macros.iter().chain(self.macro_use_prelude.iter())
|
||||
.filter_map(|(name, binding)| {
|
||||
if binding.macro_kind() == Some(kind) { Some(name) } else { None }
|
||||
});
|
||||
find_best_match_for_name(names, &name.as_str(), None)
|
||||
// Then check modules.
|
||||
}).or_else(|| {
|
||||
let is_macro = |res| {
|
||||
if let Res::Def(DefKind::Macro(def_kind), _) = res {
|
||||
def_kind == kind
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
let ident = Ident::new(name, span);
|
||||
self.lookup_typo_candidate(&[Segment::from_ident(ident)], MacroNS, is_macro, span)
|
||||
.map(|suggestion| suggestion.candidate)
|
||||
});
|
||||
|
||||
if let Some(suggestion) = suggestion {
|
||||
if suggestion != name {
|
||||
if let MacroKind::Bang = kind {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"you could try the macro",
|
||||
suggestion.to_string(),
|
||||
Applicability::MaybeIncorrect
|
||||
);
|
||||
} else {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"try",
|
||||
suggestion.to_string(),
|
||||
Applicability::MaybeIncorrect
|
||||
);
|
||||
}
|
||||
} else {
|
||||
err.help("have you added the `#[macro_use]` on the module/import?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crate fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
|
||||
// Reserve some names that are not quite covered by the general check
|
||||
// performed on `Resolver::builtin_attrs`.
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use ImportDirectiveSubclass::*;
|
||||
|
||||
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
|
||||
use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak};
|
||||
use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, ParentScope, Weak};
|
||||
use crate::Determinacy::{self, *};
|
||||
use crate::Namespace::{self, TypeNS, MacroNS};
|
||||
use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
|
||||
use crate::{Resolver, Segment};
|
||||
use crate::{names_to_string, module_to_string};
|
||||
use crate::{resolve_error, ResolutionError, Suggestion};
|
||||
use crate::{resolve_error, ResolutionError};
|
||||
use crate::ModuleKind;
|
||||
use crate::macros::ParentScope;
|
||||
use crate::diagnostics::Suggestion;
|
||||
|
||||
use errors::Applicability;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use rustc::lint as lint;
|
|||
use rustc::ty;
|
||||
use syntax;
|
||||
use syntax::ast::{self, Ident};
|
||||
use syntax::ext::base::SyntaxExtensionKind;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::DUMMY_SP;
|
||||
|
@ -425,12 +426,10 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
|||
|
||||
/// Resolves a string as a macro.
|
||||
fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtensionKind};
|
||||
let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
|
||||
let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
|
||||
let path = ast::Path::from_ident(Ident::from_str(path_str));
|
||||
cx.enter_resolver(|resolver| {
|
||||
if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
|
||||
&path, MacroKind::Bang, &resolver.dummy_parent_scope(), false, false
|
||||
&path, None, &resolver.dummy_parent_scope(), false, false
|
||||
) {
|
||||
if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
|
||||
return Some(res.map_id(|_| panic!("unexpected id")));
|
||||
|
|
|
@ -604,6 +604,7 @@ symbols! {
|
|||
rustc_then_this_would_need,
|
||||
rustc_variance,
|
||||
rustdoc,
|
||||
rustfmt,
|
||||
rust_eh_personality,
|
||||
rust_eh_unwind_resume,
|
||||
rust_oom,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Obsolete attributes fall back to feature gated custom attributes.
|
||||
|
||||
#[ab_isize="stdcall"] extern {} //~ ERROR attribute `ab_isize` is currently unknown
|
||||
#[ab_isize="stdcall"] extern {}
|
||||
//~^ ERROR cannot find attribute macro `ab_isize` in this scope
|
||||
|
||||
#[fixed_stack_segment] fn f() {} //~ ERROR attribute `fixed_stack_segment` is currently unknown
|
||||
#[fixed_stack_segment] fn f() {}
|
||||
//~^ ERROR cannot find attribute macro `fixed_stack_segment` in this scope
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,21 +1,14 @@
|
|||
error[E0658]: The attribute `fixed_stack_segment` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/obsolete-attr.rs:5:3
|
||||
error: cannot find attribute macro `fixed_stack_segment` in this scope
|
||||
--> $DIR/obsolete-attr.rs:6:3
|
||||
|
|
||||
LL | #[fixed_stack_segment] fn f() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `ab_isize` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `ab_isize` in this scope
|
||||
--> $DIR/obsolete-attr.rs:3:3
|
||||
|
|
||||
LL | #[ab_isize="stdcall"] extern {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
#![feature(custom_inner_attributes)]
|
||||
|
||||
#![mutable_doc] //~ ERROR attribute `mutable_doc` is currently unknown
|
||||
#![mutable_doc]
|
||||
//~^ ERROR cannot find attribute macro `mutable_doc` in this scope
|
||||
|
||||
#[dance] mod a {} //~ ERROR attribute `dance` is currently unknown
|
||||
#[dance] mod a {}
|
||||
//~^ ERROR cannot find attribute macro `dance` in this scope
|
||||
|
||||
#[dance] fn main() {} //~ ERROR attribute `dance` is currently unknown
|
||||
#[dance] fn main() {}
|
||||
//~^ ERROR cannot find attribute macro `dance` in this scope
|
||||
|
|
|
@ -1,30 +1,20 @@
|
|||
error[E0658]: The attribute `mutable_doc` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `mutable_doc` in this scope
|
||||
--> $DIR/unknown-attr.rs:5:4
|
||||
|
|
||||
LL | #![mutable_doc]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `dance` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/unknown-attr.rs:7:3
|
||||
error: cannot find attribute macro `dance` in this scope
|
||||
--> $DIR/unknown-attr.rs:8:3
|
||||
|
|
||||
LL | #[dance] mod a {}
|
||||
| ^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `dance` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/unknown-attr.rs:9:3
|
||||
error: cannot find attribute macro `dance` in this scope
|
||||
--> $DIR/unknown-attr.rs:11:3
|
||||
|
|
||||
LL | #[dance] fn main() {}
|
||||
| ^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
macro_rules! foo {
|
||||
() => {
|
||||
#[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown
|
||||
#[cfg_attr(all(), unknown)]
|
||||
//~^ ERROR cannot find attribute macro `unknown` in this scope
|
||||
fn foo() {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `unknown` in this scope
|
||||
--> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:3:27
|
||||
|
|
||||
LL | #[cfg_attr(all(), unknown)]
|
||||
|
@ -6,10 +6,6 @@ LL | #[cfg_attr(all(), unknown)]
|
|||
...
|
||||
LL | foo!();
|
||||
| ------- in this macro invocation
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#![feature(stmt_expr_attributes)]
|
||||
|
||||
#[foo] //~ ERROR The attribute `foo`
|
||||
#[foo] //~ ERROR cannot find attribute macro `foo` in this scope
|
||||
fn main() {
|
||||
#[foo] //~ ERROR The attribute `foo`
|
||||
#[foo] //~ ERROR cannot find attribute macro `foo` in this scope
|
||||
let x = ();
|
||||
#[foo] //~ ERROR The attribute `foo`
|
||||
#[foo] //~ ERROR cannot find attribute macro `foo` in this scope
|
||||
x
|
||||
}
|
||||
|
|
|
@ -1,30 +1,20 @@
|
|||
error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `foo` in this scope
|
||||
--> $DIR/custom_attribute.rs:3:3
|
||||
|
|
||||
LL | #[foo]
|
||||
| ^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `foo` in this scope
|
||||
--> $DIR/custom_attribute.rs:5:7
|
||||
|
|
||||
LL | #[foo]
|
||||
| ^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `foo` in this scope
|
||||
--> $DIR/custom_attribute.rs:7:7
|
||||
|
|
||||
LL | #[foo]
|
||||
| ^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -2,7 +2,7 @@ error: cannot find derive macro `Eqr` in this scope
|
|||
--> $DIR/deriving-meta-unknown-trait.rs:1:10
|
||||
|
|
||||
LL | #[derive(Eqr)]
|
||||
| ^^^ help: try: `Eq`
|
||||
| ^^^ help: a derive macro with a similar name exists: `Eq`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,23 +1,18 @@
|
|||
// Check that literals in attributes parse just fine.
|
||||
|
||||
#[fake_attr] //~ ERROR cannot find attribute macro `fake_attr` in this scope
|
||||
#[fake_attr(100)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
|
||||
#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
|
||||
#[fake_attr("hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
|
||||
#[fake_attr(name = "hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
|
||||
#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute macro `fake_attr` in th
|
||||
#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute macro `fake_attr` in this scop
|
||||
#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute macro `fake_attr` in this scope
|
||||
#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute macro `fake_attr` in
|
||||
#[fake_attr(true)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
|
||||
#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
|
||||
#[fake_attr(b"hi")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
|
||||
#[fake_doc(r"doc")] //~ ERROR cannot find attribute macro `fake_doc` in this scope
|
||||
struct Q {}
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
|
||||
struct Q { }
|
||||
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
|
|
@ -1,120 +1,80 @@
|
|||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:7:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:3:3
|
||||
|
|
||||
LL | #[fake_attr]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:8:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:4:3
|
||||
|
|
||||
LL | #[fake_attr(100)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:9:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:5:3
|
||||
|
|
||||
LL | #[fake_attr(1, 2, 3)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:10:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:6:3
|
||||
|
|
||||
LL | #[fake_attr("hello")]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:11:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:7:3
|
||||
|
|
||||
LL | #[fake_attr(name = "hello")]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:12:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:8:3
|
||||
|
|
||||
LL | #[fake_attr(1, "hi", key = 12, true, false)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:13:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:9:3
|
||||
|
|
||||
LL | #[fake_attr(key = "hello", val = 10)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:14:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:10:3
|
||||
|
|
||||
LL | #[fake_attr(key("hello"), val(10))]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:15:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:11:3
|
||||
|
|
||||
LL | #[fake_attr(enabled = true, disabled = false)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:16:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:12:3
|
||||
|
|
||||
LL | #[fake_attr(true)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:17:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:13:3
|
||||
|
|
||||
LL | #[fake_attr(pi = 3.14159)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:18:3
|
||||
error: cannot find attribute macro `fake_attr` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:14:3
|
||||
|
|
||||
LL | #[fake_attr(b"hi")]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/feature-gate-custom_attribute.rs:19:3
|
||||
error: cannot find attribute macro `fake_doc` in this scope
|
||||
--> $DIR/feature-gate-custom_attribute.rs:15:3
|
||||
|
|
||||
LL | #[fake_doc(r"doc")]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -19,5 +19,5 @@ fn g() {}
|
|||
//~^ ERROR used by the test suite
|
||||
#[rustc_unknown]
|
||||
//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
|
||||
//~| ERROR attribute `rustc_unknown` is currently unknown
|
||||
//~| ERROR cannot find attribute macro `rustc_unknown` in this scope
|
||||
fn main() {}
|
||||
|
|
|
@ -37,14 +37,11 @@ LL | #[rustc_unknown]
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `rustc_unknown` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `rustc_unknown` in this scope
|
||||
--> $DIR/feature-gate-rustc-attrs.rs:20:3
|
||||
|
|
||||
LL | #[rustc_unknown]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: used by the test suite
|
||||
--> $DIR/feature-gate-rustc-attrs.rs:18:1
|
||||
|
|
|
@ -3,8 +3,6 @@ error: cannot find macro `print!` in this scope
|
|||
|
|
||||
LL | print!();
|
||||
| ^^^^^
|
||||
|
|
||||
= help: have you added the `#[macro_use]` on the module/import?
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ error: cannot find macro `panic!` in this scope
|
|||
LL | assert_eq!(0, 0);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: have you added the `#[macro_use]` on the module/import?
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
error[E0599]: no method named `clone` found for type `()` in the current scope
|
||||
|
|
|
@ -26,6 +26,6 @@ fn main() {
|
|||
Opaque; //~ ERROR cannot find value `Opaque` in this scope
|
||||
|
||||
transparent; // OK
|
||||
semitransparent; //~ ERROR cannot find value `semitransparent` in this scope
|
||||
opaque; //~ ERROR cannot find value `opaque` in this scope
|
||||
semitransparent; //~ ERROR expected value, found macro `semitransparent`
|
||||
opaque; //~ ERROR expected value, found macro `opaque`
|
||||
}
|
||||
|
|
|
@ -4,18 +4,19 @@ error[E0425]: cannot find value `Opaque` in this scope
|
|||
LL | Opaque;
|
||||
| ^^^^^^ help: a local variable with a similar name exists: `opaque`
|
||||
|
||||
error[E0425]: cannot find value `semitransparent` in this scope
|
||||
error[E0423]: expected value, found macro `semitransparent`
|
||||
--> $DIR/rustc-macro-transparency.rs:29:5
|
||||
|
|
||||
LL | semitransparent;
|
||||
| ^^^^^^^^^^^^^^^ not found in this scope
|
||||
| ^^^^^^^^^^^^^^^ help: use `!` to invoke the macro: `semitransparent!`
|
||||
|
||||
error[E0425]: cannot find value `opaque` in this scope
|
||||
error[E0423]: expected value, found macro `opaque`
|
||||
--> $DIR/rustc-macro-transparency.rs:30:5
|
||||
|
|
||||
LL | opaque;
|
||||
| ^^^^^^ not found in this scope
|
||||
| ^^^^^^ help: use `!` to invoke the macro: `opaque!`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
||||
Some errors have detailed explanations: E0423, E0425.
|
||||
For more information about an error, try `rustc --explain E0423`.
|
||||
|
|
|
@ -6,9 +6,8 @@ fn foo(f: impl Display + Clone) -> String {
|
|||
wants_clone(f);
|
||||
}
|
||||
|
||||
fn wants_debug(g: impl Debug) { } //~ ERROR cannot find
|
||||
fn wants_display(g: impl Debug) { } //~ ERROR cannot find
|
||||
fn wants_debug(g: impl Debug) { } //~ ERROR expected trait, found derive macro `Debug`
|
||||
fn wants_display(g: impl Debug) { } //~ ERROR expected trait, found derive macro `Debug`
|
||||
fn wants_clone(g: impl Clone) { }
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
error[E0405]: cannot find trait `Debug` in this scope
|
||||
error[E0404]: expected trait, found derive macro `Debug`
|
||||
--> $DIR/universal_wrong_bounds.rs:9:24
|
||||
|
|
||||
LL | fn wants_debug(g: impl Debug) { }
|
||||
| ^^^^^ not found in this scope
|
||||
help: possible candidate is found in another module, you can import it into scope
|
||||
| ^^^^^ not a trait
|
||||
help: possible better candidate is found in another module, you can import it into scope
|
||||
|
|
||||
LL | use std::fmt::Debug;
|
||||
|
|
||||
|
||||
error[E0405]: cannot find trait `Debug` in this scope
|
||||
error[E0404]: expected trait, found derive macro `Debug`
|
||||
--> $DIR/universal_wrong_bounds.rs:10:26
|
||||
|
|
||||
LL | fn wants_display(g: impl Debug) { }
|
||||
| ^^^^^ not found in this scope
|
||||
help: possible candidate is found in another module, you can import it into scope
|
||||
| ^^^^^ not a trait
|
||||
help: possible better candidate is found in another module, you can import it into scope
|
||||
|
|
||||
LL | use std::fmt::Debug;
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0405`.
|
||||
For more information about this error, try `rustc --explain E0404`.
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
#![allow(dead_code)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
macro_rules! foo (
|
||||
() => (
|
||||
#[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown
|
||||
#[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope
|
||||
struct T;
|
||||
);
|
||||
);
|
||||
|
@ -15,7 +12,7 @@ macro_rules! bar (
|
|||
foo!();
|
||||
|
||||
bar!(
|
||||
#[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown
|
||||
#[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope
|
||||
struct S;
|
||||
);
|
||||
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/issue-32655.rs:6:11
|
||||
error: cannot find attribute macro `derive_Clone` in this scope
|
||||
--> $DIR/issue-32655.rs:3:11
|
||||
|
|
||||
LL | #[derive_Clone]
|
||||
| ^^^^^^^^^^^^
|
||||
...
|
||||
LL | foo!();
|
||||
| ------- in this macro invocation
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/issue-32655.rs:18:7
|
||||
error: cannot find attribute macro `derive_Clone` in this scope
|
||||
--> $DIR/issue-32655.rs:15:7
|
||||
|
|
||||
LL | #[derive_Clone]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
struct Foo<T: ?Hash> { }
|
||||
//~^ ERROR cannot find trait `Hash` in this scope
|
||||
//~^ ERROR expected trait, found derive macro `Hash`
|
||||
//~^^ ERROR parameter `T` is never used
|
||||
//~^^^ WARN default bound relaxed for a type parameter, but this does nothing
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
error[E0405]: cannot find trait `Hash` in this scope
|
||||
error[E0404]: expected trait, found derive macro `Hash`
|
||||
--> $DIR/issue-37534.rs:1:16
|
||||
|
|
||||
LL | struct Foo<T: ?Hash> { }
|
||||
| ^^^^ not found in this scope
|
||||
help: possible candidate is found in another module, you can import it into scope
|
||||
| ^^^^ not a trait
|
||||
help: possible better candidate is found in another module, you can import it into scope
|
||||
|
|
||||
LL | use std::hash::Hash;
|
||||
|
|
||||
|
@ -24,5 +24,5 @@ LL | struct Foo<T: ?Hash> { }
|
|||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0392, E0405.
|
||||
Some errors have detailed explanations: E0392, E0404.
|
||||
For more information about an error, try `rustc --explain E0392`.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Check that unknown attribute error is shown even if there are unresolved macros.
|
||||
|
||||
#[marco_use] // typo
|
||||
//~^ ERROR The attribute `marco_use` is currently unknown to the compiler
|
||||
//~^ ERROR cannot find attribute macro `marco_use` in this scope
|
||||
mod foo {
|
||||
macro_rules! bar {
|
||||
() => ();
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `marco_use` in this scope
|
||||
--> $DIR/issue-49074.rs:3:3
|
||||
|
|
||||
LL | #[marco_use] // typo
|
||||
| ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use`
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: cannot find macro `bar!` in this scope
|
||||
--> $DIR/issue-49074.rs:12:4
|
||||
|
@ -17,4 +14,3 @@ LL | bar!();
|
|||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -2,7 +2,7 @@ error: cannot find macro `printlx!` in this scope
|
|||
--> $DIR/macro-name-typo.rs:2:5
|
||||
|
|
||||
LL | printlx!("oh noes!");
|
||||
| ^^^^^^^ help: you could try the macro: `println`
|
||||
| ^^^^^^^ help: a macro with a similar name exists: `println`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error: cannot find macro `inline!` in this scope
|
|||
--> $DIR/macro-path-prelude-fail-3.rs:2:5
|
||||
|
|
||||
LL | inline!();
|
||||
| ^^^^^^ help: you could try the macro: `line`
|
||||
| ^^^^^^ help: a macro with a similar name exists: `line`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#![feature(macro_reexport)] //~ ERROR feature has been removed
|
||||
|
||||
#[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown
|
||||
#[macro_reexport(macro_one)] //~ ERROR cannot find attribute macro `macro_reexport` in this scope
|
||||
extern crate two_macros;
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -10,16 +10,12 @@ note: subsumed by `pub use`
|
|||
LL | #![feature(macro_reexport)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error[E0658]: The attribute `macro_reexport` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `macro_reexport` in this scope
|
||||
--> $DIR/macro-reexport-removed.rs:5:3
|
||||
|
|
||||
LL | #[macro_reexport(macro_one)]
|
||||
| ^^^^^^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_export`
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0557, E0658.
|
||||
For more information about an error, try `rustc --explain E0557`.
|
||||
For more information about this error, try `rustc --explain E0557`.
|
||||
|
|
|
@ -2,7 +2,7 @@ error: cannot find macro `macro_two!` in this scope
|
|||
--> $DIR/macro-use-wrong-name.rs:7:5
|
||||
|
|
||||
LL | macro_two!();
|
||||
| ^^^^^^^^^ help: you could try the macro: `macro_one`
|
||||
| ^^^^^^^^^ help: a macro with a similar name exists: `macro_one`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error: cannot find macro `k!` in this scope
|
|||
--> $DIR/macro_undefined.rs:11:5
|
||||
|
|
||||
LL | k!();
|
||||
| ^ help: you could try the macro: `kl`
|
||||
| ^ help: a macro with a similar name exists: `kl`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ mod foo {
|
|||
mod baz {
|
||||
struct Test;
|
||||
impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope
|
||||
impl Clone for Test {} //~ ERROR cannot find trait `Clone` in this scope
|
||||
impl Clone for Test {} //~ ERROR expected trait, found derive macro `Clone`
|
||||
impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope
|
||||
impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope
|
||||
impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope
|
||||
|
@ -21,7 +21,7 @@ mod foo {
|
|||
|
||||
struct Test;
|
||||
impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope
|
||||
impl Clone for Test {} //~ ERROR cannot find trait `Clone` in this scope
|
||||
impl Clone for Test {} //~ ERROR expected trait, found derive macro `Clone`
|
||||
impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope
|
||||
impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope
|
||||
impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope
|
||||
|
@ -36,7 +36,7 @@ fn qux() {
|
|||
mod qux_inner {
|
||||
struct Test;
|
||||
impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope
|
||||
impl Clone for Test {} //~ ERROR cannot find trait `Clone` in this scope
|
||||
impl Clone for Test {} //~ ERROR expected trait, found derive macro `Clone`
|
||||
impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope
|
||||
impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope
|
||||
impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope
|
||||
|
|
|
@ -8,12 +8,12 @@ help: possible candidate is found in another module, you can import it into scop
|
|||
LL | use std::ops::Add;
|
||||
|
|
||||
|
||||
error[E0405]: cannot find trait `Clone` in this scope
|
||||
error[E0404]: expected trait, found derive macro `Clone`
|
||||
--> $DIR/no-implicit-prelude-nested.rs:12:14
|
||||
|
|
||||
LL | impl Clone for Test {}
|
||||
| ^^^^^ not found in this scope
|
||||
help: possible candidates are found in other modules, you can import them into scope
|
||||
| ^^^^^ not a trait
|
||||
help: possible better candidates are found in other modules, you can import them into scope
|
||||
|
|
||||
LL | use std::clone::Clone;
|
||||
|
|
||||
|
@ -72,12 +72,12 @@ help: possible candidate is found in another module, you can import it into scop
|
|||
LL | use std::ops::Add;
|
||||
|
|
||||
|
||||
error[E0405]: cannot find trait `Clone` in this scope
|
||||
error[E0404]: expected trait, found derive macro `Clone`
|
||||
--> $DIR/no-implicit-prelude-nested.rs:24:10
|
||||
|
|
||||
LL | impl Clone for Test {}
|
||||
| ^^^^^ not found in this scope
|
||||
help: possible candidates are found in other modules, you can import them into scope
|
||||
| ^^^^^ not a trait
|
||||
help: possible better candidates are found in other modules, you can import them into scope
|
||||
|
|
||||
LL | use std::clone::Clone;
|
||||
|
|
||||
|
@ -136,12 +136,12 @@ help: possible candidate is found in another module, you can import it into scop
|
|||
LL | use std::ops::Add;
|
||||
|
|
||||
|
||||
error[E0405]: cannot find trait `Clone` in this scope
|
||||
error[E0404]: expected trait, found derive macro `Clone`
|
||||
--> $DIR/no-implicit-prelude-nested.rs:39:14
|
||||
|
|
||||
LL | impl Clone for Test {}
|
||||
| ^^^^^ not found in this scope
|
||||
help: possible candidates are found in other modules, you can import them into scope
|
||||
| ^^^^^ not a trait
|
||||
help: possible better candidates are found in other modules, you can import them into scope
|
||||
|
|
||||
LL | use std::clone::Clone;
|
||||
|
|
||||
|
@ -192,5 +192,5 @@ LL | use std::prelude::v1::drop;
|
|||
|
||||
error: aborting due to 18 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0405, E0425.
|
||||
For more information about an error, try `rustc --explain E0405`.
|
||||
Some errors have detailed explanations: E0404, E0405, E0425.
|
||||
For more information about an error, try `rustc --explain E0404`.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
struct Test;
|
||||
impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope
|
||||
impl Clone for Test {} //~ ERROR cannot find trait `Clone` in this scope
|
||||
impl Clone for Test {} //~ ERROR expected trait, found derive macro `Clone`
|
||||
impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope
|
||||
impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope
|
||||
impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope
|
||||
|
|
|
@ -8,12 +8,12 @@ help: possible candidate is found in another module, you can import it into scop
|
|||
LL | use std::ops::Add;
|
||||
|
|
||||
|
||||
error[E0405]: cannot find trait `Clone` in this scope
|
||||
error[E0404]: expected trait, found derive macro `Clone`
|
||||
--> $DIR/no-implicit-prelude.rs:11:6
|
||||
|
|
||||
LL | impl Clone for Test {}
|
||||
| ^^^^^ not found in this scope
|
||||
help: possible candidates are found in other modules, you can import them into scope
|
||||
| ^^^^^ not a trait
|
||||
help: possible better candidates are found in other modules, you can import them into scope
|
||||
|
|
||||
LL | use std::clone::Clone;
|
||||
|
|
||||
|
@ -64,5 +64,5 @@ LL | use std::prelude::v1::drop;
|
|||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0405, E0425.
|
||||
For more information about an error, try `rustc --explain E0405`.
|
||||
Some errors have detailed explanations: E0404, E0405, E0425.
|
||||
For more information about an error, try `rustc --explain E0404`.
|
||||
|
|
|
@ -19,7 +19,7 @@ struct S {
|
|||
struct U;
|
||||
|
||||
mod inner {
|
||||
#[empty_helper] //~ ERROR attribute `empty_helper` is currently unknown
|
||||
#[empty_helper] //~ ERROR cannot find attribute macro `empty_helper` in this scope
|
||||
struct V;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
error[E0658]: The attribute `empty_helper` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `empty_helper` in this scope
|
||||
--> $DIR/derive-helper-shadowing.rs:22:15
|
||||
|
|
||||
LL | #[empty_helper]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name)
|
||||
--> $DIR/derive-helper-shadowing.rs:8:3
|
||||
|
@ -27,5 +24,4 @@ LL | use test_macros::empty_attr as empty_helper;
|
|||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0658, E0659.
|
||||
For more information about an error, try `rustc --explain E0658`.
|
||||
For more information about this error, try `rustc --explain E0659`.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#[macro_use]
|
||||
extern crate test_macros;
|
||||
|
||||
#[derive_Empty] //~ ERROR attribute `derive_Empty` is currently unknown
|
||||
#[derive_Empty] //~ ERROR cannot find attribute macro `derive_Empty` in this scope
|
||||
struct A;
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
error[E0658]: The attribute `derive_Empty` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `derive_Empty` in this scope
|
||||
--> $DIR/derive-still-gated.rs:6:3
|
||||
|
|
||||
LL | #[derive_Empty]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// aux-build:derive-unstable-2.rs
|
||||
|
||||
#![feature(custom_attribute)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate derive_unstable_2;
|
||||
|
||||
#[derive(Unstable)]
|
||||
//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
|
||||
//~| ERROR attribute `rustc_foo` is currently unknown to the compiler
|
||||
|
||||
struct A;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
|
||||
--> $DIR/expand-to-unstable-2.rs:6:10
|
||||
--> $DIR/expand-to-unstable-2.rs:8:10
|
||||
|
|
||||
LL | #[derive(Unstable)]
|
||||
| ^^^^^^^^
|
||||
|
@ -7,15 +7,6 @@ LL | #[derive(Unstable)]
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `rustc_foo` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/expand-to-unstable-2.rs:6:10
|
||||
|
|
||||
LL | #[derive(Unstable)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
// FIXME: https://github.com/rust-lang/rust/issues/41430
|
||||
// This is a temporary regression test for the ICE reported in #41211
|
||||
|
||||
#![feature(custom_attribute)]
|
||||
#![feature(custom_inner_attributes)]
|
||||
|
||||
#![identity_attr]
|
||||
//~^ ERROR attribute `identity_attr` is currently unknown to the compiler
|
||||
//~| ERROR inconsistent resolution for a macro: first custom attribute, then attribute macro
|
||||
//~^ ERROR inconsistent resolution for a macro: first custom attribute, then attribute macro
|
||||
extern crate test_macros;
|
||||
use test_macros::identity_attr;
|
||||
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
error[E0658]: The attribute `identity_attr` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/issue-41211.rs:8:4
|
||||
|
|
||||
LL | #![identity_attr]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: inconsistent resolution for a macro: first custom attribute, then attribute macro
|
||||
--> $DIR/issue-41211.rs:8:4
|
||||
--> $DIR/issue-41211.rs:9:4
|
||||
|
|
||||
LL | #![identity_attr]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -35,7 +35,7 @@ fn check_bang3() {
|
|||
//~| ERROR expected macro, found derive macro `crate::MyTrait`
|
||||
}
|
||||
|
||||
#[my_macro] //~ ERROR attribute `my_macro` is currently unknown
|
||||
#[my_macro] //~ ERROR cannot find attribute macro `my_macro` in this scope
|
||||
#[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
|
||||
//~| ERROR expected attribute, found macro `crate::my_macro`
|
||||
fn check_attr1() {}
|
||||
|
|
|
@ -76,15 +76,6 @@ error: can't use a procedural macro from the same crate that defines it
|
|||
LL | #[derive(MyTrait)]
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0658]: The attribute `my_macro` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/macro-namespace-reserved-2.rs:38:3
|
||||
|
|
||||
LL | #[my_macro]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: can't use a procedural macro from the same crate that defines it
|
||||
--> $DIR/macro-namespace-reserved-2.rs:39:3
|
||||
|
|
||||
|
@ -97,6 +88,12 @@ error: expected attribute, found macro `crate::my_macro`
|
|||
LL | #[crate::my_macro]
|
||||
| ^^^^^^^^^^^^^^^ not an attribute
|
||||
|
||||
error: cannot find attribute macro `my_macro` in this scope
|
||||
--> $DIR/macro-namespace-reserved-2.rs:38:3
|
||||
|
|
||||
LL | #[my_macro]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: cannot find derive macro `my_macro` in this scope
|
||||
--> $DIR/macro-namespace-reserved-2.rs:48:10
|
||||
|
|
||||
|
@ -117,4 +114,3 @@ LL | MyTrait!();
|
|||
|
||||
error: aborting due to 19 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
extern crate derive_b;
|
||||
|
||||
#[B] //~ ERROR `B` is ambiguous
|
||||
#[C] //~ ERROR attribute `C` is currently unknown to the compiler
|
||||
#[C] //~ ERROR cannot find attribute macro `C` in this scope
|
||||
#[B(D)] //~ ERROR `B` is ambiguous
|
||||
#[B(E = "foo")] //~ ERROR `B` is ambiguous
|
||||
#[B(arbitrary tokens)] //~ ERROR `B` is ambiguous
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
error[E0658]: The attribute `C` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `C` in this scope
|
||||
--> $DIR/proc-macro-attributes.rs:7:3
|
||||
|
|
||||
LL | #[C]
|
||||
| ^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
| ^ help: a derive helper attribute with a similar name exists: `B`
|
||||
|
||||
error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
|
||||
--> $DIR/proc-macro-attributes.rs:6:3
|
||||
|
@ -77,5 +74,4 @@ LL | #[macro_use]
|
|||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0658, E0659.
|
||||
For more information about an error, try `rustc --explain E0658`.
|
||||
For more information about this error, try `rustc --explain E0659`.
|
||||
|
|
|
@ -24,11 +24,11 @@ macro_rules! attr_proc_mac {
|
|||
struct Foo;
|
||||
|
||||
// Interpreted as a feature gated custom attribute
|
||||
#[attr_proc_macra] //~ ERROR attribute `attr_proc_macra` is currently unknown
|
||||
#[attr_proc_macra] //~ ERROR cannot find attribute macro `attr_proc_macra` in this scope
|
||||
struct Bar;
|
||||
|
||||
// Interpreted as a feature gated custom attribute
|
||||
#[FooWithLongNan] //~ ERROR attribute `FooWithLongNan` is currently unknown
|
||||
#[FooWithLongNan] //~ ERROR cannot find attribute macro `FooWithLongNan` in this scope
|
||||
struct Asdf;
|
||||
|
||||
#[derive(Dlone)]
|
||||
|
|
|
@ -1,38 +1,32 @@
|
|||
error[E0658]: The attribute `attr_proc_macra` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/resolve-error.rs:27:3
|
||||
|
|
||||
LL | #[attr_proc_macra]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `FooWithLongNan` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/resolve-error.rs:31:3
|
||||
|
|
||||
LL | #[FooWithLongNan]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: cannot find derive macro `FooWithLongNan` in this scope
|
||||
--> $DIR/resolve-error.rs:22:10
|
||||
|
|
||||
LL | #[derive(FooWithLongNan)]
|
||||
| ^^^^^^^^^^^^^^ help: try: `FooWithLongName`
|
||||
| ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName`
|
||||
|
||||
error: cannot find attribute macro `attr_proc_macra` in this scope
|
||||
--> $DIR/resolve-error.rs:27:3
|
||||
|
|
||||
LL | #[attr_proc_macra]
|
||||
| ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro`
|
||||
|
||||
error: cannot find attribute macro `FooWithLongNan` in this scope
|
||||
--> $DIR/resolve-error.rs:31:3
|
||||
|
|
||||
LL | #[FooWithLongNan]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: cannot find derive macro `Dlone` in this scope
|
||||
--> $DIR/resolve-error.rs:34:10
|
||||
|
|
||||
LL | #[derive(Dlone)]
|
||||
| ^^^^^ help: try: `Clone`
|
||||
| ^^^^^ help: a derive macro with a similar name exists: `Clone`
|
||||
|
||||
error: cannot find derive macro `Dlona` in this scope
|
||||
--> $DIR/resolve-error.rs:38:10
|
||||
|
|
||||
LL | #[derive(Dlona)]
|
||||
| ^^^^^ help: try: `Clona`
|
||||
| ^^^^^ help: a derive macro with a similar name exists: `Clona`
|
||||
|
||||
error: cannot find derive macro `attr_proc_macra` in this scope
|
||||
--> $DIR/resolve-error.rs:42:10
|
||||
|
@ -44,13 +38,13 @@ error: cannot find macro `FooWithLongNama!` in this scope
|
|||
--> $DIR/resolve-error.rs:47:5
|
||||
|
|
||||
LL | FooWithLongNama!();
|
||||
| ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam`
|
||||
| ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam`
|
||||
|
||||
error: cannot find macro `attr_proc_macra!` in this scope
|
||||
--> $DIR/resolve-error.rs:50:5
|
||||
|
|
||||
LL | attr_proc_macra!();
|
||||
| ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac`
|
||||
| ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac`
|
||||
|
||||
error: cannot find macro `Dlona!` in this scope
|
||||
--> $DIR/resolve-error.rs:53:5
|
||||
|
@ -62,8 +56,7 @@ error: cannot find macro `bang_proc_macrp!` in this scope
|
|||
--> $DIR/resolve-error.rs:56:5
|
||||
|
|
||||
LL | bang_proc_macrp!();
|
||||
| ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro`
|
||||
| ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#[rustc_attribute_should_be_reserved]
|
||||
//~^ ERROR attribute `rustc_attribute_should_be_reserved` is currently unknown
|
||||
//~^ ERROR cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
|
||||
//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
|
||||
|
||||
macro_rules! foo {
|
||||
|
|
|
@ -7,14 +7,11 @@ LL | #[rustc_attribute_should_be_reserved]
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `rustc_attribute_should_be_reserved` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
|
||||
--> $DIR/reserved-attr-on-macro.rs:1:3
|
||||
|
|
||||
LL | #[rustc_attribute_should_be_reserved]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: cannot determine resolution for the macro `foo`
|
||||
--> $DIR/reserved-attr-on-macro.rs:10:5
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0412]: cannot find type `esize` in this scope
|
|||
--> $DIR/levenshtein.rs:5:11
|
||||
|
|
||||
LL | fn foo(c: esize) {} // Misspelled primitive type name.
|
||||
| ^^^^^ help: a primitive type with a similar name exists: `isize`
|
||||
| ^^^^^ help: a builtin type with a similar name exists: `isize`
|
||||
|
||||
error[E0412]: cannot find type `Baz` in this scope
|
||||
--> $DIR/levenshtein.rs:10:10
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// gate-test-custom_inner_attributes
|
||||
|
||||
#[foo] //~ ERROR is currently unknown to the compiler
|
||||
#![feature(custom_attribute)]
|
||||
|
||||
#[foo]
|
||||
mod foo {
|
||||
#![foo] //~ ERROR is currently unknown to the compiler
|
||||
//~| ERROR non-builtin inner attributes are unstable
|
||||
#![foo] //~ ERROR non-builtin inner attributes are unstable
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/issue-36530.rs:3:3
|
||||
|
|
||||
LL | #[foo]
|
||||
| ^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: non-builtin inner attributes are unstable
|
||||
--> $DIR/issue-36530.rs:5:5
|
||||
--> $DIR/issue-36530.rs:7:5
|
||||
|
|
||||
LL | #![foo]
|
||||
| ^^^^^^^
|
||||
|
@ -16,15 +7,6 @@ LL | #![foo]
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/54726
|
||||
= help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/issue-36530.rs:5:8
|
||||
|
|
||||
LL | #![foo]
|
||||
| ^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#[deprcated] //~ ERROR attribute `deprcated` is currently unknown
|
||||
#[deprcated] //~ ERROR cannot find attribute macro `deprcated` in this scope
|
||||
fn foo() {}
|
||||
|
||||
#[tests] //~ ERROR attribute `tests` is currently unknown to the compiler
|
||||
#[tests] //~ ERROR cannot find attribute macro `tests` in this scope
|
||||
fn bar() {}
|
||||
|
||||
#[rustc_err]
|
||||
//~^ ERROR attribute `rustc_err` is currently unknown
|
||||
//~^ ERROR cannot find attribute macro `rustc_err` in this scope
|
||||
//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -7,32 +7,23 @@ LL | #[rustc_err]
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: The attribute `rustc_err` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `rustc_err` in this scope
|
||||
--> $DIR/attribute-typos.rs:7:3
|
||||
|
|
||||
LL | #[rustc_err]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
| ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error`
|
||||
|
||||
error[E0658]: The attribute `tests` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `tests` in this scope
|
||||
--> $DIR/attribute-typos.rs:4:3
|
||||
|
|
||||
LL | #[tests]
|
||||
| ^^^^^ help: a built-in attribute with a similar name exists: `test`
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
| ^^^^^ help: an attribute macro with a similar name exists: `test`
|
||||
|
||||
error[E0658]: The attribute `deprcated` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
error: cannot find attribute macro `deprcated` in this scope
|
||||
--> $DIR/attribute-typos.rs:1:3
|
||||
|
|
||||
LL | #[deprcated]
|
||||
| ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated`
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ type B = rustfmt::skip; //~ ERROR expected type, found tool attribute `rustfmt::
|
|||
struct S;
|
||||
|
||||
// Interpreted as a feature gated custom attribute
|
||||
#[rustfmt] //~ ERROR attribute `rustfmt` is currently unknown
|
||||
#[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
|
||||
fn check() {}
|
||||
|
||||
#[rustfmt::skip] // OK
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
error[E0658]: The attribute `rustfmt` is currently unknown to the compiler and may have meaning added to it in the future
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:8:3
|
||||
|
|
||||
LL | #[rustfmt]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
|
||||
|
||||
error: cannot find derive macro `rustfmt` in this scope
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:4:10
|
||||
|
|
||||
LL | #[derive(rustfmt)]
|
||||
| ^^^^^^^
|
||||
|
||||
error: cannot find attribute macro `rustfmt` in this scope
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:8:3
|
||||
|
|
||||
LL | #[rustfmt]
|
||||
| ^^^^^^^
|
||||
|
||||
error: cannot find macro `rustfmt!` in this scope
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:14:5
|
||||
|
|
||||
|
@ -45,5 +42,4 @@ LL | rustfmt::skip;
|
|||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0423, E0658.
|
||||
For more information about an error, try `rustc --explain E0423`.
|
||||
For more information about this error, try `rustc --explain E0423`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue