Skip to content

Commit 1a1f525

Browse files
Rollup merge of #90202 - matthewjasper:xcrate-hygiene, r=petrochenkov
Improve and test cross-crate hygiene - Decode the parent expansion for traits and enums in `rustc_resolve`, this was already being used for resolution in typeck - Avoid suggesting importing names with def-site hygiene, since it's often not useful - Add more tests r? `@petrochenkov`
2 parents 7349440 + a76a2d4 commit 1a1f525

27 files changed

+525
-32
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -1198,8 +1198,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
11981198
}
11991199
}
12001200

1201-
if let EntryKind::Mod(data) = kind {
1202-
for exp in data.decode((self, sess)).reexports.decode((self, sess)) {
1201+
if let EntryKind::Mod(exports) = kind {
1202+
for exp in exports.decode((self, sess)) {
12031203
match exp.res {
12041204
Res::Def(DefKind::Macro(..), _) => {}
12051205
_ if macros_only => continue,
@@ -1219,10 +1219,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
12191219
}
12201220

12211221
fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId {
1222-
if let EntryKind::Mod(m) = self.kind(id) {
1223-
m.decode((self, sess)).expansion
1224-
} else {
1225-
panic!("Expected module, found {:?}", self.local_def_id(id))
1222+
match self.kind(id) {
1223+
EntryKind::Mod(_) | EntryKind::Enum(_) | EntryKind::Trait(_) => {
1224+
self.get_expn_that_defined(id, sess)
1225+
}
1226+
_ => panic!("Expected module, found {:?}", self.local_def_id(id)),
12261227
}
12271228
}
12281229

compiler/rustc_metadata/src/rmeta/encoder.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1086,11 +1086,11 @@ impl EncodeContext<'a, 'tcx> {
10861086
Lazy::empty()
10871087
};
10881088

1089-
let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) };
1090-
1091-
record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
1089+
record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports));
10921090
if self.is_proc_macro {
10931091
record!(self.tables.children[def_id] <- &[]);
1092+
// Encode this here because we don't do it in encode_def_ids.
1093+
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
10941094
} else {
10951095
record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| {
10961096
item_id.def_id.local_def_index

compiler/rustc_metadata/src/rmeta/mod.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ enum EntryKind {
346346
Union(Lazy<VariantData>, ReprOptions),
347347
Fn(Lazy<FnData>),
348348
ForeignFn(Lazy<FnData>),
349-
Mod(Lazy<ModData>),
349+
Mod(Lazy<[Export]>),
350350
MacroDef(Lazy<MacroDef>),
351351
ProcMacro(MacroKind),
352352
Closure,
@@ -364,12 +364,6 @@ enum EntryKind {
364364
#[derive(Encodable, Decodable)]
365365
struct RenderedConst(String);
366366

367-
#[derive(MetadataEncodable, MetadataDecodable)]
368-
struct ModData {
369-
reexports: Lazy<[Export]>,
370-
expansion: ExpnId,
371-
}
372-
373367
#[derive(MetadataEncodable, MetadataDecodable)]
374368
struct FnData {
375369
asyncness: hir::IsAsync,

compiler/rustc_resolve/src/build_reduced_graph.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -145,17 +145,11 @@ impl<'a> Resolver<'a> {
145145
} else {
146146
def_key.disambiguated_data.data.get_opt_name().expect("module without name")
147147
};
148-
let expn_id = if def_kind == DefKind::Mod {
149-
self.cstore().module_expansion_untracked(def_id, &self.session)
150-
} else {
151-
// FIXME: Parent expansions for enums and traits are not kept in metadata.
152-
ExpnId::root()
153-
};
154148

155149
Some(self.new_module(
156150
parent,
157151
ModuleKind::Def(def_kind, def_id, name),
158-
expn_id,
152+
self.cstore().module_expansion_untracked(def_id, &self.session),
159153
self.cstore().get_span_untracked(def_id, &self.session),
160154
// FIXME: Account for `#[no_implicit_prelude]` attributes.
161155
parent.map_or(false, |module| module.no_implicit_prelude),

compiler/rustc_resolve/src/diagnostics.rs

+2
Original file line numberDiff line numberDiff line change
@@ -842,9 +842,11 @@ impl<'a> Resolver<'a> {
842842

843843
// collect results based on the filter function
844844
// avoid suggesting anything from the same module in which we are resolving
845+
// avoid suggesting anything with a hygienic name
845846
if ident.name == lookup_ident.name
846847
&& ns == namespace
847848
&& !ptr::eq(in_module, parent_scope.module)
849+
&& !ident.span.normalize_to_macros_2_0().from_expansion()
848850
{
849851
let res = name_binding.res();
850852
if filter_fn(res) {

compiler/rustc_span/src/hygiene.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ impl SyntaxContext {
709709
/// pub fn f() {} // `f`'s `SyntaxContext` has a single `ExpnId` from `m`.
710710
/// pub fn $i() {} // `$i`'s `SyntaxContext` is empty.
711711
/// }
712-
/// n(f);
712+
/// n!(f);
713713
/// macro n($j:ident) {
714714
/// use foo::*;
715715
/// f(); // `f`'s `SyntaxContext` has a mark from `m` and a mark from `n`
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#![feature(decl_macro)]
2+
3+
#[derive(Copy, Clone, PartialEq, Debug)]
4+
pub enum Field {
5+
RootCtxt,
6+
MacroCtxt,
7+
}
8+
9+
#[rustfmt::skip]
10+
macro x(
11+
$macro_name:ident,
12+
$macro2_name:ident,
13+
$type_name:ident,
14+
$field_name:ident,
15+
$const_name:ident
16+
) {
17+
#[derive(Copy, Clone)]
18+
pub struct $type_name {
19+
pub field: Field,
20+
pub $field_name: Field,
21+
}
22+
23+
pub const $const_name: $type_name =
24+
$type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt };
25+
26+
#[macro_export]
27+
macro_rules! $macro_name {
28+
(check_fields_of $e:expr) => {{
29+
let e = $e;
30+
assert_eq!(e.field, Field::MacroCtxt);
31+
assert_eq!(e.$field_name, Field::RootCtxt);
32+
}};
33+
(check_fields) => {{
34+
assert_eq!($const_name.field, Field::MacroCtxt);
35+
assert_eq!($const_name.$field_name, Field::RootCtxt);
36+
}};
37+
(construct) => {
38+
$type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt }
39+
};
40+
}
41+
42+
pub macro $macro2_name {
43+
(check_fields_of $e:expr) => {{
44+
let e = $e;
45+
assert_eq!(e.field, Field::MacroCtxt);
46+
assert_eq!(e.$field_name, Field::RootCtxt);
47+
}},
48+
(check_fields) => {{
49+
assert_eq!($const_name.field, Field::MacroCtxt);
50+
assert_eq!($const_name.$field_name, Field::RootCtxt);
51+
}},
52+
(construct) => {
53+
$type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt }
54+
}
55+
}
56+
}
57+
58+
x!(test_fields, test_fields2, MyStruct, field, MY_CONST);
59+
60+
pub fn check_fields(s: MyStruct) {
61+
test_fields!(check_fields_of s);
62+
}
63+
64+
pub fn check_fields_local() {
65+
test_fields!(check_fields);
66+
test_fields2!(check_fields);
67+
68+
let s1 = test_fields!(construct);
69+
test_fields!(check_fields_of s1);
70+
71+
let s2 = test_fields2!(construct);
72+
test_fields2!(check_fields_of s2);
73+
}
+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#![feature(decl_macro)]
2+
3+
#[derive(PartialEq, Eq, Debug)]
4+
pub enum Method {
5+
DefaultMacroCtxt,
6+
DefaultRootCtxt,
7+
OverrideMacroCtxt,
8+
OverrideRootCtxt,
9+
}
10+
11+
#[rustfmt::skip]
12+
macro x($macro_name:ident, $macro2_name:ident, $trait_name:ident, $method_name:ident) {
13+
pub trait $trait_name {
14+
fn method(&self) -> Method {
15+
Method::DefaultMacroCtxt
16+
}
17+
18+
fn $method_name(&self) -> Method {
19+
Method::DefaultRootCtxt
20+
}
21+
}
22+
23+
impl $trait_name for () {}
24+
impl $trait_name for bool {
25+
fn method(&self) -> Method {
26+
Method::OverrideMacroCtxt
27+
}
28+
29+
fn $method_name(&self) -> Method {
30+
Method::OverrideRootCtxt
31+
}
32+
}
33+
34+
#[macro_export]
35+
macro_rules! $macro_name {
36+
(check_resolutions) => {
37+
assert_eq!(().method(), Method::DefaultMacroCtxt);
38+
assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt);
39+
assert_eq!(().$method_name(), Method::DefaultRootCtxt);
40+
assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt);
41+
42+
assert_eq!(false.method(), Method::OverrideMacroCtxt);
43+
assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt);
44+
assert_eq!(false.$method_name(), Method::OverrideRootCtxt);
45+
assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt);
46+
47+
assert_eq!('a'.method(), Method::DefaultMacroCtxt);
48+
assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt);
49+
assert_eq!('a'.$method_name(), Method::DefaultRootCtxt);
50+
assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt);
51+
52+
assert_eq!(1i32.method(), Method::OverrideMacroCtxt);
53+
assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt);
54+
assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt);
55+
assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt);
56+
57+
assert_eq!(1i64.method(), Method::OverrideMacroCtxt);
58+
assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt);
59+
assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt);
60+
assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt);
61+
};
62+
(assert_no_override $v:expr) => {
63+
assert_eq!($v.method(), Method::DefaultMacroCtxt);
64+
assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt);
65+
assert_eq!($v.$method_name(), Method::DefaultRootCtxt);
66+
assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt);
67+
};
68+
(assert_override $v:expr) => {
69+
assert_eq!($v.method(), Method::OverrideMacroCtxt);
70+
assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt);
71+
assert_eq!($v.$method_name(), Method::OverrideRootCtxt);
72+
assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt);
73+
};
74+
(impl for $t:ty) => {
75+
impl $trait_name for $t {
76+
fn method(&self) -> Method {
77+
Method::OverrideMacroCtxt
78+
}
79+
80+
fn $method_name(&self) -> Method {
81+
Method::OverrideRootCtxt
82+
}
83+
}
84+
};
85+
}
86+
87+
pub macro $macro2_name {
88+
(check_resolutions) => {
89+
assert_eq!(().method(), Method::DefaultMacroCtxt);
90+
assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt);
91+
assert_eq!(().$method_name(), Method::DefaultRootCtxt);
92+
assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt);
93+
94+
assert_eq!(false.method(), Method::OverrideMacroCtxt);
95+
assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt);
96+
assert_eq!(false.$method_name(), Method::OverrideRootCtxt);
97+
assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt);
98+
99+
assert_eq!('a'.method(), Method::DefaultMacroCtxt);
100+
assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt);
101+
assert_eq!('a'.$method_name(), Method::DefaultRootCtxt);
102+
assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt);
103+
104+
assert_eq!(1i32.method(), Method::OverrideMacroCtxt);
105+
assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt);
106+
assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt);
107+
assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt);
108+
109+
assert_eq!(1i64.method(), Method::OverrideMacroCtxt);
110+
assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt);
111+
assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt);
112+
assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt);
113+
},
114+
(assert_no_override $v:expr) => {
115+
assert_eq!($v.method(), Method::DefaultMacroCtxt);
116+
assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt);
117+
assert_eq!($v.$method_name(), Method::DefaultRootCtxt);
118+
assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt);
119+
},
120+
(assert_override $v:expr) => {
121+
assert_eq!($v.method(), Method::OverrideMacroCtxt);
122+
assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt);
123+
assert_eq!($v.$method_name(), Method::OverrideRootCtxt);
124+
assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt);
125+
},
126+
(impl for $t:ty) => {
127+
impl $trait_name for $t {
128+
fn method(&self) -> Method {
129+
Method::OverrideMacroCtxt
130+
}
131+
132+
fn $method_name(&self) -> Method {
133+
Method::OverrideRootCtxt
134+
}
135+
}
136+
}
137+
}
138+
}
139+
140+
x!(test_trait, test_trait2, MyTrait, method);
141+
142+
impl MyTrait for char {}
143+
test_trait!(impl for i32);
144+
test_trait2!(impl for i64);
145+
146+
pub fn check_crate_local() {
147+
test_trait!(check_resolutions);
148+
test_trait2!(check_resolutions);
149+
}
150+
151+
// Check that any comparison of idents at monomorphization time is correct
152+
pub fn check_crate_local_generic<T: MyTrait, U: MyTrait>(t: T, u: U) {
153+
test_trait!(check_resolutions);
154+
test_trait2!(check_resolutions);
155+
156+
test_trait!(assert_no_override t);
157+
test_trait2!(assert_no_override t);
158+
test_trait!(assert_override u);
159+
test_trait2!(assert_override u);
160+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(decl_macro)]
2+
3+
macro x() {
4+
pub struct MyStruct;
5+
}
6+
7+
x!();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(decl_macro)]
2+
3+
macro x($macro_name:ident) {
4+
#[macro_export]
5+
macro_rules! $macro_name {
6+
(define) => {
7+
pub struct MyStruct;
8+
};
9+
(create) => {
10+
MyStruct {}
11+
};
12+
}
13+
}
14+
15+
x!(my_struct);
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#![feature(decl_macro)]
2+
3+
#[rustfmt::skip]
4+
macro x($macro_name:ident, $macro2_name:ident, $type_name:ident, $variant_name:ident) {
5+
#[repr(u8)]
6+
pub enum $type_name {
7+
Variant = 0,
8+
$variant_name = 1,
9+
}
10+
11+
#[macro_export]
12+
macro_rules! $macro_name {
13+
() => {{
14+
assert_eq!($type_name::Variant as u8, 0);
15+
assert_eq!($type_name::$variant_name as u8, 1);
16+
assert_eq!(<$type_name>::Variant as u8, 0);
17+
assert_eq!(<$type_name>::$variant_name as u8, 1);
18+
}};
19+
}
20+
21+
pub macro $macro2_name {
22+
() => {{
23+
assert_eq!($type_name::Variant as u8, 0);
24+
assert_eq!($type_name::$variant_name as u8, 1);
25+
assert_eq!(<$type_name>::Variant as u8, 0);
26+
assert_eq!(<$type_name>::$variant_name as u8, 1);
27+
}},
28+
}
29+
}
30+
31+
x!(test_variants, test_variants2, MyEnum, Variant);
32+
33+
pub fn check_variants() {
34+
test_variants!();
35+
test_variants2!();
36+
}

0 commit comments

Comments
 (0)