mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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`
This commit is contained in:
commit
1a1f525bb0
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -346,7 +346,7 @@ enum EntryKind {
|
||||
Union(Lazy<VariantData>, ReprOptions),
|
||||
Fn(Lazy<FnData>),
|
||||
ForeignFn(Lazy<FnData>),
|
||||
Mod(Lazy<ModData>),
|
||||
Mod(Lazy<[Export]>),
|
||||
MacroDef(Lazy<MacroDef>),
|
||||
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,
|
||||
|
@ -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),
|
||||
|
@ -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) {
|
||||
|
@ -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`
|
||||
|
73
src/test/ui/hygiene/auxiliary/fields.rs
Normal file
73
src/test/ui/hygiene/auxiliary/fields.rs
Normal file
@ -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);
|
||||
}
|
160
src/test/ui/hygiene/auxiliary/methods.rs
Normal file
160
src/test/ui/hygiene/auxiliary/methods.rs
Normal file
@ -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: MyTrait, U: MyTrait>(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);
|
||||
}
|
7
src/test/ui/hygiene/auxiliary/pub_hygiene.rs
Normal file
7
src/test/ui/hygiene/auxiliary/pub_hygiene.rs
Normal file
@ -0,0 +1,7 @@
|
||||
#![feature(decl_macro)]
|
||||
|
||||
macro x() {
|
||||
pub struct MyStruct;
|
||||
}
|
||||
|
||||
x!();
|
15
src/test/ui/hygiene/auxiliary/use_by_macro.rs
Normal file
15
src/test/ui/hygiene/auxiliary/use_by_macro.rs
Normal file
@ -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);
|
36
src/test/ui/hygiene/auxiliary/variants.rs
Normal file
36
src/test/ui/hygiene/auxiliary/variants.rs
Normal file
@ -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!();
|
||||
}
|
19
src/test/ui/hygiene/cross-crate-define-and-use.rs
Normal file
19
src/test/ui/hygiene/cross-crate-define-and-use.rs
Normal file
@ -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);
|
||||
}
|
24
src/test/ui/hygiene/cross-crate-fields.rs
Normal file
24
src/test/ui/hygiene/cross-crate-fields.rs
Normal file
@ -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);
|
||||
}
|
23
src/test/ui/hygiene/cross-crate-glob-hygiene.rs
Normal file
23
src/test/ui/hygiene/cross-crate-glob-hygiene.rs
Normal file
@ -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
|
||||
}
|
11
src/test/ui/hygiene/cross-crate-glob-hygiene.stderr
Normal file
11
src/test/ui/hygiene/cross-crate-glob-hygiene.stderr
Normal file
@ -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`.
|
33
src/test/ui/hygiene/cross-crate-methods.rs
Normal file
33
src/test/ui/hygiene/cross-crate-methods.rs
Normal file
@ -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);
|
||||
}
|
12
src/test/ui/hygiene/cross-crate-name-collision.rs
Normal file
12
src/test/ui/hygiene/cross-crate-name-collision.rs
Normal file
@ -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() {}
|
15
src/test/ui/hygiene/cross-crate-name-hiding-2.rs
Normal file
15
src/test/ui/hygiene/cross-crate-name-hiding-2.rs
Normal file
@ -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
|
||||
}
|
9
src/test/ui/hygiene/cross-crate-name-hiding-2.stderr
Normal file
9
src/test/ui/hygiene/cross-crate-name-hiding-2.stderr
Normal file
@ -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`.
|
13
src/test/ui/hygiene/cross-crate-name-hiding.rs
Normal file
13
src/test/ui/hygiene/cross-crate-name-hiding.rs
Normal file
@ -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
|
||||
}
|
9
src/test/ui/hygiene/cross-crate-name-hiding.stderr
Normal file
9
src/test/ui/hygiene/cross-crate-name-hiding.stderr
Normal file
@ -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`.
|
14
src/test/ui/hygiene/cross-crate-redefine.rs
Normal file
14
src/test/ui/hygiene/cross-crate-redefine.rs
Normal file
@ -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() {}
|
15
src/test/ui/hygiene/cross-crate-redefine.stderr
Normal file
15
src/test/ui/hygiene/cross-crate-redefine.stderr
Normal file
@ -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`.
|
18
src/test/ui/hygiene/cross-crate-variants.rs
Normal file
18
src/test/ui/hygiene/cross-crate-variants.rs
Normal file
@ -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);
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
// check-pass
|
||||
// aux-build:needs_hygiene.rs
|
||||
|
||||
extern crate needs_hygiene;
|
||||
|
||||
use needs_hygiene::*;
|
||||
|
||||
fn main() {}
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user