Add more tests for cross-crate hygiene

This commit is contained in:
Matthew Jasper 2021-10-23 12:06:58 +01:00
parent 1536d7220b
commit fabede1851
18 changed files with 465 additions and 0 deletions

View 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);
}

View 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);
}

View file

@ -0,0 +1,7 @@
#![feature(decl_macro)]
macro x() {
pub struct MyStruct;
}
x!();

View 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);

View 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!();
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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`.

View file

@ -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);
}

View file

@ -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
}

View 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: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`.

View file

@ -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
}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -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);
}