1
Fork 0

Auto merge of #79294 - petrochenkov:determ, r=varkor

resolve: Do not put macros into `module.unexpanded_invocations` unless necessary

Macro invocations in modules <sup>(*)</sup> need to be tracked because they can produce named items when expanded.
We cannot give definite answer to queries like "does this module declare name `n`?" until all macro calls in that module are expanded.

Previously we marked too many macros as potentially producing named items.
E.g. in this example
```rust
mod m {
    const C: u32 = line!();
}
```
`line!()` cannot emit any items into module `m`, but it was still marked.
This PR fixes that and marks macro calls as "unexpanded in module" only if they can actually emit named items into that module.

Diagnostics in UI test outputs have different order now because this change affects macro expansion order.

<sup>*</sup> Any containers for named items are called modules in resolve (that includes blocks, traits and enums in addition to `mod` items).
This commit is contained in:
bors 2020-11-24 09:17:33 +00:00
commit 6331023708
7 changed files with 125 additions and 107 deletions

View file

@ -1155,14 +1155,18 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
false false
} }
fn visit_invoc(&mut self, id: NodeId) -> MacroRulesScopeRef<'a> { fn visit_invoc(&mut self, id: NodeId) -> ExpnId {
let invoc_id = id.placeholder_to_expn_id(); let invoc_id = id.placeholder_to_expn_id();
self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope); let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation"); assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
invoc_id
}
/// Visit invocation in context in which it can emit a named item (possibly `macro_rules`)
/// directly into its parent scope's module.
fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'a> {
let invoc_id = self.visit_invoc(id);
self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id)) self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id))
} }
@ -1291,7 +1295,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
return; return;
} }
ItemKind::MacCall(..) => { ItemKind::MacCall(..) => {
self.parent_scope.macro_rules = self.visit_invoc(item.id); self.parent_scope.macro_rules = self.visit_invoc_in_module(item.id);
return; return;
} }
ItemKind::Mod(..) => self.contains_macro_use(&item.attrs), ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
@ -1309,7 +1313,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
fn visit_stmt(&mut self, stmt: &'b ast::Stmt) { fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
if let ast::StmtKind::MacCall(..) = stmt.kind { if let ast::StmtKind::MacCall(..) = stmt.kind {
self.parent_scope.macro_rules = self.visit_invoc(stmt.id); self.parent_scope.macro_rules = self.visit_invoc_in_module(stmt.id);
} else { } else {
visit::walk_stmt(self, stmt); visit::walk_stmt(self, stmt);
} }
@ -1317,7 +1321,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) { fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) {
if let ForeignItemKind::MacCall(_) = foreign_item.kind { if let ForeignItemKind::MacCall(_) = foreign_item.kind {
self.visit_invoc(foreign_item.id); self.visit_invoc_in_module(foreign_item.id);
return; return;
} }
@ -1336,7 +1340,14 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) { fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
if let AssocItemKind::MacCall(_) = item.kind { if let AssocItemKind::MacCall(_) = item.kind {
match ctxt {
AssocCtxt::Trait => {
self.visit_invoc_in_module(item.id);
}
AssocCtxt::Impl => {
self.visit_invoc(item.id); self.visit_invoc(item.id);
}
}
return; return;
} }
@ -1460,7 +1471,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
// type and value namespaces. // type and value namespaces.
fn visit_variant(&mut self, variant: &'b ast::Variant) { fn visit_variant(&mut self, variant: &'b ast::Variant) {
if variant.is_placeholder { if variant.is_placeholder {
self.visit_invoc(variant.id); self.visit_invoc_in_module(variant.id);
return; return;
} }

View file

@ -17,21 +17,9 @@ LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
| ^ | ^
error: cannot find attribute `unknown` in this scope error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:34:43 --> $DIR/cfg-generic-params.rs:19:29
| |
LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
| ^^^^^^^
error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:30:40
|
LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
| ^^^^^^^
error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:26:34
|
LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
| ^^^^^^^ | ^^^^^^^
error: cannot find attribute `unknown` in this scope error: cannot find attribute `unknown` in this scope
@ -41,9 +29,21 @@ LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
| ^^^^^^^ | ^^^^^^^
error: cannot find attribute `unknown` in this scope error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:19:29 --> $DIR/cfg-generic-params.rs:26:34
| |
LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
| ^^^^^^^
error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:30:40
|
LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
| ^^^^^^^
error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:34:43
|
LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
| ^^^^^^^ | ^^^^^^^
error: aborting due to 8 previous errors error: aborting due to 8 previous errors

View file

@ -1,43 +1,55 @@
error: cannot find attribute `lt_hof` in this scope error: cannot find attribute `lt_struct` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:51:21 --> $DIR/feature-gate-custom_attribute2.rs:4:15
| |
LL | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 LL | struct StLt<#[lt_struct] 'a>(&'a u32);
| ^^^^^^ | ^^^^^^^^^
error: cannot find attribute `ty_meth` in this scope error: cannot find attribute `ty_struct` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:46:15 --> $DIR/feature-gate-custom_attribute2.rs:6:15
| |
LL | fn m_ty<#[ty_meth] P>(_: P) { } LL | struct StTy<#[ty_struct] I>(I);
| ^^^^^^^^^
error: cannot find attribute `lt_enum` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:9:13
|
LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
| ^^^^^^^ | ^^^^^^^
error: cannot find attribute `lt_meth` in this scope error: cannot find attribute `ty_enum` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:44:15 --> $DIR/feature-gate-custom_attribute2.rs:11:13
| |
LL | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } LL | enum EnTy<#[ty_enum] J> { A(J), B }
| ^^^^^^^ | ^^^^^^^
error: cannot find attribute `ty_fn` in this scope error: cannot find attribute `lt_trait` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:40:11 --> $DIR/feature-gate-custom_attribute2.rs:14:14
| |
LL | fn f_ty<#[ty_fn] O>(_: O) { } LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
| ^^^^^ | ^^^^^^^^
error: cannot find attribute `lt_fn` in this scope error: cannot find attribute `ty_trait` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:38:11 --> $DIR/feature-gate-custom_attribute2.rs:16:14
| |
LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
| ^^^^^ | ^^^^^^^^
error: cannot find attribute `ty_impl_for` in this scope error: cannot find attribute `lt_type` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:33:8 --> $DIR/feature-gate-custom_attribute2.rs:19:13
| |
LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> { LL | type TyLt<#[lt_type] 'd> = &'d u32;
| ^^^^^^^^^^^ | ^^^^^^^
error: cannot find attribute `lt_impl_for` in this scope error: cannot find attribute `ty_type` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:29:8 --> $DIR/feature-gate-custom_attribute2.rs:21:13
| |
LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { LL | type TyTy<#[ty_type] L> = (L, );
| ^^^^^^^
error: cannot find attribute `lt_inherent` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:24:8
|
LL | impl<#[lt_inherent] 'e> StLt<'e> { }
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: cannot find attribute `ty_inherent` in this scope error: cannot find attribute `ty_inherent` in this scope
@ -46,59 +58,47 @@ error: cannot find attribute `ty_inherent` in this scope
LL | impl<#[ty_inherent] M> StTy<M> { } LL | impl<#[ty_inherent] M> StTy<M> { }
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: cannot find attribute `lt_inherent` in this scope error: cannot find attribute `lt_impl_for` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:24:8 --> $DIR/feature-gate-custom_attribute2.rs:29:8
| |
LL | impl<#[lt_inherent] 'e> StLt<'e> { } LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: cannot find attribute `ty_type` in this scope error: cannot find attribute `ty_impl_for` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:21:13 --> $DIR/feature-gate-custom_attribute2.rs:33:8
| |
LL | type TyTy<#[ty_type] L> = (L, ); LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
| ^^^^^^^^^^^
error: cannot find attribute `lt_fn` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:38:11
|
LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
| ^^^^^
error: cannot find attribute `ty_fn` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:40:11
|
LL | fn f_ty<#[ty_fn] O>(_: O) { }
| ^^^^^
error: cannot find attribute `lt_meth` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:44:15
|
LL | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
| ^^^^^^^ | ^^^^^^^
error: cannot find attribute `lt_type` in this scope error: cannot find attribute `ty_meth` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:19:13 --> $DIR/feature-gate-custom_attribute2.rs:46:15
| |
LL | type TyLt<#[lt_type] 'd> = &'d u32; LL | fn m_ty<#[ty_meth] P>(_: P) { }
| ^^^^^^^ | ^^^^^^^
error: cannot find attribute `ty_trait` in this scope error: cannot find attribute `lt_hof` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:16:14 --> $DIR/feature-gate-custom_attribute2.rs:51:21
| |
LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } LL | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
| ^^^^^^^^ | ^^^^^^
error: cannot find attribute `lt_trait` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:14:14
|
LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
| ^^^^^^^^
error: cannot find attribute `ty_enum` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:11:13
|
LL | enum EnTy<#[ty_enum] J> { A(J), B }
| ^^^^^^^
error: cannot find attribute `lt_enum` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:9:13
|
LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
| ^^^^^^^
error: cannot find attribute `ty_struct` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:6:15
|
LL | struct StTy<#[ty_struct] I>(I);
| ^^^^^^^^^
error: cannot find attribute `lt_struct` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:4:15
|
LL | struct StLt<#[lt_struct] 'a>(&'a u32);
| ^^^^^^^^^
error: aborting due to 17 previous errors error: aborting due to 17 previous errors

View file

@ -1,14 +1,14 @@
error: cannot find macro `m` in this scope
--> $DIR/issue-40845.rs:4:10
|
LL | impl S { m!(); }
| ^
error: cannot find macro `m` in this scope error: cannot find macro `m` in this scope
--> $DIR/issue-40845.rs:1:11 --> $DIR/issue-40845.rs:1:11
| |
LL | trait T { m!(); } LL | trait T { m!(); }
| ^ | ^
error: cannot find macro `m` in this scope
--> $DIR/issue-40845.rs:4:10
|
LL | impl S { m!(); }
| ^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -39,13 +39,13 @@ LL | }
| - item list ends here | - item list ends here
error: cannot find macro `default` in this scope error: cannot find macro `default` in this scope
--> $DIR/default-unmatched-assoc.rs:12:5 --> $DIR/default-unmatched-assoc.rs:4:5
| |
LL | default!(); LL | default!();
| ^^^^^^^ | ^^^^^^^
error: cannot find macro `default` in this scope error: cannot find macro `default` in this scope
--> $DIR/default-unmatched-assoc.rs:4:5 --> $DIR/default-unmatched-assoc.rs:12:5
| |
LL | default!(); LL | default!();
| ^^^^^^^ | ^^^^^^^

View file

@ -33,17 +33,17 @@ LL | mac2! { does_not_exist!() }
= note: `mut` may be followed by `variable` and `variable @ pattern` = note: `mut` may be followed by `variable` and `variable @ pattern`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot find macro `does_not_exist` in this scope
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:20:13
|
LL | mac1! { does_not_exist!() }
| ^^^^^^^^^^^^^^
error: cannot find macro `does_not_exist` in this scope error: cannot find macro `does_not_exist` in this scope
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:22:13 --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:22:13
| |
LL | mac2! { does_not_exist!() } LL | mac2! { does_not_exist!() }
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: cannot find macro `does_not_exist` in this scope
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:20:13
|
LL | mac1! { does_not_exist!() }
| ^^^^^^^^^^^^^^
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View file

@ -0,0 +1,7 @@
// check-pass
use std as line;
const C: u32 = line!();
fn main() {}