Remove fallback to parent modules from lexical resolution
This commit is contained in:
parent
94ef9f57f5
commit
fc74e35981
16 changed files with 320 additions and 105 deletions
|
@ -129,6 +129,16 @@ pub enum Namespace {
|
||||||
MacroNS,
|
MacroNS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Namespace {
|
||||||
|
pub fn descr(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
TypeNS => "type",
|
||||||
|
ValueNS => "value",
|
||||||
|
MacroNS => "macro",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Just a helper ‒ separate structure for each namespace.
|
/// Just a helper ‒ separate structure for each namespace.
|
||||||
#[derive(Copy, Clone, Default, Debug)]
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
pub struct PerNS<T> {
|
pub struct PerNS<T> {
|
||||||
|
|
|
@ -153,6 +153,7 @@ impl Decodable for DefPathTable {
|
||||||
/// The definition table containing node definitions.
|
/// The definition table containing node definitions.
|
||||||
/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a
|
/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a
|
||||||
/// mapping from NodeIds to local DefIds.
|
/// mapping from NodeIds to local DefIds.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Definitions {
|
pub struct Definitions {
|
||||||
table: DefPathTable,
|
table: DefPathTable,
|
||||||
node_to_def_index: NodeMap<DefIndex>,
|
node_to_def_index: NodeMap<DefIndex>,
|
||||||
|
@ -161,34 +162,12 @@ pub struct Definitions {
|
||||||
/// If `Mark` is an ID of some macro expansion,
|
/// If `Mark` is an ID of some macro expansion,
|
||||||
/// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
|
/// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
|
||||||
parent_modules_of_macro_defs: FxHashMap<Mark, DefId>,
|
parent_modules_of_macro_defs: FxHashMap<Mark, DefId>,
|
||||||
/// Item with a given `DefIndex` was defined during opaque macro expansion with ID `Mark`.
|
/// Item with a given `DefIndex` was defined during macro expansion with ID `Mark`.
|
||||||
/// It can actually be defined during transparent macro expansions inside that opaque expansion,
|
expansions_that_defined: FxHashMap<DefIndex, Mark>,
|
||||||
/// but transparent expansions are ignored here.
|
|
||||||
opaque_expansions_that_defined: FxHashMap<DefIndex, Mark>,
|
|
||||||
next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>,
|
next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>,
|
||||||
def_index_to_span: FxHashMap<DefIndex, Span>,
|
def_index_to_span: FxHashMap<DefIndex, Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unfortunately we have to provide a manual impl of Clone because of the
|
|
||||||
// fixed-sized array field.
|
|
||||||
impl Clone for Definitions {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Definitions {
|
|
||||||
table: self.table.clone(),
|
|
||||||
node_to_def_index: self.node_to_def_index.clone(),
|
|
||||||
def_index_to_node: [
|
|
||||||
self.def_index_to_node[0].clone(),
|
|
||||||
self.def_index_to_node[1].clone(),
|
|
||||||
],
|
|
||||||
node_to_hir_id: self.node_to_hir_id.clone(),
|
|
||||||
parent_modules_of_macro_defs: self.parent_modules_of_macro_defs.clone(),
|
|
||||||
opaque_expansions_that_defined: self.opaque_expansions_that_defined.clone(),
|
|
||||||
next_disambiguator: self.next_disambiguator.clone(),
|
|
||||||
def_index_to_span: self.def_index_to_span.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A unique identifier that we can use to lookup a definition
|
/// A unique identifier that we can use to lookup a definition
|
||||||
/// precisely. It combines the index of the definition's parent (if
|
/// precisely. It combines the index of the definition's parent (if
|
||||||
/// any) with a `DisambiguatedDefPathData`.
|
/// any) with a `DisambiguatedDefPathData`.
|
||||||
|
@ -409,7 +388,7 @@ impl Definitions {
|
||||||
def_index_to_node: [vec![], vec![]],
|
def_index_to_node: [vec![], vec![]],
|
||||||
node_to_hir_id: IndexVec::new(),
|
node_to_hir_id: IndexVec::new(),
|
||||||
parent_modules_of_macro_defs: FxHashMap(),
|
parent_modules_of_macro_defs: FxHashMap(),
|
||||||
opaque_expansions_that_defined: FxHashMap(),
|
expansions_that_defined: FxHashMap(),
|
||||||
next_disambiguator: FxHashMap(),
|
next_disambiguator: FxHashMap(),
|
||||||
def_index_to_span: FxHashMap(),
|
def_index_to_span: FxHashMap(),
|
||||||
}
|
}
|
||||||
|
@ -584,9 +563,8 @@ impl Definitions {
|
||||||
self.node_to_def_index.insert(node_id, index);
|
self.node_to_def_index.insert(node_id, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
let expansion = expansion.modern();
|
|
||||||
if expansion != Mark::root() {
|
if expansion != Mark::root() {
|
||||||
self.opaque_expansions_that_defined.insert(index, expansion);
|
self.expansions_that_defined.insert(index, expansion);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The span is added if it isn't dummy
|
// The span is added if it isn't dummy
|
||||||
|
@ -606,8 +584,8 @@ impl Definitions {
|
||||||
self.node_to_hir_id = mapping;
|
self.node_to_hir_id = mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn opaque_expansion_that_defined(&self, index: DefIndex) -> Mark {
|
pub fn expansion_that_defined(&self, index: DefIndex) -> Mark {
|
||||||
self.opaque_expansions_that_defined.get(&index).cloned().unwrap_or(Mark::root())
|
self.expansions_that_defined.get(&index).cloned().unwrap_or(Mark::root())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parent_module_of_macro_def(&self, mark: Mark) -> DefId {
|
pub fn parent_module_of_macro_def(&self, mark: Mark) -> DefId {
|
||||||
|
|
|
@ -316,6 +316,12 @@ declare_lint! {
|
||||||
"checks the object safety of where clauses"
|
"checks the object safety of where clauses"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
||||||
|
Warn,
|
||||||
|
"detects proc macro derives using inaccessible names from parent modules"
|
||||||
|
}
|
||||||
|
|
||||||
/// Does nothing as a lint pass, but registers some `Lint`s
|
/// Does nothing as a lint pass, but registers some `Lint`s
|
||||||
/// which are used by other parts of the compiler.
|
/// which are used by other parts of the compiler.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -372,6 +378,7 @@ impl LintPass for HardwiredLints {
|
||||||
DUPLICATE_MACRO_EXPORTS,
|
DUPLICATE_MACRO_EXPORTS,
|
||||||
INTRA_DOC_LINK_RESOLUTION_FAILURE,
|
INTRA_DOC_LINK_RESOLUTION_FAILURE,
|
||||||
WHERE_CLAUSES_OBJECT_SAFETY,
|
WHERE_CLAUSES_OBJECT_SAFETY,
|
||||||
|
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,6 +391,7 @@ pub enum BuiltinLintDiagnostics {
|
||||||
BareTraitObject(Span, /* is_global */ bool),
|
BareTraitObject(Span, /* is_global */ bool),
|
||||||
AbsPathWithModule(Span),
|
AbsPathWithModule(Span),
|
||||||
DuplicatedMacroExports(ast::Ident, Span, Span),
|
DuplicatedMacroExports(ast::Ident, Span, Span),
|
||||||
|
ProcMacroDeriveResolutionFallback(Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltinLintDiagnostics {
|
impl BuiltinLintDiagnostics {
|
||||||
|
@ -420,6 +428,10 @@ impl BuiltinLintDiagnostics {
|
||||||
db.span_label(later_span, format!("`{}` already exported", ident));
|
db.span_label(later_span, format!("`{}` already exported", ident));
|
||||||
db.span_note(earlier_span, "previous macro export is now shadowed");
|
db.span_note(earlier_span, "previous macro export is now shadowed");
|
||||||
}
|
}
|
||||||
|
BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
|
||||||
|
db.span_label(span, "names from parent modules are not \
|
||||||
|
accessible without an explicit import");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2724,7 +2724,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) {
|
pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) {
|
||||||
ident = ident.modern();
|
ident = ident.modern();
|
||||||
let target_expansion = match scope.krate {
|
let target_expansion = match scope.krate {
|
||||||
LOCAL_CRATE => self.hir.definitions().opaque_expansion_that_defined(scope.index),
|
LOCAL_CRATE => self.hir.definitions().expansion_that_defined(scope.index),
|
||||||
_ => Mark::root(),
|
_ => Mark::root(),
|
||||||
};
|
};
|
||||||
let scope = match ident.span.adjust(target_expansion) {
|
let scope = match ident.span.adjust(target_expansion) {
|
||||||
|
|
|
@ -293,6 +293,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||||
reference: "issue #50589 <https://github.com/rust-lang/rust/issues/50589>",
|
reference: "issue #50589 <https://github.com/rust-lang/rust/issues/50589>",
|
||||||
edition: None,
|
edition: None,
|
||||||
},
|
},
|
||||||
|
FutureIncompatibleInfo {
|
||||||
|
id: LintId::of(PROC_MACRO_DERIVE_RESOLUTION_FALLBACK),
|
||||||
|
reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
|
||||||
|
edition: None,
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Register renamed and removed lints
|
// Register renamed and removed lints
|
||||||
|
|
|
@ -55,7 +55,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
|
||||||
|
|
||||||
use syntax::visit::{self, FnKind, Visitor};
|
use syntax::visit::{self, FnKind, Visitor};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::ast::{Arm, IsAsync, BindingMode, Block, Crate, Expr, ExprKind};
|
use syntax::ast::{CRATE_NODE_ID, Arm, IsAsync, BindingMode, Block, Crate, Expr, ExprKind};
|
||||||
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generics};
|
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generics};
|
||||||
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||||
use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
|
use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
|
||||||
|
@ -1891,7 +1891,12 @@ impl<'a> Resolver<'a> {
|
||||||
|
|
||||||
ident.span = ident.span.modern();
|
ident.span = ident.span.modern();
|
||||||
loop {
|
loop {
|
||||||
module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.span), break);
|
let (opt_module, poisoned) = if record_used {
|
||||||
|
self.hygienic_lexical_parent_with_compatibility_fallback(module, &mut ident.span)
|
||||||
|
} else {
|
||||||
|
(self.hygienic_lexical_parent(module, &mut ident.span), false)
|
||||||
|
};
|
||||||
|
module = unwrap_or!(opt_module, break);
|
||||||
let orig_current_module = self.current_module;
|
let orig_current_module = self.current_module;
|
||||||
self.current_module = module; // Lexical resolutions can never be a privacy error.
|
self.current_module = module; // Lexical resolutions can never be a privacy error.
|
||||||
let result = self.resolve_ident_in_module_unadjusted(
|
let result = self.resolve_ident_in_module_unadjusted(
|
||||||
|
@ -1900,7 +1905,19 @@ impl<'a> Resolver<'a> {
|
||||||
self.current_module = orig_current_module;
|
self.current_module = orig_current_module;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(binding) => return Some(LexicalScopeBinding::Item(binding)),
|
Ok(binding) => {
|
||||||
|
if poisoned {
|
||||||
|
self.session.buffer_lint_with_diagnostic(
|
||||||
|
lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
||||||
|
CRATE_NODE_ID, ident.span,
|
||||||
|
&format!("cannot find {} `{}` in this scope", ns.descr(), ident),
|
||||||
|
lint::builtin::BuiltinLintDiagnostics::
|
||||||
|
ProcMacroDeriveResolutionFallback(ident.span),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Some(LexicalScopeBinding::Item(binding))
|
||||||
|
}
|
||||||
|
_ if poisoned => break,
|
||||||
Err(Undetermined) => return None,
|
Err(Undetermined) => return None,
|
||||||
Err(Determined) => {}
|
Err(Determined) => {}
|
||||||
}
|
}
|
||||||
|
@ -1935,7 +1952,7 @@ impl<'a> Resolver<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span)
|
fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
|
||||||
-> Option<Module<'a>> {
|
-> Option<Module<'a>> {
|
||||||
if !module.expansion.is_descendant_of(span.ctxt().outer()) {
|
if !module.expansion.is_descendant_of(span.ctxt().outer()) {
|
||||||
return Some(self.macro_def_scope(span.remove_mark()));
|
return Some(self.macro_def_scope(span.remove_mark()));
|
||||||
|
@ -1945,22 +1962,41 @@ impl<'a> Resolver<'a> {
|
||||||
return Some(module.parent.unwrap());
|
return Some(module.parent.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut module_expansion = module.expansion.modern(); // for backward compatibility
|
None
|
||||||
while let Some(parent) = module.parent {
|
}
|
||||||
let parent_expansion = parent.expansion.modern();
|
|
||||||
if module_expansion.is_descendant_of(parent_expansion) &&
|
fn hygienic_lexical_parent_with_compatibility_fallback(
|
||||||
parent_expansion != module_expansion {
|
&mut self, module: Module<'a>, span: &mut Span) -> (Option<Module<'a>>, /* poisoned */ bool
|
||||||
return if parent_expansion.is_descendant_of(span.ctxt().outer()) {
|
) {
|
||||||
Some(parent)
|
if let module @ Some(..) = self.hygienic_lexical_parent(module, span) {
|
||||||
} else {
|
return (module, false);
|
||||||
None
|
|
||||||
};
|
|
||||||
}
|
|
||||||
module = parent;
|
|
||||||
module_expansion = parent_expansion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
// We need to support the next case under a deprecation warning
|
||||||
|
// ```
|
||||||
|
// struct MyStruct;
|
||||||
|
// ---- begin: this comes from a proc macro derive
|
||||||
|
// mod implementation_details {
|
||||||
|
// // Note that `MyStruct` is not in scope here.
|
||||||
|
// impl SomeTrait for MyStruct { ... }
|
||||||
|
// }
|
||||||
|
// ---- end
|
||||||
|
// ```
|
||||||
|
// So we have to fall back to the module's parent during lexical resolution in this case.
|
||||||
|
if let Some(parent) = module.parent {
|
||||||
|
// Inner module is inside the macro, parent module is outside of the macro.
|
||||||
|
if module.expansion != parent.expansion &&
|
||||||
|
module.expansion.is_descendant_of(parent.expansion) {
|
||||||
|
// The macro is a proc macro derive
|
||||||
|
if module.expansion.looks_like_proc_macro_derive() {
|
||||||
|
if parent.expansion.is_descendant_of(span.ctxt().outer()) {
|
||||||
|
return (module.parent, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(None, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_ident_in_module(&mut self,
|
fn resolve_ident_in_module(&mut self,
|
||||||
|
@ -4037,8 +4073,9 @@ impl<'a> Resolver<'a> {
|
||||||
let mut search_module = self.current_module;
|
let mut search_module = self.current_module;
|
||||||
loop {
|
loop {
|
||||||
self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits);
|
self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits);
|
||||||
search_module =
|
search_module = unwrap_or!(
|
||||||
unwrap_or!(self.hygienic_lexical_parent(search_module, &mut ident.span), break);
|
self.hygienic_lexical_parent(search_module, &mut ident.span), break
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(prelude) = self.prelude {
|
if let Some(prelude) = self.prelude {
|
||||||
|
@ -4395,12 +4432,6 @@ impl<'a> Resolver<'a> {
|
||||||
(TypeNS, _) => "type",
|
(TypeNS, _) => "type",
|
||||||
};
|
};
|
||||||
|
|
||||||
let namespace = match ns {
|
|
||||||
ValueNS => "value",
|
|
||||||
MacroNS => "macro",
|
|
||||||
TypeNS => "type",
|
|
||||||
};
|
|
||||||
|
|
||||||
let msg = format!("the name `{}` is defined multiple times", name);
|
let msg = format!("the name `{}` is defined multiple times", name);
|
||||||
|
|
||||||
let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
|
let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
|
||||||
|
@ -4418,7 +4449,7 @@ impl<'a> Resolver<'a> {
|
||||||
|
|
||||||
err.note(&format!("`{}` must be defined only once in the {} namespace of this {}",
|
err.note(&format!("`{}` must be defined only once in the {} namespace of this {}",
|
||||||
name,
|
name,
|
||||||
namespace,
|
ns.descr(),
|
||||||
container));
|
container));
|
||||||
|
|
||||||
err.span_label(span, format!("`{}` re{} here", name, new_participle));
|
err.span_label(span, format!("`{}` re{} here", name, new_participle));
|
||||||
|
|
|
@ -72,26 +72,16 @@ pub enum Transparency {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mark {
|
impl Mark {
|
||||||
fn fresh_with_data(mark_data: MarkData, data: &mut HygieneData) -> Self {
|
|
||||||
data.marks.push(mark_data);
|
|
||||||
Mark(data.marks.len() as u32 - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fresh(parent: Mark) -> Self {
|
pub fn fresh(parent: Mark) -> Self {
|
||||||
HygieneData::with(|data| {
|
HygieneData::with(|data| {
|
||||||
Mark::fresh_with_data(MarkData {
|
data.marks.push(MarkData {
|
||||||
parent,
|
parent,
|
||||||
// By default expansions behave like `macro_rules`.
|
// By default expansions behave like `macro_rules`.
|
||||||
default_transparency: Transparency::SemiTransparent,
|
default_transparency: Transparency::SemiTransparent,
|
||||||
is_builtin: false,
|
is_builtin: false,
|
||||||
expn_info: None,
|
expn_info: None,
|
||||||
}, data)
|
});
|
||||||
})
|
Mark(data.marks.len() as u32 - 1)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fresh_cloned(clone_from: Mark) -> Self {
|
|
||||||
HygieneData::with(|data| {
|
|
||||||
Mark::fresh_with_data(data.marks[clone_from.0 as usize].clone(), data)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,17 +118,6 @@ impl Mark {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This operation doesn't really make sense when single macro expansion
|
|
||||||
// can produce tokens with different transparencies. Figure out how to avoid it.
|
|
||||||
pub fn modern(mut self) -> Mark {
|
|
||||||
HygieneData::with(|data| {
|
|
||||||
while data.marks[self.0 as usize].default_transparency != Transparency::Opaque {
|
|
||||||
self = data.marks[self.0 as usize].parent;
|
|
||||||
}
|
|
||||||
self
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_default_transparency(self, transparency: Transparency) {
|
pub fn set_default_transparency(self, transparency: Transparency) {
|
||||||
assert_ne!(self, Mark::root());
|
assert_ne!(self, Mark::root());
|
||||||
|
@ -194,6 +173,24 @@ impl Mark {
|
||||||
b
|
b
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used for enabling some compatibility fallback in resolve.
|
||||||
|
#[inline]
|
||||||
|
pub fn looks_like_proc_macro_derive(self) -> bool {
|
||||||
|
HygieneData::with(|data| {
|
||||||
|
let mark_data = &data.marks[self.0 as usize];
|
||||||
|
if mark_data.default_transparency == Transparency::Opaque {
|
||||||
|
if let Some(expn_info) = &mark_data.expn_info {
|
||||||
|
if let ExpnFormat::MacroAttribute(name) = expn_info.format {
|
||||||
|
if name.as_str().starts_with("derive(") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -285,6 +282,7 @@ impl SyntaxContext {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extend a syntax context with a given mark and default transparency for that mark.
|
||||||
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
|
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
|
||||||
assert_ne!(mark, Mark::root());
|
assert_ne!(mark, Mark::root());
|
||||||
self.apply_mark_with_transparency(
|
self.apply_mark_with_transparency(
|
||||||
|
|
|
@ -20,9 +20,35 @@ use proc_macro::*;
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn check(_: TokenStream) -> TokenStream {
|
pub fn check(_: TokenStream) -> TokenStream {
|
||||||
"
|
"
|
||||||
|
type Alias = FromOutside; // OK
|
||||||
struct Outer;
|
struct Outer;
|
||||||
mod inner {
|
mod inner {
|
||||||
|
type Alias = FromOutside; // `FromOutside` shouldn't be available from here
|
||||||
type Inner = Outer; // `Outer` shouldn't be available from here
|
type Inner = Outer; // `Outer` shouldn't be available from here
|
||||||
}
|
}
|
||||||
".parse().unwrap()
|
".parse().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn check_attr(_: TokenStream, _: TokenStream) -> TokenStream {
|
||||||
|
"
|
||||||
|
type AliasAttr = FromOutside; // OK
|
||||||
|
struct OuterAttr;
|
||||||
|
mod inner_attr {
|
||||||
|
type Alias = FromOutside; // `FromOutside` shouldn't be available from here
|
||||||
|
type Inner = OuterAttr; // `OuterAttr` shouldn't be available from here
|
||||||
|
}
|
||||||
|
".parse().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(CheckDerive)]
|
||||||
|
pub fn check_derive(_: TokenStream) -> TokenStream {
|
||||||
|
"
|
||||||
|
type AliasDerive = FromOutside; // OK
|
||||||
|
struct OuterDerive;
|
||||||
|
mod inner_derive {
|
||||||
|
type Alias = FromOutside; // `FromOutside` shouldn't be available from here
|
||||||
|
type Inner = OuterDerive; // `OuterDerive` shouldn't be available from here
|
||||||
|
}
|
||||||
|
".parse().unwrap()
|
||||||
|
}
|
||||||
|
|
|
@ -12,10 +12,23 @@
|
||||||
|
|
||||||
// aux-build:generate-mod.rs
|
// aux-build:generate-mod.rs
|
||||||
|
|
||||||
#![feature(proc_macro, proc_macro_gen)]
|
#![feature(proc_macro, proc_macro_gen, proc_macro_path_invoc)]
|
||||||
|
|
||||||
extern crate generate_mod;
|
extern crate generate_mod;
|
||||||
|
|
||||||
generate_mod::check!(); //~ ERROR cannot find type `Outer` in this scope
|
struct FromOutside;
|
||||||
|
|
||||||
|
generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
//~| ERROR cannot find type `Outer` in this scope
|
||||||
|
|
||||||
|
#[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
//~| ERROR cannot find type `OuterAttr` in this scope
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
#[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
|
||||||
|
//~| WARN cannot find type `OuterDerive` in this scope
|
||||||
|
//~| WARN this was previously accepted
|
||||||
|
//~| WARN this was previously accepted
|
||||||
|
struct Z;
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,9 +1,46 @@
|
||||||
error[E0412]: cannot find type `Outer` in this scope
|
error[E0412]: cannot find type `FromOutside` in this scope
|
||||||
--> $DIR/generate-mod.rs:19:1
|
--> $DIR/generate-mod.rs:21:1
|
||||||
|
|
|
|
||||||
LL | generate_mod::check!(); //~ ERROR cannot find type `Outer` in this scope
|
LL | generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
| ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0412]: cannot find type `Outer` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:21:1
|
||||||
|
|
|
||||||
|
LL | generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `FromOutside` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:24:1
|
||||||
|
|
|
||||||
|
LL | #[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `OuterAttr` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:24:1
|
||||||
|
|
|
||||||
|
LL | #[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
warning: cannot find type `FromOutside` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:28:10
|
||||||
|
|
|
||||||
|
LL | #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
||||||
|
|
|
||||||
|
= note: #[warn(proc_macro_derive_resolution_fallback)] on by default
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
|
||||||
|
|
||||||
|
warning: cannot find type `OuterDerive` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:28:10
|
||||||
|
|
|
||||||
|
LL | #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0412`.
|
For more information about this error, try `rustc --explain E0412`.
|
||||||
|
|
|
@ -23,5 +23,5 @@ macro m($t:ty, $e:expr) {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct S;
|
struct S;
|
||||||
m!(S, S);
|
m!(S, S); //~ ERROR cannot find type `S` in this scope
|
||||||
}
|
}
|
9
src/test/ui/hygiene/arguments.stderr
Normal file
9
src/test/ui/hygiene/arguments.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0412]: cannot find type `S` in this scope
|
||||||
|
--> $DIR/arguments.rs:26:8
|
||||||
|
|
|
||||||
|
LL | m!(S, S); //~ ERROR cannot find type `S` in this scope
|
||||||
|
| ^ not found in this scope
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0412`.
|
|
@ -12,13 +12,46 @@
|
||||||
|
|
||||||
#![feature(decl_macro, rustc_attrs)]
|
#![feature(decl_macro, rustc_attrs)]
|
||||||
|
|
||||||
#[rustc_transparent_macro]
|
macro genmod($FromOutside: ident, $Outer: ident) {
|
||||||
macro genmod() {
|
type A = $FromOutside;
|
||||||
mod m {
|
struct $Outer;
|
||||||
type A = S; //~ ERROR cannot find type `S` in this scope
|
mod inner {
|
||||||
|
type A = $FromOutside; // `FromOutside` shouldn't be available from here
|
||||||
|
type Inner = $Outer; // `Outer` shouldn't be available from here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct S;
|
#[rustc_transparent_macro]
|
||||||
|
macro genmod_transparent() {
|
||||||
|
type A = FromOutside;
|
||||||
|
struct Outer;
|
||||||
|
mod inner {
|
||||||
|
type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
genmod!();
|
macro_rules! genmod_legacy { () => {
|
||||||
|
type A = FromOutside;
|
||||||
|
struct Outer;
|
||||||
|
mod inner {
|
||||||
|
type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
fn check() {
|
||||||
|
struct FromOutside;
|
||||||
|
genmod!(FromOutside, Outer); //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
//~| ERROR cannot find type `Outer` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_transparent() {
|
||||||
|
struct FromOutside;
|
||||||
|
genmod_transparent!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_legacy() {
|
||||||
|
struct FromOutside;
|
||||||
|
genmod_legacy!();
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,56 @@
|
||||||
error[E0412]: cannot find type `S` in this scope
|
error[E0412]: cannot find type `FromOutside` in this scope
|
||||||
--> $DIR/generate-mod.rs:18:18
|
--> $DIR/generate-mod.rs:45:13
|
||||||
|
|
|
|
||||||
LL | type A = S; //~ ERROR cannot find type `S` in this scope
|
LL | genmod!(FromOutside, Outer); //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
| ^ did you mean `A`?
|
| ^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `Outer` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:45:26
|
||||||
|
|
|
||||||
|
LL | genmod!(FromOutside, Outer); //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `FromOutside` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:29:18
|
||||||
|
|
|
||||||
|
LL | type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
| ^^^^^^^^^^^ not found in this scope
|
||||||
...
|
...
|
||||||
LL | genmod!();
|
LL | genmod_transparent!();
|
||||||
| ---------- in this macro invocation
|
| ---------------------- in this macro invocation
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `Outer` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:30:22
|
||||||
|
|
|
||||||
|
LL | type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope
|
||||||
|
| ^^^^^ not found in this scope
|
||||||
|
...
|
||||||
|
LL | genmod_transparent!();
|
||||||
|
| ---------------------- in this macro invocation
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `FromOutside` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:38:18
|
||||||
|
|
|
||||||
|
LL | type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope
|
||||||
|
| ^^^^^^^^^^^ not found in this scope
|
||||||
|
...
|
||||||
|
LL | genmod_legacy!();
|
||||||
|
| ----------------- in this macro invocation
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `Outer` in this scope
|
||||||
|
--> $DIR/generate-mod.rs:39:22
|
||||||
|
|
|
||||||
|
LL | type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope
|
||||||
|
| ^^^^^ not found in this scope
|
||||||
|
...
|
||||||
|
LL | genmod_legacy!();
|
||||||
|
| ----------------- in this macro invocation
|
||||||
|
|
||||||
error[E0601]: `main` function not found in crate `generate_mod`
|
error[E0601]: `main` function not found in crate `generate_mod`
|
||||||
|
|
|
|
||||||
= note: consider adding a `main` function to `$DIR/generate-mod.rs`
|
= note: consider adding a `main` function to `$DIR/generate-mod.rs`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
Some errors occurred: E0412, E0601.
|
Some errors occurred: E0412, E0601.
|
||||||
For more information about an error, try `rustc --explain E0412`.
|
For more information about an error, try `rustc --explain E0412`.
|
||||||
|
|
|
@ -57,12 +57,26 @@ macro n($i:ident) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
macro n_with_super($j:ident) {
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
fn g() {
|
||||||
|
let _: u32 = $i();
|
||||||
|
let _: () = f();
|
||||||
|
super::$j();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
n!(f);
|
n!(f); //~ ERROR cannot find function `f` in this scope
|
||||||
|
n_with_super!(f);
|
||||||
mod test2 {
|
mod test2 {
|
||||||
super::n! {
|
super::n! {
|
||||||
f //~ ERROR cannot find function `f` in this scope
|
f //~ ERROR cannot find function `f` in this scope
|
||||||
}
|
}
|
||||||
|
super::n_with_super! {
|
||||||
|
f
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,13 +30,23 @@ LL | use bar::g;
|
||||||
|
|
|
|
||||||
LL | use foo::test2::test::g;
|
LL | use foo::test2::test::g;
|
||||||
|
|
|
|
||||||
LL | use foo::test::g;
|
LL | use foo::test2::test::g;
|
||||||
|
|
|
|
||||||
LL | use foo::test::g;
|
LL | use foo::test::g;
|
||||||
|
|
|
|
||||||
|
and 2 other candidates
|
||||||
|
|
||||||
error[E0425]: cannot find function `f` in this scope
|
error[E0425]: cannot find function `f` in this scope
|
||||||
--> $DIR/globs.rs:64:17
|
--> $DIR/globs.rs:71:12
|
||||||
|
|
|
||||||
|
LL | n!(f);
|
||||||
|
| ------ in this macro invocation
|
||||||
|
...
|
||||||
|
LL | n!(f); //~ ERROR cannot find function `f` in this scope
|
||||||
|
| ^ not found in this scope
|
||||||
|
|
||||||
|
error[E0425]: cannot find function `f` in this scope
|
||||||
|
--> $DIR/globs.rs:75:17
|
||||||
|
|
|
|
||||||
LL | n!(f);
|
LL | n!(f);
|
||||||
| ------ in this macro invocation
|
| ------ in this macro invocation
|
||||||
|
@ -44,6 +54,6 @@ LL | n!(f);
|
||||||
LL | f //~ ERROR cannot find function `f` in this scope
|
LL | f //~ ERROR cannot find function `f` in this scope
|
||||||
| ^ not found in this scope
|
| ^ not found in this scope
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0425`.
|
For more information about this error, try `rustc --explain E0425`.
|
||||||
|
|
Loading…
Add table
Reference in a new issue