From 4ecb49eba3770e4826346486252b9e7a1b5fcb33 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 21 Oct 2021 22:06:40 +0100 Subject: [PATCH 1/5] Handle cross-crate module `ExpnId`s consistently - Always use the ExpnId serialized to `tables` - Use the Id for traits and enums from other crates in resolution. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 9 +++++---- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +++- compiler/rustc_metadata/src/rmeta/mod.rs | 1 - compiler/rustc_resolve/src/build_reduced_graph.rs | 7 +------ src/test/ui/proc-macro/meta-macro-hygiene.stdout | 2 ++ src/test/ui/proc-macro/nonterminal-token-hygiene.stdout | 2 ++ 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index ca9daa49aa2d2..1e2b4aaef805f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1219,10 +1219,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId { - if let EntryKind::Mod(m) = self.kind(id) { - m.decode((self, sess)).expansion - } else { - panic!("Expected module, found {:?}", self.local_def_id(id)) + match self.kind(id) { + EntryKind::Mod(_) | EntryKind::Enum(_) | EntryKind::Trait(_) => { + self.get_expn_that_defined(id, sess) + } + _ => panic!("Expected module, found {:?}", self.local_def_id(id)), } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 20f7b059b5600..08d9db381cf06 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1086,11 +1086,13 @@ impl EncodeContext<'a, 'tcx> { Lazy::empty() }; - let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) }; + let data = ModData { reexports }; record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data))); if self.is_proc_macro { record!(self.tables.children[def_id] <- &[]); + // Encode this here because we don't do it in encode_def_ids. + record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id)); } else { record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| { item_id.def_id.local_def_index diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 42855e9d9d12f..40c497044ded1 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -367,7 +367,6 @@ struct RenderedConst(String); #[derive(MetadataEncodable, MetadataDecodable)] struct ModData { reexports: Lazy<[Export]>, - expansion: ExpnId, } #[derive(MetadataEncodable, MetadataDecodable)] diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 2a562a06cb3cd..c215de5560ad4 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -145,12 +145,7 @@ impl<'a> Resolver<'a> { } else { def_key.disambiguated_data.data.get_opt_name().expect("module without name") }; - let expn_id = if def_kind == DefKind::Mod { - self.cstore().module_expansion_untracked(def_id, &self.session) - } else { - // FIXME: Parent expansions for enums and traits are not kept in metadata. - ExpnId::root() - }; + let expn_id = self.cstore().module_expansion_untracked(def_id, &self.session); Some(self.new_module( parent, diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout index 7f7a1009c909a..5d04fe1e3de5f 100644 --- a/src/test/ui/proc-macro/meta-macro-hygiene.stdout +++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout @@ -49,6 +49,8 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site") crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout index 0780386381373..709b2a2169e08 100644 --- a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -73,6 +73,8 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner") crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) From 1536d7220b847d8a843a3357cc62ef5704f2c690 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 21 Oct 2021 23:36:51 +0100 Subject: [PATCH 2/5] Don't suggest importing items with hygienic names This will potentially hide a few correct suggestions, but importing these items from another module is not generally possible. --- compiler/rustc_resolve/src/diagnostics.rs | 2 ++ compiler/rustc_span/src/hygiene.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 63000a9d13d41..aefb3f2cb9c83 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -831,9 +831,11 @@ impl<'a> Resolver<'a> { // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving + // avoid suggesting anything with a hygienic name if ident.name == lookup_ident.name && ns == namespace && !ptr::eq(in_module, parent_scope.module) + && !ident.span.normalize_to_macros_2_0().from_expansion() { let res = name_binding.res(); if filter_fn(res) { diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index aa15febe8853d..724d1904dc33c 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -709,7 +709,7 @@ impl SyntaxContext { /// pub fn f() {} // `f`'s `SyntaxContext` has a single `ExpnId` from `m`. /// pub fn $i() {} // `$i`'s `SyntaxContext` is empty. /// } - /// n(f); + /// n!(f); /// macro n($j:ident) { /// use foo::*; /// f(); // `f`'s `SyntaxContext` has a mark from `m` and a mark from `n` From fabede185151d10019e41273d056b36990d76399 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 23 Oct 2021 12:06:58 +0100 Subject: [PATCH 3/5] Add more tests for cross-crate hygiene --- src/test/ui/hygiene/auxiliary/fields.rs | 73 ++++++++ src/test/ui/hygiene/auxiliary/methods.rs | 160 ++++++++++++++++++ src/test/ui/hygiene/auxiliary/pub_hygiene.rs | 7 + src/test/ui/hygiene/auxiliary/use_by_macro.rs | 15 ++ src/test/ui/hygiene/auxiliary/variants.rs | 36 ++++ .../ui/hygiene/cross-crate-define-and-use.rs | 14 ++ src/test/ui/hygiene/cross-crate-fields.rs | 21 +++ .../ui/hygiene/cross-crate-glob-hygiene.rs | 18 ++ .../hygiene/cross-crate-glob-hygiene.stderr | 11 ++ src/test/ui/hygiene/cross-crate-methods.rs | 29 ++++ ...giene.rs => cross-crate-name-collision.rs} | 0 .../ui/hygiene/cross-crate-name-hiding-2.rs | 12 ++ .../hygiene/cross-crate-name-hiding-2.stderr | 9 + .../ui/hygiene/cross-crate-name-hiding.rs | 10 ++ .../ui/hygiene/cross-crate-name-hiding.stderr | 9 + src/test/ui/hygiene/cross-crate-redefine.rs | 11 ++ .../ui/hygiene/cross-crate-redefine.stderr | 15 ++ src/test/ui/hygiene/cross-crate-variants.rs | 15 ++ 18 files changed, 465 insertions(+) create mode 100644 src/test/ui/hygiene/auxiliary/fields.rs create mode 100644 src/test/ui/hygiene/auxiliary/methods.rs create mode 100644 src/test/ui/hygiene/auxiliary/pub_hygiene.rs create mode 100644 src/test/ui/hygiene/auxiliary/use_by_macro.rs create mode 100644 src/test/ui/hygiene/auxiliary/variants.rs create mode 100644 src/test/ui/hygiene/cross-crate-define-and-use.rs create mode 100644 src/test/ui/hygiene/cross-crate-fields.rs create mode 100644 src/test/ui/hygiene/cross-crate-glob-hygiene.rs create mode 100644 src/test/ui/hygiene/cross-crate-glob-hygiene.stderr create mode 100644 src/test/ui/hygiene/cross-crate-methods.rs rename src/test/ui/hygiene/{cross_crate_hygiene.rs => cross-crate-name-collision.rs} (100%) create mode 100644 src/test/ui/hygiene/cross-crate-name-hiding-2.rs create mode 100644 src/test/ui/hygiene/cross-crate-name-hiding-2.stderr create mode 100644 src/test/ui/hygiene/cross-crate-name-hiding.rs create mode 100644 src/test/ui/hygiene/cross-crate-name-hiding.stderr create mode 100644 src/test/ui/hygiene/cross-crate-redefine.rs create mode 100644 src/test/ui/hygiene/cross-crate-redefine.stderr create mode 100644 src/test/ui/hygiene/cross-crate-variants.rs diff --git a/src/test/ui/hygiene/auxiliary/fields.rs b/src/test/ui/hygiene/auxiliary/fields.rs new file mode 100644 index 0000000000000..733d11a9e8229 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/fields.rs @@ -0,0 +1,73 @@ +#![feature(decl_macro)] + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Field { + RootCtxt, + MacroCtxt, +} + +#[rustfmt::skip] +macro x( + $macro_name:ident, + $macro2_name:ident, + $type_name:ident, + $field_name:ident, + $const_name:ident +) { + #[derive(Copy, Clone)] + pub struct $type_name { + pub field: Field, + pub $field_name: Field, + } + + pub const $const_name: $type_name = + $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt }; + + #[macro_export] + macro_rules! $macro_name { + (check_fields_of $e:expr) => {{ + let e = $e; + assert_eq!(e.field, Field::MacroCtxt); + assert_eq!(e.$field_name, Field::RootCtxt); + }}; + (check_fields) => {{ + assert_eq!($const_name.field, Field::MacroCtxt); + assert_eq!($const_name.$field_name, Field::RootCtxt); + }}; + (construct) => { + $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt } + }; + } + + pub macro $macro2_name { + (check_fields_of $e:expr) => {{ + let e = $e; + assert_eq!(e.field, Field::MacroCtxt); + assert_eq!(e.$field_name, Field::RootCtxt); + }}, + (check_fields) => {{ + assert_eq!($const_name.field, Field::MacroCtxt); + assert_eq!($const_name.$field_name, Field::RootCtxt); + }}, + (construct) => { + $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt } + } + } +} + +x!(test_fields, test_fields2, MyStruct, field, MY_CONST); + +pub fn check_fields(s: MyStruct) { + test_fields!(check_fields_of s); +} + +pub fn check_fields_local() { + test_fields!(check_fields); + test_fields2!(check_fields); + + let s1 = test_fields!(construct); + test_fields!(check_fields_of s1); + + let s2 = test_fields2!(construct); + test_fields2!(check_fields_of s2); +} diff --git a/src/test/ui/hygiene/auxiliary/methods.rs b/src/test/ui/hygiene/auxiliary/methods.rs new file mode 100644 index 0000000000000..23b9c61cfc058 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/methods.rs @@ -0,0 +1,160 @@ +#![feature(decl_macro)] + +#[derive(PartialEq, Eq, Debug)] +pub enum Method { + DefaultMacroCtxt, + DefaultRootCtxt, + OverrideMacroCtxt, + OverrideRootCtxt, +} + +#[rustfmt::skip] +macro x($macro_name:ident, $macro2_name:ident, $trait_name:ident, $method_name:ident) { + pub trait $trait_name { + fn method(&self) -> Method { + Method::DefaultMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::DefaultRootCtxt + } + } + + impl $trait_name for () {} + impl $trait_name for bool { + fn method(&self) -> Method { + Method::OverrideMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::OverrideRootCtxt + } + } + + #[macro_export] + macro_rules! $macro_name { + (check_resolutions) => { + assert_eq!(().method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt); + assert_eq!(().$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt); + + assert_eq!(false.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt); + assert_eq!(false.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt); + + assert_eq!('a'.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt); + assert_eq!('a'.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt); + + assert_eq!(1i32.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt); + assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt); + + assert_eq!(1i64.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt); + assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt); + }; + (assert_no_override $v:expr) => { + assert_eq!($v.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt); + assert_eq!($v.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt); + }; + (assert_override $v:expr) => { + assert_eq!($v.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt); + assert_eq!($v.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt); + }; + (impl for $t:ty) => { + impl $trait_name for $t { + fn method(&self) -> Method { + Method::OverrideMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::OverrideRootCtxt + } + } + }; + } + + pub macro $macro2_name { + (check_resolutions) => { + assert_eq!(().method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt); + assert_eq!(().$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt); + + assert_eq!(false.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt); + assert_eq!(false.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt); + + assert_eq!('a'.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt); + assert_eq!('a'.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt); + + assert_eq!(1i32.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt); + assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt); + + assert_eq!(1i64.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt); + assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt); + }, + (assert_no_override $v:expr) => { + assert_eq!($v.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt); + assert_eq!($v.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt); + }, + (assert_override $v:expr) => { + assert_eq!($v.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt); + assert_eq!($v.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt); + }, + (impl for $t:ty) => { + impl $trait_name for $t { + fn method(&self) -> Method { + Method::OverrideMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::OverrideRootCtxt + } + } + } + } +} + +x!(test_trait, test_trait2, MyTrait, method); + +impl MyTrait for char {} +test_trait!(impl for i32); +test_trait2!(impl for i64); + +pub fn check_crate_local() { + test_trait!(check_resolutions); + test_trait2!(check_resolutions); +} + +// Check that any comparison of idents at monomorphization time is correct +pub fn check_crate_local_generic(t: T, u: U) { + test_trait!(check_resolutions); + test_trait2!(check_resolutions); + + test_trait!(assert_no_override t); + test_trait2!(assert_no_override t); + test_trait!(assert_override u); + test_trait2!(assert_override u); +} diff --git a/src/test/ui/hygiene/auxiliary/pub_hygiene.rs b/src/test/ui/hygiene/auxiliary/pub_hygiene.rs new file mode 100644 index 0000000000000..47e76a629c8b1 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/pub_hygiene.rs @@ -0,0 +1,7 @@ +#![feature(decl_macro)] + +macro x() { + pub struct MyStruct; +} + +x!(); diff --git a/src/test/ui/hygiene/auxiliary/use_by_macro.rs b/src/test/ui/hygiene/auxiliary/use_by_macro.rs new file mode 100644 index 0000000000000..791cf0358952a --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/use_by_macro.rs @@ -0,0 +1,15 @@ +#![feature(decl_macro)] + +macro x($macro_name:ident) { + #[macro_export] + macro_rules! $macro_name { + (define) => { + pub struct MyStruct; + }; + (create) => { + MyStruct {} + }; + } +} + +x!(my_struct); diff --git a/src/test/ui/hygiene/auxiliary/variants.rs b/src/test/ui/hygiene/auxiliary/variants.rs new file mode 100644 index 0000000000000..dbfcce17d47f1 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/variants.rs @@ -0,0 +1,36 @@ +#![feature(decl_macro)] + +#[rustfmt::skip] +macro x($macro_name:ident, $macro2_name:ident, $type_name:ident, $variant_name:ident) { + #[repr(u8)] + pub enum $type_name { + Variant = 0, + $variant_name = 1, + } + + #[macro_export] + macro_rules! $macro_name { + () => {{ + assert_eq!($type_name::Variant as u8, 0); + assert_eq!($type_name::$variant_name as u8, 1); + assert_eq!(<$type_name>::Variant as u8, 0); + assert_eq!(<$type_name>::$variant_name as u8, 1); + }}; + } + + pub macro $macro2_name { + () => {{ + assert_eq!($type_name::Variant as u8, 0); + assert_eq!($type_name::$variant_name as u8, 1); + assert_eq!(<$type_name>::Variant as u8, 0); + assert_eq!(<$type_name>::$variant_name as u8, 1); + }}, + } +} + +x!(test_variants, test_variants2, MyEnum, Variant); + +pub fn check_variants() { + test_variants!(); + test_variants2!(); +} diff --git a/src/test/ui/hygiene/cross-crate-define-and-use.rs b/src/test/ui/hygiene/cross-crate-define-and-use.rs new file mode 100644 index 0000000000000..9bb8d804940cd --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-define-and-use.rs @@ -0,0 +1,14 @@ +// check-pass +// aux-build:use_by_macro.rs + +#![feature(type_name_of_val)] +extern crate use_by_macro; + +use use_by_macro::*; + +enum MyStruct {} +my_struct!(define); + +fn main() { + let x = my_struct!(create); +} diff --git a/src/test/ui/hygiene/cross-crate-fields.rs b/src/test/ui/hygiene/cross-crate-fields.rs new file mode 100644 index 0000000000000..96ed412a6258a --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-fields.rs @@ -0,0 +1,21 @@ +// run-pass +// aux-build:fields.rs + +extern crate fields; + +use fields::*; + +fn main() { + check_fields_local(); + + test_fields!(check_fields); + test_fields2!(check_fields); + + let s1 = test_fields!(construct); + check_fields(s1); + test_fields!(check_fields_of s1); + + let s2 = test_fields2!(construct); + check_fields(s2); + test_fields2!(check_fields_of s2); +} diff --git a/src/test/ui/hygiene/cross-crate-glob-hygiene.rs b/src/test/ui/hygiene/cross-crate-glob-hygiene.rs new file mode 100644 index 0000000000000..ebd632d2f66d8 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-glob-hygiene.rs @@ -0,0 +1,18 @@ +// aux-build:use_by_macro.rs + +extern crate use_by_macro; + +use use_by_macro::*; + +mod m { + use use_by_macro::*; + + my_struct!(define); +} + +use m::*; + +fn main() { + let x = my_struct!(create); + //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope +} diff --git a/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr b/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr new file mode 100644 index 0000000000000..8f8ed8307b9e2 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr @@ -0,0 +1,11 @@ +error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope + --> $DIR/cross-crate-glob-hygiene.rs:16:13 + | +LL | let x = my_struct!(create); + | ^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/src/test/ui/hygiene/cross-crate-methods.rs b/src/test/ui/hygiene/cross-crate-methods.rs new file mode 100644 index 0000000000000..f27ad893a1e44 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-methods.rs @@ -0,0 +1,29 @@ +// run-pass +// aux-build:methods.rs + +extern crate methods; + +use methods::*; + +struct A; +struct B; +struct C; + +impl MyTrait for A {} +test_trait!(impl for B); +test_trait2!(impl for C); + +fn main() { + check_crate_local(); + check_crate_local_generic(A, B); + check_crate_local_generic(A, C); + + test_trait!(check_resolutions); + test_trait2!(check_resolutions); + test_trait!(assert_no_override A); + test_trait2!(assert_no_override A); + test_trait!(assert_override B); + test_trait2!(assert_override B); + test_trait!(assert_override C); + test_trait2!(assert_override C); +} diff --git a/src/test/ui/hygiene/cross_crate_hygiene.rs b/src/test/ui/hygiene/cross-crate-name-collision.rs similarity index 100% rename from src/test/ui/hygiene/cross_crate_hygiene.rs rename to src/test/ui/hygiene/cross-crate-name-collision.rs diff --git a/src/test/ui/hygiene/cross-crate-name-hiding-2.rs b/src/test/ui/hygiene/cross-crate-name-hiding-2.rs new file mode 100644 index 0000000000000..8d416b0210422 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding-2.rs @@ -0,0 +1,12 @@ +// aux-build:use_by_macro.rs + +extern crate use_by_macro; + +use use_by_macro::*; + +my_struct!(define); + +fn main() { + let x = MyStruct {}; + //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope +} diff --git a/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr b/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr new file mode 100644 index 0000000000000..1a7e4900b8f33 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr @@ -0,0 +1,9 @@ +error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope + --> $DIR/cross-crate-name-hiding-2.rs:10:13 + | +LL | let x = MyStruct {}; + | ^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/src/test/ui/hygiene/cross-crate-name-hiding.rs b/src/test/ui/hygiene/cross-crate-name-hiding.rs new file mode 100644 index 0000000000000..87d011dfe8731 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding.rs @@ -0,0 +1,10 @@ +// aux-build:pub_hygiene.rs + +extern crate pub_hygiene; + +use pub_hygiene::*; + +fn main() { + let x = MyStruct {}; + //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope +} diff --git a/src/test/ui/hygiene/cross-crate-name-hiding.stderr b/src/test/ui/hygiene/cross-crate-name-hiding.stderr new file mode 100644 index 0000000000000..149d7eec4ef4c --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding.stderr @@ -0,0 +1,9 @@ +error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope + --> $DIR/cross-crate-name-hiding.rs:8:13 + | +LL | let x = MyStruct {}; + | ^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/src/test/ui/hygiene/cross-crate-redefine.rs b/src/test/ui/hygiene/cross-crate-redefine.rs new file mode 100644 index 0000000000000..c79a6be5133d6 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-redefine.rs @@ -0,0 +1,11 @@ +// aux-build:use_by_macro.rs + +extern crate use_by_macro; + +use use_by_macro::*; + +my_struct!(define); +//~^ ERROR the name `MyStruct` is defined multiple times +my_struct!(define); + +fn main() {} diff --git a/src/test/ui/hygiene/cross-crate-redefine.stderr b/src/test/ui/hygiene/cross-crate-redefine.stderr new file mode 100644 index 0000000000000..6d0c95117ddfb --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-redefine.stderr @@ -0,0 +1,15 @@ +error[E0428]: the name `MyStruct` is defined multiple times + --> $DIR/cross-crate-redefine.rs:7:1 + | +LL | my_struct!(define); + | ^^^^^^^^^^^^^^^^^^ `MyStruct` redefined here +LL | +LL | my_struct!(define); + | ------------------ previous definition of the type `MyStruct` here + | + = note: `MyStruct` must be defined only once in the type namespace of this module + = note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/hygiene/cross-crate-variants.rs b/src/test/ui/hygiene/cross-crate-variants.rs new file mode 100644 index 0000000000000..6c5671f324958 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-variants.rs @@ -0,0 +1,15 @@ +// run-pass +// aux-build:variants.rs + +extern crate variants; + +use variants::*; + +fn main() { + check_variants(); + + test_variants!(); + test_variants2!(); + + assert_eq!(MyEnum::Variant as u8, 1); +} From d8426ea6369e88b4de12eed1ba8ecd6be5dc6559 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 28 Oct 2021 21:48:21 +0100 Subject: [PATCH 4/5] Remove `ModData` from rustc_metadata This avoids having to decode 2 `Lazy`s when decoding a modules exports. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +--- compiler/rustc_metadata/src/rmeta/mod.rs | 7 +------ compiler/rustc_resolve/src/build_reduced_graph.rs | 3 +-- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 1e2b4aaef805f..5e90aec003e9b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1198,8 +1198,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - if let EntryKind::Mod(data) = kind { - for exp in data.decode((self, sess)).reexports.decode((self, sess)) { + if let EntryKind::Mod(exports) = kind { + for exp in exports.decode((self, sess)) { match exp.res { Res::Def(DefKind::Macro(..), _) => {} _ if macros_only => continue, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 08d9db381cf06..0dbef66ac37d7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1086,9 +1086,7 @@ impl EncodeContext<'a, 'tcx> { Lazy::empty() }; - let data = ModData { reexports }; - - record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data))); + record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports)); if self.is_proc_macro { record!(self.tables.children[def_id] <- &[]); // Encode this here because we don't do it in encode_def_ids. diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 40c497044ded1..4e09d23169aca 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -346,7 +346,7 @@ enum EntryKind { Union(Lazy, ReprOptions), Fn(Lazy), ForeignFn(Lazy), - Mod(Lazy), + Mod(Lazy<[Export]>), MacroDef(Lazy), ProcMacro(MacroKind), Closure, @@ -364,11 +364,6 @@ enum EntryKind { #[derive(Encodable, Decodable)] struct RenderedConst(String); -#[derive(MetadataEncodable, MetadataDecodable)] -struct ModData { - reexports: Lazy<[Export]>, -} - #[derive(MetadataEncodable, MetadataDecodable)] struct FnData { asyncness: hir::IsAsync, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index c215de5560ad4..33af9884cbb66 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -145,12 +145,11 @@ impl<'a> Resolver<'a> { } else { def_key.disambiguated_data.data.get_opt_name().expect("module without name") }; - let expn_id = self.cstore().module_expansion_untracked(def_id, &self.session); Some(self.new_module( parent, ModuleKind::Def(def_kind, def_id, name), - expn_id, + self.cstore().module_expansion_untracked(def_id, &self.session), self.cstore().get_span_untracked(def_id, &self.session), // FIXME: Account for `#[no_implicit_prelude]` attributes. parent.map_or(false, |module| module.no_implicit_prelude), From a76a2d4ef986ec69e4ffb81c35dfb8dc91effee9 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 28 Oct 2021 21:48:39 +0100 Subject: [PATCH 5/5] Add comments to hygiene tests --- src/test/ui/hygiene/cross-crate-define-and-use.rs | 5 +++++ src/test/ui/hygiene/cross-crate-fields.rs | 3 +++ src/test/ui/hygiene/cross-crate-glob-hygiene.rs | 5 +++++ src/test/ui/hygiene/cross-crate-glob-hygiene.stderr | 2 +- src/test/ui/hygiene/cross-crate-methods.rs | 4 ++++ src/test/ui/hygiene/cross-crate-name-collision.rs | 4 ++++ src/test/ui/hygiene/cross-crate-name-hiding-2.rs | 3 +++ src/test/ui/hygiene/cross-crate-name-hiding-2.stderr | 2 +- src/test/ui/hygiene/cross-crate-name-hiding.rs | 3 +++ src/test/ui/hygiene/cross-crate-name-hiding.stderr | 2 +- src/test/ui/hygiene/cross-crate-redefine.rs | 3 +++ src/test/ui/hygiene/cross-crate-redefine.stderr | 2 +- src/test/ui/hygiene/cross-crate-variants.rs | 3 +++ 13 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/test/ui/hygiene/cross-crate-define-and-use.rs b/src/test/ui/hygiene/cross-crate-define-and-use.rs index 9bb8d804940cd..94f1adff62642 100644 --- a/src/test/ui/hygiene/cross-crate-define-and-use.rs +++ b/src/test/ui/hygiene/cross-crate-define-and-use.rs @@ -1,3 +1,8 @@ +// Check that a marco from another crate can define an item in one expansion +// and use it from another, without it being visible to everyone. +// This requires that the definition of `my_struct` preserves the hygiene +// information for the tokens in its definition. + // check-pass // aux-build:use_by_macro.rs diff --git a/src/test/ui/hygiene/cross-crate-fields.rs b/src/test/ui/hygiene/cross-crate-fields.rs index 96ed412a6258a..1bcd64573ac6e 100644 --- a/src/test/ui/hygiene/cross-crate-fields.rs +++ b/src/test/ui/hygiene/cross-crate-fields.rs @@ -1,3 +1,6 @@ +// Test that fields on a struct defined in another crate are resolved correctly +// their names differ only in `SyntaxContext`. + // run-pass // aux-build:fields.rs diff --git a/src/test/ui/hygiene/cross-crate-glob-hygiene.rs b/src/test/ui/hygiene/cross-crate-glob-hygiene.rs index ebd632d2f66d8..de5576682a6bd 100644 --- a/src/test/ui/hygiene/cross-crate-glob-hygiene.rs +++ b/src/test/ui/hygiene/cross-crate-glob-hygiene.rs @@ -1,3 +1,8 @@ +// Check that globs cannot import hygienic identifiers from a macro expansion +// in another crate. `my_struct` is a `macro_rules` macro, so the struct it +// defines is only not imported because `my_struct` is defined by a macros 2.0 +// macro. + // aux-build:use_by_macro.rs extern crate use_by_macro; diff --git a/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr b/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr index 8f8ed8307b9e2..7369e77d0709e 100644 --- a/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr +++ b/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr @@ -1,5 +1,5 @@ error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope - --> $DIR/cross-crate-glob-hygiene.rs:16:13 + --> $DIR/cross-crate-glob-hygiene.rs:21:13 | LL | let x = my_struct!(create); | ^^^^^^^^^^^^^^^^^^ not found in this scope diff --git a/src/test/ui/hygiene/cross-crate-methods.rs b/src/test/ui/hygiene/cross-crate-methods.rs index f27ad893a1e44..0e6f57c33f64a 100644 --- a/src/test/ui/hygiene/cross-crate-methods.rs +++ b/src/test/ui/hygiene/cross-crate-methods.rs @@ -1,3 +1,7 @@ +// Test that methods defined in another crate are resolved correctly their +// names differ only in `SyntaxContext`. This also checks that any name +// resolution done when monomorphizing is correct. + // run-pass // aux-build:methods.rs diff --git a/src/test/ui/hygiene/cross-crate-name-collision.rs b/src/test/ui/hygiene/cross-crate-name-collision.rs index 75742960b7e3c..8f118782f2319 100644 --- a/src/test/ui/hygiene/cross-crate-name-collision.rs +++ b/src/test/ui/hygiene/cross-crate-name-collision.rs @@ -1,3 +1,7 @@ +// Check that two items defined in another crate that have identifiers that +// only differ by `SyntaxContext` do not cause name collisions when imported +// in another crate. + // check-pass // aux-build:needs_hygiene.rs diff --git a/src/test/ui/hygiene/cross-crate-name-hiding-2.rs b/src/test/ui/hygiene/cross-crate-name-hiding-2.rs index 8d416b0210422..3eacd775c9e53 100644 --- a/src/test/ui/hygiene/cross-crate-name-hiding-2.rs +++ b/src/test/ui/hygiene/cross-crate-name-hiding-2.rs @@ -1,3 +1,6 @@ +// Check that an identifier from a 2.0 macro in another crate cannot be +// resolved with an identifier that's not from a macro expansion. + // aux-build:use_by_macro.rs extern crate use_by_macro; diff --git a/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr b/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr index 1a7e4900b8f33..46314cdd5ab4e 100644 --- a/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr +++ b/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr @@ -1,5 +1,5 @@ error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope - --> $DIR/cross-crate-name-hiding-2.rs:10:13 + --> $DIR/cross-crate-name-hiding-2.rs:13:13 | LL | let x = MyStruct {}; | ^^^^^^^^ not found in this scope diff --git a/src/test/ui/hygiene/cross-crate-name-hiding.rs b/src/test/ui/hygiene/cross-crate-name-hiding.rs index 87d011dfe8731..dd76ecc5762f5 100644 --- a/src/test/ui/hygiene/cross-crate-name-hiding.rs +++ b/src/test/ui/hygiene/cross-crate-name-hiding.rs @@ -1,3 +1,6 @@ +// Check that an item defined by a 2.0 macro in another crate cannot be used in +// another crate. + // aux-build:pub_hygiene.rs extern crate pub_hygiene; diff --git a/src/test/ui/hygiene/cross-crate-name-hiding.stderr b/src/test/ui/hygiene/cross-crate-name-hiding.stderr index 149d7eec4ef4c..f8840c8f85a33 100644 --- a/src/test/ui/hygiene/cross-crate-name-hiding.stderr +++ b/src/test/ui/hygiene/cross-crate-name-hiding.stderr @@ -1,5 +1,5 @@ error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope - --> $DIR/cross-crate-name-hiding.rs:8:13 + --> $DIR/cross-crate-name-hiding.rs:11:13 | LL | let x = MyStruct {}; | ^^^^^^^^ not found in this scope diff --git a/src/test/ui/hygiene/cross-crate-redefine.rs b/src/test/ui/hygiene/cross-crate-redefine.rs index c79a6be5133d6..3cb06b4bad873 100644 --- a/src/test/ui/hygiene/cross-crate-redefine.rs +++ b/src/test/ui/hygiene/cross-crate-redefine.rs @@ -1,3 +1,6 @@ +// Check that items with identical `SyntaxContext` conflict even when that +// context involves a mark from another crate. + // aux-build:use_by_macro.rs extern crate use_by_macro; diff --git a/src/test/ui/hygiene/cross-crate-redefine.stderr b/src/test/ui/hygiene/cross-crate-redefine.stderr index 6d0c95117ddfb..4f1419de42677 100644 --- a/src/test/ui/hygiene/cross-crate-redefine.stderr +++ b/src/test/ui/hygiene/cross-crate-redefine.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `MyStruct` is defined multiple times - --> $DIR/cross-crate-redefine.rs:7:1 + --> $DIR/cross-crate-redefine.rs:10:1 | LL | my_struct!(define); | ^^^^^^^^^^^^^^^^^^ `MyStruct` redefined here diff --git a/src/test/ui/hygiene/cross-crate-variants.rs b/src/test/ui/hygiene/cross-crate-variants.rs index 6c5671f324958..efc73a21f16f3 100644 --- a/src/test/ui/hygiene/cross-crate-variants.rs +++ b/src/test/ui/hygiene/cross-crate-variants.rs @@ -1,3 +1,6 @@ +// Test that variants of an enum defined in another crate are resolved +// correctly when their names differ only in `SyntaxContext`. + // run-pass // aux-build:variants.rs