resolve: Implement prelude search for macro paths
resolve/expansion: Implement tool attributes
This commit is contained in:
parent
c63bb1d6a7
commit
c3e54217e8
@ -49,6 +49,7 @@ pub enum Def {
|
||||
PrimTy(hir::PrimTy),
|
||||
TyParam(DefId),
|
||||
SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
|
||||
ToolMod, // e.g. `rustfmt` in `#[rustfmt::skip]`
|
||||
|
||||
// Value namespace
|
||||
Fn(DefId),
|
||||
@ -67,6 +68,7 @@ pub enum Def {
|
||||
|
||||
// Macro namespace
|
||||
Macro(DefId, MacroKind),
|
||||
NonMacroAttr, // e.g. `#[inline]` or `#[rustfmt::skip]`
|
||||
|
||||
GlobalAsm(DefId),
|
||||
|
||||
@ -259,6 +261,8 @@ impl Def {
|
||||
Def::Label(..) |
|
||||
Def::PrimTy(..) |
|
||||
Def::SelfTy(..) |
|
||||
Def::ToolMod |
|
||||
Def::NonMacroAttr |
|
||||
Def::Err => {
|
||||
bug!("attempted .def_id() on invalid def: {:?}", self)
|
||||
}
|
||||
@ -299,6 +303,8 @@ impl Def {
|
||||
Def::SelfTy(..) => "self type",
|
||||
Def::Macro(.., macro_kind) => macro_kind.descr(),
|
||||
Def::GlobalAsm(..) => "global asm",
|
||||
Def::ToolMod => "tool module",
|
||||
Def::NonMacroAttr => "non-macro attribute",
|
||||
Def::Err => "unresolved item",
|
||||
}
|
||||
}
|
||||
|
@ -1016,6 +1016,8 @@ impl_stable_hash_for!(enum hir::def::Def {
|
||||
Label(node_id),
|
||||
Macro(def_id, macro_kind),
|
||||
GlobalAsm(def_id),
|
||||
ToolMod,
|
||||
NonMacroAttr,
|
||||
Err
|
||||
});
|
||||
|
||||
|
@ -629,7 +629,8 @@ impl<'a> Resolver<'a> {
|
||||
pub fn get_macro(&mut self, def: Def) -> Lrc<SyntaxExtension> {
|
||||
let def_id = match def {
|
||||
Def::Macro(def_id, ..) => def_id,
|
||||
_ => panic!("Expected Def::Macro(..)"),
|
||||
Def::NonMacroAttr => return Lrc::new(SyntaxExtension::NonMacroAttr),
|
||||
_ => panic!("Expected Def::Macro(..) or Def::NonMacroAttr"),
|
||||
};
|
||||
if let Some(ext) = self.macro_map.get(&def_id) {
|
||||
return ext.clone();
|
||||
|
@ -131,8 +131,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
|
||||
directive.vis.get() == ty::Visibility::Public ||
|
||||
directive.span.is_dummy() => {
|
||||
if let ImportDirectiveSubclass::MacroUse = directive.subclass {
|
||||
if resolver.session.features_untracked().use_extern_macros &&
|
||||
!directive.span.is_dummy() {
|
||||
if resolver.use_extern_macros && !directive.span.is_dummy() {
|
||||
resolver.session.buffer_lint(
|
||||
lint::builtin::MACRO_USE_EXTERN_CRATE,
|
||||
directive.id,
|
||||
|
@ -86,6 +86,10 @@ mod check_unused;
|
||||
mod build_reduced_graph;
|
||||
mod resolve_imports;
|
||||
|
||||
fn is_known_tool(name: Name) -> bool {
|
||||
["clippy", "rustfmt"].contains(&&*name.as_str())
|
||||
}
|
||||
|
||||
/// A free importable items suggested in case of resolution failure.
|
||||
struct ImportSuggestion {
|
||||
path: Path,
|
||||
@ -200,15 +204,10 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
|
||||
err.span_label(typaram_span, "type variable from outer function");
|
||||
}
|
||||
},
|
||||
Def::Mod(..) | Def::Struct(..) | Def::Union(..) | Def::Enum(..) | Def::Variant(..) |
|
||||
Def::Trait(..) | Def::TyAlias(..) | Def::TyForeign(..) | Def::TraitAlias(..) |
|
||||
Def::AssociatedTy(..) | Def::PrimTy(..) | Def::Fn(..) | Def::Const(..) |
|
||||
Def::Static(..) | Def::StructCtor(..) | Def::VariantCtor(..) | Def::Method(..) |
|
||||
Def::AssociatedConst(..) | Def::Local(..) | Def::Upvar(..) | Def::Label(..) |
|
||||
Def::Existential(..) | Def::AssociatedExistential(..) |
|
||||
Def::Macro(..) | Def::GlobalAsm(..) | Def::Err =>
|
||||
_ => {
|
||||
bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \
|
||||
Def::TyParam")
|
||||
}
|
||||
}
|
||||
|
||||
// Try to retrieve the span of the function signature and generate a new message with
|
||||
@ -1711,9 +1710,7 @@ impl<'a> Resolver<'a> {
|
||||
vis: ty::Visibility::Public,
|
||||
}),
|
||||
|
||||
// The `proc_macro` and `decl_macro` features imply `use_extern_macros`
|
||||
use_extern_macros:
|
||||
features.use_extern_macros || features.decl_macro,
|
||||
use_extern_macros: features.use_extern_macros(),
|
||||
|
||||
crate_loader,
|
||||
macro_names: FxHashSet(),
|
||||
@ -1846,6 +1843,7 @@ impl<'a> Resolver<'a> {
|
||||
path_span: Span)
|
||||
-> Option<LexicalScopeBinding<'a>> {
|
||||
let record_used = record_used_id.is_some();
|
||||
assert!(ns == TypeNS || ns == ValueNS);
|
||||
if ns == TypeNS {
|
||||
ident.span = if ident.name == keywords::SelfType.name() {
|
||||
// FIXME(jseyfried) improve `Self` hygiene
|
||||
@ -1922,8 +1920,9 @@ impl<'a> Resolver<'a> {
|
||||
return Some(LexicalScopeBinding::Item(binding))
|
||||
}
|
||||
_ if poisoned.is_some() => break,
|
||||
Err(Undetermined) => return None,
|
||||
Err(Determined) => {}
|
||||
Err(Determined) => continue,
|
||||
Err(Undetermined) =>
|
||||
span_bug!(ident.span, "undetermined resolution during main resolution pass"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1945,6 +1944,11 @@ impl<'a> Resolver<'a> {
|
||||
ident.span, Mark::root()).to_name_binding(self.arenas);
|
||||
return Some(LexicalScopeBinding::Item(binding));
|
||||
}
|
||||
if ns == TypeNS && is_known_tool(ident.name) {
|
||||
let binding = (Def::ToolMod, ty::Visibility::Public,
|
||||
ident.span, Mark::root()).to_name_binding(self.arenas);
|
||||
return Some(LexicalScopeBinding::Item(binding));
|
||||
}
|
||||
if let Some(prelude) = self.prelude {
|
||||
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
|
||||
false, false, path_span) {
|
||||
@ -3505,6 +3509,8 @@ impl<'a> Resolver<'a> {
|
||||
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
|
||||
if let Some(next_module) = binding.module() {
|
||||
module = Some(next_module);
|
||||
} else if def == Def::ToolMod && i + 1 != path.len() {
|
||||
return PathResult::NonModule(PathResolution::new(Def::NonMacroAttr))
|
||||
} else if def == Def::Err {
|
||||
return PathResult::NonModule(err_path_resolution());
|
||||
} else if opt_ns.is_some() && (is_last || maybe_assoc) {
|
||||
|
@ -8,9 +8,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use {AmbiguityError, CrateLint, Resolver, ResolutionError, resolve_error};
|
||||
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult};
|
||||
use Namespace::{self, MacroNS};
|
||||
use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error};
|
||||
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
|
||||
use Namespace::{self, TypeNS, MacroNS};
|
||||
use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
|
||||
use resolve_imports::ImportResolver;
|
||||
use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex,
|
||||
@ -27,7 +27,7 @@ use syntax::ext::expand::{self, AstFragment, AstFragmentKind, Invocation, Invoca
|
||||
use syntax::ext::hygiene::{self, Mark};
|
||||
use syntax::ext::placeholders::placeholder;
|
||||
use syntax::ext::tt::macro_rules;
|
||||
use syntax::feature_gate::{self, emit_feature_err, GateIssue};
|
||||
use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
|
||||
use syntax::fold::{self, Folder};
|
||||
use syntax::parse::parser::PathStyle;
|
||||
use syntax::parse::token::{self, Token};
|
||||
@ -326,6 +326,18 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
|
||||
self.report_proc_macro_stub(invoc.span());
|
||||
return Err(Determinacy::Determined);
|
||||
} else if let Def::NonMacroAttr = def {
|
||||
if let InvocationKind::Attr { .. } = invoc.kind {
|
||||
if !self.session.features_untracked().tool_attributes {
|
||||
feature_err(&self.session.parse_sess, "tool_attributes",
|
||||
invoc.span(), GateIssue::Language,
|
||||
"tool attributes are unstable").emit();
|
||||
}
|
||||
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr)));
|
||||
} else {
|
||||
self.report_non_macro_attr(invoc.path_span());
|
||||
return Err(Determinacy::Determined);
|
||||
}
|
||||
}
|
||||
let def_id = def.def_id();
|
||||
|
||||
@ -348,6 +360,9 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
|
||||
self.report_proc_macro_stub(path.span);
|
||||
return Err(Determinacy::Determined);
|
||||
} else if let Def::NonMacroAttr = def {
|
||||
self.report_non_macro_attr(path.span);
|
||||
return Err(Determinacy::Determined);
|
||||
}
|
||||
self.unused_macros.remove(&def.def_id());
|
||||
Ok(self.get_macro(def))
|
||||
@ -378,6 +393,11 @@ impl<'a> Resolver<'a> {
|
||||
"can't use a procedural macro from the same crate that defines it");
|
||||
}
|
||||
|
||||
fn report_non_macro_attr(&self, span: Span) {
|
||||
self.session.span_err(span,
|
||||
"expected a macro, found non-macro attribute");
|
||||
}
|
||||
|
||||
fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
|
||||
-> Result<Def, Determinacy> {
|
||||
let (attr, traits, item) = match invoc.kind {
|
||||
@ -450,7 +470,15 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
|
||||
-> Result<Def, Determinacy> {
|
||||
if kind != MacroKind::Bang && path.segments.len() > 1 {
|
||||
let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
|
||||
if def != Err(Determinacy::Undetermined) {
|
||||
// Do not report duplicated errors on every undetermined resolution.
|
||||
path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
|
||||
self.session.span_err(segment.args.as_ref().unwrap().span(),
|
||||
"generic arguments in macro path");
|
||||
});
|
||||
}
|
||||
if kind != MacroKind::Bang && path.segments.len() > 1 && def != Ok(Def::NonMacroAttr) {
|
||||
if !self.session.features_untracked().proc_macro_path_invoc {
|
||||
emit_feature_err(
|
||||
&self.session.parse_sess,
|
||||
@ -462,15 +490,6 @@ impl<'a> Resolver<'a> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
|
||||
if def != Err(Determinacy::Undetermined) {
|
||||
// Do not report duplicated errors on every undetermined resolution.
|
||||
path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
|
||||
self.session.span_err(segment.args.as_ref().unwrap().span(),
|
||||
"generic arguments in macro path");
|
||||
});
|
||||
}
|
||||
def
|
||||
}
|
||||
|
||||
@ -544,67 +563,226 @@ impl<'a> Resolver<'a> {
|
||||
result
|
||||
}
|
||||
|
||||
// Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`)
|
||||
// Resolve the initial segment of a non-global macro path
|
||||
// (e.g. `foo` in `foo::bar!(); or `foo!();`).
|
||||
// This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
|
||||
// expansion and import resolution (perhaps they can be merged in the future).
|
||||
pub fn resolve_lexical_macro_path_segment(&mut self,
|
||||
mut ident: Ident,
|
||||
ns: Namespace,
|
||||
record_used: bool,
|
||||
path_span: Span)
|
||||
-> Result<MacroBinding<'a>, Determinacy> {
|
||||
ident = ident.modern();
|
||||
let mut module = Some(self.current_module);
|
||||
let mut potential_illegal_shadower = Err(Determinacy::Determined);
|
||||
let determinacy =
|
||||
if record_used { Determinacy::Determined } else { Determinacy::Undetermined };
|
||||
loop {
|
||||
let orig_current_module = self.current_module;
|
||||
let result = if let Some(module) = module {
|
||||
self.current_module = module; // Lexical resolutions can never be a privacy error.
|
||||
// Since expanded macros may not shadow the lexical scope and
|
||||
// globs may not shadow global macros (both enforced below),
|
||||
// we resolve with restricted shadowing (indicated by the penultimate argument).
|
||||
self.resolve_ident_in_module_unadjusted(
|
||||
module, ident, ns, true, record_used, path_span,
|
||||
).map(MacroBinding::Modern)
|
||||
} else {
|
||||
self.macro_prelude.get(&ident.name).cloned().ok_or(determinacy)
|
||||
.map(MacroBinding::Global)
|
||||
};
|
||||
self.current_module = orig_current_module;
|
||||
// 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 can 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).
|
||||
// (Macro NS)
|
||||
// 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
|
||||
// (open, not controlled).
|
||||
// 2. Macro prelude (language, standard library, user-defined legacy plugins lumped into
|
||||
// one set) (open, the open part is from macro expansions, not controlled).
|
||||
// 2a. User-defined prelude from macro-use
|
||||
// (open, the open part is from macro expansions, not controlled).
|
||||
// 2b. Standard library prelude, currently just a macro-use (closed, controlled)
|
||||
// 2c. Language prelude, perhaps including builtin attributes
|
||||
// (closed, controlled, except for legacy plugins).
|
||||
// 3. Builtin attributes (closed, controlled).
|
||||
|
||||
match result.map(MacroBinding::binding) {
|
||||
Ok(binding) => {
|
||||
if !record_used {
|
||||
return result;
|
||||
assert!(ns == TypeNS || ns == MacroNS);
|
||||
ident = ident.modern();
|
||||
|
||||
// Names from inner scope that can't shadow names from outer scopes, e.g.
|
||||
// mod m { ... }
|
||||
// {
|
||||
// use prefix::*; // if this imports another `m`, then it can't shadow the outer `m`
|
||||
// // and we have and ambiguity error
|
||||
// m::mac!();
|
||||
// }
|
||||
// This includes names from globs and from macro expansions.
|
||||
let mut potentially_ambiguous_result: Option<MacroBinding> = None;
|
||||
|
||||
enum WhereToResolve<'a> {
|
||||
Module(Module<'a>),
|
||||
MacroPrelude,
|
||||
BuiltinAttrs,
|
||||
ExternPrelude,
|
||||
ToolPrelude,
|
||||
StdLibPrelude,
|
||||
PrimitiveTypes,
|
||||
}
|
||||
|
||||
// Go through all the scopes and try to resolve the name.
|
||||
let mut where_to_resolve = WhereToResolve::Module(self.current_module);
|
||||
let mut use_prelude = !self.current_module.no_implicit_prelude;
|
||||
loop {
|
||||
let result = match where_to_resolve {
|
||||
WhereToResolve::Module(module) => {
|
||||
let orig_current_module = mem::replace(&mut self.current_module, module);
|
||||
let binding = self.resolve_ident_in_module_unadjusted(
|
||||
module, ident, ns, true, record_used, path_span,
|
||||
);
|
||||
self.current_module = orig_current_module;
|
||||
binding.map(MacroBinding::Modern)
|
||||
}
|
||||
WhereToResolve::MacroPrelude => {
|
||||
match self.macro_prelude.get(&ident.name).cloned() {
|
||||
Some(binding) => Ok(MacroBinding::Global(binding)),
|
||||
None => Err(Determinacy::Determined),
|
||||
}
|
||||
if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower {
|
||||
if shadower.def() != binding.def() {
|
||||
let name = ident.name;
|
||||
}
|
||||
WhereToResolve::BuiltinAttrs => {
|
||||
if is_builtin_attr_name(ident.name) {
|
||||
let binding = (Def::NonMacroAttr, ty::Visibility::Public,
|
||||
ident.span, Mark::root()).to_name_binding(self.arenas);
|
||||
Ok(MacroBinding::Global(binding))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
}
|
||||
WhereToResolve::ExternPrelude => {
|
||||
if use_prelude && self.extern_prelude.contains(&ident.name) {
|
||||
if !self.session.features_untracked().extern_prelude &&
|
||||
!self.ignore_extern_prelude_feature {
|
||||
feature_err(&self.session.parse_sess, "extern_prelude",
|
||||
ident.span, GateIssue::Language,
|
||||
"access to extern crates through prelude is experimental")
|
||||
.emit();
|
||||
}
|
||||
|
||||
let crate_id =
|
||||
self.crate_loader.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);
|
||||
|
||||
let binding = (crate_root, ty::Visibility::Public,
|
||||
ident.span, Mark::root()).to_name_binding(self.arenas);
|
||||
Ok(MacroBinding::Global(binding))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
}
|
||||
WhereToResolve::ToolPrelude => {
|
||||
if use_prelude && is_known_tool(ident.name) {
|
||||
let binding = (Def::ToolMod, ty::Visibility::Public,
|
||||
ident.span, Mark::root()).to_name_binding(self.arenas);
|
||||
Ok(MacroBinding::Global(binding))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
}
|
||||
WhereToResolve::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(prelude, ident, ns,
|
||||
false, false, path_span) {
|
||||
result = Ok(MacroBinding::Global(binding));
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
WhereToResolve::PrimitiveTypes => {
|
||||
if let Some(prim_ty) =
|
||||
self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
|
||||
let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public,
|
||||
ident.span, Mark::root()).to_name_binding(self.arenas);
|
||||
Ok(MacroBinding::Global(binding))
|
||||
} else {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
macro_rules! continue_search { () => {
|
||||
where_to_resolve = match where_to_resolve {
|
||||
WhereToResolve::Module(module) => {
|
||||
match self.hygienic_lexical_parent(module, &mut ident.span) {
|
||||
Some(parent_module) => WhereToResolve::Module(parent_module),
|
||||
None => {
|
||||
use_prelude = !module.no_implicit_prelude;
|
||||
if ns == MacroNS {
|
||||
WhereToResolve::MacroPrelude
|
||||
} else {
|
||||
WhereToResolve::ExternPrelude
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WhereToResolve::MacroPrelude => WhereToResolve::BuiltinAttrs,
|
||||
WhereToResolve::BuiltinAttrs => break, // nowhere else to search
|
||||
WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
|
||||
WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
|
||||
WhereToResolve::StdLibPrelude => WhereToResolve::PrimitiveTypes,
|
||||
WhereToResolve::PrimitiveTypes => break, // nowhere else to search
|
||||
};
|
||||
|
||||
continue;
|
||||
}}
|
||||
|
||||
match result {
|
||||
Ok(result) => {
|
||||
if !record_used {
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
let binding = result.binding();
|
||||
|
||||
// Found a solution that is ambiguous with a previously found solution.
|
||||
// Push an ambiguity error for later reporting and
|
||||
// return something for better recovery.
|
||||
if let Some(previous_result) = potentially_ambiguous_result {
|
||||
if binding.def() != previous_result.binding().def() {
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
span: path_span,
|
||||
name,
|
||||
b1: shadower,
|
||||
name: ident.name,
|
||||
b1: previous_result.binding(),
|
||||
b2: binding,
|
||||
lexical: true,
|
||||
});
|
||||
return potential_illegal_shadower;
|
||||
return Ok(previous_result);
|
||||
}
|
||||
}
|
||||
if binding.is_glob_import() || binding.expansion != Mark::root() {
|
||||
potential_illegal_shadower = result;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
},
|
||||
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
|
||||
Err(Determinacy::Determined) => {}
|
||||
}
|
||||
|
||||
module = match module {
|
||||
Some(module) => self.hygienic_lexical_parent(module, &mut ident.span),
|
||||
None => return potential_illegal_shadower,
|
||||
// Found a solution that's not an ambiguity yet, but is "suspicious" and
|
||||
// can participate in ambiguities later on.
|
||||
// Remember it and go search for other solutions in outer scopes.
|
||||
if binding.is_glob_import() || binding.expansion != Mark::root() {
|
||||
potentially_ambiguous_result = Some(result);
|
||||
|
||||
continue_search!();
|
||||
}
|
||||
|
||||
// Found a solution that can't be ambiguous, great success.
|
||||
return Ok(result);
|
||||
},
|
||||
Err(Determinacy::Determined) => {
|
||||
continue_search!();
|
||||
}
|
||||
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
|
||||
}
|
||||
}
|
||||
|
||||
// Previously found potentially ambiguous result turned out to not be ambiguous after all.
|
||||
if let Some(previous_result) = potentially_ambiguous_result {
|
||||
return Ok(previous_result);
|
||||
}
|
||||
|
||||
if record_used { Err(Determinacy::Determined) } else { Err(Determinacy::Undetermined) }
|
||||
}
|
||||
|
||||
pub fn resolve_legacy_scope(&mut self,
|
||||
|
@ -811,6 +811,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
HirDef::Label(..) |
|
||||
HirDef::Macro(..) |
|
||||
HirDef::GlobalAsm(..) |
|
||||
HirDef::ToolMod |
|
||||
HirDef::NonMacroAttr |
|
||||
HirDef::Err => None,
|
||||
}
|
||||
}
|
||||
|
@ -89,17 +89,8 @@ pub fn is_known(attr: &Attribute) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"];
|
||||
const RUST_KNOWN_LINT_TOOL: &[&str] = &["clippy"];
|
||||
|
||||
pub fn is_known_tool(attr: &Attribute) -> bool {
|
||||
let tool_name =
|
||||
attr.path.segments.iter().next().expect("empty path in attribute").ident.name;
|
||||
RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref())
|
||||
}
|
||||
|
||||
pub fn is_known_lint_tool(m_item: Ident) -> bool {
|
||||
RUST_KNOWN_LINT_TOOL.contains(&m_item.as_str().as_ref())
|
||||
["clippy"].contains(&m_item.as_str().as_ref())
|
||||
}
|
||||
|
||||
impl NestedMetaItem {
|
||||
@ -245,10 +236,6 @@ impl Attribute {
|
||||
pub fn is_value_str(&self) -> bool {
|
||||
self.value_str().is_some()
|
||||
}
|
||||
|
||||
pub fn is_scoped(&self) -> bool {
|
||||
self.path.segments.len() > 1
|
||||
}
|
||||
}
|
||||
|
||||
impl MetaItem {
|
||||
|
@ -588,6 +588,9 @@ impl MacroKind {
|
||||
|
||||
/// An enum representing the different kinds of syntax extensions.
|
||||
pub enum SyntaxExtension {
|
||||
/// A trivial "extension" that does nothing, only keeps the attribute and marks it as known.
|
||||
NonMacroAttr,
|
||||
|
||||
/// A syntax extension that is attached to an item and creates new items
|
||||
/// based upon it.
|
||||
///
|
||||
@ -667,6 +670,7 @@ impl SyntaxExtension {
|
||||
SyntaxExtension::IdentTT(..) |
|
||||
SyntaxExtension::ProcMacro { .. } =>
|
||||
MacroKind::Bang,
|
||||
SyntaxExtension::NonMacroAttr |
|
||||
SyntaxExtension::MultiDecorator(..) |
|
||||
SyntaxExtension::MultiModifier(..) |
|
||||
SyntaxExtension::AttrProcMacro(..) =>
|
||||
@ -696,6 +700,7 @@ impl SyntaxExtension {
|
||||
SyntaxExtension::AttrProcMacro(.., edition) |
|
||||
SyntaxExtension::ProcMacroDerive(.., edition) => edition,
|
||||
// Unstable legacy stuff
|
||||
SyntaxExtension::NonMacroAttr |
|
||||
SyntaxExtension::IdentTT(..) |
|
||||
SyntaxExtension::MultiDecorator(..) |
|
||||
SyntaxExtension::MultiModifier(..) |
|
||||
|
@ -36,7 +36,7 @@ use visit::{self, Visitor};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::mem;
|
||||
use std::{iter, mem};
|
||||
use std::rc::Rc;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -243,6 +243,15 @@ impl Invocation {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_span(&self) -> Span {
|
||||
match self.kind {
|
||||
InvocationKind::Bang { ref mac, .. } => mac.node.path.span,
|
||||
InvocationKind::Attr { attr: Some(ref attr), .. } => attr.path.span,
|
||||
InvocationKind::Attr { attr: None, .. } => DUMMY_SP,
|
||||
InvocationKind::Derive { ref path, .. } => path.span,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attr_id(&self) -> Option<ast::AttrId> {
|
||||
match self.kind {
|
||||
InvocationKind::Attr { attr: Some(ref attr), .. } => Some(attr.id),
|
||||
@ -566,6 +575,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
});
|
||||
|
||||
match *ext {
|
||||
NonMacroAttr => {
|
||||
attr::mark_known(&attr);
|
||||
let item = item.map_attrs(|mut attrs| { attrs.push(attr); attrs });
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
|
||||
}
|
||||
MultiModifier(ref mac) => {
|
||||
let meta = attr.parse_meta(self.cx.parse_sess)
|
||||
.map_err(|mut e| { e.emit(); }).ok()?;
|
||||
@ -810,7 +824,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
|
||||
MultiDecorator(..) | MultiModifier(..) |
|
||||
AttrProcMacro(..) | SyntaxExtension::NonMacroAttr => {
|
||||
self.cx.span_err(path.span,
|
||||
&format!("`{}` can only be used in attributes", path));
|
||||
self.cx.trace_macros_diag();
|
||||
@ -1612,13 +1627,16 @@ impl<'feat> ExpansionConfig<'feat> {
|
||||
fn enable_allow_internal_unstable = allow_internal_unstable,
|
||||
fn enable_custom_derive = custom_derive,
|
||||
fn enable_format_args_nl = format_args_nl,
|
||||
fn use_extern_macros_enabled = use_extern_macros,
|
||||
fn macros_in_extern_enabled = macros_in_extern,
|
||||
fn proc_macro_mod = proc_macro_mod,
|
||||
fn proc_macro_gen = proc_macro_gen,
|
||||
fn proc_macro_expr = proc_macro_expr,
|
||||
fn proc_macro_non_items = proc_macro_non_items,
|
||||
}
|
||||
|
||||
pub fn use_extern_macros_enabled(&self) -> bool {
|
||||
self.features.map_or(false, |features| features.use_extern_macros())
|
||||
}
|
||||
}
|
||||
|
||||
// A Marker adds the given mark to the syntax context.
|
||||
|
@ -80,6 +80,11 @@ macro_rules! declare_features {
|
||||
{
|
||||
$(f(stringify!($feature), self.$feature);)+
|
||||
}
|
||||
|
||||
pub fn use_extern_macros(&self) -> bool {
|
||||
// The `decl_macro` and `tool_attributes` features imply `use_extern_macros`.
|
||||
self.use_extern_macros || self.decl_macro || self.tool_attributes
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -689,6 +694,10 @@ pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, Att
|
||||
BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
|
||||
}
|
||||
|
||||
pub fn is_builtin_attr_name(name: ast::Name) -> bool {
|
||||
BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| name == builtin_name)
|
||||
}
|
||||
|
||||
pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
|
||||
BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name)) ||
|
||||
attr.name().as_str().starts_with("rustc_")
|
||||
@ -1198,28 +1207,9 @@ impl<'a> Context<'a> {
|
||||
// before the plugin attributes are registered
|
||||
// so we skip this then
|
||||
if !is_macro {
|
||||
if attr.is_scoped() {
|
||||
gate_feature!(self, tool_attributes, attr.span,
|
||||
&format!("scoped attribute `{}` is experimental", attr.path));
|
||||
if attr::is_known_tool(attr) {
|
||||
attr::mark_used(attr);
|
||||
} else {
|
||||
span_err!(
|
||||
self.parse_sess.span_diagnostic,
|
||||
attr.span,
|
||||
E0694,
|
||||
"an unknown tool name found in scoped attribute: `{}`.",
|
||||
attr.path
|
||||
);
|
||||
}
|
||||
} else {
|
||||
gate_feature!(self, custom_attribute, attr.span,
|
||||
&format!("The attribute `{}` is currently \
|
||||
unknown to the compiler and \
|
||||
may have meaning \
|
||||
added to it in the future",
|
||||
attr.path));
|
||||
}
|
||||
let msg = format!("The attribute `{}` is currently unknown to the compiler and \
|
||||
may have meaning added to it in the future", attr.path);
|
||||
gate_feature!(self, custom_attribute, attr.span, &msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1529,7 +1519,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
if self.context.features.use_extern_macros && attr::is_known(attr) {
|
||||
if self.context.features.use_extern_macros() && attr::is_known(attr) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -2004,7 +1994,7 @@ impl FeatureChecker {
|
||||
// the branching can be eliminated by modifying `set!()` to set these spans
|
||||
// only for the features that need to be checked for mutual exclusion.
|
||||
fn collect(&mut self, features: &Features, span: Span) {
|
||||
if features.use_extern_macros {
|
||||
if features.use_extern_macros() {
|
||||
// If self.use_extern_macros is None, set to Some(span)
|
||||
self.use_extern_macros = self.use_extern_macros.or(Some(span));
|
||||
}
|
||||
|
@ -8,9 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(tool_attributes)]
|
||||
#![feature(use_extern_macros, proc_macro_path_invoc)]
|
||||
|
||||
#![foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
|
||||
|
||||
#[foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
|
||||
#[foo::bar] //~ ERROR failed to resolve. Use of undeclared type or module `foo`
|
||||
fn main() {}
|
||||
|
@ -11,7 +11,7 @@
|
||||
// aux-build:issue-42708.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(decl_macro, use_extern_macros, proc_macro_path_invoc)]
|
||||
#![feature(decl_macro, proc_macro_path_invoc)]
|
||||
#![allow(unused)]
|
||||
|
||||
extern crate issue_42708;
|
||||
|
@ -11,7 +11,7 @@
|
||||
// aux-build:issue-50061.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(use_extern_macros, proc_macro_path_invoc, decl_macro)]
|
||||
#![feature(proc_macro_path_invoc, decl_macro)]
|
||||
|
||||
extern crate issue_50061;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
// aux-build:parent-source-spans.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(use_extern_macros, decl_macro, proc_macro_non_items)]
|
||||
#![feature(decl_macro, proc_macro_non_items)]
|
||||
|
||||
extern crate parent_source_spans;
|
||||
|
||||
|
@ -12,3 +12,8 @@
|
||||
macro_rules! mac {
|
||||
($ident:ident) => { let $ident = 42; }
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! inline {
|
||||
() => ()
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476)
|
||||
error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
|
||||
--> $DIR/feature-gate-macros_in_extern.rs:29:5
|
||||
|
|
||||
LL | returns_isize!(rust_get_test_int);
|
||||
@ -6,7 +6,7 @@ LL | returns_isize!(rust_get_test_int);
|
||||
|
|
||||
= help: add #![feature(macros_in_extern)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476)
|
||||
error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
|
||||
--> $DIR/feature-gate-macros_in_extern.rs:31:5
|
||||
|
|
||||
LL | takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
|
||||
@ -14,7 +14,7 @@ LL | takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
|
||||
|
|
||||
= help: add #![feature(macros_in_extern)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476)
|
||||
error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
|
||||
--> $DIR/feature-gate-macros_in_extern.rs:33:5
|
||||
|
|
||||
LL | emits_nothing!();
|
||||
|
@ -8,8 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(use_extern_macros)]
|
||||
|
||||
fn main() {
|
||||
#[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
|
||||
#[rustfmt::skip] //~ ERROR tool attributes are unstable
|
||||
let x = 3
|
||||
;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
error[E0658]: scoped attribute `rustfmt::skip` is experimental (see issue #44690)
|
||||
--> $DIR/feature-gate-tool_attributes.rs:12:5
|
||||
error[E0658]: tool attributes are unstable (see issue #44690)
|
||||
--> $DIR/feature-gate-tool_attributes.rs:14:5
|
||||
|
|
||||
LL | #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
|
||||
LL | #[rustfmt::skip] //~ ERROR tool attributes are unstable
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(tool_attributes)] to the crate attributes to enable
|
||||
|
@ -9,6 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
print!(test!());
|
||||
print!(testo!());
|
||||
//~^ ERROR: format argument must be a string literal
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/issue-11692-1.rs:12:12
|
||||
|
|
||||
LL | print!(test!());
|
||||
| ^^^^^^^
|
||||
LL | print!(testo!());
|
||||
| ^^^^^^^^
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | print!("{}", test!());
|
||||
LL | print!("{}", testo!());
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -10,5 +10,5 @@
|
||||
|
||||
fn main() {
|
||||
concat!(test!());
|
||||
//~^ ERROR cannot find macro `test!` in this scope
|
||||
//~^ ERROR expected a macro, found non-macro attribute
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: cannot find macro `test!` in this scope
|
||||
error: expected a macro, found non-macro attribute
|
||||
--> $DIR/issue-11692-2.rs:12:13
|
||||
|
|
||||
LL | concat!(test!());
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(use_extern_macros, decl_macro)]
|
||||
#![feature(decl_macro)]
|
||||
|
||||
mod type_ns {
|
||||
pub type A = u8;
|
||||
|
@ -8,11 +8,13 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Make sure that 'custom_attributes' feature does not allow scoped attributes.
|
||||
#![feature(use_extern_macros, extern_prelude)]
|
||||
|
||||
#![feature(custom_attributes)]
|
||||
mod m {
|
||||
fn check() {
|
||||
Vec::clone!(); //~ ERROR failed to resolve. Not a module `Vec`
|
||||
u8::clone!(); //~ ERROR failed to resolve. Not a module `u8`
|
||||
}
|
||||
}
|
||||
|
||||
#[foo::bar]
|
||||
//~^ ERROR scoped attribute `foo::bar` is experimental (see issue #44690) [E0658]
|
||||
//~^^ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
|
||||
fn main() {}
|
15
src/test/ui/macro-path-prelude-fail-1.stderr
Normal file
15
src/test/ui/macro-path-prelude-fail-1.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0433]: failed to resolve. Not a module `Vec`
|
||||
--> $DIR/macro-path-prelude-fail-1.rs:15:9
|
||||
|
|
||||
LL | Vec::clone!(); //~ ERROR failed to resolve. Not a module `Vec`
|
||||
| ^^^ Not a module `Vec`
|
||||
|
||||
error[E0433]: failed to resolve. Not a module `u8`
|
||||
--> $DIR/macro-path-prelude-fail-1.rs:16:9
|
||||
|
|
||||
LL | u8::clone!(); //~ ERROR failed to resolve. Not a module `u8`
|
||||
| ^^ Not a module `u8`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0433`.
|
19
src/test/ui/macro-path-prelude-fail-2.rs
Normal file
19
src/test/ui/macro-path-prelude-fail-2.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(use_extern_macros)]
|
||||
|
||||
mod m {
|
||||
fn check() {
|
||||
Result::Ok!(); //~ ERROR fail to resolve non-ident macro path
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
8
src/test/ui/macro-path-prelude-fail-2.stderr
Normal file
8
src/test/ui/macro-path-prelude-fail-2.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: fail to resolve non-ident macro path
|
||||
--> $DIR/macro-path-prelude-fail-2.rs:15:9
|
||||
|
|
||||
LL | Result::Ok!(); //~ ERROR fail to resolve non-ident macro path
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
18
src/test/ui/macro-path-prelude-fail-3.rs
Normal file
18
src/test/ui/macro-path-prelude-fail-3.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(use_extern_macros)]
|
||||
|
||||
#[derive(inline)] //~ ERROR expected a macro, found non-macro attribute
|
||||
struct S;
|
||||
|
||||
fn main() {
|
||||
inline!(); //~ ERROR expected a macro, found non-macro attribute
|
||||
}
|
14
src/test/ui/macro-path-prelude-fail-3.stderr
Normal file
14
src/test/ui/macro-path-prelude-fail-3.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: expected a macro, found non-macro attribute
|
||||
--> $DIR/macro-path-prelude-fail-3.rs:13:10
|
||||
|
|
||||
LL | #[derive(inline)] //~ ERROR expected a macro, found non-macro attribute
|
||||
| ^^^^^^
|
||||
|
||||
error: expected a macro, found non-macro attribute
|
||||
--> $DIR/macro-path-prelude-fail-3.rs:17:5
|
||||
|
|
||||
LL | inline!(); //~ ERROR expected a macro, found non-macro attribute
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -8,8 +8,14 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
#[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
|
||||
let x =
|
||||
3;
|
||||
// compile-pass
|
||||
|
||||
#![feature(use_extern_macros, extern_prelude)]
|
||||
|
||||
mod m {
|
||||
fn check() {
|
||||
std::panic!(); // OK
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
41
src/test/ui/macro-path-prelude-shadowing.rs
Normal file
41
src/test/ui/macro-path-prelude-shadowing.rs
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:macro-in-other-crate.rs
|
||||
|
||||
#![feature(decl_macro, extern_prelude)]
|
||||
|
||||
macro_rules! add_macro_expanded_things_to_macro_prelude {() => {
|
||||
#[macro_use]
|
||||
extern crate macro_in_other_crate;
|
||||
}}
|
||||
|
||||
add_macro_expanded_things_to_macro_prelude!();
|
||||
|
||||
mod m1 {
|
||||
fn check() {
|
||||
inline!(); //~ ERROR `inline` is ambiguous
|
||||
}
|
||||
}
|
||||
|
||||
mod m2 {
|
||||
pub mod std {
|
||||
pub macro panic() {}
|
||||
}
|
||||
}
|
||||
|
||||
mod m3 {
|
||||
use m2::*; // glob-import user-defined `std`
|
||||
fn check() {
|
||||
std::panic!(); //~ ERROR `std` is ambiguous
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
42
src/test/ui/macro-path-prelude-shadowing.stderr
Normal file
42
src/test/ui/macro-path-prelude-shadowing.stderr
Normal file
@ -0,0 +1,42 @@
|
||||
error[E0659]: `inline` is ambiguous
|
||||
--> $DIR/macro-path-prelude-shadowing.rs:24:9
|
||||
|
|
||||
LL | inline!(); //~ ERROR `inline` is ambiguous
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `inline` could refer to the name imported here
|
||||
--> $DIR/macro-path-prelude-shadowing.rs:16:5
|
||||
|
|
||||
LL | #[macro_use]
|
||||
| ^^^^^^^^^^^^
|
||||
...
|
||||
LL | add_macro_expanded_things_to_macro_prelude!();
|
||||
| ---------------------------------------------- in this macro invocation
|
||||
note: `inline` could also refer to the name defined here
|
||||
--> $DIR/macro-path-prelude-shadowing.rs:24:9
|
||||
|
|
||||
LL | inline!(); //~ ERROR `inline` is ambiguous
|
||||
| ^^^^^^
|
||||
= note: macro-expanded macro imports do not shadow
|
||||
|
||||
error[E0659]: `std` is ambiguous
|
||||
--> $DIR/macro-path-prelude-shadowing.rs:37:9
|
||||
|
|
||||
LL | std::panic!(); //~ ERROR `std` is ambiguous
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: `std` could refer to the name imported here
|
||||
--> $DIR/macro-path-prelude-shadowing.rs:35:9
|
||||
|
|
||||
LL | use m2::*; // glob-import user-defined `std`
|
||||
| ^^^^^
|
||||
note: `std` could also refer to the name defined here
|
||||
--> $DIR/macro-path-prelude-shadowing.rs:37:9
|
||||
|
|
||||
LL | std::panic!(); //~ ERROR `std` is ambiguous
|
||||
| ^^^
|
||||
= note: consider adding an explicit import of `std` to disambiguate
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0659`.
|
15
src/test/ui/tool-attributes-disabled-1.rs
Normal file
15
src/test/ui/tool-attributes-disabled-1.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// If macro modularization (`use_extern_macros`) is not enabled,
|
||||
// then tool attributes are treated as custom attributes.
|
||||
|
||||
#[rustfmt::bar] //~ ERROR The attribute `rustfmt::bar` is currently unknown to the compiler
|
||||
fn main() {}
|
11
src/test/ui/tool-attributes-disabled-1.stderr
Normal file
11
src/test/ui/tool-attributes-disabled-1.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0658]: The attribute `rustfmt::bar` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
|
||||
--> $DIR/tool-attributes-disabled-1.rs:14:1
|
||||
|
|
||||
LL | #[rustfmt::bar] //~ ERROR The attribute `rustfmt::bar` is currently unknown to the compiler
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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`.
|
19
src/test/ui/tool-attributes-disabled-2.rs
Normal file
19
src/test/ui/tool-attributes-disabled-2.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// If macro modularization (`use_extern_macros`) is not enabled,
|
||||
// then tool attributes are treated as custom attributes.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(custom_attribute)]
|
||||
|
||||
#[rustfmt::bar]
|
||||
fn main() {}
|
28
src/test/ui/tool-attributes-misplaced-1.rs
Normal file
28
src/test/ui/tool-attributes-misplaced-1.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(tool_attributes)]
|
||||
|
||||
type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
|
||||
type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip`
|
||||
|
||||
#[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
|
||||
struct S;
|
||||
|
||||
#[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
|
||||
fn check() {}
|
||||
|
||||
#[rustfmt::skip] // OK
|
||||
fn main() {
|
||||
rustfmt; //~ ERROR expected value, found tool module `rustfmt`
|
||||
rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
|
||||
|
||||
rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip`
|
||||
}
|
46
src/test/ui/tool-attributes-misplaced-1.stderr
Normal file
46
src/test/ui/tool-attributes-misplaced-1.stderr
Normal file
@ -0,0 +1,46 @@
|
||||
error: cannot find derive macro `rustfmt` in this scope
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:16:10
|
||||
|
|
||||
LL | #[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
|
||||
| ^^^^^^^
|
||||
|
||||
error: cannot find attribute macro `rustfmt` in this scope
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:19:3
|
||||
|
|
||||
LL | #[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
|
||||
| ^^^^^^^
|
||||
|
||||
error: cannot find macro `rustfmt!` in this scope
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:25:5
|
||||
|
|
||||
LL | rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0573]: expected type, found tool module `rustfmt`
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:13:10
|
||||
|
|
||||
LL | type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
|
||||
| ^^^^^^^ not a type
|
||||
|
||||
error[E0573]: expected type, found non-macro attribute `rustfmt::skip`
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:14:10
|
||||
|
|
||||
LL | type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip`
|
||||
| ^^^^^^^^^^^^^ not a type
|
||||
|
||||
error[E0423]: expected value, found tool module `rustfmt`
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:24:5
|
||||
|
|
||||
LL | rustfmt; //~ ERROR expected value, found tool module `rustfmt`
|
||||
| ^^^^^^^ not a value
|
||||
|
||||
error[E0423]: expected value, found non-macro attribute `rustfmt::skip`
|
||||
--> $DIR/tool-attributes-misplaced-1.rs:27:5
|
||||
|
|
||||
LL | rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip`
|
||||
| ^^^^^^^^^^^^^ not a value
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors occurred: E0423, E0573.
|
||||
For more information about an error, try `rustc --explain E0423`.
|
18
src/test/ui/tool-attributes-misplaced-2.rs
Normal file
18
src/test/ui/tool-attributes-misplaced-2.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(tool_attributes)]
|
||||
|
||||
#[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute
|
||||
struct S;
|
||||
|
||||
fn main() {
|
||||
rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute
|
||||
}
|
14
src/test/ui/tool-attributes-misplaced-2.stderr
Normal file
14
src/test/ui/tool-attributes-misplaced-2.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: expected a macro, found non-macro attribute
|
||||
--> $DIR/tool-attributes-misplaced-2.rs:13:10
|
||||
|
|
||||
LL | #[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: expected a macro, found non-macro attribute
|
||||
--> $DIR/tool-attributes-misplaced-2.rs:17:5
|
||||
|
|
||||
LL | rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
16
src/test/ui/tool-attributes-shadowing.rs
Normal file
16
src/test/ui/tool-attributes-shadowing.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(tool_attributes, proc_macro_path_invoc)]
|
||||
|
||||
mod rustfmt {}
|
||||
|
||||
#[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt`
|
||||
fn main() {}
|
9
src/test/ui/tool-attributes-shadowing.stderr
Normal file
9
src/test/ui/tool-attributes-shadowing.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0433]: failed to resolve. Could not find `skip` in `rustfmt`
|
||||
--> $DIR/tool-attributes-shadowing.rs:15:12
|
||||
|
|
||||
LL | #[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt`
|
||||
| ^^^^ Could not find `skip` in `rustfmt`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0433`.
|
Loading…
Reference in New Issue
Block a user