diff --git a/compiler/rustc_passes/src/eii.rs b/compiler/rustc_passes/src/eii.rs index 691576e6a05fc..ab3f9f0d21825 100644 --- a/compiler/rustc_passes/src/eii.rs +++ b/compiler/rustc_passes/src/eii.rs @@ -116,7 +116,8 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, (): } if default_impls.len() > 1 { - panic!("multiple not supported right now"); + let decl_span = tcx.def_ident_span(decl_did).unwrap(); + tcx.dcx().span_delayed_bug(decl_span, "multiple not supported right now"); } let (local_impl, is_default) = diff --git a/library/core/src/bstr/mod.rs b/library/core/src/bstr/mod.rs index e13dc5cd44d5c..34e1ea66c99ad 100644 --- a/library/core/src/bstr/mod.rs +++ b/library/core/src/bstr/mod.rs @@ -68,6 +68,30 @@ impl ByteStr { ByteStr::from_bytes(bytes.as_ref()) } + /// Returns the same string as `&ByteStr`. + /// + /// This method is redundant when used directly on `&ByteStr`, but + /// it helps dereferencing other "container" types, + /// for example `Box` or `Arc`. + #[inline] + // #[unstable(feature = "str_as_str", issue = "130366")] + #[unstable(feature = "bstr", issue = "134915")] + pub const fn as_byte_str(&self) -> &ByteStr { + self + } + + /// Returns the same string as `&mut ByteStr`. + /// + /// This method is redundant when used directly on `&mut ByteStr`, but + /// it helps dereferencing other "container" types, + /// for example `Box` or `MutexGuard`. + #[inline] + // #[unstable(feature = "str_as_str", issue = "130366")] + #[unstable(feature = "bstr", issue = "134915")] + pub const fn as_mut_byte_str(&mut self) -> &mut ByteStr { + self + } + #[doc(hidden)] #[unstable(feature = "bstr_internals", issue = "none")] #[inline] diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 9a35ed07b89ac..621277179bb38 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -648,6 +648,17 @@ impl CStr { pub fn display(&self) -> impl fmt::Display { crate::bstr::ByteStr::from_bytes(self.to_bytes()) } + + /// Returns the same string as a string slice `&CStr`. + /// + /// This method is redundant when used directly on `&CStr`, but + /// it helps dereferencing other string-like types to string slices, + /// for example references to `Box` or `Arc`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_c_str(&self) -> &CStr { + self + } } #[stable(feature = "c_string_eq_c_str", since = "1.90.0")] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index dc34d2a21ee96..256252f73e0be 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4908,6 +4908,28 @@ impl [T] { if start <= self.len() && end <= self.len() { Some(start..end) } else { None } } + + /// Returns the same slice `&[T]`. + /// + /// This method is redundant when used directly on `&[T]`, but + /// it helps dereferencing other "container" types to slices, + /// for example `Box<[T]>` or `Arc<[T]>`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_slice(&self) -> &[T] { + self + } + + /// Returns the same slice `&mut [T]`. + /// + /// This method is redundant when used directly on `&mut [T]`, but + /// it helps dereferencing other "container" types to slices, + /// for example `Box<[T]>` or `MutexGuard<[T]>`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_mut_slice(&mut self) -> &mut [T] { + self + } } impl [MaybeUninit] { diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index d390c82021c7c..4e4d377ae2708 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1278,6 +1278,17 @@ impl OsStr { pub fn display(&self) -> Display<'_> { Display { os_str: self } } + + /// Returns the same string as a string slice `&OsStr`. + /// + /// This method is redundant when used directly on `&OsStr`, but + /// it helps dereferencing other string-like types to string slices, + /// for example references to `Box` or `Arc`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_os_str(&self) -> &OsStr { + self + } } #[stable(feature = "box_from_os_str", since = "1.17.0")] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 2a57a1ed59600..e8eda3c5f76bb 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3206,6 +3206,17 @@ impl Path { Display { inner: self.inner.display() } } + /// Returns the same path as `&Path`. + /// + /// This method is redundant when used directly on `&Path`, but + /// it helps dereferencing other `PathBuf`-like types to `Path`s, + /// for example references to `Box` or `Arc`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub const fn as_path(&self) -> &Path { + self + } + /// Queries the file system to get information about a file, directory, etc. /// /// This function will traverse symbolic links to query information about the diff --git a/library/std_detect/src/detect/os/darwin/aarch64.rs b/library/std_detect/src/detect/os/darwin/aarch64.rs index 8c9fd9647b8a2..a23d65a23d811 100644 --- a/library/std_detect/src/detect/os/darwin/aarch64.rs +++ b/library/std_detect/src/detect/os/darwin/aarch64.rs @@ -76,6 +76,8 @@ pub(crate) fn detect_features() -> cache::Initializer { let sme = _sysctlbyname(c"hw.optional.arm.FEAT_SME"); let sme2 = _sysctlbyname(c"hw.optional.arm.FEAT_SME2"); let sme2p1 = _sysctlbyname(c"hw.optional.arm.FEAT_SME2p1"); + let sme_b16b16 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_B16B16"); + let sme_f16f16 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_F16F16"); let sme_f64f64 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_F64F64"); let sme_i16i64 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_I16I64"); let ssbs = _sysctlbyname(c"hw.optional.arm.FEAT_SSBS"); @@ -153,6 +155,8 @@ pub(crate) fn detect_features() -> cache::Initializer { enable_feature(Feature::sme, sme); enable_feature(Feature::sme2, sme2); enable_feature(Feature::sme2p1, sme2p1); + enable_feature(Feature::sme_b16b16, sme_b16b16); + enable_feature(Feature::sme_f16f16, sme_f16f16); enable_feature(Feature::sme_f64f64, sme_f64f64); enable_feature(Feature::sme_i16i64, sme_i16i64); enable_feature(Feature::ssbs, ssbs); diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs index 3287e018b4044..d1b51068fce5a 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -7,7 +7,7 @@ //@ [strong] compile-flags: -Z stack-protector=strong //@ [basic] compile-flags: -Z stack-protector=basic //@ [none] compile-flags: -Z stack-protector=none -//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled +//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort -Cdebuginfo=1 #![crate_type = "lib"] #![allow(internal_features)] @@ -39,6 +39,8 @@ pub fn array_char(f: fn(*const char)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: array_u8_1 @@ -55,6 +57,8 @@ pub fn array_u8_1(f: fn(*const u8)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: array_u8_small: @@ -72,6 +76,8 @@ pub fn array_u8_small(f: fn(*const u8)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: array_u8_large: @@ -88,6 +94,8 @@ pub fn array_u8_large(f: fn(*const u8)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } #[derive(Copy, Clone)] @@ -107,6 +115,8 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: local_var_addr_used_indirectly @@ -134,6 +144,8 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: local_string_addr_taken @@ -143,28 +155,15 @@ pub fn local_string_addr_taken(f: fn(&String)) { f(&x); // Taking the address of the local variable `x` leads to stack smash - // protection with the `strong` heuristic, but not with the `basic` - // heuristic. It does not matter that the reference is not mut. - // - // An interesting note is that a similar function in C++ *would* be - // protected by the `basic` heuristic, because `std::string` has a char - // array internally as a small object optimization: - // ``` - // cat < - // void f(void (*g)(const std::string&)) { - // std::string x; - // g(x); - // } - // EOF - // ``` - // + // protection. It does not matter that the reference is not mut. // all: __security_check_cookie - // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } pub trait SelfByRef { @@ -194,6 +193,8 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } pub struct Gigastruct { @@ -231,6 +232,8 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: local_large_var_cloned @@ -260,6 +263,8 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } extern "C" { @@ -300,6 +305,8 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: alloca_large_compile_time_constant_arg @@ -312,6 +319,8 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // CHECK-LABEL: alloca_dynamic_arg @@ -324,14 +333,14 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } // The question then is: in what ways can Rust code generate array-`alloca` // LLVM instructions? This appears to only be generated by // rustc_codegen_ssa::traits::Builder::array_alloca() through -// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT -// this is support for the "unsized locals" unstable feature: -// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. +// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). // CHECK-LABEL: unsized_fn_param #[no_mangle] @@ -346,14 +355,11 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // alloca, and is therefore not protected by the `strong` or `basic` // heuristics. - // We should have a __security_check_cookie call in `all` and `strong` modes but - // LLVM does not support generating stack protectors in functions with funclet - // based EH personalities. - // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 // all-NOT: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .cv_fpo_endproc } diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs index 9a3dabc74dded..56a6f08da5877 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -7,7 +7,7 @@ //@ [strong] compile-flags: -Z stack-protector=strong //@ [basic] compile-flags: -Z stack-protector=basic //@ [none] compile-flags: -Z stack-protector=none -//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled +//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort #![crate_type = "lib"] #![feature(unsized_fn_params)] @@ -25,6 +25,7 @@ pub fn emptyfn() { // CHECK-LABEL: array_char #[no_mangle] pub fn array_char(f: fn(*const char)) { + // CHECK-DAG: .seh_endprologue let a = ['c'; 1]; let b = ['d'; 3]; let c = ['e'; 15]; @@ -38,11 +39,14 @@ pub fn array_char(f: fn(*const char)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: array_u8_1 #[no_mangle] pub fn array_u8_1(f: fn(*const u8)) { + // CHECK-DAG: .seh_endprologue let a = [0u8; 1]; f(&a as *const _); @@ -54,11 +58,14 @@ pub fn array_u8_1(f: fn(*const u8)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: array_u8_small: #[no_mangle] pub fn array_u8_small(f: fn(*const u8)) { + // CHECK-DAG: .seh_endprologue let a = [0u8; 2]; let b = [0u8; 7]; f(&a as *const _); @@ -71,11 +78,14 @@ pub fn array_u8_small(f: fn(*const u8)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: array_u8_large: #[no_mangle] pub fn array_u8_large(f: fn(*const u8)) { + // CHECK-DAG: .seh_endprologue let a = [0u8; 9]; f(&a as *const _); @@ -87,6 +97,8 @@ pub fn array_u8_large(f: fn(*const u8)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } #[derive(Copy, Clone)] @@ -95,6 +107,7 @@ pub struct ByteSizedNewtype(u8); // CHECK-LABEL: array_bytesizednewtype_9: #[no_mangle] pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { + // CHECK-DAG: .seh_endprologue let a = [ByteSizedNewtype(0); 9]; f(&a as *const _); @@ -106,11 +119,14 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: local_var_addr_used_indirectly #[no_mangle] pub fn local_var_addr_used_indirectly(f: fn(bool)) { + // CHECK-DAG: .seh_endprologue let a = 5; let a_addr = &a as *const _ as usize; f(a_addr & 0x10 == 0); @@ -133,6 +149,8 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: local_string_addr_taken @@ -143,31 +161,11 @@ pub fn local_string_addr_taken(f: fn(&String)) { f(&x); // Taking the address of the local variable `x` leads to stack smash - // protection with the `strong` heuristic, but not with the `basic` - // heuristic. It does not matter that the reference is not mut. - // - // An interesting note is that a similar function in C++ *would* be - // protected by the `basic` heuristic, because `std::string` has a char - // array internally as a small object optimization: - // ``` - // cat < - // void f(void (*g)(const std::string&)) { - // std::string x; - // g(x); - // } - // EOF - // ``` - // - - // We should have a __security_check_cookie call in `all` and `strong` modes but - // LLVM does not support generating stack protectors in functions with funclet - // based EH personalities. - // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 - // all-NOT: __security_check_cookie - // strong-NOT: __security_check_cookie + // protection. It does not matter that the reference is not mut. - // basic-NOT: __security_check_cookie + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -187,6 +185,7 @@ impl SelfByRef for i32 { // CHECK-LABEL: local_var_addr_taken_used_locally_only #[no_mangle] pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) { + // CHECK-DAG: .seh_endprologue let x = factory(); let g = x.f(); sink(g); @@ -201,6 +200,8 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } pub struct Gigastruct { @@ -214,6 +215,7 @@ pub struct Gigastruct { // CHECK-LABEL: local_large_var_moved #[no_mangle] pub fn local_large_var_moved(f: fn(Gigastruct)) { + // CHECK-DAG: .seh_endprologue let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }; f(x); @@ -238,11 +240,14 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: local_large_var_cloned #[no_mangle] pub fn local_large_var_cloned(f: fn(Gigastruct)) { + // CHECK-DAG: .seh_endprologue f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }); // A new instance of `Gigastruct` is passed to `f()`, without any apparent @@ -267,6 +272,8 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } extern "C" { @@ -300,6 +307,7 @@ extern "C" { // CHECK-LABEL: alloca_small_compile_time_constant_arg #[no_mangle] pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { + // CHECK-DAG: .seh_endprologue f(unsafe { alloca(8) }); // all: __security_check_cookie @@ -307,11 +315,14 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: alloca_large_compile_time_constant_arg #[no_mangle] pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { + // CHECK-DAG: .seh_endprologue f(unsafe { alloca(9) }); // all: __security_check_cookie @@ -319,11 +330,14 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // CHECK-LABEL: alloca_dynamic_arg #[no_mangle] pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { + // CHECK-DAG: .seh_endprologue f(unsafe { alloca(n) }); // all: __security_check_cookie @@ -331,18 +345,19 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } // The question then is: in what ways can Rust code generate array-`alloca` // LLVM instructions? This appears to only be generated by // rustc_codegen_ssa::traits::Builder::array_alloca() through -// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT -// this is support for the "unsized locals" unstable feature: -// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. +// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). // CHECK-LABEL: unsized_fn_param #[no_mangle] pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { + // CHECK-DAG: .seh_endprologue let n = if l { 1 } else { 2 }; f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from @@ -353,14 +368,11 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // alloca, and is therefore not protected by the `strong` or `basic` // heuristics. - // We should have a __security_check_cookie call in `all` and `strong` modes but - // LLVM does not support generating stack protectors in functions with funclet - // based EH personalities. - // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 // all-NOT: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc } diff --git a/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs index 0218fe0a52f8a..9f182985d1573 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs @@ -173,7 +173,7 @@ //@ [r84] needs-llvm-components: x86 //@ [r85] compile-flags: --target x86_64-unknown-redox //@ [r85] needs-llvm-components: x86 -//@ compile-flags: -Z stack-protector=all +//@ compile-flags: -Z stack-protector=all -Cpanic=abort //@ compile-flags: -C opt-level=2 #![crate_type = "lib"] diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/Cargo.toml b/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/Cargo.toml new file mode 100644 index 0000000000000..870d333da3a4f --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "consumer" +version = "0.1.0" + +[dependencies] +mylib_v1 = { path = "../mylib_v1", package = "mylib" } +mylib_v2 = { path = "../mylib_v2", package = "mylib" } + +# Avoid interference with root workspace when casually testing +[workspace] diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/src/main.rs b/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/src/main.rs new file mode 100644 index 0000000000000..80e76ae281171 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/consumer/src/main.rs @@ -0,0 +1,7 @@ +fn main() { + let v1 = mylib_v1::my_macro!(); + assert_eq!(v1, "version 1"); + + let v2 = mylib_v2::my_macro!(); + assert_eq!(v2, "version 2"); +} diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/Cargo.toml b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/Cargo.toml new file mode 100644 index 0000000000000..69f80bfc89ed6 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "mylib" +version = "1.0.0" + +# Avoid interference with root workspace when casually testing +[workspace] diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/src/lib.rs b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/src/lib.rs new file mode 100644 index 0000000000000..0603b754ea82c --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v1/src/lib.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! my_macro { + () => { + "version 1" + }; +} diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/Cargo.toml b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/Cargo.toml new file mode 100644 index 0000000000000..f164616393ba1 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "mylib" +version = "2.0.0" + +# Avoid interference with root workspace when casually testing +[workspace] diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/src/lib.rs b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/src/lib.rs new file mode 100644 index 0000000000000..352c7c514f832 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/mylib_v2/src/lib.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! my_macro { + () => { + "version 2" + }; +} diff --git a/tests/run-make-cargo/same-crate-name-and-macro-name/rmake.rs b/tests/run-make-cargo/same-crate-name-and-macro-name/rmake.rs new file mode 100644 index 0000000000000..cce98cebb8044 --- /dev/null +++ b/tests/run-make-cargo/same-crate-name-and-macro-name/rmake.rs @@ -0,0 +1,13 @@ +//! Regression test for +//! +//! (that particular comment describes the issue well). +//! +//! We test that two library crates with the same name can export macros with +//! the same name without causing interference when both are used in another +//! crate. + +use run_make_support::cargo; + +fn main() { + cargo().current_dir("consumer").arg("run").run(); +} diff --git a/tests/ui/eii/default/multiple-default-impls-same-name.rs b/tests/ui/eii/default/multiple-default-impls-same-name.rs new file mode 100644 index 0000000000000..080e0a46b7557 --- /dev/null +++ b/tests/ui/eii/default/multiple-default-impls-same-name.rs @@ -0,0 +1,19 @@ +#![crate_type = "lib"] +#![feature(extern_item_impls)] +// `eii` expands to, among other things, `macro eii() {}`. +// If we have two eiis named the same thing, we have a duplicate definition +// for that macro. The compiler happily continues compiling on duplicate +// definitions though, to emit as many diagnostics as possible. +// However, in the case of eiis, this can break the assumption that every +// eii has only one default implementation, since the default for both eiis will +// name resolve to the same eii definiton (since the other definition was duplicate) +// This test tests for the previously-ICE that occurred when this assumption +// (of 1 default) was broken which was reported in #149982. + +#[eii(eii1)] +fn a() {} + +#[eii(eii1)] +//~^ ERROR the name `eii1` is defined multiple times +fn a() {} +//~^ ERROR the name `a` is defined multiple times diff --git a/tests/ui/eii/default/multiple-default-impls-same-name.stderr b/tests/ui/eii/default/multiple-default-impls-same-name.stderr new file mode 100644 index 0000000000000..20544fcfeeba5 --- /dev/null +++ b/tests/ui/eii/default/multiple-default-impls-same-name.stderr @@ -0,0 +1,25 @@ +error[E0428]: the name `a` is defined multiple times + --> $DIR/multiple-default-impls-same-name.rs:18:1 + | +LL | fn a() {} + | ------ previous definition of the value `a` here +... +LL | fn a() {} + | ^^^^^^ `a` redefined here + | + = note: `a` must be defined only once in the value namespace of this module + +error[E0428]: the name `eii1` is defined multiple times + --> $DIR/multiple-default-impls-same-name.rs:16:1 + | +LL | #[eii(eii1)] + | ------------ previous definition of the macro `eii1` here +... +LL | #[eii(eii1)] + | ^^^^^^^^^^^^ `eii1` redefined here + | + = note: `eii1` must be defined only once in the macro namespace of this module + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/eii/default/multiple-default-impls.rs b/tests/ui/eii/default/multiple-default-impls.rs new file mode 100644 index 0000000000000..8d2ad0c1e1378 --- /dev/null +++ b/tests/ui/eii/default/multiple-default-impls.rs @@ -0,0 +1,18 @@ +#![crate_type = "lib"] +#![feature(extern_item_impls)] +// `eii` expands to, among other things, `macro eii() {}`. +// If we have two eiis named the same thing, we have a duplicate definition +// for that macro. The compiler happily continues compiling on duplicate +// definitions though, to emit as many diagnostics as possible. +// However, in the case of eiis, this can break the assumption that every +// eii has only one default implementation, since the default for both eiis will +// name resolve to the same eii definiton (since the other definition was duplicate) +// This test tests for the previously-ICE that occurred when this assumption +// (of 1 default) was broken which was reported in #149982. + +#[eii(eii1)] +fn a() {} + +#[eii(eii1)] +//~^ ERROR the name `eii1` is defined multiple times +fn b() {} diff --git a/tests/ui/eii/default/multiple-default-impls.stderr b/tests/ui/eii/default/multiple-default-impls.stderr new file mode 100644 index 0000000000000..b270b2346cd50 --- /dev/null +++ b/tests/ui/eii/default/multiple-default-impls.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `eii1` is defined multiple times + --> $DIR/multiple-default-impls.rs:16:1 + | +LL | #[eii(eii1)] + | ------------ previous definition of the macro `eii1` here +... +LL | #[eii(eii1)] + | ^^^^^^^^^^^^ `eii1` redefined here + | + = note: `eii1` must be defined only once in the macro namespace of this module + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0428`.