diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index ca9daa49aa2d2..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, @@ -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..0dbef66ac37d7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1086,11 +1086,11 @@ impl EncodeContext<'a, 'tcx> { Lazy::empty() }; - let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) }; - - 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. + 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..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,12 +364,6 @@ enum EntryKind { #[derive(Encodable, Decodable)] struct RenderedConst(String); -#[derive(MetadataEncodable, MetadataDecodable)] -struct ModData { - reexports: Lazy<[Export]>, - expansion: ExpnId, -} - #[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 2a562a06cb3cd..33af9884cbb66 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -145,17 +145,11 @@ 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() - }; 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), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index ccfab263bd48e..163acebcceacf 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -842,9 +842,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` 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..94f1adff62642 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-define-and-use.rs @@ -0,0 +1,19 @@ +// 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 + +#![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..1bcd64573ac6e --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-fields.rs @@ -0,0 +1,24 @@ +// 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 + +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..de5576682a6bd --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-glob-hygiene.rs @@ -0,0 +1,23 @@ +// 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; + +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..7369e77d0709e --- /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:21: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..0e6f57c33f64a --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-methods.rs @@ -0,0 +1,33 @@ +// 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 + +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-name-collision.rs b/src/test/ui/hygiene/cross-crate-name-collision.rs new file mode 100644 index 0000000000000..8f118782f2319 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-collision.rs @@ -0,0 +1,12 @@ +// 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 + +extern crate needs_hygiene; + +use needs_hygiene::*; + +fn main() {} 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..3eacd775c9e53 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding-2.rs @@ -0,0 +1,15 @@ +// 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; + +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..46314cdd5ab4e --- /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:13: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..dd76ecc5762f5 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding.rs @@ -0,0 +1,13 @@ +// 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; + +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..f8840c8f85a33 --- /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:11: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..3cb06b4bad873 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-redefine.rs @@ -0,0 +1,14 @@ +// 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; + +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..4f1419de42677 --- /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:10: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..efc73a21f16f3 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-variants.rs @@ -0,0 +1,18 @@ +// 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 + +extern crate variants; + +use variants::*; + +fn main() { + check_variants(); + + test_variants!(); + test_variants2!(); + + assert_eq!(MyEnum::Variant as u8, 1); +} diff --git a/src/test/ui/hygiene/cross_crate_hygiene.rs b/src/test/ui/hygiene/cross_crate_hygiene.rs deleted file mode 100644 index 75742960b7e3c..0000000000000 --- a/src/test/ui/hygiene/cross_crate_hygiene.rs +++ /dev/null @@ -1,8 +0,0 @@ -// check-pass -// aux-build:needs_hygiene.rs - -extern crate needs_hygiene; - -use needs_hygiene::*; - -fn main() {} 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)