提交 60c84604 编写于 作者: B bors

Auto merge of #54336 - petrochenkov:preuni, r=alexcrichton

resolve: Some refactorings in preparation for uniform paths 2.0

The main result is that in-scope resolution performed during macro expansion / import resolution is now consolidated in a single function (`fn early_resolve_ident_in_lexical_scope`), which can now be used for resolving first import segments as well when uniform paths are enabled.

r? @ghost
......@@ -2388,6 +2388,7 @@ name = "rustc_resolve"
version = "0.0.0"
dependencies = [
"arena 0.0.0",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
......
......@@ -36,6 +36,8 @@ pub enum NonMacroAttrKind {
Tool,
/// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
DeriveHelper,
/// Single-segment custom attriubte registered by a legacy plugin (`register_attribute`).
LegacyPluginHelper,
/// Single-segment custom attribute not registered in any way (`#[my_attr]`).
Custom,
}
......@@ -259,6 +261,7 @@ fn descr(self) -> &'static str {
NonMacroAttrKind::Builtin => "built-in attribute",
NonMacroAttrKind::Tool => "tool attribute",
NonMacroAttrKind::DeriveHelper => "derive helper attribute",
NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute",
NonMacroAttrKind::Custom => "custom attribute",
}
}
......
......@@ -1012,6 +1012,7 @@ fn to_stable_hash_key(&self,
Builtin,
Tool,
DeriveHelper,
LegacyPluginHelper,
Custom,
});
......
......@@ -10,6 +10,7 @@ crate-type = ["dylib"]
test = false
[dependencies]
bitflags = "1.0"
log = "0.4"
syntax = { path = "../libsyntax" }
rustc = { path = "../librustc" }
......
......@@ -17,6 +17,8 @@
#![feature(rustc_diagnostic_macros)]
#![feature(slice_sort_by_cached_key)]
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
#[macro_use]
......@@ -1012,7 +1014,8 @@ pub struct ModuleData<'a> {
normal_ancestor_id: DefId,
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>, Option<Def>)>>,
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>,
Option<&'a NameBinding<'a>>)>>,
macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
builtin_attrs: RefCell<Vec<(Ident, ParentScope<'a>)>>,
......@@ -1210,10 +1213,6 @@ fn def_ignoring_ambiguity(&self) -> Def {
}
}
fn get_macro<'b: 'a>(&self, resolver: &mut Resolver<'a, 'b>) -> Lrc<SyntaxExtension> {
resolver.get_macro(self.def_ignoring_ambiguity())
}
// We sometimes need to treat variants as `pub` for backwards compatibility
fn pseudo_vis(&self) -> ty::Visibility {
if self.is_variant() && self.def().def_id().is_local() {
......@@ -3664,8 +3663,8 @@ fn resolve_path_with_parent_scope(
self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
} else if opt_ns == Some(MacroNS) {
assert!(ns == TypeNS);
self.resolve_lexical_macro_path_segment(ident, ns, None, parent_scope, record_used,
record_used, path_span).map(|(b, _)| b)
self.early_resolve_ident_in_lexical_scope(ident, ns, None, parent_scope,
record_used, record_used, path_span)
} else {
let record_used_id =
if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
......
此差异已折叠。
......@@ -334,7 +334,7 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
// expansion. With restricted shadowing names from globs and macro expansions cannot
// shadow names from outer scopes, so we can freely fallback from module search to search
// in outer scopes. To continue search in outer scopes we have to lie a bit and return
// `Determined` to `resolve_lexical_macro_path_segment` even if the correct answer
// `Determined` to `early_resolve_ident_in_lexical_scope` even if the correct answer
// for in-module resolution could be `Undetermined`.
if restricted_shadowing {
return Err(Determined);
......
......@@ -220,14 +220,6 @@ pub struct Invocation {
pub expansion_data: ExpansionData,
}
// Needed for feature-gating attributes used after derives or together with test/bench
#[derive(Clone, Copy, PartialEq)]
pub enum TogetherWith {
None,
Derive,
TestBench,
}
pub enum InvocationKind {
Bang {
mac: ast::Mac,
......@@ -238,7 +230,8 @@ pub enum InvocationKind {
attr: Option<ast::Attribute>,
traits: Vec<Path>,
item: Annotatable,
together_with: TogetherWith,
// We temporarily report errors for attribute macros placed after derives
after_derive: bool,
},
Derive {
path: Path,
......@@ -1084,19 +1077,17 @@ fn collect_attr(&mut self,
traits: Vec<Path>,
item: Annotatable,
kind: AstFragmentKind,
together_with: TogetherWith)
after_derive: bool)
-> AstFragment {
self.collect(kind, InvocationKind::Attr { attr, traits, item, together_with })
self.collect(kind, InvocationKind::Attr { attr, traits, item, after_derive })
}
fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, together_with: &mut TogetherWith)
fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, after_derive: &mut bool)
-> Option<ast::Attribute> {
let attr = attrs.iter()
.position(|a| {
if a.path == "derive" {
*together_with = TogetherWith::Derive
} else if a.path == "rustc_test_marker2" {
*together_with = TogetherWith::TestBench
*after_derive = true;
}
!attr::is_known(a) && !is_builtin_attr(a)
})
......@@ -1109,19 +1100,15 @@ fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, together_with: &mut T
"non-builtin inner attributes are unstable");
}
}
if together_with == &TogetherWith::None &&
attrs.iter().any(|a| a.path == "rustc_test_marker2") {
*together_with = TogetherWith::TestBench;
}
attr
}
/// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
fn classify_item<T>(&mut self, mut item: T)
-> (Option<ast::Attribute>, Vec<Path>, T, TogetherWith)
-> (Option<ast::Attribute>, Vec<Path>, T, /* after_derive */ bool)
where T: HasAttrs,
{
let (mut attr, mut traits, mut together_with) = (None, Vec::new(), TogetherWith::None);
let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false);
item = item.map_attrs(|mut attrs| {
if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
......@@ -1130,20 +1117,20 @@ fn classify_item<T>(&mut self, mut item: T)
return attrs;
}
attr = self.find_attr_invoc(&mut attrs, &mut together_with);
attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
traits = collect_derives(&mut self.cx, &mut attrs);
attrs
});
(attr, traits, item, together_with)
(attr, traits, item, after_derive)
}
/// Alternative of `classify_item()` that ignores `#[derive]` so invocations fallthrough
/// to the unused-attributes lint (making it an error on statements and expressions
/// is a breaking change)
fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T)
-> (Option<ast::Attribute>, T, TogetherWith) {
let (mut attr, mut together_with) = (None, TogetherWith::None);
-> (Option<ast::Attribute>, T, /* after_derive */ bool) {
let (mut attr, mut after_derive) = (None, false);
item = item.map_attrs(|mut attrs| {
if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
......@@ -1152,11 +1139,11 @@ fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T)
return attrs;
}
attr = self.find_attr_invoc(&mut attrs, &mut together_with);
attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
attrs
});
(attr, item, together_with)
(attr, item, after_derive)
}
fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
......@@ -1195,7 +1182,7 @@ fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
expr.node = self.cfg.configure_expr_kind(expr.node);
// ignore derives so they remain unused
let (attr, expr, together_with) = self.classify_nonitem(expr);
let (attr, expr, after_derive) = self.classify_nonitem(expr);
if attr.is_some() {
// collect the invoc regardless of whether or not attributes are permitted here
......@@ -1204,7 +1191,7 @@ fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
// AstFragmentKind::Expr requires the macro to emit an expression
return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
AstFragmentKind::Expr, together_with).make_expr();
AstFragmentKind::Expr, after_derive).make_expr();
}
if let ast::ExprKind::Mac(mac) = expr.node {
......@@ -1220,13 +1207,13 @@ fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
expr.node = self.cfg.configure_expr_kind(expr.node);
// ignore derives so they remain unused
let (attr, expr, together_with) = self.classify_nonitem(expr);
let (attr, expr, after_derive) = self.classify_nonitem(expr);
if attr.is_some() {
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
AstFragmentKind::OptExpr, together_with).make_opt_expr();
AstFragmentKind::OptExpr, after_derive).make_opt_expr();
}
if let ast::ExprKind::Mac(mac) = expr.node {
......@@ -1258,18 +1245,18 @@ fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
// we'll expand attributes on expressions separately
if !stmt.is_expr() {
let (attr, derives, stmt_, together_with) = if stmt.is_item() {
let (attr, derives, stmt_, after_derive) = if stmt.is_item() {
self.classify_item(stmt)
} else {
// ignore derives on non-item statements so it falls through
// to the unused-attributes lint
let (attr, stmt, together_with) = self.classify_nonitem(stmt);
(attr, vec![], stmt, together_with)
let (attr, stmt, after_derive) = self.classify_nonitem(stmt);
(attr, vec![], stmt, after_derive)
};
if attr.is_some() || !derives.is_empty() {
return self.collect_attr(attr, derives, Annotatable::Stmt(P(stmt_)),
AstFragmentKind::Stmts, together_with).make_stmts();
AstFragmentKind::Stmts, after_derive).make_stmts();
}
stmt = stmt_;
......@@ -1311,10 +1298,10 @@ fn fold_block(&mut self, block: P<Block>) -> P<Block> {
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
let item = configure!(self, item);
let (attr, traits, item, together_with) = self.classify_item(item);
let (attr, traits, item, after_derive) = self.classify_item(item);
if attr.is_some() || !traits.is_empty() {
return self.collect_attr(attr, traits, Annotatable::Item(item),
AstFragmentKind::Items, together_with).make_items();
AstFragmentKind::Items, after_derive).make_items();
}
match item.node {
......@@ -1386,10 +1373,10 @@ fn fold_block(&mut self, block: P<Block>) -> P<Block> {
fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
let item = configure!(self, item);
let (attr, traits, item, together_with) = self.classify_item(item);
let (attr, traits, item, after_derive) = self.classify_item(item);
if attr.is_some() || !traits.is_empty() {
return self.collect_attr(attr, traits, Annotatable::TraitItem(P(item)),
AstFragmentKind::TraitItems, together_with).make_trait_items()
AstFragmentKind::TraitItems, after_derive).make_trait_items()
}
match item.node {
......@@ -1405,10 +1392,10 @@ fn fold_block(&mut self, block: P<Block>) -> P<Block> {
fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
let item = configure!(self, item);
let (attr, traits, item, together_with) = self.classify_item(item);
let (attr, traits, item, after_derive) = self.classify_item(item);
if attr.is_some() || !traits.is_empty() {
return self.collect_attr(attr, traits, Annotatable::ImplItem(P(item)),
AstFragmentKind::ImplItems, together_with).make_impl_items();
AstFragmentKind::ImplItems, after_derive).make_impl_items();
}
match item.node {
......@@ -1440,11 +1427,11 @@ fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod
fn fold_foreign_item(&mut self, foreign_item: ast::ForeignItem)
-> SmallVec<[ast::ForeignItem; 1]>
{
let (attr, traits, foreign_item, together_with) = self.classify_item(foreign_item);
let (attr, traits, foreign_item, after_derive) = self.classify_item(foreign_item);
if attr.is_some() || !traits.is_empty() {
return self.collect_attr(attr, traits, Annotatable::ForeignItem(P(foreign_item)),
AstFragmentKind::ForeignItems, together_with)
AstFragmentKind::ForeignItems, after_derive)
.make_foreign_items();
}
......
......@@ -995,10 +995,6 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
"the `#[rustc_test_marker]` attribute \
is used internally to track tests",
cfg_fn!(rustc_attrs))),
("rustc_test_marker2", Normal, Gated(Stability::Unstable,
"rustc_attrs",
"temporarily used by rustc to report some errors",
cfg_fn!(rustc_attrs))),
("rustc_transparent_macro", Whitelisted, Gated(Stability::Unstable,
"rustc_attrs",
"used internally for testing macro hygiene",
......
......@@ -49,7 +49,7 @@ pub fn expand_test_or_bench(
// If we're not in test configuration, remove the annotated item
if !cx.ecfg.should_test { return vec![]; }
let mut item =
let item =
if let Annotatable::Item(i) = item { i }
else {
cx.parse_sess.span_diagnostic.span_fatal(item.span(),
......@@ -192,12 +192,6 @@ pub fn expand_test_or_bench(
debug!("Synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
// Temporarily add another marker to the original item for error reporting
let marker2 = cx.attribute(
attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker2"))
);
item.attrs.push(marker2);
vec![
// Access to libtest under a gensymed name
Annotatable::Item(test_extern),
......
......@@ -19,8 +19,8 @@
#[macro_use] #[no_link]
extern crate macro_crate_test;
#[derive(PartialEq, Clone, Debug)]
#[rustc_into_multi_foo]
#[derive(PartialEq, Clone, Debug)]
fn foo() -> AnotherFakeTypeThatHadBetterGoAway {}
// Check that the `#[into_multi_foo]`-generated `foo2` is configured away
......
// aux-build:attr_proc_macro.rs
// compile-flags:--test
#![feature(test)]
extern crate test;
extern crate attr_proc_macro;
use attr_proc_macro::*;
......@@ -15,18 +11,4 @@
#[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
struct After;
#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
#[test]
fn test_before() {}
#[test]
#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
fn test_after() {}
#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
#[bench]
fn bench_before(b: &mut test::Bencher) {}
#[bench]
#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
fn bench_after(b: &mut test::Bencher) {}
fn main() {}
error: macro attributes must be placed before `#[derive]`
--> $DIR/attribute-order-restricted.rs:15:1
--> $DIR/attribute-order-restricted.rs:11:1
|
LL | #[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
| ^^^^^^^^^^^^^^^^^^
error: macro attributes cannot be used together with `#[test]` or `#[bench]`
--> $DIR/attribute-order-restricted.rs:18:1
|
LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
| ^^^^^^^^^^^^^^^^^^
error: macro attributes cannot be used together with `#[test]` or `#[bench]`
--> $DIR/attribute-order-restricted.rs:23:1
|
LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
| ^^^^^^^^^^^^^^^^^^
error: macro attributes cannot be used together with `#[test]` or `#[bench]`
--> $DIR/attribute-order-restricted.rs:26:1
|
LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
| ^^^^^^^^^^^^^^^^^^
error: macro attributes cannot be used together with `#[test]` or `#[bench]`
--> $DIR/attribute-order-restricted.rs:31:1
|
LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
error: aborting due to previous error
error[E0659]: `panic` is ambiguous
--> $DIR/shadow_builtin_macros.rs:43:5
|
LL | panic!(); //~ ERROR `panic` is ambiguous
| ^^^^^ ambiguous name
|
note: `panic` could refer to the name defined here
--> $DIR/shadow_builtin_macros.rs:40:9
|
LL | macro_rules! panic { () => {} }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | } }
LL | m!();
| ----- in this macro invocation
= note: `panic` is also a builtin macro
= note: macro-expanded macros do not shadow
error[E0659]: `panic` is ambiguous
--> $DIR/shadow_builtin_macros.rs:25:14
|
......@@ -43,6 +26,23 @@ LL | ::two_macros::m!(use foo::panic;);
= note: `panic` is also a builtin macro
= note: macro-expanded macro imports do not shadow
error[E0659]: `panic` is ambiguous
--> $DIR/shadow_builtin_macros.rs:43:5
|
LL | panic!(); //~ ERROR `panic` is ambiguous
| ^^^^^ ambiguous name
|
note: `panic` could refer to the name defined here
--> $DIR/shadow_builtin_macros.rs:40:9
|
LL | macro_rules! panic { () => {} }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | } }
LL | m!();
| ----- in this macro invocation
= note: `panic` is also a builtin macro
= note: macro-expanded macros do not shadow
error[E0659]: `n` is ambiguous
--> $DIR/shadow_builtin_macros.rs:59:5
|
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册