From 316c9a9f719f1ca7458c6d42655d524376abcfc7 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 19 Sep 2023 14:51:58 -0400 Subject: [PATCH 01/94] Add stack-protector test for Windows --- ...otector-heuristics-effect-windows-32bit.rs | 406 +++++++++++++++++ ...otector-heuristics-effect-windows-64bit.rs | 414 ++++++++++++++++++ .../stack-protector-heuristics-effect.rs | 2 +- 3 files changed, 821 insertions(+), 1 deletion(-) create mode 100644 tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs create mode 100644 tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs new file mode 100644 index 000000000000..fca2c85d5a62 --- /dev/null +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -0,0 +1,406 @@ +// revisions: all strong basic none missing +// assembly-output: emit-asm +// only-windows +// only-msvc +// ignore-64bit 64-bit table based SEH has slightly different behaviors than classic SEH +// [all] compile-flags: -Z stack-protector=all +// [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 + +#![crate_type = "lib"] + +#![allow(incomplete_features)] + +#![feature(unsized_locals, unsized_fn_params)] + + +// CHECK-LABEL: emptyfn: +#[no_mangle] +pub fn emptyfn() { + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_char +#[no_mangle] +pub fn array_char(f: fn(*const char)) { + let a = ['c'; 1]; + let b = ['d'; 3]; + let c = ['e'; 15]; + + f(&a as *const _); + f(&b as *const _); + f(&c as *const _); + + // Any type of local array variable leads to stack protection with the + // "strong" heuristic. The 'basic' heuristic only adds stack protection to + // functions with local array variables of a byte-sized type, however. Since + // 'char' is 4 bytes in Rust, this function is not protected by the 'basic' + // heuristic + // + // (This test *also* takes the address of the local stack variables. We + // cannot know that this isn't what triggers the `strong` heuristic. + // However, the test strategy of passing the address of a stack array to an + // external function is sufficient to trigger the `basic` heuristic (see + // test `array_u8_large()`). Since the `basic` heuristic only checks for the + // presence of stack-local array variables, we can be confident that this + // test also captures this part of the `strong` heuristic specification.) + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_1 +#[no_mangle] +pub fn array_u8_1(f: fn(*const u8)) { + let a = [0u8; 1]; + f(&a as *const _); + + // The 'strong' heuristic adds stack protection to functions with local + // array variables regardless of their size. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_small: +#[no_mangle] +pub fn array_u8_small(f: fn(*const u8)) { + let a = [0u8; 2]; + let b = [0u8; 7]; + f(&a as *const _); + f(&b as *const _); + + // Small arrays do not lead to stack protection by the 'basic' heuristic. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_large: +#[no_mangle] +pub fn array_u8_large(f: fn(*const u8)) { + let a = [0u8; 9]; + f(&a as *const _); + + // Since `a` is a byte array with size greater than 8, the basic heuristic + // will also protect this function. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +#[derive(Copy, Clone)] +pub struct ByteSizedNewtype(u8); + +// CHECK-LABEL: array_bytesizednewtype_9: +#[no_mangle] +pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { + let a = [ByteSizedNewtype(0); 9]; + f(&a as *const _); + + // Since `a` is a byte array in the LLVM output, the basic heuristic will + // also protect this function. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: local_var_addr_used_indirectly +#[no_mangle] +pub fn local_var_addr_used_indirectly(f: fn(bool)) { + let a = 5; + let a_addr = &a as *const _ as usize; + f(a_addr & 0x10 == 0); + + // This function takes the address of a local variable taken. Although this + // address is never used as a way to refer to stack memory, the `strong` + // heuristic adds stack smash protection. This is also the case in C++: + // ``` + // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk + // #include + // void f(void (*g)(bool)) { + // int32_t x; + // g((reinterpret_cast(&x) & 0x10U) == 0); + // } + // EOF + // ``` + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +// CHECK-LABEL: local_string_addr_taken +#[no_mangle] +pub fn local_string_addr_taken(f: fn(&String)) { + let x = String::new(); + 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 + // ``` + // + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +pub trait SelfByRef { + fn f(&self) -> i32; +} + +impl SelfByRef for i32 { + fn f(&self) -> i32 { + return self + 1; + } +} + +// 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)) { + let x = factory(); + let g = x.f(); + sink(g); + + // Even though the local variable conceptually has its address taken, as + // it's passed by reference to the trait function, the use of the reference + // is easily inlined. There is therefore no stack smash protection even with + // the `strong` heuristic. + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +pub struct Gigastruct { + does: u64, + not: u64, + have: u64, + array: u64, + members: u64 +} + +// CHECK-LABEL: local_large_var_moved +#[no_mangle] +pub fn local_large_var_moved(f: fn(Gigastruct)) { + let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }; + f(x); + + // Even though the local variable conceptually doesn't have its address + // taken, it's so large that the "move" is implemented with a reference to a + // stack-local variable in the ABI. Consequently, this function *is* + // protected by the `strong` heuristic. This is also the case for + // rvalue-references in C++, regardless of struct size: + // ``` + // cat < + // #include + // void f(void (*g)(uint64_t&&)) { + // uint64_t x; + // g(std::move(x)); + // } + // EOF + // ``` + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: local_large_var_cloned +#[no_mangle] +pub fn local_large_var_cloned(f: fn(Gigastruct)) { + f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }); + + // A new instance of `Gigastruct` is passed to `f()`, without any apparent + // connection to this stack frame. Still, since instances of `Gigastruct` + // are sufficiently large, it is allocated in the caller stack frame and + // passed as a pointer. As such, this function is *also* protected by the + // `strong` heuristic, just like `local_large_var_moved`. This is also the + // case for pass-by-value of sufficiently large structs in C++: + // ``` + // cat < + // #include + // struct Gigastruct { uint64_t a, b, c, d, e; }; + // void f(void (*g)(Gigastruct)) { + // g(Gigastruct{}); + // } + // EOF + // ``` + + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +extern "C" { + // A call to an external `alloca` function is *not* recognized as an + // `alloca(3)` operation. This function is a compiler built-in, as the + // man page explains. Clang translates it to an LLVM `alloca` + // instruction with a count argument, which is also what the LLVM stack + // protector heuristics looks for. The man page for `alloca(3)` details + // a way to avoid using the compiler built-in: pass a -std=c11 + // argument, *and* don't include . Though this leads to an + // external alloca() function being called, it doesn't lead to stack + // protection being included. It even fails with a linker error + // "undefined reference to `alloca'". Example: + // ``` + // cat< + // void * alloca(size_t); + // void f(void (*g)(void*)) { + // void * p = alloca(10); + // g(p); + // } + // int main() { return 0; } + // EOF + // ``` + // The following tests demonstrate that calls to an external `alloca` + // function in Rust also doesn't trigger stack protection. + + fn alloca(size: usize) -> *mut (); +} + +// CHECK-LABEL: alloca_small_compile_time_constant_arg +#[no_mangle] +pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(8) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: alloca_large_compile_time_constant_arg +#[no_mangle] +pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(9) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +// CHECK-LABEL: alloca_dynamic_arg +#[no_mangle] +pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { + f(unsafe { alloca(n) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// 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. + + +// CHECK-LABEL: unsized_fn_param +#[no_mangle] +pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { + let n = if l { 1 } else { 2 }; + f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from + + // Even though slices are conceptually passed by-value both into this + // function and into `f()`, this is implemented with pass-by-reference + // using a suitably constructed fat-pointer (as if the functions + // accepted &[u8]). This function therefore doesn't need dynamic array + // 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-LABEL: unsized_local +#[no_mangle] +pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) { + let n = if l { 1 } else { 2 }; + let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from + f(&mut a); + + // This function allocates a slice as a local variable in its stack + // frame. Since the size is not a compile-time constant, an array + // alloca is required, and the function is protected by both the + // `strong` and `basic` heuristic. + + // We should have a __security_check_cookie call in `all`, `strong` and `basic` 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 +} diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs new file mode 100644 index 000000000000..d9abf554a92d --- /dev/null +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -0,0 +1,414 @@ +// revisions: all strong basic none missing +// assembly-output: emit-asm +// only-windows +// only-msvc +// ignore-32bit 64-bit table based SEH has slightly different behaviors than classic SEH +// [all] compile-flags: -Z stack-protector=all +// [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 + +#![crate_type = "lib"] + +#![allow(incomplete_features)] + +#![feature(unsized_locals, unsized_fn_params)] + + +// CHECK-LABEL: emptyfn: +#[no_mangle] +pub fn emptyfn() { + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_char +#[no_mangle] +pub fn array_char(f: fn(*const char)) { + let a = ['c'; 1]; + let b = ['d'; 3]; + let c = ['e'; 15]; + + f(&a as *const _); + f(&b as *const _); + f(&c as *const _); + + // Any type of local array variable leads to stack protection with the + // "strong" heuristic. The 'basic' heuristic only adds stack protection to + // functions with local array variables of a byte-sized type, however. Since + // 'char' is 4 bytes in Rust, this function is not protected by the 'basic' + // heuristic + // + // (This test *also* takes the address of the local stack variables. We + // cannot know that this isn't what triggers the `strong` heuristic. + // However, the test strategy of passing the address of a stack array to an + // external function is sufficient to trigger the `basic` heuristic (see + // test `array_u8_large()`). Since the `basic` heuristic only checks for the + // presence of stack-local array variables, we can be confident that this + // test also captures this part of the `strong` heuristic specification.) + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_1 +#[no_mangle] +pub fn array_u8_1(f: fn(*const u8)) { + let a = [0u8; 1]; + f(&a as *const _); + + // The 'strong' heuristic adds stack protection to functions with local + // array variables regardless of their size. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_small: +#[no_mangle] +pub fn array_u8_small(f: fn(*const u8)) { + let a = [0u8; 2]; + let b = [0u8; 7]; + f(&a as *const _); + f(&b as *const _); + + // Small arrays do not lead to stack protection by the 'basic' heuristic. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_large: +#[no_mangle] +pub fn array_u8_large(f: fn(*const u8)) { + let a = [0u8; 9]; + f(&a as *const _); + + // Since `a` is a byte array with size greater than 8, the basic heuristic + // will also protect this function. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +#[derive(Copy, Clone)] +pub struct ByteSizedNewtype(u8); + +// CHECK-LABEL: array_bytesizednewtype_9: +#[no_mangle] +pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { + let a = [ByteSizedNewtype(0); 9]; + f(&a as *const _); + + // Since `a` is a byte array in the LLVM output, the basic heuristic will + // also protect this function. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: local_var_addr_used_indirectly +#[no_mangle] +pub fn local_var_addr_used_indirectly(f: fn(bool)) { + let a = 5; + let a_addr = &a as *const _ as usize; + f(a_addr & 0x10 == 0); + + // This function takes the address of a local variable taken. Although this + // address is never used as a way to refer to stack memory, the `strong` + // heuristic adds stack smash protection. This is also the case in C++: + // ``` + // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk + // #include + // void f(void (*g)(bool)) { + // int32_t x; + // g((reinterpret_cast(&x) & 0x10U) == 0); + // } + // EOF + // ``` + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +// CHECK-LABEL: local_string_addr_taken +#[no_mangle] +pub fn local_string_addr_taken(f: fn(&String)) { + // CHECK-DAG: .seh_endprologue + let x = String::new(); + 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 + + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc +} + +pub trait SelfByRef { + fn f(&self) -> i32; +} + +impl SelfByRef for i32 { + fn f(&self) -> i32 { + return self + 1; + } +} + +// 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)) { + let x = factory(); + let g = x.f(); + sink(g); + + // Even though the local variable conceptually has its address taken, as + // it's passed by reference to the trait function, the use of the reference + // is easily inlined. There is therefore no stack smash protection even with + // the `strong` heuristic. + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +pub struct Gigastruct { + does: u64, + not: u64, + have: u64, + array: u64, + members: u64 +} + +// CHECK-LABEL: local_large_var_moved +#[no_mangle] +pub fn local_large_var_moved(f: fn(Gigastruct)) { + let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }; + f(x); + + // Even though the local variable conceptually doesn't have its address + // taken, it's so large that the "move" is implemented with a reference to a + // stack-local variable in the ABI. Consequently, this function *is* + // protected by the `strong` heuristic. This is also the case for + // rvalue-references in C++, regardless of struct size: + // ``` + // cat < + // #include + // void f(void (*g)(uint64_t&&)) { + // uint64_t x; + // g(std::move(x)); + // } + // EOF + // ``` + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: local_large_var_cloned +#[no_mangle] +pub fn local_large_var_cloned(f: fn(Gigastruct)) { + f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }); + + // A new instance of `Gigastruct` is passed to `f()`, without any apparent + // connection to this stack frame. Still, since instances of `Gigastruct` + // are sufficiently large, it is allocated in the caller stack frame and + // passed as a pointer. As such, this function is *also* protected by the + // `strong` heuristic, just like `local_large_var_moved`. This is also the + // case for pass-by-value of sufficiently large structs in C++: + // ``` + // cat < + // #include + // struct Gigastruct { uint64_t a, b, c, d, e; }; + // void f(void (*g)(Gigastruct)) { + // g(Gigastruct{}); + // } + // EOF + // ``` + + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +extern "C" { + // A call to an external `alloca` function is *not* recognized as an + // `alloca(3)` operation. This function is a compiler built-in, as the + // man page explains. Clang translates it to an LLVM `alloca` + // instruction with a count argument, which is also what the LLVM stack + // protector heuristics looks for. The man page for `alloca(3)` details + // a way to avoid using the compiler built-in: pass a -std=c11 + // argument, *and* don't include . Though this leads to an + // external alloca() function being called, it doesn't lead to stack + // protection being included. It even fails with a linker error + // "undefined reference to `alloca'". Example: + // ``` + // cat< + // void * alloca(size_t); + // void f(void (*g)(void*)) { + // void * p = alloca(10); + // g(p); + // } + // int main() { return 0; } + // EOF + // ``` + // The following tests demonstrate that calls to an external `alloca` + // function in Rust also doesn't trigger stack protection. + + fn alloca(size: usize) -> *mut (); +} + +// CHECK-LABEL: alloca_small_compile_time_constant_arg +#[no_mangle] +pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(8) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: alloca_large_compile_time_constant_arg +#[no_mangle] +pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(9) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +// CHECK-LABEL: alloca_dynamic_arg +#[no_mangle] +pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { + f(unsafe { alloca(n) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// 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. + + +// CHECK-LABEL: unsized_fn_param +#[no_mangle] +pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { + let n = if l { 1 } else { 2 }; + f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from + + // Even though slices are conceptually passed by-value both into this + // function and into `f()`, this is implemented with pass-by-reference + // using a suitably constructed fat-pointer (as if the functions + // accepted &[u8]). This function therefore doesn't need dynamic array + // 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-LABEL: unsized_local +#[no_mangle] +pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) { + let n = if l { 1 } else { 2 }; + let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from + f(&mut a); + + // This function allocates a slice as a local variable in its stack + // frame. Since the size is not a compile-time constant, an array + // alloca is required, and the function is protected by both the + // `strong` and `basic` heuristic. + + // We should have a __security_check_cookie call in `all`, `strong` and `basic` 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 +} diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs index a7c9e4845c70..d0ec7f80f9bf 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -1,7 +1,7 @@ // revisions: all strong basic none missing // assembly-output: emit-asm // ignore-macos slightly different policy on stack protection of arrays -// ignore-windows stack check code uses different function names +// ignore-msvc stack check code uses different function names // ignore-nvptx64 stack protector is not supported // ignore-wasm32-bare // [all] compile-flags: -Z stack-protector=all From fd23276ca87b4b56918e4a87737859cfd77d657c Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 3 Oct 2023 23:13:55 +0200 Subject: [PATCH 02/94] std: panic when the global allocator tries to register a TLS destructor --- library/std/src/sys/hermit/thread_local_dtor.rs | 11 +++++------ library/std/src/sys/solid/thread_local_dtor.rs | 12 +++++------- library/std/src/sys/unix/thread_local_dtor.rs | 12 +++++------- library/std/src/sys/windows/thread_local_key.rs | 9 +++++---- library/std/src/sys_common/thread_local_dtor.rs | 14 +++++++++----- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/library/std/src/sys/hermit/thread_local_dtor.rs b/library/std/src/sys/hermit/thread_local_dtor.rs index 613266b9530a..89db78adffc6 100644 --- a/library/std/src/sys/hermit/thread_local_dtor.rs +++ b/library/std/src/sys/hermit/thread_local_dtor.rs @@ -5,23 +5,22 @@ // The this solution works like the implementation of macOS and // doesn't additional OS support -use crate::mem; +use crate::cell::RefCell; #[thread_local] -static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); +static DTORS: RefCell> = RefCell::new(Vec::new()); pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - let list = &mut DTORS; - list.push((t, dtor)); + DTORS.try_borrow_mut().expect("global allocator may not use TLS").push((t, dtor)); } // every thread call this function to run through all possible destructors pub unsafe fn run_dtors() { - let mut list = mem::take(&mut DTORS); + let mut list = DTORS.take(); while !list.is_empty() { for (ptr, dtor) in list { dtor(ptr); } - list = mem::take(&mut DTORS); + list = DTORS.take(); } } diff --git a/library/std/src/sys/solid/thread_local_dtor.rs b/library/std/src/sys/solid/thread_local_dtor.rs index bad14bb37f72..d0fecede9551 100644 --- a/library/std/src/sys/solid/thread_local_dtor.rs +++ b/library/std/src/sys/solid/thread_local_dtor.rs @@ -4,14 +4,13 @@ // Simplify dtor registration by using a list of destructors. use super::{abi, itron::task}; -use crate::cell::Cell; -use crate::mem; +use crate::cell::{Cell, RefCell}; #[thread_local] static REGISTERED: Cell = Cell::new(false); #[thread_local] -static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); +static DTORS: RefCell> = RefCell::new(Vec::new()); pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { if !REGISTERED.get() { @@ -22,18 +21,17 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { REGISTERED.set(true); } - let list = unsafe { &mut DTORS }; - list.push((t, dtor)); + DTORS.try_borrow_mut().expect("global allocator may not use TLS").push((t, dtor)); } pub unsafe fn run_dtors() { - let mut list = mem::take(unsafe { &mut DTORS }); + let mut list = DTORS.take(); while !list.is_empty() { for (ptr, dtor) in list { unsafe { dtor(ptr) }; } - list = mem::take(unsafe { &mut DTORS }); + list = DTORS.take(); } } diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index fba2a676f280..38d275de4c8d 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -50,15 +50,14 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { // _tlv_atexit. #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - use crate::cell::Cell; - use crate::mem; + use crate::cell::{Cell, RefCell}; use crate::ptr; #[thread_local] static REGISTERED: Cell = Cell::new(false); #[thread_local] - static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); + static DTORS: RefCell> = RefCell::new(Vec::new()); if !REGISTERED.get() { _tlv_atexit(run_dtors, ptr::null_mut()); @@ -69,16 +68,15 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { fn _tlv_atexit(dtor: unsafe extern "C" fn(*mut u8), arg: *mut u8); } - let list = &mut DTORS; - list.push((t, dtor)); + DTORS.try_borrow_mut().expect("global allocator may not use TLS").push((t, dtor)); unsafe extern "C" fn run_dtors(_: *mut u8) { - let mut list = mem::take(&mut DTORS); + let mut list = DTORS.take(); while !list.is_empty() { for (ptr, dtor) in list { dtor(ptr); } - list = mem::take(&mut DTORS); + list = DTORS.take(); } } } diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs index 036d96596e9c..dd2c46fdfbc3 100644 --- a/library/std/src/sys/windows/thread_local_key.rs +++ b/library/std/src/sys/windows/thread_local_key.rs @@ -16,14 +16,15 @@ static HAS_DTORS: AtomicBool = AtomicBool::new(false); // Using a per-thread list avoids the problems in synchronizing global state. #[thread_local] #[cfg(target_thread_local)] -static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); +static DESTRUCTORS: crate::cell::RefCell> = + crate::cell::RefCell::new(Vec::new()); // Ensure this can never be inlined because otherwise this may break in dylibs. // See #44391. #[inline(never)] #[cfg(target_thread_local)] pub unsafe fn register_keyless_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - DESTRUCTORS.push((t, dtor)); + DESTRUCTORS.try_borrow_mut().expect("global allocator may not use TLS").push((t, dtor)); HAS_DTORS.store(true, Relaxed); } @@ -37,11 +38,11 @@ unsafe fn run_keyless_dtors() { // the case that this loop always terminates because we provide the // guarantee that a TLS key cannot be set after it is flagged for // destruction. - while let Some((ptr, dtor)) = DESTRUCTORS.pop() { + while let Some((ptr, dtor)) = DESTRUCTORS.borrow_mut().pop() { (dtor)(ptr); } // We're done so free the memory. - DESTRUCTORS = Vec::new(); + DESTRUCTORS.replace(Vec::new()); } type Key = c::DWORD; diff --git a/library/std/src/sys_common/thread_local_dtor.rs b/library/std/src/sys_common/thread_local_dtor.rs index 844946eda031..5d15140a9da8 100644 --- a/library/std/src/sys_common/thread_local_dtor.rs +++ b/library/std/src/sys_common/thread_local_dtor.rs @@ -13,6 +13,7 @@ #![unstable(feature = "thread_local_internals", issue = "none")] #![allow(dead_code)] +use crate::cell::RefCell; use crate::ptr; use crate::sys_common::thread_local_key::StaticKey; @@ -28,17 +29,20 @@ pub unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern "C" fn(*mut // flagged for destruction. static DTORS: StaticKey = StaticKey::new(Some(run_dtors)); - type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>; + // FIXME(joboet): integrate RefCell into pointer to avoid infinite recursion + // when the global allocator tries to register a destructor and just panic + // instead. + type List = RefCell>; if DTORS.get().is_null() { - let v: Box = Box::new(Vec::new()); + let v: Box = Box::new(RefCell::new(Vec::new())); DTORS.set(Box::into_raw(v) as *mut u8); } - let list: &mut List = &mut *(DTORS.get() as *mut List); - list.push((t, dtor)); + let list = &*(DTORS.get() as *const List); + list.try_borrow_mut().expect("global allocator may not use TLS").push((t, dtor)); unsafe extern "C" fn run_dtors(mut ptr: *mut u8) { while !ptr.is_null() { - let list: Box = Box::from_raw(ptr as *mut List); + let list = Box::from_raw(ptr as *mut List).into_inner(); for (ptr, dtor) in list.into_iter() { dtor(ptr); } From b18990b1e973a1fd0a0318a88655dc1907509b17 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 4 Oct 2023 11:49:48 +0200 Subject: [PATCH 03/94] std: abort instead of panicking if the global allocator uses TLS --- library/std/src/sys/hermit/thread_local_dtor.rs | 5 ++++- library/std/src/sys/solid/thread_local_dtor.rs | 5 ++++- library/std/src/sys/unix/thread_local_dtor.rs | 5 ++++- library/std/src/sys/windows/thread_local_key.rs | 6 +++++- library/std/src/sys_common/thread_local_dtor.rs | 5 ++++- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/hermit/thread_local_dtor.rs b/library/std/src/sys/hermit/thread_local_dtor.rs index 89db78adffc6..98adaf4bff1a 100644 --- a/library/std/src/sys/hermit/thread_local_dtor.rs +++ b/library/std/src/sys/hermit/thread_local_dtor.rs @@ -11,7 +11,10 @@ use crate::cell::RefCell; static DTORS: RefCell> = RefCell::new(Vec::new()); pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - DTORS.try_borrow_mut().expect("global allocator may not use TLS").push((t, dtor)); + match DTORS.try_borrow_mut() { + Ok(mut dtors) => dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } } // every thread call this function to run through all possible destructors diff --git a/library/std/src/sys/solid/thread_local_dtor.rs b/library/std/src/sys/solid/thread_local_dtor.rs index d0fecede9551..26918a4fcb01 100644 --- a/library/std/src/sys/solid/thread_local_dtor.rs +++ b/library/std/src/sys/solid/thread_local_dtor.rs @@ -21,7 +21,10 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { REGISTERED.set(true); } - DTORS.try_borrow_mut().expect("global allocator may not use TLS").push((t, dtor)); + match DTORS.try_borrow_mut() { + Ok(mut dtors) => dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } } pub unsafe fn run_dtors() { diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index 38d275de4c8d..58763e9fce26 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -68,7 +68,10 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { fn _tlv_atexit(dtor: unsafe extern "C" fn(*mut u8), arg: *mut u8); } - DTORS.try_borrow_mut().expect("global allocator may not use TLS").push((t, dtor)); + match DTORS.try_borrow_mut() { + Ok(mut dtors) => dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } unsafe extern "C" fn run_dtors(_: *mut u8) { let mut list = DTORS.take(); diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs index dd2c46fdfbc3..3c4e1abbba93 100644 --- a/library/std/src/sys/windows/thread_local_key.rs +++ b/library/std/src/sys/windows/thread_local_key.rs @@ -24,7 +24,11 @@ static DESTRUCTORS: crate::cell::RefCell dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } + HAS_DTORS.store(true, Relaxed); } diff --git a/library/std/src/sys_common/thread_local_dtor.rs b/library/std/src/sys_common/thread_local_dtor.rs index 5d15140a9da8..98382fc6acc2 100644 --- a/library/std/src/sys_common/thread_local_dtor.rs +++ b/library/std/src/sys_common/thread_local_dtor.rs @@ -38,7 +38,10 @@ pub unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern "C" fn(*mut DTORS.set(Box::into_raw(v) as *mut u8); } let list = &*(DTORS.get() as *const List); - list.try_borrow_mut().expect("global allocator may not use TLS").push((t, dtor)); + match list.try_borrow_mut() { + Ok(mut dtors) => dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } unsafe extern "C" fn run_dtors(mut ptr: *mut u8) { while !ptr.is_null() { From 65c66a15bf99efc75ea855733b94881953a6b9e8 Mon Sep 17 00:00:00 2001 From: joboet Date: Thu, 5 Oct 2023 10:58:39 +0200 Subject: [PATCH 04/94] std: fix registering of Windows TLS destructors --- library/std/src/sys/windows/thread_local_key.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs index 3c4e1abbba93..831f39817f4d 100644 --- a/library/std/src/sys/windows/thread_local_key.rs +++ b/library/std/src/sys/windows/thread_local_key.rs @@ -42,7 +42,10 @@ unsafe fn run_keyless_dtors() { // the case that this loop always terminates because we provide the // guarantee that a TLS key cannot be set after it is flagged for // destruction. - while let Some((ptr, dtor)) = DESTRUCTORS.borrow_mut().pop() { + loop { + let Some((ptr, dtor)) = DESTRUCTORS.borrow_mut().pop() else { + break; + }; (dtor)(ptr); } // We're done so free the memory. From 88efb1bdefc61289ab55e0483e6af36eebf8e8b8 Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 9 Oct 2023 15:08:49 +0200 Subject: [PATCH 05/94] std: explain unconventional choice of let-else binding over while-let loop --- library/std/src/sys/windows/thread_local_key.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs index 831f39817f4d..5eee4a9667ba 100644 --- a/library/std/src/sys/windows/thread_local_key.rs +++ b/library/std/src/sys/windows/thread_local_key.rs @@ -43,6 +43,9 @@ unsafe fn run_keyless_dtors() { // guarantee that a TLS key cannot be set after it is flagged for // destruction. loop { + // Use a let-else binding to ensure the `RefCell` guard is dropped + // immediately. Otherwise, a panic would occur if a TLS destructor + // tries to access the list. let Some((ptr, dtor)) = DESTRUCTORS.borrow_mut().pop() else { break; }; From e7a3c341dd517465a326ef693d49f6238789f96b Mon Sep 17 00:00:00 2001 From: niluxv Date: Sat, 5 Aug 2023 20:20:41 +0200 Subject: [PATCH 06/94] Use pointers instead of `usize` addresses for landing pads This bring unwind and personality code more in line with strict-provenance --- library/panic_unwind/src/gcc.rs | 2 +- library/std/src/sys/personality/dwarf/eh.rs | 66 ++++++++++++--------- library/std/src/sys/personality/gcc.rs | 9 ++- library/unwind/src/lib.rs | 1 + library/unwind/src/libunwind.rs | 14 ++--- 5 files changed, 50 insertions(+), 42 deletions(-) diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 08858dd92be0..54eb6627c012 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -63,7 +63,7 @@ pub unsafe fn panic(data: Box) -> u32 { _uwe: uw::_Unwind_Exception { exception_class: rust_exception_class(), exception_cleanup, - private: [0; uw::unwinder_private_data_size], + private: [core::ptr::null(); uw::unwinder_private_data_size], }, canary: &CANARY, cause: data, diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs index 79624703a4cf..dd0a76100e23 100644 --- a/library/std/src/sys/personality/dwarf/eh.rs +++ b/library/std/src/sys/personality/dwarf/eh.rs @@ -1,6 +1,7 @@ //! Parsing of GCC-style Language-Specific Data Area (LSDA) //! For details see: //! * +//! * //! * //! * //! * @@ -37,17 +38,19 @@ pub const DW_EH_PE_indirect: u8 = 0x80; #[derive(Copy, Clone)] pub struct EHContext<'a> { - pub ip: usize, // Current instruction pointer - pub func_start: usize, // Address of the current function - pub get_text_start: &'a dyn Fn() -> usize, // Get address of the code section - pub get_data_start: &'a dyn Fn() -> usize, // Get address of the data section + pub ip: *const u8, // Current instruction pointer + pub func_start: *const u8, // Pointer to the current function + pub get_text_start: &'a dyn Fn() -> *const u8, // Get pointer to the code section + pub get_data_start: &'a dyn Fn() -> *const u8, // Get pointer to the data section } +/// Landing pad. +type LPad = *const u8; pub enum EHAction { None, - Cleanup(usize), - Catch(usize), - Filter(usize), + Cleanup(LPad), + Catch(LPad), + Filter(LPad), Terminate, } @@ -82,21 +85,21 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result if !USING_SJLJ_EXCEPTIONS { while reader.ptr < action_table { - let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?; - let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?; - let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?; + let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr(); + let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr(); + let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr(); let cs_action_entry = reader.read_uleb128(); // Callsite table is sorted by cs_start, so if we've passed the ip, we // may stop searching. - if ip < func_start + cs_start { + if ip < func_start.wrapping_add(cs_start) { break; } - if ip < func_start + cs_start + cs_len { + if ip < func_start.wrapping_add(cs_start + cs_len) { if cs_lpad == 0 { return Ok(EHAction::None); } else { - let lpad = lpad_base + cs_lpad; - return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad)); + let lpad = lpad_base.wrapping_add(cs_lpad); + return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); } } } @@ -106,12 +109,12 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result // SjLj version: // The "IP" is an index into the call-site table, with two exceptions: // -1 means 'no-action', and 0 means 'terminate'. - match ip as isize { + match ip.addr() as isize { -1 => return Ok(EHAction::None), 0 => return Ok(EHAction::Terminate), _ => (), } - let mut idx = ip; + let mut idx = ip.addr(); loop { let cs_lpad = reader.read_uleb128(); let cs_action_entry = reader.read_uleb128(); @@ -119,17 +122,18 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result if idx == 0 { // Can never have null landing pad for sjlj -- that would have // been indicated by a -1 call site index. - let lpad = (cs_lpad + 1) as usize; - return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad)); + // FIXME(strict provenance) + let lpad = ptr::from_exposed_addr((cs_lpad + 1) as usize); + return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); } } } } unsafe fn interpret_cs_action( - action_table: *mut u8, + action_table: *const u8, cs_action_entry: u64, - lpad: usize, + lpad: LPad, ) -> EHAction { if cs_action_entry == 0 { // If cs_action_entry is 0 then this is a cleanup (Drop::drop). We run these @@ -138,7 +142,7 @@ unsafe fn interpret_cs_action( } else { // If lpad != 0 and cs_action_entry != 0, we have to check ttype_index. // If ttype_index == 0 under the condition, we take cleanup action. - let action_record = (action_table as *mut u8).offset(cs_action_entry as isize - 1); + let action_record = action_table.offset(cs_action_entry as isize - 1); let mut action_reader = DwarfReader::new(action_record); let ttype_index = action_reader.read_sleb128(); if ttype_index == 0 { @@ -161,15 +165,16 @@ unsafe fn read_encoded_pointer( reader: &mut DwarfReader, context: &EHContext<'_>, encoding: u8, -) -> Result { +) -> Result<*const u8, ()> { if encoding == DW_EH_PE_omit { return Err(()); } // DW_EH_PE_aligned implies it's an absolute pointer value if encoding == DW_EH_PE_aligned { - reader.ptr = reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::())?); - return Ok(reader.read::()); + reader.ptr = + reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<*const u8>())?); + return Ok(reader.read::<*const u8>()); } let mut result = match encoding & 0x0F { @@ -190,18 +195,21 @@ unsafe fn read_encoded_pointer( // relative to address of the encoded value, despite the name DW_EH_PE_pcrel => reader.ptr.expose_addr(), DW_EH_PE_funcrel => { - if context.func_start == 0 { + if context.func_start.is_null() { return Err(()); } - context.func_start + context.func_start.expose_addr() } - DW_EH_PE_textrel => (*context.get_text_start)(), - DW_EH_PE_datarel => (*context.get_data_start)(), + DW_EH_PE_textrel => (*context.get_text_start)().expose_addr(), + DW_EH_PE_datarel => (*context.get_data_start)().expose_addr(), _ => return Err(()), }; + // FIXME(strict provenance) + let mut result: *const u8 = ptr::from_exposed_addr::(result); + if encoding & DW_EH_PE_indirect != 0 { - result = *ptr::from_exposed_addr::(result); + result = *(result.cast::<*const u8>()); } Ok(result) diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index 559d2c7db471..6f317131145a 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -38,7 +38,6 @@ use super::dwarf::eh::{self, EHAction, EHContext}; use crate::ffi::c_int; -use libc::uintptr_t; use unwind as uw; // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister() @@ -160,9 +159,9 @@ cfg_if::cfg_if! { uw::_Unwind_SetGR( context, UNWIND_DATA_REG.0, - exception_object as uintptr_t, + exception_object as uw::_Unwind_Ptr, ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0); + uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); uw::_Unwind_SetIP(context, lpad); return uw::_URC_INSTALL_CONTEXT; } @@ -222,9 +221,9 @@ cfg_if::cfg_if! { uw::_Unwind_SetGR( context, UNWIND_DATA_REG.0, - exception_object as uintptr_t, + exception_object.cast(), ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0); + uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); uw::_Unwind_SetIP(context, lpad); uw::_URC_INSTALL_CONTEXT } diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 94a91dd357c9..e86408a9ed2b 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -4,6 +4,7 @@ #![feature(staged_api)] #![feature(c_unwind)] #![feature(cfg_target_abi)] +#![feature(strict_provenance)] #![cfg_attr(not(target_env = "msvc"), feature(libc))] #![allow(internal_features)] diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index a2bfa8e96dd2..dba64aa74ce6 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -1,6 +1,6 @@ #![allow(nonstandard_style)] -use libc::{c_int, c_void, uintptr_t}; +use libc::{c_int, c_void}; #[repr(C)] #[derive(Debug, Copy, Clone, PartialEq)] @@ -19,8 +19,8 @@ pub enum _Unwind_Reason_Code { pub use _Unwind_Reason_Code::*; pub type _Unwind_Exception_Class = u64; -pub type _Unwind_Word = uintptr_t; -pub type _Unwind_Ptr = uintptr_t; +pub type _Unwind_Word = *const u8; +pub type _Unwind_Ptr = *const u8; pub type _Unwind_Trace_Fn = extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code; @@ -214,7 +214,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe // On Android or ARM/Linux, these are implemented as macros: pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word { - let mut val: _Unwind_Word = 0; + let mut val: _Unwind_Word = core::ptr::null(); _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32, &mut val as *mut _ as *mut c_void); val @@ -229,14 +229,14 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word { let val = _Unwind_GetGR(ctx, UNWIND_IP_REG); - (val & !1) as _Unwind_Word + val.map_addr(|v| v & !1) } pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word) { // Propagate thumb bit to instruction pointer - let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1; - let value = value | thumb_state; + let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG).addr() & 1; + let value = value.map_addr(|v| v | thumb_state); _Unwind_SetGR(ctx, UNWIND_IP_REG, value); } From b48039f6feec314842d40236f33d6a1c5b66b3da Mon Sep 17 00:00:00 2001 From: niluxv Date: Sun, 6 Aug 2023 11:40:34 +0200 Subject: [PATCH 07/94] Rewrite `read_encoded_pointer` conforming to strict provenance * Entries in the callsite table now use a dedicated function for reading an offset rather than a pointer * `read_encoded_pointer` uses that new function for reading offsets when the "application" part of the encoding indicates an offset (relative to some pointer) * It now errors out on nonsensical "application" and "value encoding" combinations Inspired by @eddyb's comment on zulip about this: --- library/std/src/sys/personality/dwarf/eh.rs | 97 +++++++++++++++------ 1 file changed, 69 insertions(+), 28 deletions(-) diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs index dd0a76100e23..a78084de0fae 100644 --- a/library/std/src/sys/personality/dwarf/eh.rs +++ b/library/std/src/sys/personality/dwarf/eh.rs @@ -84,10 +84,12 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result let ip = context.ip; if !USING_SJLJ_EXCEPTIONS { + // read the callsite table while reader.ptr < action_table { - let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr(); - let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr(); - let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr(); + // these are offsets rather than pointers; + let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?; + let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?; + let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?; let cs_action_entry = reader.read_uleb128(); // Callsite table is sorted by cs_start, so if we've passed the ip, we // may stop searching. @@ -161,23 +163,24 @@ fn round_up(unrounded: usize, align: usize) -> Result { if align.is_power_of_two() { Ok((unrounded + align - 1) & !(align - 1)) } else { Err(()) } } -unsafe fn read_encoded_pointer( - reader: &mut DwarfReader, - context: &EHContext<'_>, - encoding: u8, -) -> Result<*const u8, ()> { - if encoding == DW_EH_PE_omit { +/// Read a offset (`usize`) from `reader` whose encoding is described by `encoding`. +/// +/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext]. +/// In addition the upper ("application") part must be zero. +/// +/// # Errors +/// Returns `Err` if `encoding` +/// * is not a valid DWARF Exception Header Encoding, +/// * is `DW_EH_PE_omit`, or +/// * has a non-zero application part. +/// +/// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html +unsafe fn read_encoded_offset(reader: &mut DwarfReader, encoding: u8) -> Result { + if encoding == DW_EH_PE_omit || encoding & 0xF0 != 0 { return Err(()); } - - // DW_EH_PE_aligned implies it's an absolute pointer value - if encoding == DW_EH_PE_aligned { - reader.ptr = - reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<*const u8>())?); - return Ok(reader.read::<*const u8>()); - } - - let mut result = match encoding & 0x0F { + let result = match encoding & 0x0F { + // despite the name, LLVM also uses absptr for offsets instead of pointers DW_EH_PE_absptr => reader.read::(), DW_EH_PE_uleb128 => reader.read_uleb128() as usize, DW_EH_PE_udata2 => reader.read::() as usize, @@ -189,28 +192,66 @@ unsafe fn read_encoded_pointer( DW_EH_PE_sdata8 => reader.read::() as usize, _ => return Err(()), }; + Ok(result) +} - result += match encoding & 0x70 { - DW_EH_PE_absptr => 0, +/// Read a pointer from `reader` whose encoding is described by `encoding`. +/// +/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext]. +/// +/// # Errors +/// Returns `Err` if `encoding` +/// * is not a valid DWARF Exception Header Encoding, +/// * is `DW_EH_PE_omit`, or +/// * combines `DW_EH_PE_absptr` or `DW_EH_PE_aligned` application part with an integer encoding +/// (not `DW_EH_PE_absptr`) in the value format part. +/// +/// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html +unsafe fn read_encoded_pointer( + reader: &mut DwarfReader, + context: &EHContext<'_>, + encoding: u8, +) -> Result<*const u8, ()> { + if encoding == DW_EH_PE_omit { + return Err(()); + } + + let base_ptr = match encoding & 0x70 { + DW_EH_PE_absptr => core::ptr::null(), // relative to address of the encoded value, despite the name - DW_EH_PE_pcrel => reader.ptr.expose_addr(), + DW_EH_PE_pcrel => reader.ptr, DW_EH_PE_funcrel => { if context.func_start.is_null() { return Err(()); } - context.func_start.expose_addr() + context.func_start + } + DW_EH_PE_textrel => (*context.get_text_start)(), + DW_EH_PE_datarel => (*context.get_data_start)(), + // aligned means the value is aligned to the size of a pointer + DW_EH_PE_aligned => { + reader.ptr = + reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<*const u8>())?); + core::ptr::null() } - DW_EH_PE_textrel => (*context.get_text_start)().expose_addr(), - DW_EH_PE_datarel => (*context.get_data_start)().expose_addr(), _ => return Err(()), }; - // FIXME(strict provenance) - let mut result: *const u8 = ptr::from_exposed_addr::(result); + let mut ptr = if base_ptr.is_null() { + // any value encoding other than absptr would be nonsensical here; + // there would be no source of pointer provenance + if encoding & 0x0F != DW_EH_PE_absptr { + return Err(()); + } + reader.read::<*const u8>() + } else { + let offset = read_encoded_offset(reader, encoding & 0x0F)?; + base_ptr.wrapping_add(offset) + }; if encoding & DW_EH_PE_indirect != 0 { - result = *(result.cast::<*const u8>()); + ptr = *(ptr.cast::<*const u8>()); } - Ok(result) + Ok(ptr) } From 1ee055f0ecbadd9e6c51182a7179d8f8acfd4720 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 12 Oct 2023 08:25:22 +0200 Subject: [PATCH 08/94] add some comments and some cleanup around Miri intptrcast --- .../rustc_const_eval/src/interpret/memory.rs | 10 +++++ src/tools/miri/src/intptrcast.rs | 37 +++++++++---------- src/tools/miri/src/machine.rs | 18 ++++++--- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index ce666e6af3bd..a646f09dee07 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1249,6 +1249,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Turning a "maybe pointer" into a proper pointer (and some information /// about where it points), or an absolute address. + /// + /// The result must be used immediately; it is not allowed to convert + /// the returned data back into a `Pointer` and store that in machine state. + /// (In fact that's not even possible since `M::ProvenanceExtra` is generic and + /// we don't have an operation to turn it back into `M::Provenance`.) pub fn ptr_try_get_alloc_id( &self, ptr: Pointer>, @@ -1267,6 +1272,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } /// Turning a "maybe pointer" into a proper pointer (and some information about where it points). + /// + /// The result must be used immediately; it is not allowed to convert + /// the returned data back into a `Pointer` and store that in machine state. + /// (In fact that's not even possible since `M::ProvenanceExtra` is generic and + /// we don't have an operation to turn it back into `M::Provenance`.) #[inline(always)] pub fn ptr_get_alloc_id( &self, diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/intptrcast.rs index 4fd0af35304e..154d86375ca2 100644 --- a/src/tools/miri/src/intptrcast.rs +++ b/src/tools/miri/src/intptrcast.rs @@ -119,24 +119,14 @@ impl<'mir, 'tcx> GlobalStateInner { Ok(()) } - pub fn ptr_from_addr_transmute( - _ecx: &MiriInterpCx<'mir, 'tcx>, - addr: u64, - ) -> Pointer> { - trace!("Transmuting {:#x} to a pointer", addr); - - // We consider transmuted pointers to be "invalid" (`None` provenance). - Pointer::new(None, Size::from_bytes(addr)) - } - pub fn ptr_from_addr_cast( ecx: &MiriInterpCx<'mir, 'tcx>, addr: u64, ) -> InterpResult<'tcx, Pointer>> { trace!("Casting {:#x} to a pointer", addr); + // Potentially emit a warning. let global_state = ecx.machine.intptrcast.borrow(); - match global_state.provenance_mode { ProvenanceMode::Default => { // The first time this happens at a particular location, print a warning. @@ -158,7 +148,12 @@ impl<'mir, 'tcx> GlobalStateInner { ProvenanceMode::Permissive => {} } - // This is how wildcard pointers are born. + // We do *not* look up the `AllocId` here! This is a `ptr as usize` cast, and it is + // completely legal to do a cast and then `wrapping_offset` to another allocation and only + // *then* do a memory access. So the allocation that the pointer happens to point to on a + // cast is fairly irrelevant. Instead we generate this as a "wildcard" pointer, such that + // *every time the pointer is used*, we do an `AllocId` lookup to find the (exposed) + // allocation it might be referencing. Ok(Pointer::new(Some(Provenance::Wildcard), Size::from_bytes(addr))) } @@ -219,22 +214,27 @@ impl<'mir, 'tcx> GlobalStateInner { }) } - /// Convert a relative (tcx) pointer to an absolute address. - pub fn rel_ptr_to_addr( + /// Convert a relative (tcx) pointer to a Miri pointer. + pub fn ptr_from_rel_ptr( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, - ) -> InterpResult<'tcx, u64> { + tag: BorTag, + ) -> InterpResult<'tcx, Pointer> { let (alloc_id, offset) = ptr.into_parts(); // offset is relative (AllocId provenance) let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id)?; // Add offset with the right kind of pointer-overflowing arithmetic. let dl = ecx.data_layout(); - Ok(dl.overflowing_offset(base_addr, offset.bytes()).0) + let absolute_addr = dl.overflowing_offset(base_addr, offset.bytes()).0; + Ok(Pointer::new( + Provenance::Concrete { alloc_id, tag }, + Size::from_bytes(absolute_addr), + )) } /// When a pointer is used for a memory access, this computes where in which allocation the /// access is going. - pub fn abs_ptr_to_rel( + pub fn ptr_get_alloc( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, ) -> Option<(AllocId, Size)> { @@ -252,12 +252,11 @@ impl<'mir, 'tcx> GlobalStateInner { let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id).unwrap(); // Wrapping "addr - base_addr" - let dl = ecx.data_layout(); #[allow(clippy::cast_possible_wrap)] // we want to wrap here let neg_base_addr = (base_addr as i64).wrapping_neg(); Some(( alloc_id, - Size::from_bytes(dl.overflowing_signed_offset(addr.bytes(), neg_base_addr).0), + Size::from_bytes(ecx.overflowing_signed_offset(addr.bytes(), neg_base_addr).0), )) } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 3de27460860c..96c734c55008 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1136,19 +1136,16 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { _ => {} } } - let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr)?; let tag = if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { borrow_tracker.borrow_mut().base_ptr_tag(ptr.provenance, &ecx.machine) } else { // Value does not matter, SB is disabled BorTag::default() }; - Ok(Pointer::new( - Provenance::Concrete { alloc_id: ptr.provenance, tag }, - Size::from_bytes(absolute_addr), - )) + intptrcast::GlobalStateInner::ptr_from_rel_ptr(ecx, ptr, tag) } + /// Called on `usize as ptr` casts. #[inline(always)] fn ptr_from_addr_cast( ecx: &MiriInterpCx<'mir, 'tcx>, @@ -1157,6 +1154,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { intptrcast::GlobalStateInner::ptr_from_addr_cast(ecx, addr) } + /// Called on `ptr as usize` casts. + /// (Actually computing the resulting `usize` doesn't need machine help, + /// that's just `Scalar::try_to_int`.) fn expose_ptr( ecx: &mut InterpCx<'mir, 'tcx, Self>, ptr: Pointer, @@ -1174,11 +1174,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { /// Convert a pointer with provenance into an allocation-offset pair, /// or a `None` with an absolute address if that conversion is not possible. + /// + /// This is called when a pointer is about to be used for memory access, + /// an in-bounds check, or anything else that requires knowing which allocation it points to. + /// The resulting `AllocId` will just be used for that one step and the forgotten again + /// (i.e., we'll never turn the data returned here back into a `Pointer` that might be + /// stored in machine state). fn ptr_get_alloc( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> { - let rel = intptrcast::GlobalStateInner::abs_ptr_to_rel(ecx, ptr); + let rel = intptrcast::GlobalStateInner::ptr_get_alloc(ecx, ptr); rel.map(|(alloc_id, size)| { let tag = match ptr.provenance { From e92c93466535d52aa569f6584606bb61e305acc6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 13 Oct 2023 07:41:10 +0200 Subject: [PATCH 09/94] doc comment for Provenance::Wildcard --- src/tools/miri/src/machine.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 96c734c55008..f956015c8087 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -169,11 +169,29 @@ impl fmt::Display for MiriMemoryKind { /// Pointer provenance. #[derive(Clone, Copy)] pub enum Provenance { + /// For pointers with concrete provenance. we exactly know which allocation they are attached to + /// and what their borrow tag is. Concrete { alloc_id: AllocId, /// Borrow Tracker tag. tag: BorTag, }, + /// Pointers with wildcard provenance are created on int-to-ptr casts. According to the + /// specification, we should at that point angelically "guess" a provenance that will make all + /// future uses of this pointer work, if at all possible. Of course such a semantics cannot be + /// actually implemented in Miri. So instead, we approximate this, erroring on the side of + /// accepting too much code rather than rejecting correct code: a pointer with wildcard + /// provenance "acts like" any previously exposed pointer. Each time it is used, we check + /// whether *some* exposed pointer could have done what we want to do, and if the answer is yes + /// then we allow the access. This allows too much code in two ways: + /// - The same wildcard pointer can "take the role" of multiple different exposed pointers on + /// subsequenct memory accesses. + /// - In the aliasing model, we don't just have to know the borrow tag of the pointer used for + /// the access, we also have to update the aliasing state -- and that update can be very + /// different depending on which borrow tag we pick! Stacked Borrows has support for this by + /// switching to a stack that is only approximately known, i.e. we overapproximate the effect + /// of using *any* exposed pointer for this access, and only keep information about the borrow + /// stack that would be true with all possible choices. Wildcard, } From dfadd177a9738de289a3a6d4b39c08d94f384c1a Mon Sep 17 00:00:00 2001 From: Denis Smirnov Date: Thu, 5 Oct 2023 16:04:28 +0700 Subject: [PATCH 10/94] Make TCP connect() handle EINTR correctly According to the POSIX standard, if connect() is interrupted by a signal that is caught while blocked waiting to establish a connection, connect() shall fail and set errno to EINTR, but the connection request shall not be aborted, and the connection shall be established asynchronously. If asynchronous connection was successfully established after EINTR and before the next connection attempt, OS returns EISCONN that was handled as an error before. This behavior is fixed now and we handle it as success. The problem affects MacOS users: Linux doesn't return EISCONN in this case, Windows connect() can not be interrupted without an old-fashoin WSACancelBlockingCall function that is not used in the library. So current solution gives connect() as OS specific implementation. --- library/std/src/sys/hermit/net.rs | 6 ++++++ library/std/src/sys/solid/net.rs | 11 +++++++---- library/std/src/sys/unix/net.rs | 17 +++++++++++++++++ library/std/src/sys/windows/net.rs | 12 +++++++----- library/std/src/sys_common/net.rs | 4 +--- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs index a564f1698bae..bd8b493d65aa 100644 --- a/library/std/src/sys/hermit/net.rs +++ b/library/std/src/sys/hermit/net.rs @@ -56,6 +56,12 @@ impl Socket { unimplemented!() } + pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { + let (addr, len) = addr.into_inner(); + cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; + Ok(()) + } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; let r = unsafe { diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 6adced787f3b..1eae0fc0642b 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -233,12 +233,15 @@ impl Socket { } } + pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { + let (addr, len) = addr.into_inner(); + cvt(unsafe { netc::connect(self.0.raw(), addr.as_ptr(), len) })?; + Ok(()) + } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; - let r = unsafe { - let (addr, len) = addr.into_inner(); - cvt(netc::connect(self.0.raw(), addr.as_ptr(), len)) - }; + let r = self.connect(addr); self.set_nonblocking(false)?; match r { diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index f450d708dae6..5c4d776e18ae 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -6,6 +6,7 @@ use crate::net::{Shutdown, SocketAddr}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::str; use crate::sys::fd::FileDesc; +use crate::sys::unix::IsMinusOne; use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::{Duration, Instant}; @@ -140,6 +141,22 @@ impl Socket { unimplemented!() } + pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { + let (addr, len) = addr.into_inner(); + loop { + let result = unsafe { libc::connect(self.as_raw_fd(), addr.as_ptr(), len) }; + if result.is_minus_one() { + let err = crate::sys::os::errno(); + match err { + libc::EINTR => continue, + libc::EISCONN => return Ok(()), + _ => return Err(io::Error::from_raw_os_error(err)), + } + } + return Ok(()); + } + } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; let r = unsafe { diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 4b7115f97c50..c29b863665f1 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -140,13 +140,15 @@ impl Socket { } } + pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { + let (addr, len) = addr.into_inner(); + let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) }; + cvt(result).map(drop) + } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; - let result = { - let (addr, len) = addr.into_inner(); - let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) }; - cvt(result).map(drop) - }; + let result = self.connect(addr); self.set_nonblocking(false)?; match result { diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 4f5b17deaa2d..8712bd2eca76 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -226,9 +226,7 @@ impl TcpStream { init(); let sock = Socket::new(addr, c::SOCK_STREAM)?; - - let (addr, len) = addr.into_inner(); - cvt_r(|| unsafe { c::connect(sock.as_raw(), addr.as_ptr(), len) })?; + sock.connect(addr)?; Ok(TcpStream { inner: sock }) } From e5e95eba457b17a1f8005403fa0287e1cd8d82f3 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 1 May 2023 14:17:56 +0200 Subject: [PATCH 11/94] MCP636: Add simpler and more explicit syntax to check-cfg This add a new form and deprecated the other ones: - cfg(name1, ..., nameN, values("value1", "value2", ... "valueN")) - cfg(name1, ..., nameN) or cfg(name1, ..., nameN, values()) - cfg(any()) It also changes the default exhaustiveness to be enable-by-default in the presence of any --check-cfg arguments. --- compiler/rustc_interface/src/interface.rs | 139 +++++++- compiler/rustc_interface/src/lib.rs | 1 + src/doc/rustdoc/src/unstable-features.md | 4 +- .../src/compiler-flags/check-cfg.md | 302 ++++++++++-------- 4 files changed, 311 insertions(+), 135 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 1c330c064ab6..65ef4a1442cd 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -124,8 +124,13 @@ pub fn parse_cfgspecs( /// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> CheckCfg { rustc_span::create_default_session_if_not_set_then(move |_| { - let mut check_cfg = CheckCfg::default(); + // If any --check-cfg is passed then exhaustive_values and exhaustive_names + // are enabled by default. + let exhaustive_names = !specs.is_empty(); + let exhaustive_values = !specs.is_empty(); + let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; + let mut old_syntax = None; for s in specs { let sess = ParseSess::with_silent_emitter(Some(format!( "this error occurred on the command line: `--check-cfg={s}`" @@ -141,18 +146,21 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> Check }; } - let expected_error = || { - error!( - "expected `names(name1, name2, ... nameN)` or \ - `values(name, \"value1\", \"value2\", ... \"valueN\")`" - ) - }; + let expected_error = + || error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`"); match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { Ok(mut parser) => match parser.parse_meta_item() { Ok(meta_item) if parser.token == token::Eof => { if let Some(args) = meta_item.meta_item_list() { if meta_item.has_name(sym::names) { + // defaults are flipped for the old syntax + if old_syntax == None { + check_cfg.exhaustive_names = false; + check_cfg.exhaustive_values = false; + } + old_syntax = Some(true); + check_cfg.exhaustive_names = true; for arg in args { if arg.is_word() && arg.ident().is_some() { @@ -166,6 +174,13 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> Check } } } else if meta_item.has_name(sym::values) { + // defaults are flipped for the old syntax + if old_syntax == None { + check_cfg.exhaustive_names = false; + check_cfg.exhaustive_values = false; + } + old_syntax = Some(true); + if let Some((name, values)) = args.split_first() { if name.is_word() && name.ident().is_some() { let ident = name.ident().expect("multi-segment cfg key"); @@ -215,6 +230,116 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> Check } else { expected_error(); } + } else if meta_item.has_name(sym::cfg) { + old_syntax = Some(false); + + let mut names = Vec::new(); + let mut values: FxHashSet<_> = Default::default(); + + let mut any_specified = false; + let mut values_specified = false; + let mut values_any_specified = false; + + for arg in args { + if arg.is_word() && let Some(ident) = arg.ident() { + if values_specified { + error!("`cfg()` names cannot be after values"); + } + names.push(ident); + } else if arg.has_name(sym::any) + && let Some(args) = arg.meta_item_list() + { + if any_specified { + error!("`any()` cannot be specified multiple times"); + } + any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); + } + } else if arg.has_name(sym::values) + && let Some(args) = arg.meta_item_list() + { + if names.is_empty() { + error!( + "`values()` cannot be specified before the names" + ); + } else if values_specified { + error!( + "`values()` cannot be specified multiple times" + ); + } + values_specified = true; + + for arg in args { + if let Some(LitKind::Str(s, _)) = + arg.lit().map(|lit| &lit.kind) + { + values.insert(Some(s.to_string())); + } else if arg.has_name(sym::any) + && let Some(args) = arg.meta_item_list() + { + if values_any_specified { + error!( + "`any()` in `values()` cannot be specified multiple times" + ); + } + values_any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); + } + } else { + error!( + "`values()` arguments must be string literals or `any()`" + ); + } + } + } else { + error!( + "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`" + ); + } + } + + if values.is_empty() && !values_any_specified && !any_specified { + values.insert(None); + } else if !values.is_empty() && values_any_specified { + error!( + "`values()` arguments cannot specify string literals and `any()` at the same time" + ); + } + + if any_specified { + if !names.is_empty() + || !values.is_empty() + || values_any_specified + { + error!("`cfg(any())` can only be provided in isolation"); + } + + check_cfg.exhaustive_names = false; + } else { + for name in names { + check_cfg + .expecteds + .entry(name.to_string()) + .and_modify(|v| match v { + ExpectedValues::Some(v) + if !values_any_specified => + { + v.extend(values.clone()) + } + ExpectedValues::Some(_) => *v = ExpectedValues::Any, + ExpectedValues::Any => {} + }) + .or_insert_with(|| { + if values_any_specified { + ExpectedValues::Any + } else { + ExpectedValues::Some(values.clone()) + } + }); + } + } } else { expected_error(); } diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 76131c1ad69b..ffa2667a351e 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -3,6 +3,7 @@ #![feature(internal_output_capture)] #![feature(thread_spawn_unchecked)] #![feature(lazy_cell)] +#![feature(let_chains)] #![feature(try_blocks)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 199b5d69a1c7..41602dec44c4 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -628,10 +628,10 @@ Using this flag looks like this: ```bash $ rustdoc src/lib.rs -Z unstable-options \ - --check-cfg='names()' --check-cfg='values(feature, "foo", "bar")' + --check-cfg='cfg(feature, values("foo", "bar"))' ``` -The example above check every well known names (`target_os`, `doc`, `test`, ... via `names()`) +The example above check every well known names and values (`target_os`, `doc`, `test`, ...) and check the values of `feature`: `foo` and `bar`. ### `--generate-link-to-definition`: Generate links on types in source code diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index 10f0fbc50626..ca18ec567a4f 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -10,18 +10,185 @@ This feature allows you to enable complete or partial checking of configuration. check them. The `--check-cfg` option takes a value, called the _check cfg specification_. The check cfg specification is parsed using the Rust metadata syntax, just as the `--cfg` option is. -`--check-cfg` option can take one of two forms: +`--check-cfg` option take one form: -1. `--check-cfg names(...)` enables checking condition names. -2. `--check-cfg values(...)` enables checking the values within list-valued conditions. - -These two options are independent. `names` checks only the namespace of condition names -while `values` checks only the namespace of the values of list-valued conditions. +1. `--check-cfg cfg(...)` enables checking the values within list-valued conditions. NOTE: No implicit expectation is added when using `--cfg` for both forms. Users are expected to -pass all expected names and values using `names(...)` and `values(...)`. +pass all expected names and values using `cfg(...)`. -## The `names(...)` form +## The `cfg(...)` form + +The `cfg(...)` form enables checking the values within list-valued conditions. It has this +basic form: + +```bash +rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))' +``` + +where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal +string. `name` specifies the name of the condition, such as `feature` or `my_cfg`. + +When the `cfg(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]` +attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]` +and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the +list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs` +lint diagnostic. The default diagnostic level for this lint is `Warn`. + +To enable checking of values, but to provide an empty set of expected values, use these forms: + +```bash +rustc --check-cfg 'cfg(name1, ..., nameN)' +rustc --check-cfg 'cfg(name1, ..., nameN, values())' +``` + +To enable checking of name but not values (i.e. unknown expected values), use this form: + +```bash +rustc --check-cfg 'cfg(name1, ..., nameN, values(any()))' +``` + +The `--check-cfg cfg(...)` option can be repeated, both for the same condition name and for +different names. If it is repeated for the same condition name, then the sets of values for that +condition are merged together (presedence is given to `any()`). + +## Well known names and values + +`rustc` has a internal list of well known names and their corresponding values. +Those well known names and values follows the same stability as what they refer to. + +Well known values checking is always enabled as long as a `--check-cfg` argument is present. + +Well known names checking is always enable as long as a `--check-cfg` argument is present +**unless** any `cfg(any())` argument is passed. + +To disable checking of well known names, use this form: + +```bash +rustc --check-cfg 'cfg(any())' +``` + +NOTE: If one want to enable values and names checking without having any cfg to declare, one +can use an empty `cfg()` argument. + +## Examples + +Consider this command line: + +```bash +rustc --check-cfg 'cfg(feature, values("lion", "zebra"))' \ + --cfg 'feature="lion"' -Z unstable-options \ + example.rs +``` + +This command line indicates that this crate has two features: `lion` and `zebra`. The `lion` +feature is enabled, while the `zebra` feature is disabled. Exhaustive checking of names and +values are enabled by default. Consider compiling this code: + +```rust +// This is expected, and tame_lion() will be compiled +#[cfg(feature = "lion")] +fn tame_lion(lion: Lion) {} + +// This is expected, and ride_zebra() will NOT be compiled. +#[cfg(feature = "zebra")] +fn ride_zebra(zebra: Zebra) {} + +// This is UNEXPECTED, and will cause a compiler warning (by default). +#[cfg(feature = "platypus")] +fn poke_platypus() {} + +// This is UNEXPECTED, because 'feechure' is not a known condition name, +// and will cause a compiler warning (by default). +#[cfg(feechure = "lion")] +fn tame_lion() {} + +// This is UNEXPECTED, because 'windows' is a well known condition name, +// and because 'windows' doens't take any values, +// and will cause a compiler warning (by default). +#[cfg(windows = "unix")] +fn tame_windows() {} +``` + +### Example: Checking condition names, but not values + +```bash +# This turns on checking for condition names, but not values, such as 'feature' values. +rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \ + --cfg has_feathers -Z unstable-options +``` + +```rust +#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in cfg() +fn do_embedded() {} // and because names exhaustiveness was not disabled + +#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in cfg() +fn do_features() {} // and because names exhaustiveness was not disbaled + +#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in cfg() + // and because no value checking was enable for "has_feathers" + // no warning is emitted for the value "zapping" +fn do_zapping() {} + +#[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and + // "has_mumble_frotz" was not provided in cfg() +fn do_mumble_frotz() {} +``` + +### Example: Checking feature values, but not condition names + +```bash +# This turns on checking for feature values, but not for condition names. +rustc --check-cfg 'configure(feature, values("zapping", "lasers"))' \ + --check-cfg 'cfg(any())' \ + --cfg 'feature="zapping"' -Z unstable-options +``` + +```rust +#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was + // disabled by 'cfg(any())' +fn do_embedded() {} + +#[cfg(has_feathers)] // Same as above, 'cfg(any())' was provided so no name + // checking is performed +fn do_features() {} + +#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list +fn shoot_lasers() {} + +#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the + // cfg(feature) list +fn write_shakespeare() {} +``` + +### Example: Checking both condition names and feature values + +```bash +# This turns on checking for feature values and for condition names. +rustc --check-cfg 'cfg(is_embedded, has_feathers)' \ + --check-cfg 'cfg(feature, values("zapping", "lasers"))' \ + --cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options +``` + +```rust +#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in cfg() +fn do_embedded() {} // and doesn't take any value + +#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in cfg() +fn do_features() {} // and deosn't take any value + +#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because "has_mumble_frotz" was never provided +fn do_mumble_frotz() {} + +#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list +fn shoot_lasers() {} + +#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in + // the cfg(feature) list +fn write_shakespeare() {} +``` + +## The deprecated `names(...)` form The `names(...)` form enables checking the names. This form uses a named list: @@ -56,7 +223,7 @@ The first form enables checking condition names, while specifying that there are condition names (outside of the set of well-known names defined by `rustc`). Omitting the `--check-cfg 'names(...)'` option does not enable checking condition names. -## The `values(...)` form +## The deprecated `values(...)` form The `values(...)` form enables checking the values within list-valued conditions. It has this form: @@ -87,120 +254,3 @@ condition are merged together. If `values()` is specified, then `rustc` will enable the checking of well-known values defined by itself. Note that it's necessary to specify the `values()` form to enable the checking of well known values, specifying the other forms doesn't implicitly enable it. - -## Examples - -Consider this command line: - -```bash -rustc --check-cfg 'names(feature)' \ - --check-cfg 'values(feature, "lion", "zebra")' \ - --cfg 'feature="lion"' -Z unstable-options \ - example.rs -``` - -This command line indicates that this crate has two features: `lion` and `zebra`. The `lion` -feature is enabled, while the `zebra` feature is disabled. Consider compiling this code: - -```rust -// This is expected, and tame_lion() will be compiled -#[cfg(feature = "lion")] -fn tame_lion(lion: Lion) {} - -// This is expected, and ride_zebra() will NOT be compiled. -#[cfg(feature = "zebra")] -fn ride_zebra(zebra: Zebra) {} - -// This is UNEXPECTED, and will cause a compiler warning (by default). -#[cfg(feature = "platypus")] -fn poke_platypus() {} - -// This is UNEXPECTED, because 'feechure' is not a known condition name, -// and will cause a compiler warning (by default). -#[cfg(feechure = "lion")] -fn tame_lion() {} -``` - -> Note: The `--check-cfg names(feature)` option is necessary only to enable checking the condition -> name, as in the last example. `feature` is a well-known (always-expected) condition name, and so -> it is not necessary to specify it in a `--check-cfg 'names(...)'` option. That option can be -> shortened to > `--check-cfg names()` in order to enable checking well-known condition names. - -### Example: Checking condition names, but not values - -```bash -# This turns on checking for condition names, but not values, such as 'feature' values. -rustc --check-cfg 'names(is_embedded, has_feathers)' \ - --cfg has_feathers -Z unstable-options -``` - -```rust -#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in names() -fn do_embedded() {} - -#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in names() -fn do_features() {} - -#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in names() - // and because no value checking was enable for "has_feathers" - // no warning is emitted for the value "zapping" -fn do_zapping() {} - -#[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and - // "has_mumble_frotz" was not provided in names() -fn do_mumble_frotz() {} -``` - -### Example: Checking feature values, but not condition names - -```bash -# This turns on checking for feature values, but not for condition names. -rustc --check-cfg 'values(feature, "zapping", "lasers")' \ - --cfg 'feature="zapping"' -Z unstable-options -``` - -```rust -#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was not - // enable (ie not names()) -fn do_embedded() {} - -#[cfg(has_feathers)] // Same as above, --check-cfg names(...) was never used so no name - // checking is performed -fn do_features() {} - - -#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list -fn shoot_lasers() {} - -#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the - // --check-cfg values(feature) list -fn write_shakespeare() {} -``` - -### Example: Checking both condition names and feature values - -```bash -# This turns on checking for feature values and for condition names. -rustc --check-cfg 'names(is_embedded, has_feathers)' \ - --check-cfg 'values(feature, "zapping", "lasers")' \ - --cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options -``` - -```rust -#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in names() -fn do_embedded() {} - -#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in names() -fn do_features() {} - -#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because has_mumble_frotz is not in the - // --check-cfg names(...) list -fn do_mumble_frotz() {} - -#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list -fn shoot_lasers() {} - -#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in - // the values(feature) list -fn write_shakespeare() {} -``` From fc78d789887047e128a36bd6e8294e15e57f50a0 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 1 May 2023 14:16:38 +0200 Subject: [PATCH 12/94] MCP636: Adapt check-cfg tests to the new syntax --- .../check-cfg/check-cfg-unstable.rs | 2 +- tests/rustdoc-ui/check-cfg/check-cfg.rs | 2 +- tests/rustdoc-ui/doctest/check-cfg-test.rs | 2 +- tests/ui/check-cfg/allow-at-crate-level.rs | 2 +- tests/ui/check-cfg/allow-macro-cfg.rs | 2 +- tests/ui/check-cfg/allow-same-level.rs | 2 +- tests/ui/check-cfg/allow-top-level.rs | 2 +- tests/ui/check-cfg/allow-upper-level.rs | 2 +- tests/ui/check-cfg/compact-names.rs | 2 +- tests/ui/check-cfg/compact-values.rs | 2 +- tests/ui/check-cfg/concat-values.rs | 13 ++ tests/ui/check-cfg/concat-values.stderr | 19 ++ tests/ui/check-cfg/diagnotics.rs | 2 +- tests/ui/check-cfg/empty-names.rs | 10 - tests/ui/check-cfg/empty-values.rs | 10 - .../exhaustive-names-values.empty_cfg.stderr | 25 +++ ...ive-names-values.empty_names_values.stderr | 25 +++ .../exhaustive-names-values.feature.stderr | 33 +++ .../exhaustive-names-values.full.stderr | 33 +++ tests/ui/check-cfg/exhaustive-names-values.rs | 34 ++++ ...rr => exhaustive-names.empty_names.stderr} | 8 +- .../exhaustive-names.exhaustive_names.stderr | 15 ++ tests/ui/check-cfg/exhaustive-names.rs | 12 ++ .../exhaustive-values.empty_cfg.stderr | 17 ++ ... => exhaustive-values.empty_values.stderr} | 2 +- tests/ui/check-cfg/exhaustive-values.rs | 13 ++ .../exhaustive-values.without_names.stderr | 13 ++ .../invalid-arguments.anything_else.stderr | 2 +- .../invalid-arguments.giberich.stderr | 2 + ...invalid-arguments.ident_in_values_1.stderr | 2 + ...invalid-arguments.ident_in_values_2.stderr | 2 + .../invalid-arguments.mixed_any.stderr | 2 + .../invalid-arguments.mixed_values_any.stderr | 2 + .../invalid-arguments.multiple_any.stderr | 2 + .../invalid-arguments.multiple_values.stderr | 2 + ...valid-arguments.multiple_values_any.stderr | 2 + .../invalid-arguments.not_empty_any.stderr | 2 + ...alid-arguments.not_empty_values_any.stderr | 2 + tests/ui/check-cfg/invalid-arguments.rs | 32 ++- ...invalid-arguments.string_for_name_1.stderr | 2 + ...invalid-arguments.string_for_name_2.stderr | 2 + ...valid-arguments.unknown_meta_item_1.stderr | 2 + ...valid-arguments.unknown_meta_item_2.stderr | 2 + ...valid-arguments.unknown_meta_item_3.stderr | 2 + ...d-arguments.values_any_before_ident.stderr | 2 + ...arguments.values_any_missing_values.stderr | 2 + tests/ui/check-cfg/invalid-cfg-name.rs | 14 -- tests/ui/check-cfg/invalid-cfg-value.rs | 18 -- .../check-cfg/{mix.stderr => mix.cfg.stderr} | 54 ++--- tests/ui/check-cfg/mix.names_values.stderr | 192 ++++++++++++++++++ tests/ui/check-cfg/mix.rs | 6 +- ...stderr => no-expected-values.empty.stderr} | 4 +- .../check-cfg/no-expected-values.mixed.stderr | 23 +++ tests/ui/check-cfg/no-expected-values.rs | 20 ++ .../no-expected-values.simple.stderr | 23 +++ .../no-expected-values.values.stderr | 23 +++ tests/ui/check-cfg/no-values.rs | 14 -- tests/ui/check-cfg/stmt-no-ice.rs | 2 +- ... => unexpected-cfg-name.exhaustive.stderr} | 2 +- .../unexpected-cfg-name.names.stderr | 10 + tests/ui/check-cfg/unexpected-cfg-name.rs | 16 ++ ...stderr => unexpected-cfg-value.cfg.stderr} | 4 +- tests/ui/check-cfg/unexpected-cfg-value.rs | 22 ++ .../unexpected-cfg-value.values.stderr | 25 +++ tests/ui/check-cfg/unknown-values.rs | 17 ++ tests/ui/check-cfg/well-known-names.rs | 2 +- tests/ui/check-cfg/well-known-names.stderr | 8 +- tests/ui/check-cfg/well-known-values.rs | 2 +- 68 files changed, 749 insertions(+), 124 deletions(-) create mode 100644 tests/ui/check-cfg/concat-values.rs create mode 100644 tests/ui/check-cfg/concat-values.stderr delete mode 100644 tests/ui/check-cfg/empty-names.rs delete mode 100644 tests/ui/check-cfg/empty-values.rs create mode 100644 tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr create mode 100644 tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr create mode 100644 tests/ui/check-cfg/exhaustive-names-values.feature.stderr create mode 100644 tests/ui/check-cfg/exhaustive-names-values.full.stderr create mode 100644 tests/ui/check-cfg/exhaustive-names-values.rs rename tests/ui/check-cfg/{empty-names.stderr => exhaustive-names.empty_names.stderr} (76%) create mode 100644 tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr create mode 100644 tests/ui/check-cfg/exhaustive-names.rs create mode 100644 tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr rename tests/ui/check-cfg/{empty-values.stderr => exhaustive-values.empty_values.stderr} (88%) create mode 100644 tests/ui/check-cfg/exhaustive-values.rs create mode 100644 tests/ui/check-cfg/exhaustive-values.without_names.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.giberich.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.mixed_any.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.multiple_any.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.multiple_values.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr delete mode 100644 tests/ui/check-cfg/invalid-cfg-name.rs delete mode 100644 tests/ui/check-cfg/invalid-cfg-value.rs rename tests/ui/check-cfg/{mix.stderr => mix.cfg.stderr} (81%) create mode 100644 tests/ui/check-cfg/mix.names_values.stderr rename tests/ui/check-cfg/{no-values.stderr => no-expected-values.empty.stderr} (86%) create mode 100644 tests/ui/check-cfg/no-expected-values.mixed.stderr create mode 100644 tests/ui/check-cfg/no-expected-values.rs create mode 100644 tests/ui/check-cfg/no-expected-values.simple.stderr create mode 100644 tests/ui/check-cfg/no-expected-values.values.stderr delete mode 100644 tests/ui/check-cfg/no-values.rs rename tests/ui/check-cfg/{invalid-cfg-name.stderr => unexpected-cfg-name.exhaustive.stderr} (86%) create mode 100644 tests/ui/check-cfg/unexpected-cfg-name.names.stderr create mode 100644 tests/ui/check-cfg/unexpected-cfg-name.rs rename tests/ui/check-cfg/{invalid-cfg-value.stderr => unexpected-cfg-value.cfg.stderr} (89%) create mode 100644 tests/ui/check-cfg/unexpected-cfg-value.rs create mode 100644 tests/ui/check-cfg/unexpected-cfg-value.values.stderr create mode 100644 tests/ui/check-cfg/unknown-values.rs diff --git a/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs b/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs index 5c500ce6ce08..806b6d1253da 100644 --- a/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs +++ b/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs @@ -1,2 +1,2 @@ // check-fail -// compile-flags: --check-cfg=names() +// compile-flags: --check-cfg=cfg() diff --git a/tests/rustdoc-ui/check-cfg/check-cfg.rs b/tests/rustdoc-ui/check-cfg/check-cfg.rs index fa8789ad3ede..96fa9e08ddee 100644 --- a/tests/rustdoc-ui/check-cfg/check-cfg.rs +++ b/tests/rustdoc-ui/check-cfg/check-cfg.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: --check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options /// uniz is nor a builtin nor pass as arguments so is unexpected #[cfg(uniz)] diff --git a/tests/rustdoc-ui/doctest/check-cfg-test.rs b/tests/rustdoc-ui/doctest/check-cfg-test.rs index 49a801c3fb35..38cd59aa790d 100644 --- a/tests/rustdoc-ui/doctest/check-cfg-test.rs +++ b/tests/rustdoc-ui/doctest/check-cfg-test.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: --test --nocapture --check-cfg=values(feature,"test") -Z unstable-options +// compile-flags: --test --nocapture --check-cfg=cfg(feature,values("test")) -Z unstable-options // normalize-stderr-test: "tests/rustdoc-ui/doctest" -> "$$DIR" // normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/ui/check-cfg/allow-at-crate-level.rs b/tests/ui/check-cfg/allow-at-crate-level.rs index ce3383a2961a..1629d2e0b673 100644 --- a/tests/ui/check-cfg/allow-at-crate-level.rs +++ b/tests/ui/check-cfg/allow-at-crate-level.rs @@ -1,7 +1,7 @@ // This test check that #![allow(unexpected_cfgs)] works with --cfg // // check-pass -// compile-flags: --cfg=unexpected --check-cfg=names() -Z unstable-options +// compile-flags: --cfg=unexpected --check-cfg=cfg() -Z unstable-options #![allow(unexpected_cfgs)] diff --git a/tests/ui/check-cfg/allow-macro-cfg.rs b/tests/ui/check-cfg/allow-macro-cfg.rs index 8016a4d190cc..ea26355aca8f 100644 --- a/tests/ui/check-cfg/allow-macro-cfg.rs +++ b/tests/ui/check-cfg/allow-macro-cfg.rs @@ -1,7 +1,7 @@ // This test check that local #[allow(unexpected_cfgs)] works // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[allow(unexpected_cfgs)] fn foo() { diff --git a/tests/ui/check-cfg/allow-same-level.rs b/tests/ui/check-cfg/allow-same-level.rs index 6c869dc42023..29491e0b39e2 100644 --- a/tests/ui/check-cfg/allow-same-level.rs +++ b/tests/ui/check-cfg/allow-same-level.rs @@ -1,7 +1,7 @@ // This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[allow(unexpected_cfgs)] #[cfg(FALSE)] diff --git a/tests/ui/check-cfg/allow-top-level.rs b/tests/ui/check-cfg/allow-top-level.rs index d14b0eae5ccd..df06f655d9af 100644 --- a/tests/ui/check-cfg/allow-top-level.rs +++ b/tests/ui/check-cfg/allow-top-level.rs @@ -1,7 +1,7 @@ // This test check that a top-level #![allow(unexpected_cfgs)] works // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #![allow(unexpected_cfgs)] diff --git a/tests/ui/check-cfg/allow-upper-level.rs b/tests/ui/check-cfg/allow-upper-level.rs index 04340694d9c1..bd5c97815f2d 100644 --- a/tests/ui/check-cfg/allow-upper-level.rs +++ b/tests/ui/check-cfg/allow-upper-level.rs @@ -1,7 +1,7 @@ // This test check that #[allow(unexpected_cfgs)] work if put on an upper level // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[allow(unexpected_cfgs)] mod aa { diff --git a/tests/ui/check-cfg/compact-names.rs b/tests/ui/check-cfg/compact-names.rs index bff807400396..4f7168255cf3 100644 --- a/tests/ui/check-cfg/compact-names.rs +++ b/tests/ui/check-cfg/compact-names.rs @@ -1,7 +1,7 @@ // This test check that we correctly emit an warning for compact cfg // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #![feature(cfg_target_compact)] diff --git a/tests/ui/check-cfg/compact-values.rs b/tests/ui/check-cfg/compact-values.rs index 1f17057840cc..13c072fe9206 100644 --- a/tests/ui/check-cfg/compact-values.rs +++ b/tests/ui/check-cfg/compact-values.rs @@ -1,7 +1,7 @@ // This test check that we correctly emit an warning for compact cfg // // check-pass -// compile-flags:--check-cfg=values() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #![feature(cfg_target_compact)] diff --git a/tests/ui/check-cfg/concat-values.rs b/tests/ui/check-cfg/concat-values.rs new file mode 100644 index 000000000000..0f9178ce6a57 --- /dev/null +++ b/tests/ui/check-cfg/concat-values.rs @@ -0,0 +1,13 @@ +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(my_cfg,values("foo")) --check-cfg=cfg(my_cfg,values("bar")) + +#[cfg(my_cfg)] +//~^ WARNING unexpected `cfg` condition value +fn my_cfg() {} + +#[cfg(my_cfg = "unk")] +//~^ WARNING unexpected `cfg` condition value +fn my_cfg() {} + +fn main() {} diff --git a/tests/ui/check-cfg/concat-values.stderr b/tests/ui/check-cfg/concat-values.stderr new file mode 100644 index 000000000000..da2bd7d6ad92 --- /dev/null +++ b/tests/ui/check-cfg/concat-values.stderr @@ -0,0 +1,19 @@ +warning: unexpected `cfg` condition value: (none) + --> $DIR/concat-values.rs:5:7 + | +LL | #[cfg(my_cfg)] + | ^^^^^^ + | + = note: expected values for `my_cfg` are: `bar`, `foo` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `unk` + --> $DIR/concat-values.rs:9:7 + | +LL | #[cfg(my_cfg = "unk")] + | ^^^^^^^^^^^^^^ + | + = note: expected values for `my_cfg` are: `bar`, `foo` + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/diagnotics.rs b/tests/ui/check-cfg/diagnotics.rs index 49e127d079a7..45875bddc176 100644 --- a/tests/ui/check-cfg/diagnotics.rs +++ b/tests/ui/check-cfg/diagnotics.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --check-cfg=values(no_values) -Z unstable-options +// compile-flags: --check-cfg=cfg(feature,values("foo")) --check-cfg=cfg(no_values) -Z unstable-options #[cfg(featur)] //~^ WARNING unexpected `cfg` condition name diff --git a/tests/ui/check-cfg/empty-names.rs b/tests/ui/check-cfg/empty-names.rs deleted file mode 100644 index 046ff0364e27..000000000000 --- a/tests/ui/check-cfg/empty-names.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Check warning for unexpected cfg -// -// check-pass -// compile-flags: --check-cfg=names() -Z unstable-options - -#[cfg(unknown_key = "value")] -//~^ WARNING unexpected `cfg` condition name -pub fn f() {} - -fn main() {} diff --git a/tests/ui/check-cfg/empty-values.rs b/tests/ui/check-cfg/empty-values.rs deleted file mode 100644 index 9bda42e5d15f..000000000000 --- a/tests/ui/check-cfg/empty-values.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Check warning for unexpected cfg value -// -// check-pass -// compile-flags: --check-cfg=values() -Z unstable-options - -#[cfg(test = "value")] -//~^ WARNING unexpected `cfg` condition value -pub fn f() {} - -fn main() {} diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr new file mode 100644 index 000000000000..53ccc0f4d317 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -0,0 +1,25 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names-values.rs:12:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-names-values.rs:16:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: unexpected `empty_cfg` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr new file mode 100644 index 000000000000..5e8b74054ceb --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr @@ -0,0 +1,25 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names-values.rs:12:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-names-values.rs:16:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: unexpected `empty_names_values` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr new file mode 100644 index 000000000000..7705a665eb77 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -0,0 +1,33 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names-values.rs:12:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-names-values.rs:16:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: unexpected `cfg` condition value: `unk` + --> $DIR/exhaustive-names-values.rs:20:7 + | +LL | #[cfg(feature = "unk")] + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `std` + +warning: unexpected condition value `` for condition name `feature` + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected values + +warning: 4 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr new file mode 100644 index 000000000000..f0224a2e33c7 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -0,0 +1,33 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names-values.rs:12:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-names-values.rs:16:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: unexpected `cfg` condition value: `unk` + --> $DIR/exhaustive-names-values.rs:20:7 + | +LL | #[cfg(feature = "unk")] + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `std` + +warning: unexpected `full` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 4 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names-values.rs b/tests/ui/check-cfg/exhaustive-names-values.rs new file mode 100644 index 000000000000..f553d93cae2a --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.rs @@ -0,0 +1,34 @@ +// Check warning for unexpected cfg in the code and in the CLI +// arguments (here the revision cfg). +// +// check-pass +// revisions: empty_names_values empty_cfg feature full +// compile-flags: -Z unstable-options +// [empty_names_values]compile-flags: --check-cfg=names() --check-cfg=values() +// [empty_cfg]compile-flags: --check-cfg=cfg() +// [feature]compile-flags: --check-cfg=cfg(feature,values("std")) +// [full]compile-flags: --check-cfg=cfg(feature,values("std")) --check-cfg=cfg() + +#[cfg(unknown_key = "value")] +//~^ WARNING unexpected `cfg` condition name +pub fn f() {} + +#[cfg(test = "value")] +//~^ WARNING unexpected `cfg` condition value +pub fn f() {} + +#[cfg(feature = "unk")] +//[feature]~^ WARNING unexpected `cfg` condition value +//[full]~^^ WARNING unexpected `cfg` condition value +pub fn feat() {} + +#[cfg(feature = "std")] +pub fn feat() {} + +#[cfg(windows)] +pub fn win() {} + +#[cfg(unix)] +pub fn unix() {} + +fn main() {} diff --git a/tests/ui/check-cfg/empty-names.stderr b/tests/ui/check-cfg/exhaustive-names.empty_names.stderr similarity index 76% rename from tests/ui/check-cfg/empty-names.stderr rename to tests/ui/check-cfg/exhaustive-names.empty_names.stderr index 9bba852c6def..6190ff71464c 100644 --- a/tests/ui/check-cfg/empty-names.stderr +++ b/tests/ui/check-cfg/exhaustive-names.empty_names.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/empty-names.rs:6:7 + --> $DIR/exhaustive-names.rs:8:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,9 @@ LL | #[cfg(unknown_key = "value")] = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = note: `#[warn(unexpected_cfgs)]` on by default -warning: 1 warning emitted +warning: unexpected `empty_names` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 2 warnings emitted diff --git a/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr new file mode 100644 index 000000000000..f338434cd299 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr @@ -0,0 +1,15 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names.rs:8:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `exhaustive_names` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names.rs b/tests/ui/check-cfg/exhaustive-names.rs new file mode 100644 index 000000000000..b86a7f84eb4b --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names.rs @@ -0,0 +1,12 @@ +// Check warning for unexpected cfg +// +// check-pass +// revisions: empty_names exhaustive_names +// [empty_names]compile-flags: --check-cfg=names() -Z unstable-options +// [exhaustive_names]compile-flags: --check-cfg=cfg() -Z unstable-options + +#[cfg(unknown_key = "value")] +//~^ WARNING unexpected `cfg` condition name +pub fn f() {} + +fn main() {} diff --git a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr new file mode 100644 index 000000000000..999b27028497 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr @@ -0,0 +1,17 @@ +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-values.rs:9:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `empty_cfg` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/empty-values.stderr b/tests/ui/check-cfg/exhaustive-values.empty_values.stderr similarity index 88% rename from tests/ui/check-cfg/empty-values.stderr rename to tests/ui/check-cfg/exhaustive-values.empty_values.stderr index 932651c5bfe1..77ddc35100ae 100644 --- a/tests/ui/check-cfg/empty-values.stderr +++ b/tests/ui/check-cfg/exhaustive-values.empty_values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `value` - --> $DIR/empty-values.rs:6:7 + --> $DIR/exhaustive-values.rs:9:7 | LL | #[cfg(test = "value")] | ^^^^---------- diff --git a/tests/ui/check-cfg/exhaustive-values.rs b/tests/ui/check-cfg/exhaustive-values.rs new file mode 100644 index 000000000000..8a1689ba86b5 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-values.rs @@ -0,0 +1,13 @@ +// Check warning for unexpected cfg value +// +// check-pass +// revisions: empty_values empty_cfg without_names +// [empty_values]compile-flags: --check-cfg=values() -Z unstable-options +// [empty_cfg]compile-flags: --check-cfg=cfg() -Z unstable-options +// [without_names]compile-flags: --check-cfg=cfg(any()) -Z unstable-options + +#[cfg(test = "value")] +//~^ WARNING unexpected `cfg` condition value +pub fn f() {} + +fn main() {} diff --git a/tests/ui/check-cfg/exhaustive-values.without_names.stderr b/tests/ui/check-cfg/exhaustive-values.without_names.stderr new file mode 100644 index 000000000000..77ddc35100ae --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-values.without_names.stderr @@ -0,0 +1,13 @@ +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-values.rs:9:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/invalid-arguments.anything_else.stderr b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr index 850924d993ac..925664bb3fc6 100644 --- a/tests/ui/check-cfg/invalid-arguments.anything_else.stderr +++ b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr @@ -1,2 +1,2 @@ -error: invalid `--check-cfg` argument: `anything_else(...)` (expected `names(name1, name2, ... nameN)` or `values(name, "value1", "value2", ... "valueN")`) +error: invalid `--check-cfg` argument: `anything_else(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) diff --git a/tests/ui/check-cfg/invalid-arguments.giberich.stderr b/tests/ui/check-cfg/invalid-arguments.giberich.stderr new file mode 100644 index 000000000000..d427033fcc26 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.giberich.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) + diff --git a/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr b/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr new file mode 100644 index 000000000000..0dc44d9ac76c --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(bar))` (`values()` arguments must be string literals or `any()`) + diff --git a/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr b/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr new file mode 100644 index 000000000000..d0a1453e3c40 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))` (`values()` arguments must be string literals or `any()`) + diff --git a/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr b/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr new file mode 100644 index 000000000000..9239f8cce945 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(any(),values(any()))` (`values()` cannot be specified before the names) + diff --git a/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr new file mode 100644 index 000000000000..4c406143d080 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values("bar",any()))` (`values()` arguments cannot specify string literals and `any()` at the same time) + diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr new file mode 100644 index 000000000000..6f1db1b13c31 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(any(),any())` (`any()` cannot be specified multiple times) + diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr new file mode 100644 index 000000000000..bce305b09c30 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(),values())` (`values()` cannot be specified multiple times) + diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr new file mode 100644 index 000000000000..748ce231af73 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(any(),any()))` (`any()` in `values()` cannot be specified multiple times) + diff --git a/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr b/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr new file mode 100644 index 000000000000..daf38147fe53 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(any(foo))` (`any()` must be empty) + diff --git a/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr new file mode 100644 index 000000000000..79f83e802ca5 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(any(bar)))` (`any()` must be empty) + diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index 5090ce3e845d..79bef89c9574 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -2,9 +2,33 @@ // // check-fail // revisions: anything_else names_simple_ident values_simple_ident values_string_literals -// [anything_else]compile-flags: -Z unstable-options --check-cfg=anything_else(...) -// [names_simple_ident]compile-flags: -Z unstable-options --check-cfg=names("NOT_IDENT") -// [values_simple_ident]compile-flags: -Z unstable-options --check-cfg=values("NOT_IDENT") -// [values_string_literals]compile-flags: -Z unstable-options --check-cfg=values(test,12) +// revisions: string_for_name_1 string_for_name_2 multiple_any multiple_values +// revisions: multiple_values_any not_empty_any not_empty_values_any +// revisions: values_any_missing_values values_any_before_ident ident_in_values_1 +// revisions: ident_in_values_2 unknown_meta_item_1 unknown_meta_item_2 unknown_meta_item_3 +// revisions: mixed_values_any mixed_any giberich +// +// compile-flags: -Z unstable-options +// [anything_else]compile-flags: --check-cfg=anything_else(...) +// [names_simple_ident]compile-flags: --check-cfg=names("NOT_IDENT") +// [values_simple_ident]compile-flags: --check-cfg=values("NOT_IDENT") +// [values_string_literals]compile-flags: --check-cfg=values(test,12) +// [string_for_name_1]compile-flags: --check-cfg=cfg("NOT_IDENT") +// [string_for_name_2]compile-flags: --check-cfg=cfg(foo,"NOT_IDENT",bar) +// [multiple_any]compile-flags: --check-cfg=cfg(any(),any()) +// [multiple_values]compile-flags: --check-cfg=cfg(foo,values(),values()) +// [multiple_values_any]compile-flags: --check-cfg=cfg(foo,values(any(),any())) +// [not_empty_any]compile-flags: --check-cfg=cfg(any(foo)) +// [not_empty_values_any]compile-flags: --check-cfg=cfg(foo,values(any(bar))) +// [values_any_missing_values]compile-flags: --check-cfg=cfg(foo,any()) +// [values_any_before_ident]compile-flags: --check-cfg=cfg(values(any()),foo) +// [ident_in_values_1]compile-flags: --check-cfg=cfg(foo,values(bar)) +// [ident_in_values_2]compile-flags: --check-cfg=cfg(foo,values("bar",bar,"bar")) +// [unknown_meta_item_1]compile-flags: --check-cfg=abc() +// [unknown_meta_item_2]compile-flags: --check-cfg=cfg(foo,test()) +// [unknown_meta_item_3]compile-flags: --check-cfg=cfg(foo,values(test())) +// [mixed_values_any]compile-flags: --check-cfg=cfg(foo,values("bar",any())) +// [mixed_any]compile-flags: --check-cfg=cfg(any(),values(any())) +// [giberich]compile-flags: --check-cfg=cfg(...) fn main() {} diff --git a/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr b/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr new file mode 100644 index 000000000000..c6f6834ffd30 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg("NOT_IDENT")` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) + diff --git a/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr b/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr new file mode 100644 index 000000000000..ab3dc86cd1ad --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,"NOT_IDENT",bar)` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) + diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr new file mode 100644 index 000000000000..c04b15ec265c --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `abc()` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) + diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr new file mode 100644 index 000000000000..cee65f9887b9 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,test())` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) + diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr new file mode 100644 index 000000000000..2441e2537b74 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(test()))` (`values()` arguments must be string literals or `any()`) + diff --git a/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr b/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr new file mode 100644 index 000000000000..fc93ec8fbdfd --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(values(any()),foo)` (`values()` cannot be specified before the names) + diff --git a/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr b/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr new file mode 100644 index 000000000000..f41672fcbdb6 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,any())` (`cfg(any())` can only be provided in isolation) + diff --git a/tests/ui/check-cfg/invalid-cfg-name.rs b/tests/ui/check-cfg/invalid-cfg-name.rs deleted file mode 100644 index 8499d3d4448d..000000000000 --- a/tests/ui/check-cfg/invalid-cfg-name.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Check warning for invalid configuration name -// -// edition:2018 -// check-pass -// compile-flags: --check-cfg=names() -Z unstable-options - -#[cfg(widnows)] -//~^ WARNING unexpected `cfg` condition name -pub fn f() {} - -#[cfg(windows)] -pub fn g() {} - -pub fn main() {} diff --git a/tests/ui/check-cfg/invalid-cfg-value.rs b/tests/ui/check-cfg/invalid-cfg-value.rs deleted file mode 100644 index 9e428d367fdf..000000000000 --- a/tests/ui/check-cfg/invalid-cfg-value.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Check warning for invalid configuration value -// -// edition:2018 -// check-pass -// compile-flags: --check-cfg=values(feature,"serde","full") --cfg=feature="rand" -Z unstable-options - -#[cfg(feature = "sedre")] -//~^ WARNING unexpected `cfg` condition value -pub fn f() {} - -#[cfg(feature = "serde")] -pub fn g() {} - -#[cfg(feature = "rand")] -//~^ WARNING unexpected `cfg` condition value -pub fn h() {} - -pub fn main() {} diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.cfg.stderr similarity index 81% rename from tests/ui/check-cfg/mix.stderr rename to tests/ui/check-cfg/mix.cfg.stderr index 23da9f22a72c..daa200440cc9 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.cfg.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `widnows` - --> $DIR/mix.rs:11:7 + --> $DIR/mix.rs:15:7 | LL | #[cfg(widnows)] | ^^^^^^^ help: there is a config with a similar name: `windows` @@ -7,7 +7,7 @@ LL | #[cfg(widnows)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) - --> $DIR/mix.rs:15:7 + --> $DIR/mix.rs:19:7 | LL | #[cfg(feature)] | ^^^^^^^- help: specify a config value: `= "foo"` @@ -15,7 +15,7 @@ LL | #[cfg(feature)] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `bar` - --> $DIR/mix.rs:22:7 + --> $DIR/mix.rs:26:7 | LL | #[cfg(feature = "bar")] | ^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | #[cfg(feature = "bar")] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:26:7 + --> $DIR/mix.rs:30:7 | LL | #[cfg(feature = "zebra")] | ^^^^^^^^^^^^^^^^^ @@ -31,12 +31,12 @@ LL | #[cfg(feature = "zebra")] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `uu` - --> $DIR/mix.rs:30:12 + --> $DIR/mix.rs:34:12 | LL | #[cfg_attr(uu, test)] | ^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` warning: unexpected condition value `bar` for condition name `feature` | @@ -47,13 +47,13 @@ warning: unexpected `unknown_name` as condition name = help: was set with `--cfg` but isn't in the `--check-cfg` expected names warning: unexpected `cfg` condition name: `widnows` - --> $DIR/mix.rs:39:10 + --> $DIR/mix.rs:43:10 | LL | cfg!(widnows); | ^^^^^^^ help: there is a config with a similar name: `windows` warning: unexpected `cfg` condition value: `bar` - --> $DIR/mix.rs:42:10 + --> $DIR/mix.rs:46:10 | LL | cfg!(feature = "bar"); | ^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | cfg!(feature = "bar"); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:44:10 + --> $DIR/mix.rs:48:10 | LL | cfg!(feature = "zebra"); | ^^^^^^^^^^^^^^^^^ @@ -69,25 +69,25 @@ LL | cfg!(feature = "zebra"); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:46:10 + --> $DIR/mix.rs:50:10 | LL | cfg!(xxx = "foo"); | ^^^^^^^^^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:48:10 + --> $DIR/mix.rs:52:10 | LL | cfg!(xxx); | ^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:50:14 + --> $DIR/mix.rs:54:14 | LL | cfg!(any(xxx, windows)); | ^^^ warning: unexpected `cfg` condition value: `bad` - --> $DIR/mix.rs:52:14 + --> $DIR/mix.rs:56:14 | LL | cfg!(any(feature = "bad", windows)); | ^^^^^^^^^^^^^^^ @@ -95,43 +95,43 @@ LL | cfg!(any(feature = "bad", windows)); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:54:23 + --> $DIR/mix.rs:58:23 | LL | cfg!(any(windows, xxx)); | ^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:56:20 + --> $DIR/mix.rs:60:20 | LL | cfg!(all(unix, xxx)); | ^^^ warning: unexpected `cfg` condition name: `aa` - --> $DIR/mix.rs:58:14 + --> $DIR/mix.rs:62:14 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name: `bb` - --> $DIR/mix.rs:58:18 + --> $DIR/mix.rs:62:18 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name: `aa` - --> $DIR/mix.rs:61:14 + --> $DIR/mix.rs:65:14 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition name: `bb` - --> $DIR/mix.rs:61:18 + --> $DIR/mix.rs:65:18 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:64:20 + --> $DIR/mix.rs:68:20 | LL | cfg!(any(unix, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -139,13 +139,13 @@ LL | cfg!(any(unix, feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:66:14 + --> $DIR/mix.rs:70:14 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^ warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:66:19 + --> $DIR/mix.rs:70:19 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -153,19 +153,19 @@ LL | cfg!(any(xxx, feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:69:14 + --> $DIR/mix.rs:73:14 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:69:25 + --> $DIR/mix.rs:73:25 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:72:14 + --> $DIR/mix.rs:76:14 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -173,7 +173,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:72:33 + --> $DIR/mix.rs:76:33 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:72:52 + --> $DIR/mix.rs:76:52 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/mix.names_values.stderr b/tests/ui/check-cfg/mix.names_values.stderr new file mode 100644 index 000000000000..daa200440cc9 --- /dev/null +++ b/tests/ui/check-cfg/mix.names_values.stderr @@ -0,0 +1,192 @@ +warning: unexpected `cfg` condition name: `widnows` + --> $DIR/mix.rs:15:7 + | +LL | #[cfg(widnows)] + | ^^^^^^^ help: there is a config with a similar name: `windows` + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: (none) + --> $DIR/mix.rs:19:7 + | +LL | #[cfg(feature)] + | ^^^^^^^- help: specify a config value: `= "foo"` + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `bar` + --> $DIR/mix.rs:26:7 + | +LL | #[cfg(feature = "bar")] + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:30:7 + | +LL | #[cfg(feature = "zebra")] + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `uu` + --> $DIR/mix.rs:34:12 + | +LL | #[cfg_attr(uu, test)] + | ^^ + | + = help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + +warning: unexpected condition value `bar` for condition name `feature` + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected values + +warning: unexpected `unknown_name` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: unexpected `cfg` condition name: `widnows` + --> $DIR/mix.rs:43:10 + | +LL | cfg!(widnows); + | ^^^^^^^ help: there is a config with a similar name: `windows` + +warning: unexpected `cfg` condition value: `bar` + --> $DIR/mix.rs:46:10 + | +LL | cfg!(feature = "bar"); + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:48:10 + | +LL | cfg!(feature = "zebra"); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:50:10 + | +LL | cfg!(xxx = "foo"); + | ^^^^^^^^^^^ + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:52:10 + | +LL | cfg!(xxx); + | ^^^ + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:54:14 + | +LL | cfg!(any(xxx, windows)); + | ^^^ + +warning: unexpected `cfg` condition value: `bad` + --> $DIR/mix.rs:56:14 + | +LL | cfg!(any(feature = "bad", windows)); + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:58:23 + | +LL | cfg!(any(windows, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:60:20 + | +LL | cfg!(all(unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name: `aa` + --> $DIR/mix.rs:62:14 + | +LL | cfg!(all(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name: `bb` + --> $DIR/mix.rs:62:18 + | +LL | cfg!(all(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name: `aa` + --> $DIR/mix.rs:65:14 + | +LL | cfg!(any(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name: `bb` + --> $DIR/mix.rs:65:18 + | +LL | cfg!(any(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:68:20 + | +LL | cfg!(any(unix, feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:70:14 + | +LL | cfg!(any(xxx, feature = "zebra")); + | ^^^ + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:70:19 + | +LL | cfg!(any(xxx, feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:73:14 + | +LL | cfg!(any(xxx, unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:73:25 + | +LL | cfg!(any(xxx, unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:76:14 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:76:33 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:76:52 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: 28 warnings emitted + diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs index 9adf5c46e43f..d7b3b4953b7a 100644 --- a/tests/ui/check-cfg/mix.rs +++ b/tests/ui/check-cfg/mix.rs @@ -3,7 +3,11 @@ // we correctly lint on the `cfg!` macro and `cfg_attr` attribute. // // check-pass -// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" --cfg unknown_name -Z unstable-options +// revisions: names_values cfg +// compile-flags: --cfg feature="bar" --cfg unknown_name -Z unstable-options +// compile-flags: --check-cfg=cfg(names_values,cfg) +// [names_values]compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") +// [cfg]compile-flags: --check-cfg=cfg(feature,values("foo")) #[cfg(windows)] fn do_windows_stuff() {} diff --git a/tests/ui/check-cfg/no-values.stderr b/tests/ui/check-cfg/no-expected-values.empty.stderr similarity index 86% rename from tests/ui/check-cfg/no-values.stderr rename to tests/ui/check-cfg/no-expected-values.empty.stderr index b05a569dd01c..5d261b2a5e63 100644 --- a/tests/ui/check-cfg/no-values.stderr +++ b/tests/ui/check-cfg/no-expected-values.empty.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-values.rs:6:7 + --> $DIR/no-expected-values.rs:12:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^-------- @@ -10,7 +10,7 @@ LL | #[cfg(feature = "foo")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-values.rs:10:7 + --> $DIR/no-expected-values.rs:16:7 | LL | #[cfg(test = "foo")] | ^^^^-------- diff --git a/tests/ui/check-cfg/no-expected-values.mixed.stderr b/tests/ui/check-cfg/no-expected-values.mixed.stderr new file mode 100644 index 000000000000..5d261b2a5e63 --- /dev/null +++ b/tests/ui/check-cfg/no-expected-values.mixed.stderr @@ -0,0 +1,23 @@ +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:12:7 + | +LL | #[cfg(feature = "foo")] + | ^^^^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `feature` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:16:7 + | +LL | #[cfg(test = "foo")] + | ^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/no-expected-values.rs b/tests/ui/check-cfg/no-expected-values.rs new file mode 100644 index 000000000000..9e2a9f09aedc --- /dev/null +++ b/tests/ui/check-cfg/no-expected-values.rs @@ -0,0 +1,20 @@ +// Check that we detect unexpected value when none are allowed +// +// check-pass +// revisions: values simple mixed empty +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(values,simple,mixed,empty) +// [values]compile-flags: --check-cfg=values(test) --check-cfg=values(feature) +// [simple]compile-flags: --check-cfg=cfg(test) --check-cfg=cfg(feature) +// [mixed]compile-flags: --check-cfg=cfg(test,feature) +// [empty]compile-flags: --check-cfg=cfg(test,feature,values()) + +#[cfg(feature = "foo")] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +#[cfg(test = "foo")] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +fn main() {} diff --git a/tests/ui/check-cfg/no-expected-values.simple.stderr b/tests/ui/check-cfg/no-expected-values.simple.stderr new file mode 100644 index 000000000000..5d261b2a5e63 --- /dev/null +++ b/tests/ui/check-cfg/no-expected-values.simple.stderr @@ -0,0 +1,23 @@ +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:12:7 + | +LL | #[cfg(feature = "foo")] + | ^^^^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `feature` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:16:7 + | +LL | #[cfg(test = "foo")] + | ^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/no-expected-values.values.stderr b/tests/ui/check-cfg/no-expected-values.values.stderr new file mode 100644 index 000000000000..5d261b2a5e63 --- /dev/null +++ b/tests/ui/check-cfg/no-expected-values.values.stderr @@ -0,0 +1,23 @@ +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:12:7 + | +LL | #[cfg(feature = "foo")] + | ^^^^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `feature` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:16:7 + | +LL | #[cfg(test = "foo")] + | ^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/no-values.rs b/tests/ui/check-cfg/no-values.rs deleted file mode 100644 index 8c80f56cb5a3..000000000000 --- a/tests/ui/check-cfg/no-values.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Check that we detect unexpected value when none are allowed -// -// check-pass -// compile-flags: --check-cfg=values(test) --check-cfg=values(feature) -Z unstable-options - -#[cfg(feature = "foo")] -//~^ WARNING unexpected `cfg` condition value -fn do_foo() {} - -#[cfg(test = "foo")] -//~^ WARNING unexpected `cfg` condition value -fn do_foo() {} - -fn main() {} diff --git a/tests/ui/check-cfg/stmt-no-ice.rs b/tests/ui/check-cfg/stmt-no-ice.rs index cf76487ed46f..383e830a1b22 100644 --- a/tests/ui/check-cfg/stmt-no-ice.rs +++ b/tests/ui/check-cfg/stmt-no-ice.rs @@ -1,7 +1,7 @@ // This test checks that there is no ICE with this code // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags:--check-cfg=cfg() -Z unstable-options fn main() { #[cfg(crossbeam_loom)] diff --git a/tests/ui/check-cfg/invalid-cfg-name.stderr b/tests/ui/check-cfg/unexpected-cfg-name.exhaustive.stderr similarity index 86% rename from tests/ui/check-cfg/invalid-cfg-name.stderr rename to tests/ui/check-cfg/unexpected-cfg-name.exhaustive.stderr index 8c3c72c96671..513f7ac7fd18 100644 --- a/tests/ui/check-cfg/invalid-cfg-name.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-name.exhaustive.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `widnows` - --> $DIR/invalid-cfg-name.rs:7:7 + --> $DIR/unexpected-cfg-name.rs:9:7 | LL | #[cfg(widnows)] | ^^^^^^^ help: there is a config with a similar name: `windows` diff --git a/tests/ui/check-cfg/unexpected-cfg-name.names.stderr b/tests/ui/check-cfg/unexpected-cfg-name.names.stderr new file mode 100644 index 000000000000..513f7ac7fd18 --- /dev/null +++ b/tests/ui/check-cfg/unexpected-cfg-name.names.stderr @@ -0,0 +1,10 @@ +warning: unexpected `cfg` condition name: `widnows` + --> $DIR/unexpected-cfg-name.rs:9:7 + | +LL | #[cfg(widnows)] + | ^^^^^^^ help: there is a config with a similar name: `windows` + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/unexpected-cfg-name.rs b/tests/ui/check-cfg/unexpected-cfg-name.rs new file mode 100644 index 000000000000..15c3aa6e0812 --- /dev/null +++ b/tests/ui/check-cfg/unexpected-cfg-name.rs @@ -0,0 +1,16 @@ +// Check warning for unexpected configuration name +// +// check-pass +// revisions: names exhaustive +// compile-flags: --check-cfg=cfg(names,exhaustive) +// [names]compile-flags: --check-cfg=names() -Z unstable-options +// [exhaustive]compile-flags: --check-cfg=cfg() -Z unstable-options + +#[cfg(widnows)] +//~^ WARNING unexpected `cfg` condition name +pub fn f() {} + +#[cfg(windows)] +pub fn g() {} + +pub fn main() {} diff --git a/tests/ui/check-cfg/invalid-cfg-value.stderr b/tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr similarity index 89% rename from tests/ui/check-cfg/invalid-cfg-value.stderr rename to tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr index 947beac6ffd6..2ed7f9005573 100644 --- a/tests/ui/check-cfg/invalid-cfg-value.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `sedre` - --> $DIR/invalid-cfg-value.rs:7:7 + --> $DIR/unexpected-cfg-value.rs:11:7 | LL | #[cfg(feature = "sedre")] | ^^^^^^^^^^------- @@ -10,7 +10,7 @@ LL | #[cfg(feature = "sedre")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `rand` - --> $DIR/invalid-cfg-value.rs:14:7 + --> $DIR/unexpected-cfg-value.rs:18:7 | LL | #[cfg(feature = "rand")] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/unexpected-cfg-value.rs b/tests/ui/check-cfg/unexpected-cfg-value.rs new file mode 100644 index 000000000000..a84458071de8 --- /dev/null +++ b/tests/ui/check-cfg/unexpected-cfg-value.rs @@ -0,0 +1,22 @@ +// Check warning for invalid configuration value in the code and +// in the cli +// +// check-pass +// revisions: values cfg +// compile-flags: --cfg=feature="rand" -Z unstable-options +// compile-flags: --check-cfg=cfg(values,cfg) +// [values]compile-flags: --check-cfg=values(feature,"serde","full") +// [cfg]compile-flags: --check-cfg=cfg(feature,values("serde","full")) + +#[cfg(feature = "sedre")] +//~^ WARNING unexpected `cfg` condition value +pub fn f() {} + +#[cfg(feature = "serde")] +pub fn g() {} + +#[cfg(feature = "rand")] +//~^ WARNING unexpected `cfg` condition value +pub fn h() {} + +pub fn main() {} diff --git a/tests/ui/check-cfg/unexpected-cfg-value.values.stderr b/tests/ui/check-cfg/unexpected-cfg-value.values.stderr new file mode 100644 index 000000000000..2ed7f9005573 --- /dev/null +++ b/tests/ui/check-cfg/unexpected-cfg-value.values.stderr @@ -0,0 +1,25 @@ +warning: unexpected `cfg` condition value: `sedre` + --> $DIR/unexpected-cfg-value.rs:11:7 + | +LL | #[cfg(feature = "sedre")] + | ^^^^^^^^^^------- + | | + | help: there is a expected value with a similar name: `"serde"` + | + = note: expected values for `feature` are: `full`, `serde` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `rand` + --> $DIR/unexpected-cfg-value.rs:18:7 + | +LL | #[cfg(feature = "rand")] + | ^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `full`, `serde` + +warning: unexpected condition value `rand` for condition name `feature` + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected values + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/unknown-values.rs b/tests/ui/check-cfg/unknown-values.rs new file mode 100644 index 000000000000..c082a2f25ace --- /dev/null +++ b/tests/ui/check-cfg/unknown-values.rs @@ -0,0 +1,17 @@ +// Check that no warning is emitted for unknown cfg value +// +// check-pass +// revisions: simple mixed with_values +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(simple,mixed,with_values) +// [simple]compile-flags: --check-cfg=cfg(foo,values(any())) +// [mixed]compile-flags: --check-cfg=cfg(foo) --check-cfg=cfg(foo,values(any())) +// [with_values]compile-flags:--check-cfg=cfg(foo,values(any())) --check-cfg=cfg(foo,values("aa")) + +#[cfg(foo = "value")] +pub fn f() {} + +#[cfg(foo)] +pub fn f() {} + +fn main() {} diff --git a/tests/ui/check-cfg/well-known-names.rs b/tests/ui/check-cfg/well-known-names.rs index e57fb69a1e05..1dcb419b4a73 100644 --- a/tests/ui/check-cfg/well-known-names.rs +++ b/tests/ui/check-cfg/well-known-names.rs @@ -1,7 +1,7 @@ // This test checks that we lint on non well known names and that we don't lint on well known names // // check-pass -// compile-flags: --check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[cfg(target_oz = "linux")] //~^ WARNING unexpected `cfg` condition name diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index a5d38a99eeec..3001289b7e06 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -2,11 +2,13 @@ warning: unexpected `cfg` condition name: `target_oz` --> $DIR/well-known-names.rs:6:7 | LL | #[cfg(target_oz = "linux")] - | ---------^^^^^^^^^^ - | | - | help: there is a config with a similar name: `target_os` + | ^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unexpected_cfgs)]` on by default +help: there is a config with a similar name and value + | +LL | #[cfg(target_os = "linux")] + | ~~~~~~~~~ warning: unexpected `cfg` condition name: `features` --> $DIR/well-known-names.rs:13:7 diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index 96375dc8d313..8b56c8729d84 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -2,7 +2,7 @@ // values // // check-pass -// compile-flags: --check-cfg=values() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[cfg(target_os = "linuz")] //~^ WARNING unexpected `cfg` condition value From 6d23ee8430df1b2dfedb48f8321d9c47b26d7858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 14 Oct 2023 04:11:54 +0000 Subject: [PATCH 13/94] Special case iterator chain checks for suggestion When encountering method call chains of `Iterator`, check for trailing `;` in the body of closures passed into `Iterator::map`, as well as calls to `::clone` when `T` is a type param and `T: !Clone`. Fix #9082. --- .../src/traits/error_reporting/suggestions.rs | 92 +++++++++- .../invalid-iterator-chain-fixable.fixed | 42 +++++ .../invalid-iterator-chain-fixable.rs | 42 +++++ .../invalid-iterator-chain-fixable.stderr | 157 ++++++++++++++++++ .../iterators/invalid-iterator-chain.stderr | 26 +++ 5 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 tests/ui/iterators/invalid-iterator-chain-fixable.fixed create mode 100644 tests/ui/iterators/invalid-iterator-chain-fixable.rs create mode 100644 tests/ui/iterators/invalid-iterator-chain-fixable.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 9aebe77a1048..fd52d6296603 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3611,13 +3611,103 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut prev_ty = self.resolve_vars_if_possible( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), ); - while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind { + while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind { // Point at every method call in the chain with the resulting type. // vec![1, 2, 3].iter().map(mapper).sum() // ^^^^^^ ^^^^^^^^^^^ expr = rcvr_expr; let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env); + // Special case for iterator chains, we look at potential failures of `Iterator::Item` + // not being `: Clone` and `Iterator::map` calls with spurious trailing `;`. + for entry in &assocs_in_this_method { + let Some((_span, (def_id, ty))) = entry else { + continue; + }; + for diff in &type_diffs { + let Sorts(expected_found) = diff else { + continue; + }; + if tcx.is_diagnostic_item(sym::IteratorItem, *def_id) + && path_segment.ident.name == sym::map + && self.can_eq(param_env, expected_found.found, *ty) + && let [arg] = args + && let hir::ExprKind::Closure(closure) = arg.kind + { + let body = tcx.hir().body(closure.body); + if let hir::ExprKind::Block(block, None) = body.value.kind + && let None = block.expr + && let [.., stmt] = block.stmts + && let hir::StmtKind::Semi(expr) = stmt.kind + // FIXME: actually check the expected vs found types, but right now + // the expected is a projection that we need to resolve. + // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr) + && expected_found.found.is_unit() + { + err.span_suggestion_verbose( + expr.span.shrink_to_hi().with_hi(stmt.span.hi()), + "consider removing this semicolon", + String::new(), + Applicability::MachineApplicable, + ); + } + let expr = if let hir::ExprKind::Block(block, None) = body.value.kind + && let Some(expr) = block.expr + { + expr + } else { + body.value + }; + if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind + && path_segment.ident.name == sym::clone + && let Some(expr_ty) = typeck_results.expr_ty_opt(expr) + && let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr) + && self.can_eq(param_env, expr_ty, rcvr_ty) + && let ty::Ref(_, ty, _) = expr_ty.kind() + { + err.span_label( + span, + format!( + "this method call is cloning the reference `{expr_ty}`, not \ + `{ty}` which doesn't implement `Clone`", + ), + ); + let ty::Param(..) = ty.kind() else { + continue; + }; + let hir = tcx.hir(); + let node = hir.get_by_def_id(hir.get_parent_item(expr.hir_id).def_id); + + let pred = ty::Binder::dummy(ty::TraitPredicate { + trait_ref: ty::TraitRef::from_lang_item( + tcx, + LangItem::Clone, + span, + [*ty], + ), + polarity: ty::ImplPolarity::Positive, + }); + let Some(generics) = node.generics() else { + continue; + }; + let Some(body_id) = node.body_id() else { + continue; + }; + suggest_restriction( + tcx, + hir.body_owner_def_id(body_id), + &generics, + &format!("type parameter `{ty}`"), + err, + node.fn_sig(), + None, + pred, + None, + ); + } + } + } + } assocs.push(assocs_in_this_method); prev_ty = self.resolve_vars_if_possible( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.fixed b/tests/ui/iterators/invalid-iterator-chain-fixable.fixed new file mode 100644 index 000000000000..513b5bd13d83 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.fixed @@ -0,0 +1,42 @@ +// run-rustfix +use std::collections::hash_set::Iter; +use std::collections::HashSet; + +fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec where X: Clone { + let i = i.map(|x| x.clone()); + i.collect() //~ ERROR E0277 +} + +fn main() { + let v = vec![(0, 0)]; + let scores = v + .iter() + .map(|(a, b)| { + a + b + }); + println!("{}", scores.sum::()); //~ ERROR E0277 + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| { x }) + .map(|x| { x }) + .sum::(), //~ ERROR E0277 + ); + println!("{}", vec![0, 1].iter().map(|x| { x }).sum::()); //~ ERROR E0277 + let a = vec![0]; + let b = a.into_iter(); + let c = b.map(|x| x + 1); + let d = c.filter(|x| *x > 10 ); + let e = d.map(|x| { + x + 1 + }); + let f = e.filter(|_| false); + let g: Vec = f.collect(); //~ ERROR E0277 + println!("{g:?}"); + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); +} diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.rs b/tests/ui/iterators/invalid-iterator-chain-fixable.rs new file mode 100644 index 000000000000..79b861702c78 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.rs @@ -0,0 +1,42 @@ +// run-rustfix +use std::collections::hash_set::Iter; +use std::collections::HashSet; + +fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec { + let i = i.map(|x| x.clone()); + i.collect() //~ ERROR E0277 +} + +fn main() { + let v = vec![(0, 0)]; + let scores = v + .iter() + .map(|(a, b)| { + a + b; + }); + println!("{}", scores.sum::()); //~ ERROR E0277 + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| { x; }) + .map(|x| { x }) + .sum::(), //~ ERROR E0277 + ); + println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); //~ ERROR E0277 + let a = vec![0]; + let b = a.into_iter(); + let c = b.map(|x| x + 1); + let d = c.filter(|x| *x > 10 ); + let e = d.map(|x| { + x + 1; + }); + let f = e.filter(|_| false); + let g: Vec = f.collect(); //~ ERROR E0277 + println!("{g:?}"); + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); +} diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr new file mode 100644 index 000000000000..1bfe765e78af --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr @@ -0,0 +1,157 @@ +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&X` + --> $DIR/invalid-iterator-chain-fixable.rs:7:7 + | +LL | let i = i.map(|x| x.clone()); + | ------- this method call is cloning the reference `&X`, not `X` which doesn't implement `Clone` +LL | i.collect() + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<&X>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` + = help: for that trait implementation, expected `X`, found `&X` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:5:26 + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec { + | ^^^^^^^^^^^ `Iterator::Item` is `&X` here +LL | let i = i.map(|x| x.clone()); + | ------------------ `Iterator::Item` remains `&X` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider further restricting type parameter `X` + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec where X: Clone { + | ++++++++++++++ + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:17:33 + | +LL | println!("{}", scores.sum::()); + | --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | | + | required by a bound introduced by this call + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + + > +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:14:10 + | +LL | let v = vec![(0, 0)]; + | ------------ this expression has type `Vec<({integer}, {integer})>` +LL | let scores = v +LL | .iter() + | ------ `Iterator::Item` is `&({integer}, {integer})` here +LL | .map(|(a, b)| { + | __________^ +LL | | a + b; +LL | | }); + | |__________^ `Iterator::Item` changed to `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - a + b; +LL + a + b + | + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:25:20 + | +LL | .sum::(), + | --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | | + | required by a bound introduced by this call + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + + > +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:23:14 + | +LL | vec![0, 1] + | ---------- this expression has type `Vec<{integer}>` +LL | .iter() + | ------ `Iterator::Item` is `&{integer}` here +LL | .map(|x| x * 2) + | -------------- `Iterator::Item` changed to `{integer}` here +LL | .map(|x| { x; }) + | ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here +LL | .map(|x| { x }) + | -------------- `Iterator::Item` remains `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - .map(|x| { x; }) +LL + .map(|x| { x }) + | + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:27:60 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); + | --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | | + | required by a bound introduced by this call + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + + > +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:27:38 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); + | ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here + | | | + | | `Iterator::Item` is `&{integer}` here + | this expression has type `Vec<{integer}>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); +LL + println!("{}", vec![0, 1].iter().map(|x| { x }).sum::()); + | + +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:36:25 + | +LL | let g: Vec = f.collect(); + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<()>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` + = help: for that trait implementation, expected `i32`, found `()` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:32:15 + | +LL | let a = vec![0]; + | ------- this expression has type `Vec<{integer}>` +LL | let b = a.into_iter(); + | ----------- `Iterator::Item` is `{integer}` here +LL | let c = b.map(|x| x + 1); + | -------------- `Iterator::Item` remains `{integer}` here +LL | let d = c.filter(|x| *x > 10 ); + | -------------------- `Iterator::Item` remains `{integer}` here +LL | let e = d.map(|x| { + | _______________^ +LL | | x + 1; +LL | | }); + | |______^ `Iterator::Item` changed to `()` here +LL | let f = e.filter(|_| false); + | ----------------- `Iterator::Item` remains `()` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - x + 1; +LL + x + 1 + | + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr index 2601c9c0d69d..4dc130869123 100644 --- a/tests/ui/iterators/invalid-iterator-chain.stderr +++ b/tests/ui/iterators/invalid-iterator-chain.stderr @@ -1,6 +1,8 @@ error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&X` --> $DIR/invalid-iterator-chain.rs:6:7 | +LL | let i = i.map(|x| x.clone()); + | ------- this method call is cloning the reference `&X`, not `X` which doesn't implement `Clone` LL | i.collect() | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | @@ -16,6 +18,10 @@ LL | let i = i.map(|x| x.clone()); | ------------------ `Iterator::Item` remains `&X` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider further restricting type parameter `X` + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec where X: Clone { + | ++++++++++++++ error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:15:33 @@ -43,6 +49,11 @@ LL | | }); | |__________^ `Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - a + b; +LL + a + b + | error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:26:20 @@ -77,6 +88,11 @@ LL | .map(|x| { x; }) | ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - .map(|x| { x; }) +LL + .map(|x| { x }) + | error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64` --> $DIR/invalid-iterator-chain.rs:36:20 @@ -130,6 +146,11 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); | this expression has type `Vec<{integer}>` note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); +LL + println!("{}", vec![0, 1].iter().map(|x| { x }).sum::()); + | error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` --> $DIR/invalid-iterator-chain.rs:39:46 @@ -182,6 +203,11 @@ LL | let f = e.filter(|_| false); | ----------------- `Iterator::Item` remains `()` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - x + 1; +LL + x + 1 + | error: aborting due to 7 previous errors From f0f89d6d43fc78f0aeefa2e7180257592fa57917 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 15 Oct 2023 08:51:54 +0000 Subject: [PATCH 14/94] Duplicate `~const` bounds with a non-const one in effects desugaring --- .../rustc_hir_analysis/src/astconv/mod.rs | 34 +- compiler/rustc_hir_analysis/src/bounds.rs | 27 + .../src/collect/predicates_of.rs | 37 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 +- compiler/rustc_middle/src/ty/generics.rs | 4 + .../assoc-type-const-bound-usage.stderr | 14 +- .../effects/minicore.rs | 504 ++++++++++++++++++ .../effects/minicore.stderr | 32 ++ .../effects/project.rs | 11 + .../trait-where-clause-const.stderr | 34 +- 10 files changed, 661 insertions(+), 40 deletions(-) create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index a91d92313902..82cbed2639ed 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1088,7 +1088,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name) }); - let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) { + let (mut bound, mut next_cand) = match (matching_candidates.next(), const_candidates.next()) + { (Some(bound), _) => (bound, matching_candidates.next()), (None, Some(bound)) => (bound, const_candidates.next()), (None, None) => { @@ -1103,6 +1104,37 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; debug!(?bound); + // look for a candidate that is not the same as our first bound, disregarding + // whether the bound is const. + while let Some(mut bound2) = next_cand { + debug!(?bound2); + let tcx = self.tcx(); + if bound2.bound_vars() != bound.bound_vars() { + break; + } + + let generics = tcx.generics_of(bound.def_id()); + let Some(host_index) = generics.host_effect_index else { break }; + + // always return the bound that contains the host param. + if let ty::ConstKind::Param(_) = bound2.skip_binder().args.const_at(host_index).kind() { + (bound, bound2) = (bound2, bound); + } + + let unconsted_args = bound + .skip_binder() + .args + .iter() + .enumerate() + .map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg }); + + if unconsted_args.eq(bound2.skip_binder().args.iter()) { + next_cand = matching_candidates.next().or_else(|| const_candidates.next()); + } else { + break; + } + } + if let Some(bound2) = next_cand { debug!(?bound2); diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 1d9ae2b9cb73..af1a4e5d99e9 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -43,6 +43,33 @@ impl<'tcx> Bounds<'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, span: Span, polarity: ty::ImplPolarity, + ) { + self.push_trait_bound_inner(tcx, trait_ref, span, polarity); + + // if we have a host param, we push an unconst trait bound in addition + // to the const one. + // FIXME(effects) we should find a better way than name matching + if tcx.features().effects && trait_ref.skip_binder().args.host_effect_param().is_some() { + let generics = tcx.generics_of(trait_ref.def_id()); + let Some(host_index) = generics.host_effect_index else { return }; + let trait_ref = trait_ref.map_bound(|mut trait_ref| { + trait_ref.args = + tcx.mk_args_from_iter(trait_ref.args.iter().enumerate().map(|(n, arg)| { + if host_index == n { tcx.consts.true_.into() } else { arg } + })); + trait_ref + }); + + self.push_trait_bound_inner(tcx, trait_ref, span, polarity); + } + } + + fn push_trait_bound_inner( + &mut self, + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + span: Span, + polarity: ty::ImplPolarity, ) { self.clauses.push(( trait_ref diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 1298c0860871..06e18785a60e 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate}; use rustc_span::symbol::Ident; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{sym, Span, DUMMY_SP}; /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus @@ -38,11 +38,38 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic // an obligation and instead be skipped. Otherwise we'd use // `tcx.def_span(def_id);` let span = rustc_span::DUMMY_SP; - result.predicates = - tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( - ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), + let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) { + // when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound, + // because only implementing `Self: Trait<.., false>` is currently not possible. + Some(( + ty::TraitRef::new( + tcx, + def_id, + ty::GenericArgs::for_item(tcx, def_id, |param, _| { + if param.is_host_effect() { + tcx.consts.true_.into() + } else { + tcx.mk_param_from_def(param) + } + }), + ) + .to_predicate(tcx), span, - )))); + )) + } else { + None + }; + result.predicates = tcx.arena.alloc_from_iter( + result + .predicates + .iter() + .copied() + .chain(std::iter::once(( + ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), + span, + ))) + .chain(non_const_bound), + ); } debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); result diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 4a245d30c8e3..7677d6f953b6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -221,14 +221,14 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { let item_def_id = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; + // HACK(eddyb) should get the original `Span`. + let span = tcx.def_span(def_id); ty::GenericPredicates { parent: None, predicates: tcx.arena.alloc_from_iter( self.param_env.caller_bounds().iter().filter_map(|predicate| { match predicate.kind().skip_binder() { ty::ClauseKind::Trait(data) if data.self_ty().is_param(index) => { - // HACK(eddyb) should get the original `Span`. - let span = tcx.def_span(def_id); Some((predicate, span)) } _ => None, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 8e6c1cd4bbb6..44e88d3e2302 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -79,6 +79,10 @@ impl GenericParamDef { } } + pub fn is_host_effect(&self) -> bool { + matches!(self.kind, GenericParamDefKind::Const { is_host_effect: true, .. }) + } + pub fn default_value<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr index ad11c090f122..6d436018bf4b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr @@ -1,14 +1,12 @@ -error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/assoc-type-const-bound-usage.rs:12:6 +error[E0308]: mismatched types + --> $DIR/assoc-type-const-bound-usage.rs:12:5 | LL | ::Assoc::foo(); - | ^ the trait `Foo` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true` | -help: consider further restricting this bound - | -LL | const fn foo() { - | +++++ + = note: expected constant `host` + found constant `true` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs new file mode 100644 index 000000000000..c38b4b3f1a2e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -0,0 +1,504 @@ +#![crate_type = "lib"] +#![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs)] +#![feature(fundamental)] +#![feature(const_trait_impl, effects, const_mut_refs)] +#![allow(internal_features)] +#![no_std] +#![no_core] + +// known-bug: #110395 + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[lang = "add"] +#[const_trait] +trait Add { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; +} + +// FIXME we shouldn't need to have to specify `Rhs`. +impl const Add for i32 { + type Output = i32; + fn add(self, rhs: i32) -> i32 { + loop {} + } +} + +fn foo() { + let x = 42_i32 + 43_i32; +} + +const fn bar() { + let x = 42_i32 + 43_i32; +} + + +#[lang = "Try"] +#[const_trait] +trait Try: FromResidual { + type Output; + type Residual; + + #[lang = "from_output"] + fn from_output(output: Self::Output) -> Self; + + #[lang = "branch"] + fn branch(self) -> ControlFlow; +} + +// FIXME +// #[const_trait] +trait FromResidual::Residual> { + #[lang = "from_residual"] + fn from_residual(residual: R) -> Self; +} + +enum ControlFlow { + #[lang = "Continue"] + Continue(C), + #[lang = "Break"] + Break(B), +} + +#[const_trait] +#[lang = "fn"] +#[rustc_paren_sugar] +trait Fn: ~const FnMut { + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_mut"] +#[rustc_paren_sugar] +trait FnMut: ~const FnOnce { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_once"] +#[rustc_paren_sugar] +trait FnOnce { + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct ConstFnMutClosure { + data: CapturedData, + func: Function, +} + +#[lang = "tuple_trait"] +pub trait Tuple {} + +macro_rules! impl_fn_mut_tuple { + ($($var:ident)*) => { + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnOnce for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue, + Function: ~const Destruct, + { + type Output = ClosureReturnValue; + + extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { + self.call_mut(args) + } + } + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnMut for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue, + Function: ~const Destruct, + { + extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { + #[allow(non_snake_case)] + let ($($var),*) = &mut self.data; + (self.func)(($($var),*), args) + } + } + }; +} +//impl_fn_mut_tuple!(A); +//impl_fn_mut_tuple!(A B); +//impl_fn_mut_tuple!(A B C); +//impl_fn_mut_tuple!(A B C D); +//impl_fn_mut_tuple!(A B C D E); + +#[lang = "receiver"] +trait Receiver {} + +impl Receiver for &T {} + +impl Receiver for &mut T {} + +#[lang = "destruct"] +#[const_trait] +trait Destruct {} + +#[lang = "freeze"] +unsafe auto trait Freeze {} + +#[lang = "drop"] +#[const_trait] +trait Drop { + fn drop(&mut self); +} + +/* +#[const_trait] +trait Residual { + type TryType: ~const Try + Try; +} +*/ + +const fn size_of() -> usize { + 42 +} + +impl Copy for u8 {} + +impl usize { + #[rustc_allow_incoherent_impl] + const fn repeat_u8(x: u8) -> usize { + usize::from_ne_bytes([x; size_of::()]) + } + #[rustc_allow_incoherent_impl] + const fn from_ne_bytes(bytes: [u8; size_of::()]) -> Self { + loop {} + } +} + +#[rustc_do_not_const_check] // hooked by const-eval +const fn panic_display() { + panic_fmt(); +} + +fn panic_fmt() {} + +#[lang = "index"] +#[const_trait] +trait Index { + type Output: ?Sized; + + fn index(&self, index: Idx) -> &Self::Output; +} + + +#[const_trait] +unsafe trait SliceIndex { + type Output: ?Sized; + fn index(self, slice: &T) -> &Self::Output; +} + +impl const Index for [T] +where + I: ~const SliceIndex<[T]>, +{ + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &I::Output { + index.index(self) + } +} +/* FIXME +impl const Index for [T; N] +where + [T]: ~const Index, +{ + type Output = <[T] as Index>::Output; + + #[inline] + // FIXME: make `Self::Output` act like `>::Output` + fn index(&self, index: I) -> &<[T] as Index>::Output { + Index::index(self as &[T], index) + } +} +*/ + +#[lang = "unsize"] +trait Unsize { +} + +#[lang = "coerce_unsized"] +trait CoerceUnsized { +} + +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} + + +#[lang = "deref"] +// #[const_trait] FIXME +trait Deref { + #[lang = "deref_target"] + type Target: ?Sized; + + fn deref(&self) -> &Self::Target; +} + + +impl /* const */ Deref for &T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +impl /* const */ Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +enum Option { + #[lang = "None"] + None, + #[lang = "Some"] + Some(T), +} + +impl Option { + const fn as_ref(&self) -> Option<&T> { + match *self { + Some(ref x) => Some(x), + None => None, + } + } + + const fn as_mut(&mut self) -> Option<&mut T> { + match *self { + Some(ref mut x) => Some(x), + None => None, + } + } +} + +use Option::*; + +/* +const fn as_deref(opt: &Option) -> Option<&T::Target> +where + T: ~const Deref, +{ + match opt { + Option::Some(t) => Option::Some(t.deref()), + Option::None => Option::None, + } +} +*/ + +#[const_trait] +trait Into: Sized { + fn into(self) -> T; +} + +#[const_trait] +trait From: Sized { + fn from(value: T) -> Self; +} + +impl const Into for T +where + U: ~const From, +{ + fn into(self) -> U { + U::from(self) + } +} + +impl const From for T { + fn from(t: T) -> T { + t + } +} + +enum Result { + Ok(T), + Err(E), +} +use Result::*; + +fn from_str(s: &str) -> Result { + match s { + "true" => Ok(true), + "false" => Ok(false), + _ => Err(()), + } +} + +#[lang = "eq"] +#[const_trait] +trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +// FIXME(effects): again, this should not error without Rhs specified +impl PartialEq for str { + fn eq(&self, other: &str) -> bool { + loop {} + } +} + + +#[lang = "not"] +#[const_trait] +trait Not { + type Output; + fn not(self) -> Self::Output; +} + +impl const Not for bool { + type Output = bool; + fn not(self) -> bool { + !self + } +} + +impl Copy for bool {} +impl<'a> Copy for &'a str {} + +#[lang = "pin"] +#[fundamental] +#[repr(transparent)] +struct Pin

{ + pointer: P, +} + +impl

Pin

{ + #[lang = "new_unchecked"] + const unsafe fn new_unchecked(pointer: P) -> Pin

{ + Pin { pointer } + } +} + +impl<'a, T: ?Sized> Pin<&'a T> { + const fn get_ref(self) -> &'a T { + self.pointer + } +} + + +impl Pin

{ + /* const */ fn as_ref(&self) -> Pin<&P::Target> + where + P: /* ~const */ Deref, + { + unsafe { Pin::new_unchecked(&*self.pointer) } + } +} + + +impl<'a, T: ?Sized> Pin<&'a mut T> { + const unsafe fn get_unchecked_mut(self) -> &'a mut T { + self.pointer + } +} +/* FIXME lol +impl Option { + const fn as_pin_ref(self: Pin<&Self>) -> Option> { + match Pin::get_ref(self).as_ref() { + Some(x) => unsafe { Some(Pin::new_unchecked(x)) }, + None => None, + } + } + + const fn as_pin_mut(self: Pin<&mut Self>) -> Option> { + unsafe { + match Pin::get_unchecked_mut(self).as_mut() { + Some(x) => Some(Pin::new_unchecked(x)), + None => None, + } + } + } +} +*/ + +impl /* const */ Deref for Pin

{ + type Target = P::Target; + fn deref(&self) -> &P::Target { + Pin::get_ref(Pin::as_ref(self)) + } +} + +impl /* const */ Deref for Option { + type Target = T; + fn deref(&self) -> &T { + loop {} + } +} + +impl Receiver for Pin

- | - this type parameter + | - expected this type parameter ... LL | builder.push(output); | ---- ^^^^^^ expected type parameter `F`, found `Class

` diff --git a/tests/ui/traits/new-solver/object-unsafety.stderr b/tests/ui/traits/new-solver/object-unsafety.stderr index bb7c68b8941f..914a8f9d4c5f 100644 --- a/tests/ui/traits/new-solver/object-unsafety.stderr +++ b/tests/ui/traits/new-solver/object-unsafety.stderr @@ -42,7 +42,7 @@ error[E0308]: mismatched types LL | pub fn copy_any(t: &T) -> T { | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter LL | copy::>(t) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ | diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr index e24cb11288e2..96a5c1327633 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr +++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:13:25 | LL | impl Enum { - | - this type parameter + | - expected this type parameter LL | fn ts_variant() { LL | Self::TSVariant(()); | --------------- ^^ expected type parameter `T`, found `()` @@ -50,7 +50,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:17:31 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::<()>::TSVariant(()); | --------------------- ^^ expected type parameter `T`, found `()` @@ -98,7 +98,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:26:29 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::SVariant { v: () }; | ^^ expected type parameter `T`, found `()` @@ -125,7 +125,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:28:35 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::SVariant::<()> { v: () }; | ^^ expected type parameter `T`, found `()` @@ -158,7 +158,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:31:35 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::<()>::SVariant { v: () }; | ^^ expected type parameter `T`, found `()` @@ -206,7 +206,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:34:41 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::<()>::SVariant::<()> { v: () }; | ^^ expected type parameter `T`, found `()` diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr index f9cdb280e276..0b705d467ffb 100644 --- a/tests/ui/typeck/bad-index-due-to-nested.stderr +++ b/tests/ui/typeck/bad-index-due-to-nested.stderr @@ -40,7 +40,7 @@ error[E0308]: mismatched types --> $DIR/bad-index-due-to-nested.rs:20:9 | LL | fn index<'a, K, V>(map: &'a HashMap, k: K) -> &'a V { - | - this type parameter + | - found this type parameter LL | map[k] | ^ expected `&K`, found type parameter `K` | @@ -55,7 +55,7 @@ error[E0308]: mismatched types --> $DIR/bad-index-due-to-nested.rs:20:5 | LL | fn index<'a, K, V>(map: &'a HashMap, k: K) -> &'a V { - | - this type parameter ----- expected `&'a V` because of return type + | - found this type parameter ----- expected `&'a V` because of return type LL | map[k] | ^^^^^^ expected `&V`, found type parameter `V` | diff --git a/tests/ui/typeck/issue-13853.stderr b/tests/ui/typeck/issue-13853.stderr index 8ecb8b680160..0683c782933a 100644 --- a/tests/ui/typeck/issue-13853.stderr +++ b/tests/ui/typeck/issue-13853.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-13853.rs:14:9 | LL | fn nodes<'a, I: Iterator>(&self) -> I - | - this type parameter - expected `I` because of return type + | - expected this type parameter - expected `I` because of return type ... LL | self.iter() | ^^^^^^^^^^^ expected type parameter `I`, found `Iter<'_, N>` From 2d144d21150d98424f7dff8af028f58a9c9b6c82 Mon Sep 17 00:00:00 2001 From: Vitaliy Busko Date: Thu, 19 Oct 2023 08:52:46 +0700 Subject: [PATCH 91/94] fix(bootstrap) info message show correct path now --- src/bootstrap/src/core/build_steps/setup.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index ebe093674fc7..435ebb6df90d 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -183,7 +183,7 @@ pub fn setup(config: &Config, profile: Profile) { eprintln!(); eprintln!( "note: the `tools` profile sets up the `stage2` toolchain (use \ - `rustup toolchain link 'name' host/build/stage2` to use rustc)" + `rustup toolchain link 'name' build/host/stage2` to use rustc)" ) } From 8fb03fba152705229d065bc2f5a7c1b60fd56537 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 19 Oct 2023 17:57:28 +0200 Subject: [PATCH 92/94] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index a7c9d720c0cf..4664cc39820f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c07693c1608258f3577eb15057fc0744fa924ae9 +c104861b7b51d2c28e7023e7e53db16cc6677e29 From e8e9f6a32af51fab7aae62f3f551aa3be8ff1ba2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 19 Oct 2023 16:41:43 +0000 Subject: [PATCH 93/94] Uplift movability and mutability, the simple way --- Cargo.lock | 1 + compiler/rustc_ast/Cargo.toml | 2 + compiler/rustc_ast/src/ast.rs | 63 +------------------ compiler/rustc_ast/src/lib.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 8 +-- compiler/rustc_type_ir/src/lib.rs | 5 +- compiler/rustc_type_ir/src/sty.rs | 84 ++++++++++++++++++++----- 7 files changed, 79 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa2f9c4147e3..9d7e5ee4f926 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3419,6 +3419,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "rustc_type_ir", "smallvec", "thin-vec", "tracing", diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index f0632ac92e96..e0948471acb5 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -14,6 +14,8 @@ rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } +# depends on Mutability and Movability, which could be uplifted into a common crate. +rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e8cbd7b69fbe..e94e26a63bc6 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -34,6 +34,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; +pub use rustc_type_ir::{Movability, Mutability}; use std::fmt; use std::mem; use thin_vec::{thin_vec, ThinVec}; @@ -800,57 +801,6 @@ pub enum PatKind { MacCall(P), } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[derive(HashStable_Generic, Encodable, Decodable)] -pub enum Mutability { - // N.B. Order is deliberate, so that Not < Mut - Not, - Mut, -} - -impl Mutability { - pub fn invert(self) -> Self { - match self { - Mutability::Mut => Mutability::Not, - Mutability::Not => Mutability::Mut, - } - } - - /// Returns `""` (empty string) or `"mut "` depending on the mutability. - pub fn prefix_str(self) -> &'static str { - match self { - Mutability::Mut => "mut ", - Mutability::Not => "", - } - } - - /// Returns `"&"` or `"&mut "` depending on the mutability. - pub fn ref_prefix_str(self) -> &'static str { - match self { - Mutability::Not => "&", - Mutability::Mut => "&mut ", - } - } - - /// Returns `""` (empty string) or `"mutably "` depending on the mutability. - pub fn mutably_str(self) -> &'static str { - match self { - Mutability::Not => "", - Mutability::Mut => "mutably ", - } - } - - /// Return `true` if self is mutable - pub fn is_mut(self) -> bool { - matches!(self, Self::Mut) - } - - /// Return `true` if self is **not** mutable - pub fn is_not(self) -> bool { - matches!(self, Self::Not) - } -} - /// The kind of borrow in an `AddrOf` expression, /// e.g., `&place` or `&raw const place`. #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -1579,17 +1529,6 @@ pub enum CaptureBy { Ref, } -/// The movability of a generator / closure literal: -/// whether a generator contains self-references, causing it to be `!Unpin`. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)] -#[derive(HashStable_Generic)] -pub enum Movability { - /// May contain self-references, `!Unpin`. - Static, - /// Must not contain self-references, `Unpin`. - Movable, -} - /// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum ClosureBinder { diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index ddc7c8ee8258..ada5c95dc34d 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -60,7 +60,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext: rustc_span::HashStableContext { +pub trait HashStableContext: + rustc_type_ir::HashStableContext + rustc_span::HashStableContext +{ fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher); } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 82c7f8ab4867..cad3aac23d87 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -88,8 +88,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Predicate = Predicate<'tcx>; type PredicateKind = ty::PredicateKind<'tcx>; type TypeAndMut = TypeAndMut<'tcx>; - type Mutability = hir::Mutability; - type Movability = hir::Movability; type Ty = Ty<'tcx>; type Tys = &'tcx List>; type AliasTy = ty::AliasTy<'tcx>; @@ -118,13 +116,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn ty_and_mut_to_parts( TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>, - ) -> (Self::Ty, Self::Mutability) { + ) -> (Self::Ty, ty::Mutability) { (ty, mutbl) } - - fn mutability_is_mut(mutbl: Self::Mutability) -> bool { - mutbl.is_mut() - } } type InternedSet<'tcx, T> = ShardedHashMap, ()>; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 6b1f0bae91ad..0a35e8d3a90c 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -59,8 +59,6 @@ pub trait Interner: Sized { type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; type TypeAndMut: Clone + Debug + Hash + Ord; - type Mutability: Clone + Debug + Hash + Ord; - type Movability: Clone + Debug + Hash + Ord; // Kinds of tys type Ty: Clone + DebugWithInfcx + Hash + Ord; @@ -95,8 +93,7 @@ pub trait Interner: Sized { type InferRegion: Clone + DebugWithInfcx + Hash + Ord; type PlaceholderRegion: Clone + Debug + Hash + Ord; - fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability); - fn mutability_is_mut(mutbl: Self::Mutability) -> bool; + fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability); } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index 991b8e1589bc..5ca77701eb01 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -18,6 +18,68 @@ use self::TyKind::*; use rustc_data_structures::stable_hasher::HashStable; use rustc_serialize::{Decodable, Decoder, Encodable}; +/// The movability of a generator / closure literal: +/// whether a generator contains self-references, causing it to be `!Unpin`. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)] +#[derive(HashStable_Generic)] +pub enum Movability { + /// May contain self-references, `!Unpin`. + Static, + /// Must not contain self-references, `Unpin`. + Movable, +} + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] +#[derive(HashStable_Generic, Encodable, Decodable)] +pub enum Mutability { + // N.B. Order is deliberate, so that Not < Mut + Not, + Mut, +} + +impl Mutability { + pub fn invert(self) -> Self { + match self { + Mutability::Mut => Mutability::Not, + Mutability::Not => Mutability::Mut, + } + } + + /// Returns `""` (empty string) or `"mut "` depending on the mutability. + pub fn prefix_str(self) -> &'static str { + match self { + Mutability::Mut => "mut ", + Mutability::Not => "", + } + } + + /// Returns `"&"` or `"&mut "` depending on the mutability. + pub fn ref_prefix_str(self) -> &'static str { + match self { + Mutability::Not => "&", + Mutability::Mut => "&mut ", + } + } + + /// Returns `""` (empty string) or `"mutably "` depending on the mutability. + pub fn mutably_str(self) -> &'static str { + match self { + Mutability::Not => "", + Mutability::Mut => "mutably ", + } + } + + /// Return `true` if self is mutable + pub fn is_mut(self) -> bool { + matches!(self, Self::Mut) + } + + /// Return `true` if self is **not** mutable + pub fn is_not(self) -> bool { + matches!(self, Self::Not) + } +} + /// Specifies how a trait object is represented. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable_Generic)] @@ -98,7 +160,7 @@ pub enum TyKind { /// A reference; a pointer with an associated lifetime. Written as /// `&'a mut T` or `&'a T`. - Ref(I::Region, I::Ty, I::Mutability), + Ref(I::Region, I::Ty, Mutability), /// The anonymous type of a function declaration/definition. Each /// function has a unique type. @@ -141,7 +203,7 @@ pub enum TyKind { /// /// For more info about generator args, visit the documentation for /// `GeneratorArgs`. - Generator(I::DefId, I::GenericArgs, I::Movability), + Generator(I::DefId, I::GenericArgs, Movability), /// A type representing the types stored inside a generator. /// This should only appear as part of the `GeneratorArgs`. @@ -506,15 +568,15 @@ impl DebugWithInfcx for TyKind { Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), RawPtr(p) => { let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone()); - match I::mutability_is_mut(mutbl) { - true => write!(f, "*mut "), - false => write!(f, "*const "), + match mutbl { + Mutability::Mut => write!(f, "*mut "), + Mutability::Not => write!(f, "*const "), }?; write!(f, "{:?}", &this.wrap(ty)) } - Ref(r, t, m) => match I::mutability_is_mut(m.clone()) { - true => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)), - false => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)), + Ref(r, t, m) => match m { + Mutability::Mut => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)), + Mutability::Not => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)), }, FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)), FnPtr(s) => write!(f, "{:?}", &this.wrap(s)), @@ -573,8 +635,6 @@ where I::Const: Encodable, I::Region: Encodable, I::TypeAndMut: Encodable, - I::Mutability: Encodable, - I::Movability: Encodable, I::PolyFnSig: Encodable, I::BoundExistentialPredicates: Encodable, I::Tys: Encodable, @@ -687,8 +747,6 @@ where I::Const: Decodable, I::Region: Decodable, I::TypeAndMut: Decodable, - I::Mutability: Decodable, - I::Movability: Decodable, I::PolyFnSig: Decodable, I::BoundExistentialPredicates: Decodable, I::Tys: Decodable, @@ -753,8 +811,6 @@ where I::PolyFnSig: HashStable, I::BoundExistentialPredicates: HashStable, I::Region: HashStable, - I::Movability: HashStable, - I::Mutability: HashStable, I::Tys: HashStable, I::AliasTy: HashStable, I::BoundTy: HashStable, From b01c4801810a7abe99d6f04fd412a651512f9b6e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 19 Oct 2023 21:26:38 +0200 Subject: [PATCH 94/94] fmt --- src/tools/miri/src/intptrcast.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/intptrcast.rs index 154d86375ca2..0bdea1576339 100644 --- a/src/tools/miri/src/intptrcast.rs +++ b/src/tools/miri/src/intptrcast.rs @@ -226,10 +226,7 @@ impl<'mir, 'tcx> GlobalStateInner { // Add offset with the right kind of pointer-overflowing arithmetic. let dl = ecx.data_layout(); let absolute_addr = dl.overflowing_offset(base_addr, offset.bytes()).0; - Ok(Pointer::new( - Provenance::Concrete { alloc_id, tag }, - Size::from_bytes(absolute_addr), - )) + Ok(Pointer::new(Provenance::Concrete { alloc_id, tag }, Size::from_bytes(absolute_addr))) } /// When a pointer is used for a memory access, this computes where in which allocation the

{} + +impl Clone for RefCell { + fn clone(&self) -> RefCell { + RefCell::new(self.borrow().clone()) + } +} + +struct RefCell { + borrow: UnsafeCell<()>, + value: UnsafeCell, +} +impl RefCell { + const fn new(value: T) -> RefCell { + loop {} + } +} +impl RefCell { + fn borrow(&self) -> Ref<'_, T> { + loop {} + } +} + +#[lang = "unsafe_cell"] +#[repr(transparent)] +struct UnsafeCell { + value: T, +} + +struct Ref<'b, T: ?Sized + 'b> { + value: *const T, + borrow: &'b UnsafeCell<()>, +} + +impl Deref for Ref<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + loop {} + } +} + +#[lang = "clone"] +#[rustc_trivial_field_reads] +#[const_trait] +trait Clone: Sized { + fn clone(&self) -> Self; + fn clone_from(&mut self, source: &Self) + where + Self: ~const Destruct, + { + *self = source.clone() + } +} + +#[lang = "structural_peq"] +trait StructuralPartialEq {} + +#[lang = "structural_teq"] +trait StructuralEq {} + +const fn drop(_: T) {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr new file mode 100644 index 000000000000..024293742189 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr @@ -0,0 +1,32 @@ +error[E0369]: cannot add `i32` to `i32` + --> $DIR/minicore.rs:33:20 + | +LL | let x = 42_i32 + 43_i32; + | ------ ^ ------ i32 + | | + | i32 + +error[E0369]: cannot add `i32` to `i32` + --> $DIR/minicore.rs:37:20 + | +LL | let x = 42_i32 + 43_i32; + | ------ ^ ------ i32 + | | + | i32 + +error[E0600]: cannot apply unary operator `!` to type `bool` + --> $DIR/minicore.rs:343:9 + | +LL | !self.eq(other) + | ^^^^^^^^^^^^^^^ cannot apply unary operator `!` + +error[E0600]: cannot apply unary operator `!` to type `bool` + --> $DIR/minicore.rs:365:9 + | +LL | !self + | ^^^^^ cannot apply unary operator `!` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0369, E0600. +For more information about an error, try `rustc --explain E0369`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs new file mode 100644 index 000000000000..b30d7743edfc --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs @@ -0,0 +1,11 @@ +// check-pass +#![feature(const_trait_impl, effects)] + +pub trait Owo::T> {} + +#[const_trait] +pub trait Uwu: Owo { + type T; +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr index c94563d3591b..2a9647da7823 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -1,35 +1,21 @@ -error[E0277]: the trait bound `T: ~const Bar` is not satisfied +error[E0308]: mismatched types --> $DIR/trait-where-clause-const.rs:21:5 | LL | T::b(); - | ^ the trait `Bar` is not implemented for `T` + | ^^^^^^ expected `host`, found `true` | -note: required by a bound in `Foo::b` - --> $DIR/trait-where-clause-const.rs:15:24 - | -LL | fn b() where Self: ~const Bar; - | ^^^^^^^^^^ required by this bound in `Foo::b` -help: consider further restricting this bound - | -LL | const fn test1() { - | +++++ + = note: expected constant `host` + found constant `true` -error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:23:12 +error[E0308]: mismatched types + --> $DIR/trait-where-clause-const.rs:23:5 | LL | T::c::(); - | ^ the trait `Bar` is not implemented for `T` + | ^^^^^^^^^^^ expected `host`, found `true` | -note: required by a bound in `Foo::c` - --> $DIR/trait-where-clause-const.rs:16:13 - | -LL | fn c(); - | ^^^^^^^^^^ required by this bound in `Foo::c` -help: consider further restricting this bound - | -LL | const fn test1() { - | +++++ + = note: expected constant `host` + found constant `true` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. From 6ab84b5895ad6b5fb09b929076a3c6dd93a82d8e Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 15 Oct 2023 12:44:25 +0200 Subject: [PATCH 15/94] Fix podman detection in CI scripts When docker-podman compat was set up in a way that causes "docker" to be the argv[0] of podman, the previous detection did not work. This was for example the case in the compat package from nixpkgs. This checks the output and should work everywhere. --- src/ci/docker/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 22aabda2bb34..99e3ce199f45 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -235,7 +235,7 @@ else args="$args --volume /tmp/toolstate:/tmp/toolstate" id=$(id -u) - if [[ "$id" != 0 && "$(docker -v)" =~ ^podman ]]; then + if [[ "$id" != 0 && "$(docker version)" =~ Podman ]]; then # Rootless podman creates a separate user namespace, where an inner # LOCAL_USER_ID will map to a different subuid range on the host. # The "keep-id" mode maps the current UID directly into the container. From b5e67a00d90fb7e77471f8bbc9a5469ee611929f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 5 Sep 2023 19:50:48 +0200 Subject: [PATCH 16/94] document when atomic loads are guaranteed read-only --- library/core/src/sync/atomic.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index de41bd1a1167..1443b9d594c6 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -79,6 +79,26 @@ //! //! [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm //! +//! # Atomic accesses to read-only memory +//! +//! In general, atomic accesses on read-only memory are Undefined Behavior. For instance, attempting +//! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only +//! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since +//! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault +//! on read-only memory. +//! +//! However, as an exception from this general rule, Rust guarantees that "sufficiently small" +//! atomic loads are implemented in a way that works on read-only memory. This threshold of +//! "sufficiently small" depends on the architecture: +//! +//! | Target architecture | Maximal atomic `load` size that is guaranteed read-only | +//! |----------|---------| +//! | `x86` | 4 bytes | +//! | `x86_64` | 8 bytes | +//! +//! Any atomic `load` on read-only memory larger than the given size are Undefined Behavior. For +//! architectures not listed above, all atomic `load` on read-only memory are Undefined Behavior. +//! //! # Examples //! //! A simple spinlock: From 7453235febe1230fd475edb8a9ac9d446c9d3008 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 5 Sep 2023 21:55:42 +0200 Subject: [PATCH 17/94] add ARM and RISC-V values --- library/core/src/sync/atomic.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 1443b9d594c6..118b90b5d64e 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -92,9 +92,13 @@ //! "sufficiently small" depends on the architecture: //! //! | Target architecture | Maximal atomic `load` size that is guaranteed read-only | -//! |----------|---------| -//! | `x86` | 4 bytes | -//! | `x86_64` | 8 bytes | +//! |-----------|---------| +//! | `x86` | 4 bytes | +//! | `x86_64` | 8 bytes | +//! | `arm` | 4 bytes | +//! | `aarch64` | 8 bytes | +//! | `riscv32` | 4 bytes | +//! | `riscv64` | 8 bytes | //! //! Any atomic `load` on read-only memory larger than the given size are Undefined Behavior. For //! architectures not listed above, all atomic `load` on read-only memory are Undefined Behavior. From 07b8c10ed89c64d7cb03e16cf9f61509100a3a2b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 8 Sep 2023 09:26:06 +0200 Subject: [PATCH 18/94] add general powerpc64le bound (some powerpc64le targets can guarantee more, but for now it doesn't seem worth separating by OS/vendor) --- library/core/src/sync/atomic.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 118b90b5d64e..b3f277654a73 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -92,13 +92,14 @@ //! "sufficiently small" depends on the architecture: //! //! | Target architecture | Maximal atomic `load` size that is guaranteed read-only | -//! |-----------|---------| -//! | `x86` | 4 bytes | -//! | `x86_64` | 8 bytes | -//! | `arm` | 4 bytes | -//! | `aarch64` | 8 bytes | -//! | `riscv32` | 4 bytes | -//! | `riscv64` | 8 bytes | +//! |---------------|---------| +//! | `x86` | 4 bytes | +//! | `x86_64` | 8 bytes | +//! | `arm` | 4 bytes | +//! | `aarch64` | 8 bytes | +//! | `riscv32` | 4 bytes | +//! | `riscv64` | 8 bytes | +//! | `powerpc64le` | 8 bytes | //! //! Any atomic `load` on read-only memory larger than the given size are Undefined Behavior. For //! architectures not listed above, all atomic `load` on read-only memory are Undefined Behavior. From 69b62ecc69ce42967eefb08c40d59c6b6f4a6d5a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 8 Sep 2023 10:35:09 +0200 Subject: [PATCH 19/94] define 'read-only memory' --- library/core/src/sync/atomic.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index b3f277654a73..6adf199a7631 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -81,12 +81,19 @@ //! //! # Atomic accesses to read-only memory //! -//! In general, atomic accesses on read-only memory are Undefined Behavior. For instance, attempting +//! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting //! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only //! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since //! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault //! on read-only memory. //! +//! For the purpose of this section, "read-only memory" is defined as memory that is read-only in +//! the underlying target, i.e., the pages are mapped with a read-only flag and any attempt to write +//! will cause a page fault. In particular, an `&u128` reference that points to memory that is +//! read-write mapped is *not* considered to point to "read-only memory". In Rust, almost all memory +//! is read-write; the only exceptions are memory created by `const` items or `static` items without +//! interior mutability. +//! //! However, as an exception from this general rule, Rust guarantees that "sufficiently small" //! atomic loads are implemented in a way that works on read-only memory. This threshold of //! "sufficiently small" depends on the architecture: From 275d5c82518897d465ae1c9d1d4cc0e6d426a4d1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Sep 2023 17:06:10 +0200 Subject: [PATCH 20/94] wording --- library/core/src/sync/atomic.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 6adf199a7631..71ee578f8b46 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -87,18 +87,21 @@ //! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault //! on read-only memory. //! -//! For the purpose of this section, "read-only memory" is defined as memory that is read-only in +//! (For the purpose of this section, "read-only memory" is defined as memory that is read-only in //! the underlying target, i.e., the pages are mapped with a read-only flag and any attempt to write //! will cause a page fault. In particular, an `&u128` reference that points to memory that is //! read-write mapped is *not* considered to point to "read-only memory". In Rust, almost all memory //! is read-write; the only exceptions are memory created by `const` items or `static` items without -//! interior mutability. +//! interior mutability, and memory that was specifically marked as read-only by the operating +//! system via platform-specific APIs.) //! -//! However, as an exception from this general rule, Rust guarantees that "sufficiently small" -//! atomic loads are implemented in a way that works on read-only memory. This threshold of -//! "sufficiently small" depends on the architecture: +//! However, as an exception from this general rule, "sufficiently small" atomic loads are +//! implemented in a way that works on read-only memory. The exact threshold for what makes a load +//! "sufficiently small" varies depending on the architecture and feature flags, but Rust guarantees +//! that atomic loads that do not exceed the size documented in the following table are guaranteed +//! to be read-only: //! -//! | Target architecture | Maximal atomic `load` size that is guaranteed read-only | +//! | Target architecture | Atomic loads no larger than this are guaranteed read-only | //! |---------------|---------| //! | `x86` | 4 bytes | //! | `x86_64` | 8 bytes | @@ -106,10 +109,11 @@ //! | `aarch64` | 8 bytes | //! | `riscv32` | 4 bytes | //! | `riscv64` | 8 bytes | -//! | `powerpc64le` | 8 bytes | +//! | `powerpc64` | 8 bytes | //! -//! Any atomic `load` on read-only memory larger than the given size are Undefined Behavior. For -//! architectures not listed above, all atomic `load` on read-only memory are Undefined Behavior. +//! Atomics loads that are larger than this threshold (and *all* atomic loads on targets not listed +//! in the table) might still be read-only under certain conditions, but that is not a stable +//! guarantee and should not be relied upon. //! //! # Examples //! From 9b8686d832d1122f3ac25a558d393366082e9e38 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 14 Oct 2023 11:13:07 +0200 Subject: [PATCH 21/94] only guarantee for Relaxed; add ptr-size fallback --- library/core/src/sync/atomic.rs | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 71ee578f8b46..53a57412f826 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -87,33 +87,30 @@ //! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault //! on read-only memory. //! -//! (For the purpose of this section, "read-only memory" is defined as memory that is read-only in +//! For the purpose of this section, "read-only memory" is defined as memory that is read-only in //! the underlying target, i.e., the pages are mapped with a read-only flag and any attempt to write //! will cause a page fault. In particular, an `&u128` reference that points to memory that is //! read-write mapped is *not* considered to point to "read-only memory". In Rust, almost all memory //! is read-write; the only exceptions are memory created by `const` items or `static` items without //! interior mutability, and memory that was specifically marked as read-only by the operating -//! system via platform-specific APIs.) +//! system via platform-specific APIs. //! -//! However, as an exception from this general rule, "sufficiently small" atomic loads are -//! implemented in a way that works on read-only memory. The exact threshold for what makes a load -//! "sufficiently small" varies depending on the architecture and feature flags, but Rust guarantees -//! that atomic loads that do not exceed the size documented in the following table are guaranteed -//! to be read-only: +//! As an exception from the general rule stated above, "sufficiently small" atomic loads with +//! `Ordering::Relaxed` are implemented in a way that works on read-only memory, and are hence not +//! Undefined Behavior. The exact size limit for what makes a load "sufficiently small" varies +//! depending on the target: //! -//! | Target architecture | Atomic loads no larger than this are guaranteed read-only | +//! | Target triple prefix (regular expression) | Size limit | //! |---------------|---------| -//! | `x86` | 4 bytes | -//! | `x86_64` | 8 bytes | -//! | `arm` | 4 bytes | -//! | `aarch64` | 8 bytes | -//! | `riscv32` | 4 bytes | -//! | `riscv64` | 8 bytes | -//! | `powerpc64` | 8 bytes | +//! | `i(3|5|6)86-`, `arm`, `thumb`, `mips(|el)-`, `powerpc-`, `riscv32`, `sparc-` | 4 bytes | +//! | `x86_64-`, `aarch64-`, `loongarch64-`, `mips64(|el)-`, `powerpc64-`, `riscv64` | 8 bytes | +//! | `powerpc64le-` | 16 bytes | +//! | `s390x-` | 16 bytes | //! -//! Atomics loads that are larger than this threshold (and *all* atomic loads on targets not listed -//! in the table) might still be read-only under certain conditions, but that is not a stable -//! guarantee and should not be relied upon. +//! Atomics loads that are larger than this limit as well as atomic loads with ordering other +//! than `Relaxed`, as well as *all* atomic loads on targets not listed in the table, might still be +//! read-only under certain conditions, but that is not a stable guarantee and should not be relied +//! upon. //! //! # Examples //! From 9d8506d27faf8b396dd54c361182269d265d5d98 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 15 Oct 2023 17:41:38 +0200 Subject: [PATCH 22/94] acquire loads can be done as relaxed load; acquire fence --- library/core/src/sync/atomic.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 53a57412f826..aa8ca1e025f3 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -112,6 +112,9 @@ //! read-only under certain conditions, but that is not a stable guarantee and should not be relied //! upon. //! +//! If you need to do an acquire load on read-only memory, you can do a relaxed load followed by an +//! acquire fence instead. +//! //! # Examples //! //! A simple spinlock: From 0df670fb67a156e3f0199f5c7c55bc8e1c3575d3 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 16 Oct 2023 15:16:57 +0200 Subject: [PATCH 23/94] Add `#[track_caller]` to `Option::unwrap_or_else` --- library/core/src/option.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index bdaeea666221..12de349d22bc 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -959,6 +959,7 @@ impl Option { /// assert_eq!(None.unwrap_or_else(|| 2 * k), 20); /// ``` #[inline] + #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap_or_else(self, f: F) -> T where From 02424e4bc57344dc7436644f897b5500a1973242 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 15 Oct 2023 17:00:11 +0000 Subject: [PATCH 24/94] Normalize alloc-id in tests. --- Cargo.lock | 1 + src/tools/compiletest/Cargo.toml | 1 + src/tools/compiletest/src/runtest.rs | 28 +++++++++++++ .../custom/consts.statics.built.after.mir | 8 ++-- ...main.SimplifyCfg-elaborate-drops.after.mir | 2 +- ..._allocation.main.ConstProp.after.32bit.mir | 36 ++++++++--------- ..._allocation.main.ConstProp.after.64bit.mir | 40 +++++++++---------- ...allocation2.main.ConstProp.after.32bit.mir | 34 ++++++++-------- ...allocation2.main.ConstProp.after.64bit.mir | 36 ++++++++--------- ...allocation3.main.ConstProp.after.32bit.mir | 20 +++++----- ...allocation3.main.ConstProp.after.64bit.mir | 18 ++++----- ...d[0].SimplifyCfg-elaborate-drops.after.mir | 4 +- ...motion_extern_static.BAR.PromoteTemps.diff | 4 +- ...d[0].SimplifyCfg-elaborate-drops.after.mir | 4 +- ...motion_extern_static.FOO.PromoteTemps.diff | 4 +- ...hecked_add.main.ConstProp.panic-abort.diff | 2 +- ...ecked_add.main.ConstProp.panic-unwind.diff | 2 +- .../indirect.main.ConstProp.panic-abort.diff | 2 +- .../indirect.main.ConstProp.panic-unwind.diff | 2 +- ...t_overflow.main.ConstProp.panic-abort.diff | 2 +- ..._overflow.main.ConstProp.panic-unwind.diff | 2 +- ...ssue_66971.main.ConstProp.panic-abort.diff | 4 +- ...sue_66971.main.ConstProp.panic-unwind.diff | 4 +- ...ssue_67019.main.ConstProp.panic-abort.diff | 6 +-- ...sue_67019.main.ConstProp.panic-unwind.diff | 6 +-- ...ble_variable_aggregate.main.ConstProp.diff | 4 +- ...table_variable_no_prop.main.ConstProp.diff | 4 +- ...rop_assign.main.ConstProp.panic-abort.diff | 2 +- ...op_assign.main.ConstProp.panic-unwind.diff | 2 +- .../read_immutable_static.main.ConstProp.diff | 6 +-- ...eturn_place.add.ConstProp.panic-abort.diff | 2 +- ...turn_place.add.ConstProp.panic-unwind.diff | 2 +- ...lace.add.PreCodegen.before.panic-abort.mir | 2 +- ...ace.add.PreCodegen.before.panic-unwind.mir | 2 +- ...ropagation.main.ConstProp.panic-abort.diff | 6 +-- ...opagation.main.ConstProp.panic-unwind.diff | 6 +-- ...lice.main.ConstProp.32bit.panic-abort.diff | 12 +++--- ...ice.main.ConstProp.32bit.panic-unwind.diff | 12 +++--- ...lice.main.ConstProp.64bit.panic-abort.diff | 12 +++--- ...ice.main.ConstProp.64bit.panic-unwind.diff | 12 +++--- ...n.DataflowConstProp.32bit.panic-abort.diff | 12 +++--- ....DataflowConstProp.32bit.panic-unwind.diff | 12 +++--- ...n.DataflowConstProp.64bit.panic-abort.diff | 12 +++--- ....DataflowConstProp.64bit.panic-unwind.diff | 12 +++--- .../enum.statics.DataflowConstProp.32bit.diff | 12 +++--- .../enum.statics.DataflowConstProp.64bit.diff | 12 +++--- .../struct.main.DataflowConstProp.32bit.diff | 8 ++-- .../struct.main.DataflowConstProp.64bit.diff | 8 ++-- .../enum_opt.cand.EnumSizeOpt.32bit.diff | 2 +- .../enum_opt.cand.EnumSizeOpt.64bit.diff | 2 +- .../enum_opt.unin.EnumSizeOpt.32bit.diff | 2 +- .../enum_opt.unin.EnumSizeOpt.64bit.diff | 2 +- .../issue_99325.main.built.after.32bit.mir | 2 +- .../issue_99325.main.built.after.64bit.mir | 2 +- ...able.main.ConstProp.32bit.panic-abort.diff | 2 +- ...ble.main.ConstProp.32bit.panic-unwind.diff | 2 +- ...able.main.ConstProp.64bit.panic-abort.diff | 2 +- ...ble.main.ConstProp.64bit.panic-unwind.diff | 2 +- .../const-generics/issues/issue-100313.stderr | 2 +- tests/ui/const-ptr/forbidden_slices.rs | 4 +- tests/ui/const-ptr/forbidden_slices.stderr | 4 +- tests/ui/const-ptr/out_of_bounds_read.stderr | 6 +-- tests/ui/consts/const-compare-bytes-ub.stderr | 8 ++-- .../heap/alloc_intrinsic_uninit.32bit.stderr | 2 +- .../heap/alloc_intrinsic_uninit.64bit.stderr | 2 +- .../heap/dealloc_intrinsic_dangling.stderr | 2 +- .../heap/dealloc_intrinsic_duplicate.stderr | 2 +- .../dealloc_intrinsic_incorrect_layout.stderr | 6 +-- tests/ui/consts/const-eval/issue-49296.stderr | 2 +- .../const-eval/partial_ptr_overwrite.stderr | 2 +- .../consts/const-eval/raw-bytes.32bit.stderr | 12 +++--- .../consts/const-eval/raw-bytes.64bit.stderr | 10 ++--- tests/ui/consts/const-eval/raw-bytes.rs | 4 +- tests/ui/consts/const-eval/raw-pointer-ub.rs | 2 +- .../consts/const-eval/raw-pointer-ub.stderr | 2 +- .../ub-incorrect-vtable.32bit.stderr | 22 +++++----- .../ub-incorrect-vtable.64bit.stderr | 22 +++++----- .../consts/const-eval/ub-incorrect-vtable.rs | 2 +- tests/ui/consts/const-eval/ub-nonnull.rs | 2 +- tests/ui/consts/const-eval/ub-nonnull.stderr | 2 +- tests/ui/consts/const-eval/ub-ref-ptr.rs | 2 +- tests/ui/consts/const-eval/ub-ref-ptr.stderr | 2 +- .../consts/const-eval/ub-upvars.32bit.stderr | 2 +- .../consts/const-eval/ub-upvars.64bit.stderr | 2 +- tests/ui/consts/const-eval/ub-wide-ptr.rs | 4 +- tests/ui/consts/const-eval/ub-wide-ptr.stderr | 16 ++++---- .../const-points-to-static.32bit.stderr | 2 +- .../const-points-to-static.64bit.stderr | 2 +- tests/ui/consts/copy-intrinsic.stderr | 4 +- tests/ui/consts/invalid-union.32bit.stderr | 2 +- tests/ui/consts/invalid-union.64bit.stderr | 2 +- tests/ui/consts/issue-63952.32bit.stderr | 2 +- tests/ui/consts/issue-63952.64bit.stderr | 2 +- tests/ui/consts/issue-79690.64bit.stderr | 2 +- .../const_refers_to_static.32bit.stderr | 4 +- .../const_refers_to_static.64bit.stderr | 4 +- ..._refers_to_static_cross_crate.32bit.stderr | 4 +- ..._refers_to_static_cross_crate.64bit.stderr | 4 +- .../mutable_references_err.32bit.stderr | 6 +-- .../mutable_references_err.64bit.stderr | 6 +-- tests/ui/consts/missing_span_in_backtrace.rs | 2 +- .../consts/missing_span_in_backtrace.stderr | 2 +- tests/ui/consts/offset_from_ub.stderr | 6 +-- tests/ui/consts/offset_ub.rs | 2 +- tests/ui/consts/offset_ub.stderr | 8 ++-- .../intrinsic-raw_eq-const-bad.stderr | 2 +- 106 files changed, 357 insertions(+), 327 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5cfb7feb6f54..4ba9977cc902 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -697,6 +697,7 @@ dependencies = [ "getopts", "glob", "home", + "indexmap 2.0.0", "lazycell", "libc", "miow", diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index bb1fa6e9237d..31c6353e6754 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -11,6 +11,7 @@ colored = "2" diff = "0.1.10" unified-diff = "0.2.1" getopts = "0.2" +indexmap = "2.0.0" miropt-test-tools = { path = "../miropt-test-tools" } build_helper = { path = "../build_helper" } tracing = "0.1" diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7b42d8e9b584..3982b7893280 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -4258,6 +4258,34 @@ impl<'test> TestCx<'test> { V0_BACK_REF_RE.replace_all(&normalized, V0_BACK_REF_PLACEHOLDER).into_owned(); } + // Normalize AllocId counter + { + use std::fmt::Write; + + let re = Regex::new(r"(╾a|─a|\balloc)([0-9]+)\b(─|\+0x[0-9]+─)?").unwrap(); + let mut seen_allocs = indexmap::IndexSet::new(); + normalized = re + .replace_all(&normalized, |caps: &Captures<'_>| { + // Use uppercase to distinguish with the non-normalized version. + let mut ret = caps.get(1).unwrap().as_str().to_uppercase(); + // Renumber the captured index. + let index = caps.get(2).unwrap().as_str().to_string(); + let (index, _) = seen_allocs.insert_full(index); + write!(&mut ret, "{index}").unwrap(); + // If we have a tail finishing with `─`, this means pretty-printing. + // Complete with filler `─` to preserve the pretty-print. + if let Some(tail) = caps.get(3) { + ret.push_str(tail.as_str()); + let diff = caps.get(0).unwrap().as_str().len() - ret.len(); + for _ in 0..diff { + ret.push('─'); + } + } + ret + }) + .into_owned(); + } + // Custom normalization rules for rule in custom_rules { let re = Regex::new(&rule.0).expect("bad regex in custom normalization rule"); diff --git a/tests/mir-opt/building/custom/consts.statics.built.after.mir b/tests/mir-opt/building/custom/consts.statics.built.after.mir index ea394c5b7276..a5cb6ff992ee 100644 --- a/tests/mir-opt/building/custom/consts.statics.built.after.mir +++ b/tests/mir-opt/building/custom/consts.statics.built.after.mir @@ -6,16 +6,16 @@ fn statics() -> () { let mut _2: *mut i32; bb0: { - _1 = const {alloc1: &i32}; - _2 = const {alloc2: *mut i32}; + _1 = const {ALLOC0: &i32}; + _2 = const {ALLOC1: *mut i32}; return; } } -alloc2 (static: T, size: 4, align: 4) { +ALLOC1 (static: T, size: 4, align: 4) { 0a 0a 0a 0a │ .... } -alloc1 (static: S, size: 4, align: 4) { +ALLOC0 (static: S, size: 4, align: 4) { 05 05 05 05 │ .... } diff --git a/tests/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir index 9b17b4b63dd3..09a65e6e6a6e 100644 --- a/tests/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir @@ -23,6 +23,6 @@ fn main() -> () { } } -alloc1 (size: 3, align: 1) { +ALLOC0 (size: 3, align: 1) { 66 6f 6f │ foo } diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index 8c8e69595950..c44483b21674 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&str])]}; + _2 = const {ALLOC0: &&[(Option, &[&str])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,43 +17,43 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 8, align: 4) { - ╾─alloc19─╼ 03 00 00 00 │ ╾──╼.... +ALLOC0 (static: FOO, size: 8, align: 4) { + ╾─ALLOC1──╼ 03 00 00 00 │ ╾──╼.... } -alloc19 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc6──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc10─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ....*...╾──╼.... +ALLOC1 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾─ALLOC2──╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─ALLOC3──╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─ALLOC4──╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc6 (size: 0, align: 4) {} +ALLOC2 (size: 0, align: 4) {} -alloc10 (size: 16, align: 4) { - ╾─alloc9──╼ 03 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ╾──╼....╾──╼.... +ALLOC3 (size: 16, align: 4) { + ╾─ALLOC5──╼ 03 00 00 00 ╾─ALLOC6──╼ 03 00 00 00 │ ╾──╼....╾──╼.... } -alloc9 (size: 3, align: 1) { +ALLOC5 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc11 (size: 3, align: 1) { +ALLOC6 (size: 3, align: 1) { 62 61 72 │ bar } -alloc15 (size: 24, align: 4) { - 0x00 │ ╾─alloc14─╼ 03 00 00 00 ╾─alloc16─╼ 03 00 00 00 │ ╾──╼....╾──╼.... - 0x10 │ ╾─alloc17─╼ 04 00 00 00 │ ╾──╼.... +ALLOC4 (size: 24, align: 4) { + 0x00 │ ╾─ALLOC7──╼ 03 00 00 00 ╾─ALLOC8──╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾─ALLOC9──╼ 04 00 00 00 │ ╾──╼.... } -alloc14 (size: 3, align: 1) { +ALLOC7 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc16 (size: 3, align: 1) { +ALLOC8 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc17 (size: 4, align: 1) { +ALLOC9 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index e22547032967..02fd6a8da531 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&str])]}; + _2 = const {ALLOC0: &&[(Option, &[&str])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,47 +17,47 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 16, align: 8) { - ╾───────alloc19───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC0 (static: FOO, size: 16, align: 8) { + ╾───────ALLOC1────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc19 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc6────────╼ │ ....░░░░╾──────╼ +ALLOC1 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────ALLOC2────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc10───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc15───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────ALLOC3────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────ALLOC4────────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc6 (size: 0, align: 8) {} +ALLOC2 (size: 0, align: 8) {} -alloc10 (size: 32, align: 8) { - 0x00 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc11───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC3 (size: 32, align: 8) { + 0x00 │ ╾───────ALLOC5────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────ALLOC6────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc9 (size: 3, align: 1) { +ALLOC5 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc11 (size: 3, align: 1) { +ALLOC6 (size: 3, align: 1) { 62 61 72 │ bar } -alloc15 (size: 48, align: 8) { - 0x00 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc16───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x20 │ ╾───────alloc17───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC4 (size: 48, align: 8) { + 0x00 │ ╾───────ALLOC7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────ALLOC8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾───────ALLOC9────────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc14 (size: 3, align: 1) { +ALLOC7 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc16 (size: 3, align: 1) { +ALLOC8 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc17 (size: 4, align: 1) { +ALLOC9 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index c5f6902b4b48..5fe485ea815e 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&u8])]}; + _2 = const {ALLOC0: &&[(Option, &[&u8])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,42 +17,42 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 8, align: 4) { - ╾─alloc23─╼ 03 00 00 00 │ ╾──╼.... +ALLOC0 (static: FOO, size: 8, align: 4) { + ╾─ALLOC1──╼ 03 00 00 00 │ ╾──╼.... } -alloc23 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc10─╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc15─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc21─╼ 03 00 00 00 │ ....*...╾──╼.... +ALLOC1 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾─ALLOC2──╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─ALLOC3──╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─ALLOC4──╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc10 (size: 0, align: 4) {} +ALLOC2 (size: 0, align: 4) {} -alloc15 (size: 8, align: 4) { - ╾─alloc13─╼ ╾─alloc14─╼ │ ╾──╼╾──╼ +ALLOC3 (size: 8, align: 4) { + ╾─ALLOC5──╼ ╾─ALLOC6──╼ │ ╾──╼╾──╼ } -alloc13 (size: 1, align: 1) { +ALLOC5 (size: 1, align: 1) { 05 │ . } -alloc14 (size: 1, align: 1) { +ALLOC6 (size: 1, align: 1) { 06 │ . } -alloc21 (size: 12, align: 4) { - ╾─a18+0x3─╼ ╾─alloc19─╼ ╾─a20+0x2─╼ │ ╾──╼╾──╼╾──╼ +ALLOC4 (size: 12, align: 4) { + ╾─A7+0x3──╼ ╾─ALLOC8──╼ ╾─A9+0x2──╼ │ ╾──╼╾──╼╾──╼ } -alloc18 (size: 4, align: 1) { +ALLOC7 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc19 (size: 1, align: 1) { +ALLOC8 (size: 1, align: 1) { 2a │ * } -alloc20 (size: 4, align: 1) { +ALLOC9 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index b95b8c787487..b55e35bb9c5f 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&u8])]}; + _2 = const {ALLOC0: &&[(Option, &[&u8])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,45 +17,45 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 16, align: 8) { - ╾───────alloc23───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC0 (static: FOO, size: 16, align: 8) { + ╾───────ALLOC1────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc23 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc10───────╼ │ ....░░░░╾──────╼ +ALLOC1 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────ALLOC2────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc15───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc21───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────ALLOC3────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────ALLOC4────────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc10 (size: 0, align: 8) {} +ALLOC2 (size: 0, align: 8) {} -alloc15 (size: 16, align: 8) { - ╾───────alloc13───────╼ ╾───────alloc14───────╼ │ ╾──────╼╾──────╼ +ALLOC3 (size: 16, align: 8) { + ╾───────ALLOC5────────╼ ╾───────ALLOC6────────╼ │ ╾──────╼╾──────╼ } -alloc13 (size: 1, align: 1) { +ALLOC5 (size: 1, align: 1) { 05 │ . } -alloc14 (size: 1, align: 1) { +ALLOC6 (size: 1, align: 1) { 06 │ . } -alloc21 (size: 24, align: 8) { - 0x00 │ ╾─────alloc18+0x3─────╼ ╾───────alloc19───────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────alloc20+0x2─────╼ │ ╾──────╼ +ALLOC4 (size: 24, align: 8) { + 0x00 │ ╾─────ALLOC7+0x3──────╼ ╾───────ALLOC8────────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾─────ALLOC9+0x2──────╼ │ ╾──────╼ } -alloc18 (size: 4, align: 1) { +ALLOC7 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc19 (size: 1, align: 1) { +ALLOC8 (size: 1, align: 1) { 2a │ * } -alloc20 (size: 4, align: 1) { +ALLOC9 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir index e172c7540014..d487d813e8a8 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&Packed}; + _2 = const {ALLOC0: &&Packed}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,31 +17,31 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 4, align: 4) { - ╾─alloc12─╼ │ ╾──╼ +ALLOC0 (static: FOO, size: 4, align: 4) { + ╾─ALLOC1──╼ │ ╾──╼ } -alloc12 (size: 168, align: 1) { +ALLOC1 (size: 168, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc7──╼ │ ............╾──╼ + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─ALLOC2──╼ │ ............╾──╼ 0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc9──╼ 00 00 │ ..........╾──╼.. - 0x90 │ ╾a10+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ + 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─ALLOC3──╼ 00 00 │ ..........╾──╼.. + 0x90 │ ╾A4+0x63──╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ 0xa0 │ 00 00 00 00 00 00 00 00 │ ........ } -alloc7 (size: 4, align: 4) { +ALLOC2 (size: 4, align: 4) { 2a 00 00 00 │ *... } -alloc9 (fn: main) +ALLOC3 (fn: main) -alloc10 (size: 100, align: 1) { +ALLOC4 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir index d5feea723e7c..3cdc1cbbcf4c 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&Packed}; + _2 = const {ALLOC0: &&Packed}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,13 +17,13 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 8, align: 8) { - ╾───────alloc12───────╼ │ ╾──────╼ +ALLOC0 (static: FOO, size: 8, align: 8) { + ╾───────ALLOC1────────╼ │ ╾──────╼ } -alloc12 (size: 180, align: 1) { +ALLOC1 (size: 180, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc7── │ ............╾─── + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──ALLOC2── │ ............╾─── 0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ @@ -31,18 +31,18 @@ alloc12 (size: 180, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─ - 0x90 │ ─────alloc9─────╼ 00 00 ╾────alloc10+0x63─────╼ │ ─────╼..╾──────╼ + 0x90 │ ─────ALLOC3─────╼ 00 00 ╾────ALLOC4+0x63──────╼ │ ─────╼..╾──────╼ 0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0xb0 │ 00 00 00 00 │ .... } -alloc7 (size: 4, align: 4) { +ALLOC2 (size: 4, align: 4) { 2a 00 00 00 │ *... } -alloc9 (fn: main) +ALLOC3 (fn: main) -alloc10 (size: 100, align: 1) { +ALLOC4 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 5b8d3ca78e3f..960b982242d2 100644 --- a/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -7,7 +7,7 @@ promoted[0] in BAR: &[&i32; 1] = { let mut _3: &i32; bb0: { - _3 = const {alloc1: &i32}; + _3 = const {ALLOC0: &i32}; _2 = &(*_3); _1 = [move _2]; _0 = &_1; @@ -15,6 +15,6 @@ promoted[0] in BAR: &[&i32; 1] = { } } -alloc1 (static: Y, size: 4, align: 4) { +ALLOC0 (static: Y, size: 4, align: 4) { 2a 00 00 00 │ *... } diff --git a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index 14d2d7fc85cf..4a93db3fcaa8 100644 --- a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -16,7 +16,7 @@ - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); -- _5 = const {alloc1: &i32}; +- _5 = const {ALLOC0: &i32}; - _4 = &(*_5); - _3 = [move _4]; - _2 = &_3; @@ -40,7 +40,7 @@ } - } - -- alloc1 (static: Y, size: 4, align: 4) { +- ALLOC0 (static: Y, size: 4, align: 4) { - 2a 00 00 00 │ *... } diff --git a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 85355389be5e..a9c05442764e 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -7,7 +7,7 @@ promoted[0] in FOO: &[&i32; 1] = { let mut _3: *const i32; bb0: { - _3 = const {alloc3: *const i32}; + _3 = const {ALLOC0: *const i32}; _2 = &(*_3); _1 = [move _2]; _0 = &_1; @@ -15,4 +15,4 @@ promoted[0] in FOO: &[&i32; 1] = { } } -alloc3 (extern static: X) +ALLOC0 (extern static: X) diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index ffdd195eca36..21d21b0eee0e 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -18,7 +18,7 @@ - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); -- _5 = const {alloc3: *const i32}; +- _5 = const {ALLOC0: *const i32}; - _4 = &(*_5); - _3 = [move _4]; - _2 = &_3; @@ -42,5 +42,5 @@ } } - -- alloc3 (extern static: X) +- ALLOC0 (extern static: X) diff --git a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff index c2fd7f65f5ee..5a958cc7a470 100644 --- a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff @@ -26,7 +26,7 @@ } + } + -+ alloc3 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 02 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff index 21a31f9aba31..ab48186aed9a 100644 --- a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff @@ -26,7 +26,7 @@ } + } + -+ alloc3 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 02 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff index c0efc8730292..530cfc6539a3 100644 --- a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff @@ -31,7 +31,7 @@ } + } + -+ alloc3 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 03 00 │ .. } diff --git a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff index 2aee6f164aeb..08cf72e47a90 100644 --- a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff @@ -31,7 +31,7 @@ } + } + -+ alloc3 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 03 00 │ .. } diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff index d585ae89e829..b30deb2a4d43 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff @@ -39,7 +39,7 @@ } + } + -+ alloc3 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 00 01 │ .. } diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff index 9fe390906380..47c51196c02a 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff @@ -39,7 +39,7 @@ } + } + -+ alloc3 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 00 01 │ .. } diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff index 18341ba7db92..6484b4b67af9 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff @@ -20,11 +20,11 @@ } + } + -+ alloc8 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 00 00 │ .. + } + -+ alloc7 (size: 2, align: 1) { ++ ALLOC1 (size: 2, align: 1) { + 00 00 │ .. } diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff index 50763c10f0c2..b02f04078398 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff @@ -20,11 +20,11 @@ } + } + -+ alloc8 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 00 00 │ .. + } + -+ alloc7 (size: 2, align: 1) { ++ ALLOC1 (size: 2, align: 1) { + 00 00 │ .. } diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff index 015180db896b..c1ef453e9df6 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff @@ -25,15 +25,15 @@ } + } + -+ alloc12 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 01 02 │ .. + } + -+ alloc11 (size: 2, align: 1) { ++ ALLOC1 (size: 2, align: 1) { + 01 02 │ .. + } + -+ alloc8 (size: 2, align: 1) { ++ ALLOC2 (size: 2, align: 1) { + 01 02 │ .. } diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff index 8e41705c1af2..53cdcc181672 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff @@ -25,15 +25,15 @@ } + } + -+ alloc12 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 01 02 │ .. + } + -+ alloc11 (size: 2, align: 1) { ++ ALLOC1 (size: 2, align: 1) { + 01 02 │ .. + } + -+ alloc8 (size: 2, align: 1) { ++ ALLOC2 (size: 2, align: 1) { + 01 02 │ .. } diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff index 56a127ae31eb..c3ace9687e65 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff @@ -27,11 +27,11 @@ } + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 2a 00 00 00 63 00 00 00 │ *...c... + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 2a 00 00 00 2b 00 00 00 │ *...+... } diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff index ac26f8ef4aef..1f74bdcfd032 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff @@ -23,7 +23,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = const {alloc1: *mut u32}; + _4 = const {ALLOC0: *mut u32}; _3 = (*_4); _1 = move _3; StorageDead(_3); @@ -39,7 +39,7 @@ } } - alloc1 (static: STATIC, size: 4, align: 4) { + ALLOC0 (static: STATIC, size: 4, align: 4) { 42 42 42 42 │ BBBB } diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff index a1b433716c84..85bd2b6e722f 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff @@ -48,7 +48,7 @@ } + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff index 2dc514194bc1..06e96e57a62f 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff @@ -48,7 +48,7 @@ } + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff b/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff index 29c455f35b35..e193c82d2c0e 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff @@ -16,12 +16,12 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); - _3 = const {alloc1: &u8}; + _3 = const {ALLOC0: &u8}; - _2 = (*_3); + _2 = const 2_u8; StorageLive(_4); StorageLive(_5); - _5 = const {alloc1: &u8}; + _5 = const {ALLOC0: &u8}; - _4 = (*_5); - _1 = Add(move _2, move _4); + _4 = const 2_u8; @@ -36,7 +36,7 @@ } } - alloc1 (static: FOO, size: 1, align: 1) { + ALLOC0 (static: FOO, size: 1, align: 1) { 02 │ . } diff --git a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff index 6c9de4764658..974a42e50780 100644 --- a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff @@ -19,7 +19,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff index 0f079278c43d..55dbc7002859 100644 --- a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff @@ -19,7 +19,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir index c2488f3944cb..f87c26bb004c 100644 --- a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir +++ b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir @@ -15,6 +15,6 @@ fn add() -> u32 { } } -alloc5 (size: 8, align: 4) { +ALLOC0 (size: 8, align: 4) { 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir index fa0b9c77eaf6..33f97591387c 100644 --- a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir +++ b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir @@ -15,6 +15,6 @@ fn add() -> u32 { } } -alloc5 (size: 8, align: 4) { +ALLOC0 (size: 8, align: 4) { 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff index 988ef7dd2254..f19650d5a83d 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff @@ -31,15 +31,15 @@ } + } + -+ alloc9 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ + } + -+ alloc8 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ + } + -+ alloc6 (size: 8, align: 4) { ++ ALLOC2 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff index 298446197203..67307c423310 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff @@ -31,15 +31,15 @@ } + } + -+ alloc9 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ + } + -+ alloc8 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ + } + -+ alloc6 (size: 8, align: 4) { ++ ALLOC2 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff index b9b46f16a8b7..9bfd46231c40 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff @@ -87,13 +87,13 @@ + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -105,15 +105,15 @@ } + } + -+ alloc11 (size: 8, align: 4) { ++ ALLOC2 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + -+ alloc10 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff index 93b18f23e61a..dba50b1428eb 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff @@ -87,13 +87,13 @@ + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -109,15 +109,15 @@ } + } + -+ alloc11 (size: 8, align: 4) { ++ ALLOC2 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + -+ alloc10 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff index 3d3af62856bd..33fe4628d83e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff @@ -87,13 +87,13 @@ + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -105,15 +105,15 @@ } + } + -+ alloc11 (size: 16, align: 8) { ++ ALLOC2 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + -+ alloc10 (size: 16, align: 8) { ++ ALLOC1 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + -+ alloc7 (size: 16, align: 8) { ++ ALLOC0 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff index 1933f9bafb36..b2d561911de5 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff @@ -87,13 +87,13 @@ + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -109,15 +109,15 @@ } + } + -+ alloc11 (size: 16, align: 8) { ++ ALLOC2 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + -+ alloc10 (size: 16, align: 8) { ++ ALLOC1 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + -+ alloc7 (size: 16, align: 8) { ++ ALLOC0 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 7862c23da809..1751b0de2f1b 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -81,11 +81,11 @@ StorageDead(_6); _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -97,15 +97,15 @@ } } - alloc11 (size: 8, align: 4) { + ALLOC2 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } - alloc10 (size: 8, align: 4) { + ALLOC1 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } - alloc7 (size: 8, align: 4) { + ALLOC0 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index bd4150ebb452..858a9d33ddff 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -81,11 +81,11 @@ StorageDead(_6); _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -101,15 +101,15 @@ } } - alloc11 (size: 8, align: 4) { + ALLOC2 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } - alloc10 (size: 8, align: 4) { + ALLOC1 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } - alloc7 (size: 8, align: 4) { + ALLOC0 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 312fc7b7a82b..517070420754 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -81,11 +81,11 @@ StorageDead(_6); _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -97,15 +97,15 @@ } } - alloc11 (size: 16, align: 8) { + ALLOC2 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } - alloc10 (size: 16, align: 8) { + ALLOC1 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } - alloc7 (size: 16, align: 8) { + ALLOC0 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 3227d8b84353..9141a6c67bee 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -81,11 +81,11 @@ StorageDead(_6); _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -101,15 +101,15 @@ } } - alloc11 (size: 16, align: 8) { + ALLOC2 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } - alloc10 (size: 16, align: 8) { + ALLOC1 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } - alloc7 (size: 16, align: 8) { + ALLOC0 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index ae8b44c953e3..f5da5d567776 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -43,7 +43,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &E}; + _2 = const {ALLOC0: &E}; _1 = (*_2); StorageDead(_2); StorageLive(_3); @@ -78,7 +78,7 @@ bb4: { StorageLive(_7); StorageLive(_8); - _8 = const {alloc2: &&E}; + _8 = const {ALLOC1: &&E}; _7 = (*_8); StorageDead(_8); StorageLive(_9); @@ -112,15 +112,15 @@ } } - alloc2 (static: RC, size: 4, align: 4) { - ╾─alloc14─╼ │ ╾──╼ + ALLOC1 (static: RC, size: 4, align: 4) { + ╾─ALLOC2──╼ │ ╾──╼ } - alloc14 (size: 8, align: 4) { + ALLOC2 (size: 8, align: 4) { 01 00 00 00 04 00 00 00 │ ........ } - alloc1 (static: statics::C, size: 8, align: 4) { + ALLOC0 (static: statics::C, size: 8, align: 4) { 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index 63799b3bac32..db4eb162bda7 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -43,7 +43,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &E}; + _2 = const {ALLOC0: &E}; _1 = (*_2); StorageDead(_2); StorageLive(_3); @@ -78,7 +78,7 @@ bb4: { StorageLive(_7); StorageLive(_8); - _8 = const {alloc2: &&E}; + _8 = const {ALLOC1: &&E}; _7 = (*_8); StorageDead(_8); StorageLive(_9); @@ -112,15 +112,15 @@ } } - alloc2 (static: RC, size: 8, align: 8) { - ╾───────alloc14───────╼ │ ╾──────╼ + ALLOC1 (static: RC, size: 8, align: 8) { + ╾───────ALLOC2────────╼ │ ╾──────╼ } - alloc14 (size: 8, align: 4) { + ALLOC2 (size: 8, align: 4) { 01 00 00 00 04 00 00 00 │ ........ } - alloc1 (static: statics::C, size: 8, align: 4) { + ALLOC0 (static: statics::C, size: 8, align: 4) { 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 2de6ba307d58..f208d82dfd5b 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -84,7 +84,7 @@ + _10 = const S(13_i32); StorageDead(_11); StorageLive(_16); - _16 = const {alloc1: &&BigStruct}; + _16 = const {ALLOC0: &&BigStruct}; _17 = deref_copy (*_16); StorageLive(_12); _18 = deref_copy (*_16); @@ -119,11 +119,11 @@ } } - alloc1 (static: STAT, size: 4, align: 4) { - ╾─alloc15─╼ │ ╾──╼ + ALLOC0 (static: STAT, size: 4, align: 4) { + ╾─ALLOC1──╼ │ ╾──╼ } - alloc15 (size: 16, align: 4) { + ALLOC1 (size: 16, align: 4) { 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index 71a28f2165b2..f8e9d34e5e7c 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -84,7 +84,7 @@ + _10 = const S(13_i32); StorageDead(_11); StorageLive(_16); - _16 = const {alloc1: &&BigStruct}; + _16 = const {ALLOC0: &&BigStruct}; _17 = deref_copy (*_16); StorageLive(_12); _18 = deref_copy (*_16); @@ -119,11 +119,11 @@ } } - alloc1 (static: STAT, size: 8, align: 8) { - ╾───────alloc15───────╼ │ ╾──────╼ + ALLOC0 (static: STAT, size: 8, align: 8) { + ╾───────ALLOC1────────╼ │ ╾──────╼ } - alloc15 (size: 16, align: 4) { + ALLOC1 (size: 16, align: 4) { 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ } diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff index ec5f5c1f1fc6..775a60f1c960 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff @@ -66,7 +66,7 @@ } + } + -+ alloc15 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 02 00 00 00 05 20 00 00 │ ..... .. } diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff index 9bf8637ec765..c4b57579943d 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff @@ -66,7 +66,7 @@ } + } + -+ alloc15 (size: 16, align: 8) { ++ ALLOC0 (size: 16, align: 8) { + 02 00 00 00 00 00 00 00 05 20 00 00 00 00 00 00 │ ......... ...... } diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff index 7dc6d21a9076..f7d0d1fb56c3 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff @@ -66,7 +66,7 @@ } + } + -+ alloc14 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 05 20 00 00 01 00 00 00 │ . ...... } diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff index 0b000876a866..15f1bd0df51a 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff @@ -66,7 +66,7 @@ } + } + -+ alloc14 (size: 16, align: 8) { ++ ALLOC0 (size: 16, align: 8) { + 05 20 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ . .............. } diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index 132b713356ec..f8ac75513bae 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -271,6 +271,6 @@ fn main() -> () { } } -alloc4 (size: 4, align: 1) { +ALLOC0 (size: 4, align: 1) { 41 41 41 41 │ AAAA } diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index 132b713356ec..f8ac75513bae 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -271,6 +271,6 @@ fn main() -> () { } } -alloc4 (size: 4, align: 1) { +ALLOC0 (size: 4, align: 1) { 41 41 41 41 │ AAAA } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff index 681e9666e0fb..bddd961c9330 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff @@ -57,7 +57,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff index db16b8d82d2c..297ebd79fad7 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff @@ -57,7 +57,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff index 681e9666e0fb..bddd961c9330 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff @@ -57,7 +57,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff index db16b8d82d2c..297ebd79fad7 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff @@ -57,7 +57,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr index 796966b22d51..5832dbe1777d 100644 --- a/tests/ui/const-generics/issues/issue-100313.stderr +++ b/tests/ui/const-generics/issues/issue-100313.stderr @@ -11,7 +11,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-100313.rs:10:13 | LL | *(B as *const bool as *mut bool) = false; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc7 which is read-only + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to ALLOC0 which is read-only | note: inside `T::<&true>::set_false` --> $DIR/issue-100313.rs:10:13 diff --git a/tests/ui/const-ptr/forbidden_slices.rs b/tests/ui/const-ptr/forbidden_slices.rs index 93e3bb09ff15..03d6499aefbb 100644 --- a/tests/ui/const-ptr/forbidden_slices.rs +++ b/tests/ui/const-ptr/forbidden_slices.rs @@ -1,7 +1,7 @@ // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" -// normalize-stderr-test "alloc\d+" -> "allocN" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" + #![feature( slice_from_ptr_range, const_slice_from_ptr_range, diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr index 4ae0ffff63d5..8243a3631caa 100644 --- a/tests/ui/const-ptr/forbidden_slices.stderr +++ b/tests/ui/const-ptr/forbidden_slices.stderr @@ -122,7 +122,7 @@ LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; error[E0080]: could not evaluate static initializer --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC6 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::add` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -181,7 +181,7 @@ LL | pub static R7: &[u16] = unsafe { error[E0080]: could not evaluate static initializer --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC11 has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds | note: inside `ptr::const_ptr::::add` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr index bfdd5859719b..be75f76b26f2 100644 --- a/tests/ui/const-ptr/out_of_bounds_read.stderr +++ b/tests/ui/const-ptr/out_of_bounds_read.stderr @@ -1,7 +1,7 @@ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL @@ -14,7 +14,7 @@ LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL @@ -29,7 +29,7 @@ LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr index 54fafded07ba..d8971eb9969f 100644 --- a/tests/ui/consts/const-compare-bytes-ub.stderr +++ b/tests/ui/consts/const-compare-bytes-ub.stderr @@ -20,25 +20,25 @@ error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:22:9 | LL | compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc6 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:26:9 | LL | compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc13 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC1 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:30:9 | LL | compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc17[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:34:9 | LL | compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc25[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:38:9 diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr index a0f4519eaad3..fc9d2d258658 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -6,7 +6,7 @@ LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc2──╼ │ ╾──╼ + ╾─ALLOC0──╼ │ ╾──╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr index d2bffa42561a..553359e0479a 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr @@ -6,7 +6,7 @@ LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc2────────╼ │ ╾──────╼ + ╾───────ALLOC0────────╼ │ ╾──────╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr index 032dcad86a49..5f4630f6f4bc 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr @@ -8,7 +8,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_dangling.rs:18:5 | LL | *reference - | ^^^^^^^^^^ memory access failed: alloc4 has been freed, so this pointer is dangling + | ^^^^^^^^^^ memory access failed: ALLOC0 has been freed, so this pointer is dangling error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr index 0884ade45a7e..916344a7b816 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_duplicate.rs:9:5 | LL | intrinsics::const_deallocate(ptr, 4, 4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc2 has been freed, so this pointer is dangling + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has been freed, so this pointer is dangling error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr index 4c23957a1f80..4b1f0f686ca0 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr @@ -2,19 +2,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_incorrect_layout.rs:8:5 | LL | intrinsics::const_deallocate(ptr, 4, 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc2 has size 4 and alignment 4, but gave size 4 and alignment 2 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC0 has size 4 and alignment 4, but gave size 4 and alignment 2 error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_incorrect_layout.rs:13:5 | LL | intrinsics::const_deallocate(ptr, 2, 4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc4 has size 4 and alignment 4, but gave size 2 and alignment 4 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC1 has size 4 and alignment 4, but gave size 2 and alignment 4 error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_incorrect_layout.rs:19:5 | LL | intrinsics::const_deallocate(ptr, 3, 4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc6 has size 4 and alignment 4, but gave size 3 and alignment 4 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC2 has size 4 and alignment 4, but gave size 3 and alignment 4 error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_incorrect_layout.rs:25:5 diff --git a/tests/ui/consts/const-eval/issue-49296.stderr b/tests/ui/consts/const-eval/issue-49296.stderr index 1f9b1dfe31e5..2022a16e789e 100644 --- a/tests/ui/consts/const-eval/issue-49296.stderr +++ b/tests/ui/consts/const-eval/issue-49296.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-49296.rs:9:16 | LL | const X: u64 = *wat(42); - | ^^^^^^^^ memory access failed: alloc3 has been freed, so this pointer is dangling + | ^^^^^^^^ memory access failed: ALLOC0 has been freed, so this pointer is dangling error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr index 13ca4379b7bd..b948e07b92db 100644 --- a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr +++ b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/partial_ptr_overwrite.rs:8:9 | LL | *(ptr as *mut u8) = 123; - | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4 + | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at ALLOC0 | = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr index 042e7eeb31e1..7693e596c8cf 100644 --- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -211,7 +211,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:106:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -385,7 +385,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:175:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC16, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -396,7 +396,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:179:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC18, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -418,7 +418,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:186:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC21, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -451,7 +451,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:196:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC26, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -556,7 +556,7 @@ LL | pub static S7: &[u16] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC_ID+0x2╼ 04 00 00 00 │ ╾──╼.... + ╾A31+0x2──╼ 04 00 00 00 │ ╾──╼.... } error[E0080]: it is undefined behavior to use this value diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr index 8426a95055cc..ac19e4f5d543 100644 --- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -211,7 +211,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:106:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -385,7 +385,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:175:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC16, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -396,7 +396,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:179:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC18, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -418,7 +418,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:186:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC21, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -451,7 +451,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:196:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC26, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs index 6c1238c0a063..e005922223ad 100644 --- a/tests/ui/consts/const-eval/raw-bytes.rs +++ b/tests/ui/consts/const-eval/raw-bytes.rs @@ -1,8 +1,8 @@ // stderr-per-bitwidth // ignore-endian-big // ignore-tidy-linelength -// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼" -// normalize-stderr-test "alloc\d+" -> "allocN" +// normalize-stderr-test "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$1╼" + #![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)] #![allow(invalid_value)] diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs index 2d09b5494c68..9b79a0a7d347 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.rs +++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs @@ -1,8 +1,8 @@ -// normalize-stderr-test "alloc\d+" -> "allocN" #![feature(const_pointer_byte_offsets)] #![feature(pointer_byte_offsets)] #![feature(const_mut_refs)] + const MISALIGNED_LOAD: () = unsafe { let mem = [0u32; 8]; let ptr = mem.as_ptr().byte_add(1); diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr index 663d49f21b44..f644e5f87481 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr +++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr @@ -35,7 +35,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/raw-pointer-ub.rs:43:16 | LL | let _val = *ptr; - | ^^^^ memory access failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds + | ^^^^ memory access failed: ALLOC0 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds error: aborting due to 5 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr index 13c5920bd37b..3ec7d88e79c1 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -2,55 +2,55 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:18:1 | LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC0, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN──╼ ╾─allocN──╼ │ ╾──╼╾──╼ + ╾─ALLOC1──╼ ╾─ALLOC0──╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:23:1 | LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC2, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾─ALLOC3──╼ ╾─ALLOC2──╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC4, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾─ALLOC5──╼ ╾─ALLOC4──╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC6, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾─ALLOC7──╼ ╾─ALLOC6──╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC8, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾─ALLOC9──╼ ╾─ALLOC8──╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -61,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾─ALLOC10─╼ ╾─ALLOC11─╼ │ ╾──╼╾──╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr index ba47865bcf96..9f0588ac033a 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -2,55 +2,55 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:18:1 | LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC0, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN────────╼ ╾───────allocN────────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC1────────╼ ╾───────ALLOC0────────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:23:1 | LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC2, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC3────────╼ ╾───────ALLOC2────────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC4, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC5────────╼ ╾───────ALLOC4────────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC6, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC7────────╼ ╾───────ALLOC6────────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC8, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC9────────╼ ╾───────ALLOC8────────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -61,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC10───────╼ ╾───────ALLOC11───────╼ │ ╾──────╼╾──────╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs index 7fb58f43bcb9..7d1927253f22 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs @@ -11,7 +11,7 @@ // errors are emitted instead of ICEs. // stderr-per-bitwidth -// normalize-stderr-test "alloc\d+" -> "allocN" + trait Trait {} diff --git a/tests/ui/consts/const-eval/ub-nonnull.rs b/tests/ui/consts/const-eval/ub-nonnull.rs index a64b3a74cf6c..fe4ec4d23d05 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.rs +++ b/tests/ui/consts/const-eval/ub-nonnull.rs @@ -1,6 +1,6 @@ // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" #![feature(rustc_attrs, ptr_metadata)] #![allow(invalid_value)] // make sure we cannot allow away the errors tested here diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index 2df76f2c9e2c..27befc413883 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -13,7 +13,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/ub-nonnull.rs:20:29 | LL | let out_of_bounds_ptr = &ptr[255]; - | ^^^^^^^^^ out-of-bounds pointer arithmetic: alloc11 has size 1, so pointer to 255 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC0 has size 1, so pointer to 255 bytes starting at offset 0 is out-of-bounds error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:24:1 diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.rs b/tests/ui/consts/const-eval/ub-ref-ptr.rs index a5d2ea014865..08d4dce4d17f 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.rs +++ b/tests/ui/consts/const-eval/ub-ref-ptr.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" #![allow(invalid_value)] use std::mem; diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr index 2144d1471082..c608bad2a47b 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr @@ -141,7 +141,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:59:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc39, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC2, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { diff --git a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr index f7898e55ee2c..f0101c6c29df 100644 --- a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr @@ -6,7 +6,7 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{ | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc3──╼ ╾─alloc4──╼ │ ╾──╼╾──╼ + ╾─ALLOC0──╼ ╾─ALLOC1──╼ │ ╾──╼╾──╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr index 60432380e134..c4da26353d77 100644 --- a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr @@ -6,7 +6,7 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{ | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc3────────╼ ╾───────alloc4────────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC0────────╼ ╾───────ALLOC1────────╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs index 02cf5326c6a1..dc8d4c640c2f 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.rs +++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs @@ -5,11 +5,11 @@ use std::mem; // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" // normalize-stderr-test "offset \d+" -> "offset N" -// normalize-stderr-test "alloc\d+" -> "allocN" // normalize-stderr-test "size \d+" -> "size N" + /// A newtype wrapper to prevent MIR generation from inserting reborrows that would affect the error /// message. #[repr(transparent)] diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr index d57e4720c918..c98ae2948c44 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -189,7 +189,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:113:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC11, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -200,7 +200,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:117:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC13, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -222,7 +222,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:124:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC16, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -233,7 +233,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:127:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC18, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -244,7 +244,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:130:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC20, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -255,7 +255,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:133:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -288,7 +288,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:145:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -310,7 +310,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:154:1 | LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC30, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { diff --git a/tests/ui/consts/const-points-to-static.32bit.stderr b/tests/ui/consts/const-points-to-static.32bit.stderr index c7a435a1ee3f..9a77e5a5764c 100644 --- a/tests/ui/consts/const-points-to-static.32bit.stderr +++ b/tests/ui/consts/const-points-to-static.32bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc1──╼ │ ╾──╼ + ╾─ALLOC0──╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/const-points-to-static.64bit.stderr b/tests/ui/consts/const-points-to-static.64bit.stderr index 4d5b8eac541d..982c64ecc725 100644 --- a/tests/ui/consts/const-points-to-static.64bit.stderr +++ b/tests/ui/consts/const-points-to-static.64bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc1────────╼ │ ╾──────╼ + ╾───────ALLOC0────────╼ │ ╾──────╼ } warning: skipping const checks diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr index be41c2db398b..0e4e6a6ad6c4 100644 --- a/tests/ui/consts/copy-intrinsic.stderr +++ b/tests/ui/consts/copy-intrinsic.stderr @@ -2,13 +2,13 @@ error[E0080]: evaluation of constant value failed --> $DIR/copy-intrinsic.rs:27:5 | LL | copy_nonoverlapping(0x100 as *const i32, dangle, 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer at offset 40 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has size 4, so pointer at offset 40 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/copy-intrinsic.rs:34:5 | LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc7 has size 4, so pointer at offset 40 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC1 has size 4, so pointer at offset 40 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/copy-intrinsic.rs:41:5 diff --git a/tests/ui/consts/invalid-union.32bit.stderr b/tests/ui/consts/invalid-union.32bit.stderr index 0c57751cbfa4..448bfe78b596 100644 --- a/tests/ui/consts/invalid-union.32bit.stderr +++ b/tests/ui/consts/invalid-union.32bit.stderr @@ -6,7 +6,7 @@ LL | fn main() { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc7──╼ │ ╾──╼ + ╾─ALLOC0──╼ │ ╾──╼ } note: erroneous constant encountered diff --git a/tests/ui/consts/invalid-union.64bit.stderr b/tests/ui/consts/invalid-union.64bit.stderr index 6c4d5882158d..6e01391d3a7c 100644 --- a/tests/ui/consts/invalid-union.64bit.stderr +++ b/tests/ui/consts/invalid-union.64bit.stderr @@ -6,7 +6,7 @@ LL | fn main() { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc7────────╼ │ ╾──────╼ + ╾───────ALLOC0────────╼ │ ╾──────╼ } note: erroneous constant encountered diff --git a/tests/ui/consts/issue-63952.32bit.stderr b/tests/ui/consts/issue-63952.32bit.stderr index 755c7fb7d4d9..2a9a9bc9eec8 100644 --- a/tests/ui/consts/issue-63952.32bit.stderr +++ b/tests/ui/consts/issue-63952.32bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc4──╼ ff ff ff ff │ ╾──╼.... + ╾─ALLOC0──╼ ff ff ff ff │ ╾──╼.... } error: aborting due to previous error diff --git a/tests/ui/consts/issue-63952.64bit.stderr b/tests/ui/consts/issue-63952.64bit.stderr index abdb9a4f7920..e83cf1ba36e9 100644 --- a/tests/ui/consts/issue-63952.64bit.stderr +++ b/tests/ui/consts/issue-63952.64bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc4────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + ╾───────ALLOC0────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ } error: aborting due to previous error diff --git a/tests/ui/consts/issue-79690.64bit.stderr b/tests/ui/consts/issue-79690.64bit.stderr index b8798a9755fe..e3a5e2acbbdc 100644 --- a/tests/ui/consts/issue-79690.64bit.stderr +++ b/tests/ui/consts/issue-79690.64bit.stderr @@ -6,7 +6,7 @@ LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc3────────╼ ╾───────alloc4────────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC0────────╼ ╾───────ALLOC1────────╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr index a6f467b9ef48..dbc57573ff3a 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr @@ -24,7 +24,7 @@ LL | const REF_INTERIOR_MUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc4──╼ │ ╾──╼ + ╾─ALLOC0──╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -35,7 +35,7 @@ LL | const READ_IMMUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc5──╼ │ ╾──╼ + ╾─ALLOC1──╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr index cfaf31a6e0c4..9340254fd4fb 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr @@ -24,7 +24,7 @@ LL | const REF_INTERIOR_MUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc4────────╼ │ ╾──────╼ + ╾───────ALLOC0────────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -35,7 +35,7 @@ LL | const READ_IMMUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc5────────╼ │ ╾──────╼ + ╾───────ALLOC1────────╼ │ ╾──────╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index e3a0d93f09b7..430187d4fec5 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_MUT: &[u8; 1] = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc1──╼ │ ╾──╼ + ╾─ALLOC0──╼ │ ╾──╼ } error: could not evaluate constant pattern @@ -23,7 +23,7 @@ LL | const U8_MUT: &u8 = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc1──╼ │ ╾──╼ + ╾─ALLOC0──╼ │ ╾──╼ } error: could not evaluate constant pattern diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr index a323e9a05f09..90579f2d7084 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_MUT: &[u8; 1] = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc1────────╼ │ ╾──────╼ + ╾───────ALLOC0────────╼ │ ╾──────╼ } error: could not evaluate constant pattern @@ -23,7 +23,7 @@ LL | const U8_MUT: &u8 = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc1────────╼ │ ╾──────╼ + ╾───────ALLOC0────────╼ │ ╾──────╼ } error: could not evaluate constant pattern diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index 0ea1792409b8..65030ead85c0 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -6,7 +6,7 @@ LL | const MUH: Meh = Meh { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc3──╼ │ ╾──╼ + ╾─ALLOC0──╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -17,7 +17,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc7──╼ ╾─alloc8──╼ │ ╾──╼╾──╼ + ╾─ALLOC1──╼ ╾─ALLOC2──╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc10─╼ │ ╾──╼ + ╾─ALLOC3──╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr index 67959d25634a..fd9d13adcbcc 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -6,7 +6,7 @@ LL | const MUH: Meh = Meh { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc3────────╼ │ ╾──────╼ + ╾───────ALLOC0────────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -17,7 +17,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc7────────╼ ╾───────alloc8────────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC1────────╼ ╾───────ALLOC2────────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc10───────╼ │ ╾──────╼ + ╾───────ALLOC3────────╼ │ ╾──────╼ } warning: skipping const checks diff --git a/tests/ui/consts/missing_span_in_backtrace.rs b/tests/ui/consts/missing_span_in_backtrace.rs index dd2b81c5af2b..1ac3777f5feb 100644 --- a/tests/ui/consts/missing_span_in_backtrace.rs +++ b/tests/ui/consts/missing_span_in_backtrace.rs @@ -1,5 +1,5 @@ // compile-flags: -Z ui-testing=no -// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID" + #![feature(const_swap)] #![feature(const_mut_refs)] diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr index fcfb9fbb3f8c..6860cee4184f 100644 --- a/tests/ui/consts/missing_span_in_backtrace.stderr +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -1,7 +1,7 @@ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: unable to copy parts of a pointer from memory at ALLOC_ID + = note: unable to copy parts of a pointer from memory at ALLOC0 | note: inside `std::ptr::read::>>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr index 97ff6efdd791..1ef727e5b0f3 100644 --- a/tests/ui/consts/offset_from_ub.stderr +++ b/tests/ui/consts/offset_from_ub.stderr @@ -39,19 +39,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:53:14 | LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc17 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC0 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:62:14 | LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC1 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:70:14 | LL | unsafe { ptr_offset_from(end_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc23 has size 4, so pointer at offset 10 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC2 has size 4, so pointer at offset 10 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:79:14 diff --git a/tests/ui/consts/offset_ub.rs b/tests/ui/consts/offset_ub.rs index 1b01e4fd1473..db28a6c6a2b4 100644 --- a/tests/ui/consts/offset_ub.rs +++ b/tests/ui/consts/offset_ub.rs @@ -1,6 +1,6 @@ use std::ptr; -// normalize-stderr-test "alloc\d+" -> "allocN" + // normalize-stderr-test "0x7f+" -> "0x7f..f" diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr index c0c851df5076..8bc59d50ee4b 100644 --- a/tests/ui/consts/offset_ub.stderr +++ b/tests/ui/consts/offset_ub.stderr @@ -14,7 +14,7 @@ LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC0 has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -27,7 +27,7 @@ LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC1 has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -92,7 +92,7 @@ LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).of error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC2 has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds | note: inside `ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -105,7 +105,7 @@ LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC3 has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index 4fc304cda604..317466eb3226 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/intrinsic-raw_eq-const-bad.rs:5:5 | LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc3[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory error[E0080]: evaluation of constant value failed --> $DIR/intrinsic-raw_eq-const-bad.rs:11:5 From 6605116463a4c1173db7026ee21a22c963569b44 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 16 Oct 2023 19:29:16 +0200 Subject: [PATCH 25/94] use target-arch based table --- library/core/src/sync/atomic.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index aa8ca1e025f3..5a429826c0d4 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -100,12 +100,11 @@ //! Undefined Behavior. The exact size limit for what makes a load "sufficiently small" varies //! depending on the target: //! -//! | Target triple prefix (regular expression) | Size limit | +//! | `target_arch` | Size limit | //! |---------------|---------| -//! | `i(3|5|6)86-`, `arm`, `thumb`, `mips(|el)-`, `powerpc-`, `riscv32`, `sparc-` | 4 bytes | -//! | `x86_64-`, `aarch64-`, `loongarch64-`, `mips64(|el)-`, `powerpc64-`, `riscv64` | 8 bytes | -//! | `powerpc64le-` | 16 bytes | -//! | `s390x-` | 16 bytes | +//! | `x86`, `arm`, `mips`, `mips32r6, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes | +//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64` | 8 bytes | +//! | `s390x`, `powerpc64` with `target_feature = "quadword-atomics"` | 16 bytes | //! //! Atomics loads that are larger than this limit as well as atomic loads with ordering other //! than `Relaxed`, as well as *all* atomic loads on targets not listed in the table, might still be From c423305d415cbeea5ac2460a4ba577f7d00a27cf Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 16 Oct 2023 18:24:30 +0000 Subject: [PATCH 26/94] Motivate renumbering and avoid underflow. --- src/tools/compiletest/src/runtest.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3982b7893280..dfb5013850f8 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -4258,7 +4258,9 @@ impl<'test> TestCx<'test> { V0_BACK_REF_RE.replace_all(&normalized, V0_BACK_REF_PLACEHOLDER).into_owned(); } - // Normalize AllocId counter + // AllocId are numbered globally in a compilation session. This can lead to changes + // depending on the exact compilation flags and host architecture. Meanwhile, we want + // to keep them numbered, to see if the same id appears multiple times. { use std::fmt::Write; @@ -4276,8 +4278,9 @@ impl<'test> TestCx<'test> { // Complete with filler `─` to preserve the pretty-print. if let Some(tail) = caps.get(3) { ret.push_str(tail.as_str()); - let diff = caps.get(0).unwrap().as_str().len() - ret.len(); - for _ in 0..diff { + let orig_len = caps.get(0).unwrap().as_str().len(); + let ret_len = ret.len(); + for _ in orig_len..ret_len { ret.push('─'); } } From 669b99d35e222f9449a4bdf9b0a0f615fce11666 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 16 Oct 2023 18:33:05 +0000 Subject: [PATCH 27/94] Elaborate comment. --- src/tools/compiletest/src/runtest.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index dfb5013850f8..4868225f5e46 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -4261,6 +4261,8 @@ impl<'test> TestCx<'test> { // AllocId are numbered globally in a compilation session. This can lead to changes // depending on the exact compilation flags and host architecture. Meanwhile, we want // to keep them numbered, to see if the same id appears multiple times. + // So we remap to deterministic numbers that only depend on the subset of allocations + // that actually appear in the output. { use std::fmt::Write; From 0eb958a89b4f1ad4b7b6785b5d6faef3e3ff3267 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 16 Oct 2023 18:36:47 +0000 Subject: [PATCH 28/94] Rebless. --- ...const_allocation.main.ConstProp.after.32bit.mir | 12 ++++++------ ...const_allocation.main.ConstProp.after.64bit.mir | 14 +++++++------- ...onst_allocation2.main.ConstProp.after.32bit.mir | 12 ++++++------ ...onst_allocation2.main.ConstProp.after.64bit.mir | 14 +++++++------- ...onst_allocation3.main.ConstProp.after.32bit.mir | 4 ++-- ...onst_allocation3.main.ConstProp.after.64bit.mir | 4 ++-- .../enum.statics.DataflowConstProp.32bit.diff | 2 +- .../enum.statics.DataflowConstProp.64bit.diff | 2 +- .../struct.main.DataflowConstProp.32bit.diff | 2 +- .../struct.main.DataflowConstProp.64bit.diff | 2 +- tests/ui/consts/const-eval/raw-bytes.32bit.stderr | 2 +- .../const-eval/ub-incorrect-vtable.32bit.stderr | 8 ++++---- .../const-eval/ub-incorrect-vtable.64bit.stderr | 8 ++++---- .../mutable_references_err.32bit.stderr | 2 +- .../mutable_references_err.64bit.stderr | 2 +- 15 files changed, 45 insertions(+), 45 deletions(-) diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index c44483b21674..cc80ff449a75 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -18,19 +18,19 @@ fn main() -> () { } ALLOC0 (static: FOO, size: 8, align: 4) { - ╾─ALLOC1──╼ 03 00 00 00 │ ╾──╼.... + ╾─ALLOC1─╼ 03 00 00 00 │ ╾──╼.... } ALLOC1 (size: 48, align: 4) { 0x00 │ 00 00 00 00 __ __ __ __ ╾─ALLOC2──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─ALLOC3──╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─ALLOC4──╼ 03 00 00 00 │ ....*...╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─ALLOC3─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─ALLOC4─╼ 03 00 00 00 │ ....*...╾──╼.... } ALLOC2 (size: 0, align: 4) {} ALLOC3 (size: 16, align: 4) { - ╾─ALLOC5──╼ 03 00 00 00 ╾─ALLOC6──╼ 03 00 00 00 │ ╾──╼....╾──╼.... + ╾─ALLOC5──╼ 03 00 00 00 ╾─ALLOC6─╼ 03 00 00 00 │ ╾──╼....╾──╼.... } ALLOC5 (size: 3, align: 1) { @@ -42,8 +42,8 @@ ALLOC6 (size: 3, align: 1) { } ALLOC4 (size: 24, align: 4) { - 0x00 │ ╾─ALLOC7──╼ 03 00 00 00 ╾─ALLOC8──╼ 03 00 00 00 │ ╾──╼....╾──╼.... - 0x10 │ ╾─ALLOC9──╼ 04 00 00 00 │ ╾──╼.... + 0x00 │ ╾─ALLOC7─╼ 03 00 00 00 ╾─ALLOC8─╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾─ALLOC9─╼ 04 00 00 00 │ ╾──╼.... } ALLOC7 (size: 3, align: 1) { diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index 02fd6a8da531..60019708cad0 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -18,14 +18,14 @@ fn main() -> () { } ALLOC0 (static: FOO, size: 16, align: 8) { - ╾───────ALLOC1────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────ALLOC1───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } ALLOC1 (size: 72, align: 8) { 0x00 │ 00 00 00 00 __ __ __ __ ╾───────ALLOC2────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────ALLOC3────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────ALLOC4────────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────ALLOC3───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────ALLOC4───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } @@ -33,7 +33,7 @@ ALLOC2 (size: 0, align: 8) {} ALLOC3 (size: 32, align: 8) { 0x00 │ ╾───────ALLOC5────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────ALLOC6────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────ALLOC6───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } ALLOC5 (size: 3, align: 1) { @@ -45,9 +45,9 @@ ALLOC6 (size: 3, align: 1) { } ALLOC4 (size: 48, align: 8) { - 0x00 │ ╾───────ALLOC7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────ALLOC8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x20 │ ╾───────ALLOC9────────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x00 │ ╾───────ALLOC7───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────ALLOC8───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾───────ALLOC9───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } ALLOC7 (size: 3, align: 1) { diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index 5fe485ea815e..c0b0cc2f69b5 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -18,19 +18,19 @@ fn main() -> () { } ALLOC0 (static: FOO, size: 8, align: 4) { - ╾─ALLOC1──╼ 03 00 00 00 │ ╾──╼.... + ╾─ALLOC1─╼ 03 00 00 00 │ ╾──╼.... } ALLOC1 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─ALLOC2──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─ALLOC3──╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─ALLOC4──╼ 03 00 00 00 │ ....*...╾──╼.... + 0x00 │ 00 00 00 00 __ __ __ __ ╾─ALLOC2─╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─ALLOC3─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─ALLOC4─╼ 03 00 00 00 │ ....*...╾──╼.... } ALLOC2 (size: 0, align: 4) {} ALLOC3 (size: 8, align: 4) { - ╾─ALLOC5──╼ ╾─ALLOC6──╼ │ ╾──╼╾──╼ + ╾─ALLOC5─╼ ╾─ALLOC6─╼ │ ╾──╼╾──╼ } ALLOC5 (size: 1, align: 1) { @@ -42,7 +42,7 @@ ALLOC6 (size: 1, align: 1) { } ALLOC4 (size: 12, align: 4) { - ╾─A7+0x3──╼ ╾─ALLOC8──╼ ╾─A9+0x2──╼ │ ╾──╼╾──╼╾──╼ + ╾─A7+0x3─╼ ╾─ALLOC8─╼ ╾─A9+0x2─╼ │ ╾──╼╾──╼╾──╼ } ALLOC7 (size: 4, align: 1) { diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index b55e35bb9c5f..bd98633c7598 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -18,21 +18,21 @@ fn main() -> () { } ALLOC0 (static: FOO, size: 16, align: 8) { - ╾───────ALLOC1────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────ALLOC1───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } ALLOC1 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────ALLOC2────────╼ │ ....░░░░╾──────╼ + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────ALLOC2───────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────ALLOC3────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────ALLOC4────────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────ALLOC3───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────ALLOC4───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } ALLOC2 (size: 0, align: 8) {} ALLOC3 (size: 16, align: 8) { - ╾───────ALLOC5────────╼ ╾───────ALLOC6────────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC5───────╼ ╾───────ALLOC6───────╼ │ ╾──────╼╾──────╼ } ALLOC5 (size: 1, align: 1) { @@ -44,8 +44,8 @@ ALLOC6 (size: 1, align: 1) { } ALLOC4 (size: 24, align: 8) { - 0x00 │ ╾─────ALLOC7+0x3──────╼ ╾───────ALLOC8────────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────ALLOC9+0x2──────╼ │ ╾──────╼ + 0x00 │ ╾─────ALLOC7+0x3─────╼ ╾───────ALLOC8───────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾─────ALLOC9+0x2─────╼ │ ╾──────╼ } ALLOC7 (size: 4, align: 1) { diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir index d487d813e8a8..e2db4b52e0c7 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir @@ -18,7 +18,7 @@ fn main() -> () { } ALLOC0 (static: FOO, size: 4, align: 4) { - ╾─ALLOC1──╼ │ ╾──╼ + ╾─ALLOC1─╼ │ ╾──╼ } ALLOC1 (size: 168, align: 1) { @@ -31,7 +31,7 @@ ALLOC1 (size: 168, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─ALLOC3──╼ 00 00 │ ..........╾──╼.. - 0x90 │ ╾A4+0x63──╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ + 0x90 │ ╾A4+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ 0xa0 │ 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir index 3cdc1cbbcf4c..392c5aedcaf1 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir @@ -18,7 +18,7 @@ fn main() -> () { } ALLOC0 (static: FOO, size: 8, align: 8) { - ╾───────ALLOC1────────╼ │ ╾──────╼ + ╾───────ALLOC1───────╼ │ ╾──────╼ } ALLOC1 (size: 180, align: 1) { @@ -31,7 +31,7 @@ ALLOC1 (size: 180, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─ - 0x90 │ ─────ALLOC3─────╼ 00 00 ╾────ALLOC4+0x63──────╼ │ ─────╼..╾──────╼ + 0x90 │ ─────ALLOC3─────╼ 00 00 ╾────ALLOC4+0x63─────╼ │ ─────╼..╾──────╼ 0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0xb0 │ 00 00 00 00 │ .... } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index f5da5d567776..f51431b101f1 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -113,7 +113,7 @@ } ALLOC1 (static: RC, size: 4, align: 4) { - ╾─ALLOC2──╼ │ ╾──╼ + ╾─ALLOC2─╼ │ ╾──╼ } ALLOC2 (size: 8, align: 4) { diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index db4eb162bda7..b104801c48a3 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -113,7 +113,7 @@ } ALLOC1 (static: RC, size: 8, align: 8) { - ╾───────ALLOC2────────╼ │ ╾──────╼ + ╾───────ALLOC2───────╼ │ ╾──────╼ } ALLOC2 (size: 8, align: 4) { diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index f208d82dfd5b..8e0ce7eafd77 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -120,7 +120,7 @@ } ALLOC0 (static: STAT, size: 4, align: 4) { - ╾─ALLOC1──╼ │ ╾──╼ + ╾─ALLOC1─╼ │ ╾──╼ } ALLOC1 (size: 16, align: 4) { diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index f8e9d34e5e7c..de941e51f2f5 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -120,7 +120,7 @@ } ALLOC0 (static: STAT, size: 8, align: 8) { - ╾───────ALLOC1────────╼ │ ╾──────╼ + ╾───────ALLOC1───────╼ │ ╾──────╼ } ALLOC1 (size: 16, align: 4) { diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr index 7693e596c8cf..a240a78255b5 100644 --- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -556,7 +556,7 @@ LL | pub static S7: &[u16] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾A31+0x2──╼ 04 00 00 00 │ ╾──╼.... + ╾A31+0x2─╼ 04 00 00 00 │ ╾──╼.... } error[E0080]: it is undefined behavior to use this value diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr index 3ec7d88e79c1..25b773939dcb 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -17,7 +17,7 @@ LL | const INVALID_VTABLE_SIZE: &dyn Trait = | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC3──╼ ╾─ALLOC2──╼ │ ╾──╼╾──╼ + ╾─ALLOC3─╼ ╾─ALLOC2─╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -28,7 +28,7 @@ LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC5──╼ ╾─ALLOC4──╼ │ ╾──╼╾──╼ + ╾─ALLOC5─╼ ╾─ALLOC4─╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -39,7 +39,7 @@ LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC7──╼ ╾─ALLOC6──╼ │ ╾──╼╾──╼ + ╾─ALLOC7─╼ ╾─ALLOC6─╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -50,7 +50,7 @@ LL | const INVALID_VTABLE_UB: W<&dyn Trait> = | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC9──╼ ╾─ALLOC8──╼ │ ╾──╼╾──╼ + ╾─ALLOC9─╼ ╾─ALLOC8─╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr index 9f0588ac033a..3d2868f6cb4a 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -17,7 +17,7 @@ LL | const INVALID_VTABLE_SIZE: &dyn Trait = | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC3────────╼ ╾───────ALLOC2────────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC3───────╼ ╾───────ALLOC2───────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -28,7 +28,7 @@ LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC5────────╼ ╾───────ALLOC4────────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC5───────╼ ╾───────ALLOC4───────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -39,7 +39,7 @@ LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC7────────╼ ╾───────ALLOC6────────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC7───────╼ ╾───────ALLOC6───────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -50,7 +50,7 @@ LL | const INVALID_VTABLE_UB: W<&dyn Trait> = | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC9────────╼ ╾───────ALLOC8────────╼ │ ╾──────╼╾──────╼ + ╾───────ALLOC9───────╼ ╾───────ALLOC8───────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index 65030ead85c0..5ec4ce529e13 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC3──╼ │ ╾──╼ + ╾─ALLOC3─╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr index fd9d13adcbcc..22a0c57b91a8 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC3────────╼ │ ╾──────╼ + ╾───────ALLOC3───────╼ │ ╾──────╼ } warning: skipping const checks From 364f1a3f1676968195f62ebed999837034dd5aae Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Fri, 13 Oct 2023 22:40:35 -0700 Subject: [PATCH 29/94] Add MonoItems and Instance to stable_mir Also add a few methods to instantiate instances and get an instance definition. We're still missing support to actually monomorphize the instance body. --- compiler/rustc_smir/src/rustc_internal/mod.rs | 28 +++- compiler/rustc_smir/src/rustc_smir/mod.rs | 125 ++++++++++++++---- compiler/stable_mir/src/error.rs | 69 ++++++++++ compiler/stable_mir/src/lib.rs | 43 +++--- compiler/stable_mir/src/mir.rs | 1 + compiler/stable_mir/src/mir/mono.rs | 89 +++++++++++++ tests/ui-fulldeps/stable-mir/instance.rs | 91 +++++++++++++ 7 files changed, 401 insertions(+), 45 deletions(-) create mode 100644 compiler/stable_mir/src/error.rs create mode 100644 compiler/stable_mir/src/mir/mono.rs create mode 100644 tests/ui-fulldeps/stable-mir/instance.rs diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index e3c84f06543e..5ea805e5739b 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -6,9 +6,11 @@ use crate::rustc_internal; use crate::rustc_smir::Tables; use rustc_data_structures::fx; +use rustc_data_structures::fx::FxIndexMap; use rustc_driver::{Callbacks, Compilation, RunCompiler}; use rustc_interface::{interface, Queries}; use rustc_middle::mir::interpret::AllocId; +use rustc_middle::ty; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::Span; @@ -97,7 +99,7 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::Prov(self.create_alloc_id(aid)) } - fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { + pub(crate) fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { self.def_ids.create_or_fetch(did) } @@ -108,6 +110,17 @@ impl<'tcx> Tables<'tcx> { pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span { self.spans.create_or_fetch(span) } + + pub(crate) fn instance_def( + &mut self, + instance: ty::Instance<'tcx>, + ) -> stable_mir::mir::mono::InstanceDef { + self.instances.create_or_fetch(instance) + } + + pub(crate) fn static_def(&mut self, did: DefId) -> stable_mir::mir::mono::StaticDef { + stable_mir::mir::mono::StaticDef(self.create_def_id(did)) + } } pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { @@ -118,10 +131,11 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { stable_mir::run( Tables { tcx, - def_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() }, - alloc_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() }, - spans: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() }, + def_ids: IndexMap::default(), + alloc_ids: IndexMap::default(), + spans: IndexMap::default(), types: vec![], + instances: IndexMap::default(), }, f, ); @@ -192,6 +206,12 @@ pub struct IndexMap { index_map: fx::FxIndexMap, } +impl Default for IndexMap { + fn default() -> Self { + Self { index_map: FxIndexMap::default() } + } +} + impl IndexMap { pub fn create_or_fetch(&mut self, key: K) -> V { let len = self.index_map.len(); diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index f26d18ad38f2..94dc15b4767c 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -13,10 +13,12 @@ use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region}; use rustc_hir as hir; use rustc_middle::mir; use rustc_middle::mir::interpret::{alloc_range, AllocId}; -use rustc_middle::ty::{self, Ty, TyCtxt, Variance}; +use rustc_middle::mir::mono::MonoItem; +use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt, Variance}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_target::abi::FieldIdx; -use stable_mir::mir::{CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx}; +use stable_mir::mir::mono::InstanceDef; +use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx}; use stable_mir::ty::{ FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy, }; @@ -119,29 +121,7 @@ impl<'tcx> Context for Tables<'tcx> { fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body { let def_id = self[item]; - let mir = self.tcx.instance_mir(ty::InstanceDef::Item(def_id)); - stable_mir::mir::Body { - blocks: mir - .basic_blocks - .iter() - .map(|block| stable_mir::mir::BasicBlock { - terminator: block.terminator().stable(self), - statements: block - .statements - .iter() - .map(|statement| statement.stable(self)) - .collect(), - }) - .collect(), - locals: mir - .local_decls - .iter() - .map(|decl| stable_mir::mir::LocalDecl { - ty: self.intern_ty(decl.ty), - span: decl.source_info.span.stable(self), - }) - .collect(), - } + self.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(self) } fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind { @@ -190,6 +170,34 @@ impl<'tcx> Context for Tables<'tcx> { .collect(), } } + + fn instance_body(&mut self, _def: InstanceDef) -> Body { + todo!("Monomorphize the body") + } + + fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty { + let instance = self.instances[def]; + let ty = instance.ty(self.tcx, ParamEnv::empty()); + self.intern_ty(ty) + } + + fn instance_def_id(&mut self, def: InstanceDef) -> stable_mir::DefId { + let def_id = self.instances[def].def_id(); + self.create_def_id(def_id) + } + + fn mono_instance(&mut self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance { + let def_id = self[item.0]; + Instance::mono(self.tcx, def_id).stable(self) + } + + fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool { + let def_id = self[def_id]; + let generics = self.tcx.generics_of(def_id); + let result = generics.requires_monomorphization(self.tcx); + println!("req {result}: {def_id:?}"); + result + } } #[derive(Clone)] @@ -224,7 +232,8 @@ pub struct Tables<'tcx> { pub def_ids: IndexMap, pub alloc_ids: IndexMap, pub spans: IndexMap, - pub types: Vec>>, + pub types: Vec>>, + pub instances: IndexMap, InstanceDef>, } impl<'tcx> Tables<'tcx> { @@ -254,6 +263,35 @@ pub(crate) trait Stable<'tcx> { fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T; } +impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { + type T = stable_mir::mir::Body; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + stable_mir::mir::Body { + blocks: self + .basic_blocks + .iter() + .map(|block| stable_mir::mir::BasicBlock { + terminator: block.terminator().stable(tables), + statements: block + .statements + .iter() + .map(|statement| statement.stable(tables)) + .collect(), + }) + .collect(), + locals: self + .local_decls + .iter() + .map(|decl| stable_mir::mir::LocalDecl { + ty: tables.intern_ty(decl.ty), + span: decl.source_info.span.stable(tables), + }) + .collect(), + } + } +} + impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { type T = stable_mir::mir::Statement; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { @@ -1637,3 +1675,38 @@ impl<'tcx> Stable<'tcx> for DefKind { opaque(self) } } + +impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { + type T = stable_mir::mir::mono::Instance; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let def = tables.instance_def(*self); + let kind = match self.def { + ty::InstanceDef::Item(..) => stable_mir::mir::mono::InstanceKind::Item, + ty::InstanceDef::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic, + ty::InstanceDef::Virtual(..) => stable_mir::mir::mono::InstanceKind::Virtual, + ty::InstanceDef::VTableShim(..) + | ty::InstanceDef::ReifyShim(..) + | ty::InstanceDef::FnPtrAddrShim(..) + | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ThreadLocalShim(..) + | ty::InstanceDef::DropGlue(..) + | ty::InstanceDef::CloneShim(..) + | ty::InstanceDef::FnPtrShim(..) => stable_mir::mir::mono::InstanceKind::Shim, + }; + stable_mir::mir::mono::Instance { def, kind } + } +} + +impl<'tcx> Stable<'tcx> for MonoItem<'tcx> { + type T = stable_mir::mir::mono::MonoItem; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::mir::mono::MonoItem as StableMonoItem; + match self { + MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables)), + MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)), + MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)), + } + } +} diff --git a/compiler/stable_mir/src/error.rs b/compiler/stable_mir/src/error.rs new file mode 100644 index 000000000000..12ac8f1ca65a --- /dev/null +++ b/compiler/stable_mir/src/error.rs @@ -0,0 +1,69 @@ +//! When things go wrong, we need some error handling. +//! There are a few different types of errors in StableMIR: +//! +//! - [CompilerError]: This represents errors that can be raised when invoking the compiler. +//! - [Error]: Generic error that represents the reason why a request that could not be fulfilled. + +use std::fmt::{Debug, Display, Formatter}; +use std::{error, fmt}; + +/// An error type used to represent an error that has already been reported by the compiler. +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum CompilerError { + /// Internal compiler error (I.e.: Compiler crashed). + ICE, + /// Compilation failed. + CompilationFailed, + /// Compilation was interrupted. + Interrupted(T), + /// Compilation skipped. This happens when users invoke rustc to retrieve information such as + /// --version. + Skipped, +} + +/// A generic error to represent an API request that cannot be fulfilled. +#[derive(Debug)] +pub struct Error(String); + +impl Error { + pub(crate) fn new(msg: String) -> Self { + Self(msg) + } +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl Display for CompilerError +where + T: Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + CompilerError::ICE => write!(f, "Internal Compiler Error"), + CompilerError::CompilationFailed => write!(f, "Compilation Failed"), + CompilerError::Interrupted(reason) => write!(f, "Compilation Interrupted: {reason}"), + CompilerError::Skipped => write!(f, "Compilation Skipped"), + } + } +} + +impl Debug for CompilerError +where + T: Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + CompilerError::ICE => write!(f, "Internal Compiler Error"), + CompilerError::CompilationFailed => write!(f, "Compilation Failed"), + CompilerError::Interrupted(reason) => write!(f, "Compilation Interrupted: {reason:?}"), + CompilerError::Skipped => write!(f, "Compilation Skipped"), + } + } +} + +impl error::Error for Error {} +impl error::Error for CompilerError where T: Display + Debug {} diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index a3b05f2435eb..59af3f64ad34 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -17,6 +17,8 @@ //! The goal is to eventually be published on //! [crates.io](https://crates.io). +use crate::mir::mono::InstanceDef; +use crate::mir::Body; use std::cell::Cell; use std::fmt; use std::fmt::Debug; @@ -29,11 +31,15 @@ use self::ty::{ #[macro_use] extern crate scoped_tls; +pub mod error; pub mod fold; pub mod mir; pub mod ty; pub mod visitor; +pub use error::*; +use mir::mono::Instance; + /// Use String for now but we should replace it. pub type Symbol = String; @@ -85,20 +91,6 @@ pub type TraitDecls = Vec; /// A list of impl trait decls. pub type ImplTraitDecls = Vec; -/// An error type used to represent an error that has already been reported by the compiler. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum CompilerError { - /// Internal compiler error (I.e.: Compiler crashed). - ICE, - /// Compilation failed. - CompilationFailed, - /// Compilation was interrupted. - Interrupted(T), - /// Compilation skipped. This happens when users invoke rustc to retrieve information such as - /// --version. - Skipped, -} - /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Crate { @@ -113,7 +105,7 @@ pub type Filename = Opaque; /// Holds information about an item in the crate. /// For now, it only stores the item DefId. Use functions inside `rustc_internal` module to /// use this item. -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct CrateItem(pub DefId); impl CrateItem { @@ -132,6 +124,10 @@ impl CrateItem { pub fn kind(&self) -> DefKind { with(|cx| cx.def_kind(self.0)) } + + pub fn requires_monomorphization(&self) -> bool { + with(|cx| cx.requires_monomorphization(self.0)) + } } /// Return the function where execution starts if the current @@ -220,6 +216,23 @@ pub trait Context { /// Create a new `Ty` from scratch without information from rustc. fn mk_ty(&mut self, kind: TyKind) -> Ty; + + /// Get the body of an Instance. + /// FIXME: Monomorphize the body. + fn instance_body(&mut self, instance: InstanceDef) -> Body; + + /// Get the instance type with generic substitutions applied and lifetimes erased. + fn instance_ty(&mut self, instance: InstanceDef) -> Ty; + + /// Get the instance. + fn instance_def_id(&mut self, instance: InstanceDef) -> DefId; + + /// Convert a non-generic crate item into an instance. + /// This function will panic if the item is generic. + fn mono_instance(&mut self, item: CrateItem) -> Instance; + + /// Item requires monomorphization. + fn requires_monomorphization(&self, def_id: DefId) -> bool; } // A thread local variable that stores a pointer to the tables mapping between TyCtxt diff --git a/compiler/stable_mir/src/mir.rs b/compiler/stable_mir/src/mir.rs index a9dbc3463f80..3138bb1ec832 100644 --- a/compiler/stable_mir/src/mir.rs +++ b/compiler/stable_mir/src/mir.rs @@ -1,3 +1,4 @@ mod body; +pub mod mono; pub use body::*; diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs new file mode 100644 index 000000000000..d8e8ccb04548 --- /dev/null +++ b/compiler/stable_mir/src/mir/mono.rs @@ -0,0 +1,89 @@ +use crate::mir::Body; +use crate::ty::{IndexedVal, Ty}; +use crate::{with, CrateItem, DefId, Error, Opaque}; +use std::fmt::Debug; + +#[derive(Clone, Debug)] +pub enum MonoItem { + Fn(Instance), + Static(StaticDef), + GlobalAsm(Opaque), +} + +#[derive(Copy, Clone, Debug)] +pub struct Instance { + /// The type of instance. + pub kind: InstanceKind, + /// An ID used to get the instance definition from the compiler. + /// Do not use this field directly. + pub def: InstanceDef, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum InstanceKind { + /// A user defined item. + Item, + /// A compiler intrinsic function. + Intrinsic, + /// A virtual function definition stored in a VTable. + Virtual, + /// A compiler generated shim. + Shim, +} + +impl Instance { + /// Get the body of an Instance. The body will be eagerly monomorphized. + pub fn body(&self) -> Body { + with(|context| context.instance_body(self.def)) + } + + /// Get the instance type with generic substitutions applied and lifetimes erased. + pub fn ty(&self) -> Ty { + with(|context| context.instance_ty(self.def)) + } +} + +/// Try to convert a crate item into an instance. +/// The item cannot be generic in order to be converted into an instance. +impl TryFrom for Instance { + type Error = crate::Error; + + fn try_from(item: CrateItem) -> Result { + with(|context| { + if !context.requires_monomorphization(item.0) { + Ok(context.mono_instance(item)) + } else { + Err(Error::new("Item requires monomorphization".to_string())) + } + }) + } +} + +/// Try to convert an instance into a crate item. +/// Only user defined instances can be converted. +impl TryFrom for CrateItem { + type Error = crate::Error; + + fn try_from(value: Instance) -> Result { + if value.kind == InstanceKind::Item { + Ok(CrateItem(with(|context| context.instance_def_id(value.def)))) + } else { + Err(Error::new(format!("Item kind `{:?}` cannot be converted", value.kind))) + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct InstanceDef(usize); + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct StaticDef(pub DefId); + +impl IndexedVal for InstanceDef { + fn to_val(index: usize) -> Self { + InstanceDef(index) + } + fn to_index(&self) -> usize { + self.0 + } +} diff --git a/tests/ui-fulldeps/stable-mir/instance.rs b/tests/ui-fulldeps/stable-mir/instance.rs new file mode 100644 index 000000000000..fe06d9b5cc96 --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/instance.rs @@ -0,0 +1,91 @@ +// run-pass +// Test that users are able to use stable mir APIs to retrieve monomorphized instances + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +extern crate rustc_middle; +extern crate rustc_smir; +extern crate stable_mir; + +use rustc_middle::ty::TyCtxt; + +use stable_mir::*; +use rustc_smir::rustc_internal; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + let items = stable_mir::all_local_items(); + + // Get all items and split generic vs monomorphic items. + let (generic, mono) : (Vec<_>, Vec<_>) = items.into_iter().partition(|item| { + item.requires_monomorphization() + }); + assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant"); + assert_eq!(generic.len(), 2, "Expected 2 generic functions"); + + // For all monomorphic items, get the correspondent instances. + let instances = mono.iter().filter_map(|item| { + mir::mono::Instance::try_from(*item).ok() + }).collect::>(); + assert_eq!(instances.len(), mono.len()); + + // For all generic items, try_from should fail. + assert!(generic.iter().all(|item| mir::mono::Instance::try_from(*item).is_err())); + + ControlFlow::Continue(()) +} + + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "instance_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + rustc_internal::StableMir::new(args, test_stable_mir).run().unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + pub fn ty_param(t: &T) -> T where T: Clone {{ + t.clone() + }} + + pub fn const_param(a: [bool; LEN]) -> bool {{ + LEN > 0 && a[0] + }} + + pub fn monomorphic() {{ + }} + + pub mod foo {{ + pub fn bar_mono(i: i32) -> i64 {{ + i as i64 + }} + }} + "# + )?; + Ok(()) +} From 1f90d857d75a3e6696a5ac731d2ae601f647fb7b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 16 Oct 2023 18:49:32 +0000 Subject: [PATCH 30/94] Stop trying to preserve pretty-printing. --- src/tools/compiletest/src/runtest.rs | 34 ++++++++-------- ..._allocation.main.ConstProp.after.32bit.mir | 36 ++++++++--------- ..._allocation.main.ConstProp.after.64bit.mir | 40 +++++++++---------- ...allocation2.main.ConstProp.after.32bit.mir | 34 ++++++++-------- ...allocation2.main.ConstProp.after.64bit.mir | 36 ++++++++--------- ...allocation3.main.ConstProp.after.32bit.mir | 20 +++++----- ...allocation3.main.ConstProp.after.64bit.mir | 18 ++++----- .../enum.statics.DataflowConstProp.32bit.diff | 12 +++--- .../enum.statics.DataflowConstProp.64bit.diff | 12 +++--- .../struct.main.DataflowConstProp.32bit.diff | 8 ++-- .../struct.main.DataflowConstProp.64bit.diff | 8 ++-- tests/ui/const-ptr/forbidden_slices.stderr | 2 +- .../heap/alloc_intrinsic_uninit.32bit.stderr | 2 +- .../heap/alloc_intrinsic_uninit.64bit.stderr | 2 +- .../consts/const-eval/raw-bytes.32bit.stderr | 10 ++--- .../consts/const-eval/raw-bytes.64bit.stderr | 8 ++-- .../ub-incorrect-vtable.32bit.stderr | 22 +++++----- .../ub-incorrect-vtable.64bit.stderr | 22 +++++----- tests/ui/consts/const-eval/ub-nonnull.stderr | 2 +- .../consts/const-eval/ub-upvars.32bit.stderr | 2 +- .../consts/const-eval/ub-upvars.64bit.stderr | 2 +- tests/ui/consts/const-eval/ub-wide-ptr.stderr | 16 ++++---- .../const-points-to-static.32bit.stderr | 2 +- .../const-points-to-static.64bit.stderr | 2 +- tests/ui/consts/invalid-union.32bit.stderr | 2 +- tests/ui/consts/invalid-union.64bit.stderr | 2 +- tests/ui/consts/issue-63952.32bit.stderr | 2 +- tests/ui/consts/issue-63952.64bit.stderr | 2 +- tests/ui/consts/issue-79690.64bit.stderr | 2 +- .../const_refers_to_static.32bit.stderr | 4 +- .../const_refers_to_static.64bit.stderr | 4 +- ..._refers_to_static_cross_crate.32bit.stderr | 4 +- ..._refers_to_static_cross_crate.64bit.stderr | 4 +- .../mutable_references_err.32bit.stderr | 6 +-- .../mutable_references_err.64bit.stderr | 6 +-- 35 files changed, 195 insertions(+), 195 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4868225f5e46..875671c64e00 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -4263,30 +4263,30 @@ impl<'test> TestCx<'test> { // to keep them numbered, to see if the same id appears multiple times. // So we remap to deterministic numbers that only depend on the subset of allocations // that actually appear in the output. + // We use uppercase ALLOC to distinguish from the non-normalized version. { - use std::fmt::Write; - - let re = Regex::new(r"(╾a|─a|\balloc)([0-9]+)\b(─|\+0x[0-9]+─)?").unwrap(); let mut seen_allocs = indexmap::IndexSet::new(); + + // The alloc-id appears in pretty-printed allocations. + let re = Regex::new(r"╾─*a(lloc)?([0-9]+)(\+0x[0-9]+)?─*╼").unwrap(); normalized = re .replace_all(&normalized, |caps: &Captures<'_>| { - // Use uppercase to distinguish with the non-normalized version. - let mut ret = caps.get(1).unwrap().as_str().to_uppercase(); // Renumber the captured index. let index = caps.get(2).unwrap().as_str().to_string(); let (index, _) = seen_allocs.insert_full(index); - write!(&mut ret, "{index}").unwrap(); - // If we have a tail finishing with `─`, this means pretty-printing. - // Complete with filler `─` to preserve the pretty-print. - if let Some(tail) = caps.get(3) { - ret.push_str(tail.as_str()); - let orig_len = caps.get(0).unwrap().as_str().len(); - let ret_len = ret.len(); - for _ in orig_len..ret_len { - ret.push('─'); - } - } - ret + let offset = caps.get(3).map_or("", |c| c.as_str()); + // Do not bother keeping it pretty, just make it deterministic. + format!("╾ALLOC{index}{offset}╼") + }) + .into_owned(); + + // The alloc-id appears in a sentence. + let re = Regex::new(r"\balloc([0-9]+)\b").unwrap(); + normalized = re + .replace_all(&normalized, |caps: &Captures<'_>| { + let index = caps.get(1).unwrap().as_str().to_string(); + let (index, _) = seen_allocs.insert_full(index); + format!("ALLOC{index}") }) .into_owned(); } diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index cc80ff449a75..f20bfef8c794 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC0: &&[(Option, &[&str])]}; + _2 = const {ALLOC9: &&[(Option, &[&str])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,43 +17,43 @@ fn main() -> () { } } -ALLOC0 (static: FOO, size: 8, align: 4) { - ╾─ALLOC1─╼ 03 00 00 00 │ ╾──╼.... +ALLOC9 (static: FOO, size: 8, align: 4) { + ╾ALLOC0╼ 03 00 00 00 │ ╾──╼.... } -ALLOC1 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─ALLOC2──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─ALLOC3─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─ALLOC4─╼ 03 00 00 00 │ ....*...╾──╼.... +ALLOC0 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾ALLOC2╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ 03 00 00 00 │ ....*...╾──╼.... } -ALLOC2 (size: 0, align: 4) {} +ALLOC1 (size: 0, align: 4) {} -ALLOC3 (size: 16, align: 4) { - ╾─ALLOC5──╼ 03 00 00 00 ╾─ALLOC6─╼ 03 00 00 00 │ ╾──╼....╾──╼.... +ALLOC2 (size: 16, align: 4) { + ╾ALLOC4╼ 03 00 00 00 ╾ALLOC5╼ 03 00 00 00 │ ╾──╼....╾──╼.... } -ALLOC5 (size: 3, align: 1) { +ALLOC4 (size: 3, align: 1) { 66 6f 6f │ foo } -ALLOC6 (size: 3, align: 1) { +ALLOC5 (size: 3, align: 1) { 62 61 72 │ bar } -ALLOC4 (size: 24, align: 4) { - 0x00 │ ╾─ALLOC7─╼ 03 00 00 00 ╾─ALLOC8─╼ 03 00 00 00 │ ╾──╼....╾──╼.... - 0x10 │ ╾─ALLOC9─╼ 04 00 00 00 │ ╾──╼.... +ALLOC3 (size: 24, align: 4) { + 0x00 │ ╾ALLOC6╼ 03 00 00 00 ╾ALLOC7╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾ALLOC8╼ 04 00 00 00 │ ╾──╼.... } -ALLOC7 (size: 3, align: 1) { +ALLOC6 (size: 3, align: 1) { 6d 65 68 │ meh } -ALLOC8 (size: 3, align: 1) { +ALLOC7 (size: 3, align: 1) { 6d 6f 70 │ mop } -ALLOC9 (size: 4, align: 1) { +ALLOC8 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index 60019708cad0..263cae2f3ea5 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC0: &&[(Option, &[&str])]}; + _2 = const {ALLOC9: &&[(Option, &[&str])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,47 +17,47 @@ fn main() -> () { } } -ALLOC0 (static: FOO, size: 16, align: 8) { - ╾───────ALLOC1───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC9 (static: FOO, size: 16, align: 8) { + ╾ALLOC0╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -ALLOC1 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────ALLOC2────────╼ │ ....░░░░╾──────╼ +ALLOC0 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────ALLOC3───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────ALLOC4───────╼ │ ....*...╾──────╼ + 0x20 │ ╾ALLOC2╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -ALLOC2 (size: 0, align: 8) {} +ALLOC1 (size: 0, align: 8) {} -ALLOC3 (size: 32, align: 8) { - 0x00 │ ╾───────ALLOC5────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────ALLOC6───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC2 (size: 32, align: 8) { + 0x00 │ ╾ALLOC4╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾ALLOC5╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -ALLOC5 (size: 3, align: 1) { +ALLOC4 (size: 3, align: 1) { 66 6f 6f │ foo } -ALLOC6 (size: 3, align: 1) { +ALLOC5 (size: 3, align: 1) { 62 61 72 │ bar } -ALLOC4 (size: 48, align: 8) { - 0x00 │ ╾───────ALLOC7───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────ALLOC8───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x20 │ ╾───────ALLOC9───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC3 (size: 48, align: 8) { + 0x00 │ ╾ALLOC6╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾ALLOC7╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾ALLOC8╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } -ALLOC7 (size: 3, align: 1) { +ALLOC6 (size: 3, align: 1) { 6d 65 68 │ meh } -ALLOC8 (size: 3, align: 1) { +ALLOC7 (size: 3, align: 1) { 6d 6f 70 │ mop } -ALLOC9 (size: 4, align: 1) { +ALLOC8 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index c0b0cc2f69b5..713abb264a70 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC0: &&[(Option, &[&u8])]}; + _2 = const {ALLOC9: &&[(Option, &[&u8])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,42 +17,42 @@ fn main() -> () { } } -ALLOC0 (static: FOO, size: 8, align: 4) { - ╾─ALLOC1─╼ 03 00 00 00 │ ╾──╼.... +ALLOC9 (static: FOO, size: 8, align: 4) { + ╾ALLOC0╼ 03 00 00 00 │ ╾──╼.... } -ALLOC1 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─ALLOC2─╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─ALLOC3─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─ALLOC4─╼ 03 00 00 00 │ ....*...╾──╼.... +ALLOC0 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾ALLOC2╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ 03 00 00 00 │ ....*...╾──╼.... } -ALLOC2 (size: 0, align: 4) {} +ALLOC1 (size: 0, align: 4) {} -ALLOC3 (size: 8, align: 4) { - ╾─ALLOC5─╼ ╾─ALLOC6─╼ │ ╾──╼╾──╼ +ALLOC2 (size: 8, align: 4) { + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ } -ALLOC5 (size: 1, align: 1) { +ALLOC4 (size: 1, align: 1) { 05 │ . } -ALLOC6 (size: 1, align: 1) { +ALLOC5 (size: 1, align: 1) { 06 │ . } -ALLOC4 (size: 12, align: 4) { - ╾─A7+0x3─╼ ╾─ALLOC8─╼ ╾─A9+0x2─╼ │ ╾──╼╾──╼╾──╼ +ALLOC3 (size: 12, align: 4) { + ╾ALLOC6+0x3╼ ╾ALLOC7╼ ╾ALLOC8+0x2╼ │ ╾──╼╾──╼╾──╼ } -ALLOC7 (size: 4, align: 1) { +ALLOC6 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -ALLOC8 (size: 1, align: 1) { +ALLOC7 (size: 1, align: 1) { 2a │ * } -ALLOC9 (size: 4, align: 1) { +ALLOC8 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index bd98633c7598..e9d61ef120c7 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC0: &&[(Option, &[&u8])]}; + _2 = const {ALLOC9: &&[(Option, &[&u8])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,45 +17,45 @@ fn main() -> () { } } -ALLOC0 (static: FOO, size: 16, align: 8) { - ╾───────ALLOC1───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC9 (static: FOO, size: 16, align: 8) { + ╾ALLOC0╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -ALLOC1 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────ALLOC2───────╼ │ ....░░░░╾──────╼ +ALLOC0 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────ALLOC3───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────ALLOC4───────╼ │ ....*...╾──────╼ + 0x20 │ ╾ALLOC2╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -ALLOC2 (size: 0, align: 8) {} +ALLOC1 (size: 0, align: 8) {} -ALLOC3 (size: 16, align: 8) { - ╾───────ALLOC5───────╼ ╾───────ALLOC6───────╼ │ ╾──────╼╾──────╼ +ALLOC2 (size: 16, align: 8) { + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ } -ALLOC5 (size: 1, align: 1) { +ALLOC4 (size: 1, align: 1) { 05 │ . } -ALLOC6 (size: 1, align: 1) { +ALLOC5 (size: 1, align: 1) { 06 │ . } -ALLOC4 (size: 24, align: 8) { - 0x00 │ ╾─────ALLOC7+0x3─────╼ ╾───────ALLOC8───────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────ALLOC9+0x2─────╼ │ ╾──────╼ +ALLOC3 (size: 24, align: 8) { + 0x00 │ ╾ALLOC6+0x3╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾ALLOC8+0x2╼ │ ╾──────╼ } -ALLOC7 (size: 4, align: 1) { +ALLOC6 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -ALLOC8 (size: 1, align: 1) { +ALLOC7 (size: 1, align: 1) { 2a │ * } -ALLOC9 (size: 4, align: 1) { +ALLOC8 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir index e2db4b52e0c7..c18c067c72e7 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC0: &&Packed}; + _2 = const {ALLOC4: &&Packed}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,31 +17,31 @@ fn main() -> () { } } -ALLOC0 (static: FOO, size: 4, align: 4) { - ╾─ALLOC1─╼ │ ╾──╼ +ALLOC4 (static: FOO, size: 4, align: 4) { + ╾ALLOC0╼ │ ╾──╼ } -ALLOC1 (size: 168, align: 1) { +ALLOC0 (size: 168, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─ALLOC2──╼ │ ............╾──╼ + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾ALLOC1╼ │ ............╾──╼ 0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─ALLOC3──╼ 00 00 │ ..........╾──╼.. - 0x90 │ ╾A4+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ + 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾ALLOC2╼ 00 00 │ ..........╾──╼.. + 0x90 │ ╾ALLOC3+0x63╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ 0xa0 │ 00 00 00 00 00 00 00 00 │ ........ } -ALLOC2 (size: 4, align: 4) { +ALLOC1 (size: 4, align: 4) { 2a 00 00 00 │ *... } -ALLOC3 (fn: main) +ALLOC2 (fn: main) -ALLOC4 (size: 100, align: 1) { +ALLOC3 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir index 392c5aedcaf1..6af0e3cbd94c 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC0: &&Packed}; + _2 = const {ALLOC2: &&Packed}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,13 +17,13 @@ fn main() -> () { } } -ALLOC0 (static: FOO, size: 8, align: 8) { - ╾───────ALLOC1───────╼ │ ╾──────╼ +ALLOC2 (static: FOO, size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ } -ALLOC1 (size: 180, align: 1) { +ALLOC0 (size: 180, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──ALLOC2── │ ............╾─── + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──ALLOC3── │ ............╾─── 0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ @@ -31,18 +31,18 @@ ALLOC1 (size: 180, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─ - 0x90 │ ─────ALLOC3─────╼ 00 00 ╾────ALLOC4+0x63─────╼ │ ─────╼..╾──────╼ + 0x90 │ ─────ALLOC4─────╼ 00 00 ╾ALLOC1+0x63╼ │ ─────╼..╾──────╼ 0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0xb0 │ 00 00 00 00 │ .... } -ALLOC2 (size: 4, align: 4) { +ALLOC3 (size: 4, align: 4) { 2a 00 00 00 │ *... } -ALLOC3 (fn: main) +ALLOC4 (fn: main) -ALLOC4 (size: 100, align: 1) { +ALLOC1 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index f51431b101f1..1348b2793308 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -43,7 +43,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC0: &E}; + _2 = const {ALLOC1: &E}; _1 = (*_2); StorageDead(_2); StorageLive(_3); @@ -78,7 +78,7 @@ bb4: { StorageLive(_7); StorageLive(_8); - _8 = const {ALLOC1: &&E}; + _8 = const {ALLOC2: &&E}; _7 = (*_8); StorageDead(_8); StorageLive(_9); @@ -112,15 +112,15 @@ } } - ALLOC1 (static: RC, size: 4, align: 4) { - ╾─ALLOC2─╼ │ ╾──╼ + ALLOC2 (static: RC, size: 4, align: 4) { + ╾ALLOC0╼ │ ╾──╼ } - ALLOC2 (size: 8, align: 4) { + ALLOC0 (size: 8, align: 4) { 01 00 00 00 04 00 00 00 │ ........ } - ALLOC0 (static: statics::C, size: 8, align: 4) { + ALLOC1 (static: statics::C, size: 8, align: 4) { 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index b104801c48a3..66929e886d3c 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -43,7 +43,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {ALLOC0: &E}; + _2 = const {ALLOC1: &E}; _1 = (*_2); StorageDead(_2); StorageLive(_3); @@ -78,7 +78,7 @@ bb4: { StorageLive(_7); StorageLive(_8); - _8 = const {ALLOC1: &&E}; + _8 = const {ALLOC2: &&E}; _7 = (*_8); StorageDead(_8); StorageLive(_9); @@ -112,15 +112,15 @@ } } - ALLOC1 (static: RC, size: 8, align: 8) { - ╾───────ALLOC2───────╼ │ ╾──────╼ + ALLOC2 (static: RC, size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ } - ALLOC2 (size: 8, align: 4) { + ALLOC0 (size: 8, align: 4) { 01 00 00 00 04 00 00 00 │ ........ } - ALLOC0 (static: statics::C, size: 8, align: 4) { + ALLOC1 (static: statics::C, size: 8, align: 4) { 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 8e0ce7eafd77..e80f31ca9348 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -84,7 +84,7 @@ + _10 = const S(13_i32); StorageDead(_11); StorageLive(_16); - _16 = const {ALLOC0: &&BigStruct}; + _16 = const {ALLOC1: &&BigStruct}; _17 = deref_copy (*_16); StorageLive(_12); _18 = deref_copy (*_16); @@ -119,11 +119,11 @@ } } - ALLOC0 (static: STAT, size: 4, align: 4) { - ╾─ALLOC1─╼ │ ╾──╼ + ALLOC1 (static: STAT, size: 4, align: 4) { + ╾ALLOC0╼ │ ╾──╼ } - ALLOC1 (size: 16, align: 4) { + ALLOC0 (size: 16, align: 4) { 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index de941e51f2f5..de9cf1971997 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -84,7 +84,7 @@ + _10 = const S(13_i32); StorageDead(_11); StorageLive(_16); - _16 = const {ALLOC0: &&BigStruct}; + _16 = const {ALLOC1: &&BigStruct}; _17 = deref_copy (*_16); StorageLive(_12); _18 = deref_copy (*_16); @@ -119,11 +119,11 @@ } } - ALLOC0 (static: STAT, size: 8, align: 8) { - ╾───────ALLOC1───────╼ │ ╾──────╼ + ALLOC1 (static: STAT, size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ } - ALLOC1 (size: 16, align: 4) { + ALLOC0 (size: 16, align: 4) { 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ } diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr index 8243a3631caa..00230d59a371 100644 --- a/tests/ui/const-ptr/forbidden_slices.stderr +++ b/tests/ui/const-ptr/forbidden_slices.stderr @@ -122,7 +122,7 @@ LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; error[E0080]: could not evaluate static initializer --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: ALLOC6 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC10 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::add` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr index fc9d2d258658..82de91effe73 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -6,7 +6,7 @@ LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC0──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr index 553359e0479a..de23aafe05cc 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr @@ -6,7 +6,7 @@ LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC0────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr index a240a78255b5..689ebf752236 100644 --- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -385,7 +385,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:175:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC16, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -396,7 +396,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:179:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC18, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -418,7 +418,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:186:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC21, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -451,7 +451,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:196:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC26, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -556,7 +556,7 @@ LL | pub static S7: &[u16] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾A31+0x2─╼ 04 00 00 00 │ ╾──╼.... + ╾ALLOC_ID+0x2╼ 04 00 00 00 │ ╾──╼.... } error[E0080]: it is undefined behavior to use this value diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr index ac19e4f5d543..3447a8ab432c 100644 --- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -385,7 +385,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:175:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC16, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -396,7 +396,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:179:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC18, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -418,7 +418,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:186:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC21, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -451,7 +451,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:196:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC26, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr index 25b773939dcb..7b30233c0256 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -2,55 +2,55 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:18:1 | LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC0, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC1──╼ ╾─ALLOC0──╼ │ ╾──╼╾──╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:23:1 | LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC2, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC3─╼ ╾─ALLOC2─╼ │ ╾──╼╾──╼ + ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC4, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC5─╼ ╾─ALLOC4─╼ │ ╾──╼╾──╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC6, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC7─╼ ╾─ALLOC6─╼ │ ╾──╼╾──╼ + ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC8, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC9─╼ ╾─ALLOC8─╼ │ ╾──╼╾──╼ + ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -61,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC10─╼ ╾─ALLOC11─╼ │ ╾──╼╾──╼ + ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──╼╾──╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr index 3d2868f6cb4a..9330ae3c9a6b 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -2,55 +2,55 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:18:1 | LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC0, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC1────────╼ ╾───────ALLOC0────────╼ │ ╾──────╼╾──────╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:23:1 | LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC2, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC3───────╼ ╾───────ALLOC2───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC4, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC5───────╼ ╾───────ALLOC4───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC6, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC7───────╼ ╾───────ALLOC6───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC8, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC9───────╼ ╾───────ALLOC8───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -61,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC10───────╼ ╾───────ALLOC11───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──────╼╾──────╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index 27befc413883..7822306b654c 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -13,7 +13,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/ub-nonnull.rs:20:29 | LL | let out_of_bounds_ptr = &ptr[255]; - | ^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC0 has size 1, so pointer to 255 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC1 has size 1, so pointer to 255 bytes starting at offset 0 is out-of-bounds error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:24:1 diff --git a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr index f0101c6c29df..353a9b782240 100644 --- a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr @@ -6,7 +6,7 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{ | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC0──╼ ╾─ALLOC1──╼ │ ╾──╼╾──╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr index c4da26353d77..097f6b049dc8 100644 --- a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr @@ -6,7 +6,7 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{ | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC0────────╼ ╾───────ALLOC1────────╼ │ ╾──────╼╾──────╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr index c98ae2948c44..b203794858ac 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -189,7 +189,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:113:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC11, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC12, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -200,7 +200,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:117:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC13, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC14, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -222,7 +222,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:124:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC16, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC17, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -233,7 +233,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:127:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC18, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC19, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -244,7 +244,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:130:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC20, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC21, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -255,7 +255,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:133:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC23, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -288,7 +288,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:145:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC28, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -310,7 +310,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:154:1 | LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC30, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC31, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { diff --git a/tests/ui/consts/const-points-to-static.32bit.stderr b/tests/ui/consts/const-points-to-static.32bit.stderr index 9a77e5a5764c..12cc7fbb1fc6 100644 --- a/tests/ui/consts/const-points-to-static.32bit.stderr +++ b/tests/ui/consts/const-points-to-static.32bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC0──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/const-points-to-static.64bit.stderr b/tests/ui/consts/const-points-to-static.64bit.stderr index 982c64ecc725..86506e6ca010 100644 --- a/tests/ui/consts/const-points-to-static.64bit.stderr +++ b/tests/ui/consts/const-points-to-static.64bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC0────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } warning: skipping const checks diff --git a/tests/ui/consts/invalid-union.32bit.stderr b/tests/ui/consts/invalid-union.32bit.stderr index 448bfe78b596..32b67a13061c 100644 --- a/tests/ui/consts/invalid-union.32bit.stderr +++ b/tests/ui/consts/invalid-union.32bit.stderr @@ -6,7 +6,7 @@ LL | fn main() { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC0──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } note: erroneous constant encountered diff --git a/tests/ui/consts/invalid-union.64bit.stderr b/tests/ui/consts/invalid-union.64bit.stderr index 6e01391d3a7c..45f999eb23c2 100644 --- a/tests/ui/consts/invalid-union.64bit.stderr +++ b/tests/ui/consts/invalid-union.64bit.stderr @@ -6,7 +6,7 @@ LL | fn main() { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC0────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } note: erroneous constant encountered diff --git a/tests/ui/consts/issue-63952.32bit.stderr b/tests/ui/consts/issue-63952.32bit.stderr index 2a9a9bc9eec8..5375ec1188a5 100644 --- a/tests/ui/consts/issue-63952.32bit.stderr +++ b/tests/ui/consts/issue-63952.32bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC0──╼ ff ff ff ff │ ╾──╼.... + ╾ALLOC0╼ ff ff ff ff │ ╾──╼.... } error: aborting due to previous error diff --git a/tests/ui/consts/issue-63952.64bit.stderr b/tests/ui/consts/issue-63952.64bit.stderr index e83cf1ba36e9..a6edbf9321b9 100644 --- a/tests/ui/consts/issue-63952.64bit.stderr +++ b/tests/ui/consts/issue-63952.64bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC0────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + ╾ALLOC0╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ } error: aborting due to previous error diff --git a/tests/ui/consts/issue-79690.64bit.stderr b/tests/ui/consts/issue-79690.64bit.stderr index e3a5e2acbbdc..af59729d438d 100644 --- a/tests/ui/consts/issue-79690.64bit.stderr +++ b/tests/ui/consts/issue-79690.64bit.stderr @@ -6,7 +6,7 @@ LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC0────────╼ ╾───────ALLOC1────────╼ │ ╾──────╼╾──────╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr index dbc57573ff3a..4a3344a5b045 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr @@ -24,7 +24,7 @@ LL | const REF_INTERIOR_MUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC0──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -35,7 +35,7 @@ LL | const READ_IMMUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC1──╼ │ ╾──╼ + ╾ALLOC1╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr index 9340254fd4fb..7573bfa39ec2 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr @@ -24,7 +24,7 @@ LL | const REF_INTERIOR_MUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC0────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -35,7 +35,7 @@ LL | const READ_IMMUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC1────────╼ │ ╾──────╼ + ╾ALLOC1╼ │ ╾──────╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index 430187d4fec5..de59d743b17d 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_MUT: &[u8; 1] = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC0──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error: could not evaluate constant pattern @@ -23,7 +23,7 @@ LL | const U8_MUT: &u8 = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC0──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error: could not evaluate constant pattern diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr index 90579f2d7084..e62520ef6ad2 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_MUT: &[u8; 1] = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC0────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error: could not evaluate constant pattern @@ -23,7 +23,7 @@ LL | const U8_MUT: &u8 = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC0────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error: could not evaluate constant pattern diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index 5ec4ce529e13..c9da91a95977 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -6,7 +6,7 @@ LL | const MUH: Meh = Meh { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC0──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -17,7 +17,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─ALLOC1──╼ ╾─ALLOC2──╼ │ ╾──╼╾──╼ + ╾ALLOC1╼ ╾ALLOC2╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─ALLOC3─╼ │ ╾──╼ + ╾ALLOC3╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr index 22a0c57b91a8..71be616b7ed7 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -6,7 +6,7 @@ LL | const MUH: Meh = Meh { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC0────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -17,7 +17,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC1────────╼ ╾───────ALLOC2────────╼ │ ╾──────╼╾──────╼ + ╾ALLOC1╼ ╾ALLOC2╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────ALLOC3───────╼ │ ╾──────╼ + ╾ALLOC3╼ │ ╾──────╼ } warning: skipping const checks From 26954f60ffd4fa462b06edf05290104aa8cdbdc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 16 Oct 2023 19:48:53 +0000 Subject: [PATCH 31/94] address review comment --- .../src/traits/error_reporting/suggestions.rs | 215 ++++++++++-------- 1 file changed, 125 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index fd52d6296603..34097cb173ec 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -313,6 +313,18 @@ pub trait TypeErrCtxtExt<'tcx> { predicate: ty::Predicate<'tcx>, call_hir_id: HirId, ); + + fn look_for_iterator_item_mistakes( + &self, + assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>], + typeck_results: &TypeckResults<'tcx>, + type_diffs: &[TypeError<'tcx>], + param_env: ty::ParamEnv<'tcx>, + path_segment: &hir::PathSegment<'_>, + args: &[hir::Expr<'_>], + err: &mut Diagnostic, + ); + fn point_at_chain( &self, expr: &hir::Expr<'_>, @@ -321,6 +333,7 @@ pub trait TypeErrCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, err: &mut Diagnostic, ); + fn probe_assoc_types_at_expr( &self, type_diffs: &[TypeError<'tcx>], @@ -3592,6 +3605,109 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + fn look_for_iterator_item_mistakes( + &self, + assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>], + typeck_results: &TypeckResults<'tcx>, + type_diffs: &[TypeError<'tcx>], + param_env: ty::ParamEnv<'tcx>, + path_segment: &hir::PathSegment<'_>, + args: &[hir::Expr<'_>], + err: &mut Diagnostic, + ) { + let tcx = self.tcx; + // Special case for iterator chains, we look at potential failures of `Iterator::Item` + // not being `: Clone` and `Iterator::map` calls with spurious trailing `;`. + for entry in assocs_in_this_method { + let Some((_span, (def_id, ty))) = entry else { + continue; + }; + for diff in type_diffs { + let Sorts(expected_found) = diff else { + continue; + }; + if tcx.is_diagnostic_item(sym::IteratorItem, *def_id) + && path_segment.ident.name == sym::map + && self.can_eq(param_env, expected_found.found, *ty) + && let [arg] = args + && let hir::ExprKind::Closure(closure) = arg.kind + { + let body = tcx.hir().body(closure.body); + if let hir::ExprKind::Block(block, None) = body.value.kind + && let None = block.expr + && let [.., stmt] = block.stmts + && let hir::StmtKind::Semi(expr) = stmt.kind + // FIXME: actually check the expected vs found types, but right now + // the expected is a projection that we need to resolve. + // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr) + && expected_found.found.is_unit() + { + err.span_suggestion_verbose( + expr.span.shrink_to_hi().with_hi(stmt.span.hi()), + "consider removing this semicolon", + String::new(), + Applicability::MachineApplicable, + ); + } + let expr = if let hir::ExprKind::Block(block, None) = body.value.kind + && let Some(expr) = block.expr + { + expr + } else { + body.value + }; + if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind + && path_segment.ident.name == sym::clone + && let Some(expr_ty) = typeck_results.expr_ty_opt(expr) + && let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr) + && self.can_eq(param_env, expr_ty, rcvr_ty) + && let ty::Ref(_, ty, _) = expr_ty.kind() + { + err.span_label( + span, + format!( + "this method call is cloning the reference `{expr_ty}`, not \ + `{ty}` which doesn't implement `Clone`", + ), + ); + let ty::Param(..) = ty.kind() else { + continue; + }; + let hir = tcx.hir(); + let node = hir.get_by_def_id(hir.get_parent_item(expr.hir_id).def_id); + + let pred = ty::Binder::dummy(ty::TraitPredicate { + trait_ref: ty::TraitRef::from_lang_item( + tcx, + LangItem::Clone, + span, + [*ty], + ), + polarity: ty::ImplPolarity::Positive, + }); + let Some(generics) = node.generics() else { + continue; + }; + let Some(body_id) = node.body_id() else { + continue; + }; + suggest_restriction( + tcx, + hir.body_owner_def_id(body_id), + &generics, + &format!("type parameter `{ty}`"), + err, + node.fn_sig(), + None, + pred, + None, + ); + } + } + } + } + } + fn point_at_chain( &self, expr: &hir::Expr<'_>, @@ -3618,96 +3734,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { expr = rcvr_expr; let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env); - // Special case for iterator chains, we look at potential failures of `Iterator::Item` - // not being `: Clone` and `Iterator::map` calls with spurious trailing `;`. - for entry in &assocs_in_this_method { - let Some((_span, (def_id, ty))) = entry else { - continue; - }; - for diff in &type_diffs { - let Sorts(expected_found) = diff else { - continue; - }; - if tcx.is_diagnostic_item(sym::IteratorItem, *def_id) - && path_segment.ident.name == sym::map - && self.can_eq(param_env, expected_found.found, *ty) - && let [arg] = args - && let hir::ExprKind::Closure(closure) = arg.kind - { - let body = tcx.hir().body(closure.body); - if let hir::ExprKind::Block(block, None) = body.value.kind - && let None = block.expr - && let [.., stmt] = block.stmts - && let hir::StmtKind::Semi(expr) = stmt.kind - // FIXME: actually check the expected vs found types, but right now - // the expected is a projection that we need to resolve. - // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr) - && expected_found.found.is_unit() - { - err.span_suggestion_verbose( - expr.span.shrink_to_hi().with_hi(stmt.span.hi()), - "consider removing this semicolon", - String::new(), - Applicability::MachineApplicable, - ); - } - let expr = if let hir::ExprKind::Block(block, None) = body.value.kind - && let Some(expr) = block.expr - { - expr - } else { - body.value - }; - if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind - && path_segment.ident.name == sym::clone - && let Some(expr_ty) = typeck_results.expr_ty_opt(expr) - && let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr) - && self.can_eq(param_env, expr_ty, rcvr_ty) - && let ty::Ref(_, ty, _) = expr_ty.kind() - { - err.span_label( - span, - format!( - "this method call is cloning the reference `{expr_ty}`, not \ - `{ty}` which doesn't implement `Clone`", - ), - ); - let ty::Param(..) = ty.kind() else { - continue; - }; - let hir = tcx.hir(); - let node = hir.get_by_def_id(hir.get_parent_item(expr.hir_id).def_id); - - let pred = ty::Binder::dummy(ty::TraitPredicate { - trait_ref: ty::TraitRef::from_lang_item( - tcx, - LangItem::Clone, - span, - [*ty], - ), - polarity: ty::ImplPolarity::Positive, - }); - let Some(generics) = node.generics() else { - continue; - }; - let Some(body_id) = node.body_id() else { - continue; - }; - suggest_restriction( - tcx, - hir.body_owner_def_id(body_id), - &generics, - &format!("type parameter `{ty}`"), - err, - node.fn_sig(), - None, - pred, - None, - ); - } - } - } - } + self.look_for_iterator_item_mistakes( + &assocs_in_this_method, + typeck_results, + &type_diffs, + param_env, + path_segment, + args, + err, + ); assocs.push(assocs_in_this_method); prev_ty = self.resolve_vars_if_possible( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), From df5ea58287419d6f8c89019dafeb48ca7aed3a62 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 16 Oct 2023 15:41:04 -0700 Subject: [PATCH 32/94] Add `crate_name` to test so that it can be renamed --- tests/rustdoc/issue-29449.rs | 2 ++ tests/rustdoc/issue-29503.rs | 2 ++ tests/rustdoc/issue-29584.rs | 2 ++ tests/rustdoc/issue-30109.rs | 2 ++ tests/rustdoc/issue-30252.rs | 2 ++ tests/rustdoc/issue-30366.rs | 2 ++ tests/rustdoc/issue-31808.rs | 2 ++ tests/rustdoc/issue-31899.rs | 2 ++ tests/rustdoc/issue-32374.rs | 1 + tests/rustdoc/issue-32395.rs | 2 ++ tests/rustdoc/issue-32556.rs | 2 ++ tests/rustdoc/issue-32890.rs | 2 ++ tests/rustdoc/issue-33069.rs | 2 ++ tests/rustdoc/issue-33178-1.rs | 2 ++ tests/rustdoc/issue-33178.rs | 2 ++ tests/rustdoc/issue-33302.rs | 2 ++ 16 files changed, 31 insertions(+) diff --git a/tests/rustdoc/issue-29449.rs b/tests/rustdoc/issue-29449.rs index 0d829cf6fcff..0b9b29a69eef 100644 --- a/tests/rustdoc/issue-29449.rs +++ b/tests/rustdoc/issue-29449.rs @@ -1,3 +1,5 @@ +#![crate_name="issue_29449"] + // @has issue_29449/struct.Foo.html pub struct Foo; diff --git a/tests/rustdoc/issue-29503.rs b/tests/rustdoc/issue-29503.rs index 01ae4438500d..310acd09a823 100644 --- a/tests/rustdoc/issue-29503.rs +++ b/tests/rustdoc/issue-29503.rs @@ -1,3 +1,5 @@ +#![crate_name="issue_29503"] + use std::fmt; // @has issue_29503/trait.MyTrait.html diff --git a/tests/rustdoc/issue-29584.rs b/tests/rustdoc/issue-29584.rs index 4364a9649b57..6e3feafc7ad6 100644 --- a/tests/rustdoc/issue-29584.rs +++ b/tests/rustdoc/issue-29584.rs @@ -1,6 +1,8 @@ // aux-build:issue-29584.rs // ignore-cross-compile +#![crate_name="issue_29584"] + extern crate issue_29584; // @has issue_29584/struct.Foo.html diff --git a/tests/rustdoc/issue-30109.rs b/tests/rustdoc/issue-30109.rs index e9447538ad78..ff9a22b5f7b3 100644 --- a/tests/rustdoc/issue-30109.rs +++ b/tests/rustdoc/issue-30109.rs @@ -2,6 +2,8 @@ // aux-build:issue-30109-1.rs // ignore-cross-compile +#![crate_name="issue_30109"] + pub mod quux { extern crate issue_30109_1 as bar; use self::bar::Bar; diff --git a/tests/rustdoc/issue-30252.rs b/tests/rustdoc/issue-30252.rs index c3777362a66d..749c63d741c6 100644 --- a/tests/rustdoc/issue-30252.rs +++ b/tests/rustdoc/issue-30252.rs @@ -1,5 +1,7 @@ // compile-flags:--test --cfg feature="bar" +#![crate_name="issue_30252"] + /// ```rust /// assert_eq!(cfg!(feature = "bar"), true); /// ``` diff --git a/tests/rustdoc/issue-30366.rs b/tests/rustdoc/issue-30366.rs index c6274a058b0e..0fa5dc6fe7f4 100644 --- a/tests/rustdoc/issue-30366.rs +++ b/tests/rustdoc/issue-30366.rs @@ -1,5 +1,7 @@ // @has issue_30366/index.html '//a/@href' 'http://www.rust-lang.org/' +#![crate_name="issue_30366"] + /// Describe it. [Link somewhere][1]. /// /// [1]: http://www.rust-lang.org/ diff --git a/tests/rustdoc/issue-31808.rs b/tests/rustdoc/issue-31808.rs index e55c5bd4f7ce..58f9daaff591 100644 --- a/tests/rustdoc/issue-31808.rs +++ b/tests/rustdoc/issue-31808.rs @@ -1,5 +1,7 @@ // Test that associated item impls on primitive types don't crash rustdoc +#![crate_name="issue_31808"] + pub trait Foo { const BAR: usize; type BAZ; diff --git a/tests/rustdoc/issue-31899.rs b/tests/rustdoc/issue-31899.rs index 3eee374465d2..570ab59bbe98 100644 --- a/tests/rustdoc/issue-31899.rs +++ b/tests/rustdoc/issue-31899.rs @@ -1,3 +1,5 @@ +#![crate_name="issue_31899"] + // @has issue_31899/index.html // @hasraw - 'Make this line a bit longer.' // @!hasraw - 'rust rust-example-rendered' diff --git a/tests/rustdoc/issue-32374.rs b/tests/rustdoc/issue-32374.rs index 985bf03a1215..36070dbb731d 100644 --- a/tests/rustdoc/issue-32374.rs +++ b/tests/rustdoc/issue-32374.rs @@ -1,6 +1,7 @@ #![feature(staged_api)] #![doc(issue_tracker_base_url = "https://issue_url/")] #![unstable(feature = "test", issue = "32374")] +#![crate_name="issue_32374"] // @matches issue_32374/index.html '//*[@class="item-name"]/span[@class="stab deprecated"]' \ // 'Deprecated' diff --git a/tests/rustdoc/issue-32395.rs b/tests/rustdoc/issue-32395.rs index 5552300f9fe8..d419c75b71c7 100644 --- a/tests/rustdoc/issue-32395.rs +++ b/tests/rustdoc/issue-32395.rs @@ -2,6 +2,8 @@ // build-aux-docs // ignore-cross-compile +#![crate_name="issue_32395"] + // @has variant_struct/enum.Foo.html // @!hasraw - 'pub qux' // @!hasraw - 'pub(crate) qux' diff --git a/tests/rustdoc/issue-32556.rs b/tests/rustdoc/issue-32556.rs index e1cf11509972..369aef72e190 100644 --- a/tests/rustdoc/issue-32556.rs +++ b/tests/rustdoc/issue-32556.rs @@ -1,3 +1,5 @@ +#![crate_name="issue_32556"] + /// Blah blah blah /// ```ignore (testing rustdoc's handling of ignore) /// bad_assert!(); diff --git a/tests/rustdoc/issue-32890.rs b/tests/rustdoc/issue-32890.rs index 970954433ec7..dfac0ef22b7f 100644 --- a/tests/rustdoc/issue-32890.rs +++ b/tests/rustdoc/issue-32890.rs @@ -1,3 +1,5 @@ +#![crate_name="issue_32890"] + // @has issue_32890/struct.Foo.html pub struct Foo(T); diff --git a/tests/rustdoc/issue-33069.rs b/tests/rustdoc/issue-33069.rs index 0213a53cab5d..9c0e0014bd1a 100644 --- a/tests/rustdoc/issue-33069.rs +++ b/tests/rustdoc/issue-33069.rs @@ -1,3 +1,5 @@ +#![crate_name="issue_33069"] + pub trait Bar {} #[doc(hidden)] diff --git a/tests/rustdoc/issue-33178-1.rs b/tests/rustdoc/issue-33178-1.rs index 4dc425346abb..24740c12952c 100644 --- a/tests/rustdoc/issue-33178-1.rs +++ b/tests/rustdoc/issue-33178-1.rs @@ -2,6 +2,8 @@ // aux-build:variant-struct.rs // ignore-cross-compile +#![crate_name="issue_33178_1"] + // @has issue_33178_1/index.html // @!has - //a/@title empty pub extern crate empty; diff --git a/tests/rustdoc/issue-33178.rs b/tests/rustdoc/issue-33178.rs index ed643f5ae118..fb44d8efc8c8 100644 --- a/tests/rustdoc/issue-33178.rs +++ b/tests/rustdoc/issue-33178.rs @@ -3,6 +3,8 @@ // build-aux-docs // ignore-cross-compile +#![crate_name="issue_33178"] + // @has issue_33178/index.html // @has - '//a[@title="mod empty"][@href="../empty/index.html"]' empty pub extern crate empty; diff --git a/tests/rustdoc/issue-33302.rs b/tests/rustdoc/issue-33302.rs index a316f3ad99bc..b4e6cc7aaac2 100644 --- a/tests/rustdoc/issue-33302.rs +++ b/tests/rustdoc/issue-33302.rs @@ -1,3 +1,5 @@ +#![crate_name="issue_33302"] + // Ensure constant and array length values are not taken from source // code, which wreaks havoc with macros. From 69dc19043bee2ce720f83bf1d6582240547c842e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 16 Oct 2023 16:06:58 -0700 Subject: [PATCH 33/94] Rename `issue-\d+.rs` tests to have meaningful names --- tests/rustdoc/{issue-29503.rs => blanket-impl-29503.rs} | 0 tests/rustdoc/{issue-33302.rs => const-rendering-macros-33302.rs} | 0 tests/rustdoc/{issue-32890.rs => disambiguate-anchors-32890.rs} | 0 .../{issue-29449.rs => disambiguate-anchors-header-29449.rs} | 0 .../{issue-33069.rs => doc-hidden-trait-implementors-33069.rs} | 0 tests/rustdoc/{issue-30252.rs => doctest-cfg-feature-30252.rs} | 0 tests/rustdoc/{issue-32556.rs => doctest-ignore-32556.rs} | 0 tests/rustdoc/{issue-34025.rs => hidden-extern-34025.rs} | 0 .../{issue-31808.rs => ice-assoc-const-for-primitive-31808.rs} | 0 tests/rustdoc/{issue-33592.rs => impl-type-parameter-33592.rs} | 0 tests/rustdoc/{ => inline_cross}/auxiliary/issue-29584.rs | 0 .../doc-hidden-extern-trait-impl-29584.rs} | 0 tests/rustdoc/{issue-33178.rs => link-extern-crate-33178.rs} | 0 tests/rustdoc/{issue-30109.rs => link-extern-crate-item-30109.rs} | 0 .../{issue-33178-1.rs => link-extern-crate-title-33178.rs} | 0 .../{issue-32395.rs => render-enum-variant-structlike-32395.rs} | 0 tests/rustdoc/{issue-34274.rs => src-links-inlined-34274.rs} | 0 .../{issue-32374.rs => staged-api-deprecated-unstable-32374.rs} | 0 tests/rustdoc/{issue-31899.rs => summary-codeblock-31899.rs} | 0 tests/rustdoc/{issue-30366.rs => summary-reference-link-30366.rs} | 0 ...{issue-32077-type-alias-impls.rs => type-alias-impls-32077.rs} | 0 21 files changed, 0 insertions(+), 0 deletions(-) rename tests/rustdoc/{issue-29503.rs => blanket-impl-29503.rs} (100%) rename tests/rustdoc/{issue-33302.rs => const-rendering-macros-33302.rs} (100%) rename tests/rustdoc/{issue-32890.rs => disambiguate-anchors-32890.rs} (100%) rename tests/rustdoc/{issue-29449.rs => disambiguate-anchors-header-29449.rs} (100%) rename tests/rustdoc/{issue-33069.rs => doc-hidden-trait-implementors-33069.rs} (100%) rename tests/rustdoc/{issue-30252.rs => doctest-cfg-feature-30252.rs} (100%) rename tests/rustdoc/{issue-32556.rs => doctest-ignore-32556.rs} (100%) rename tests/rustdoc/{issue-34025.rs => hidden-extern-34025.rs} (100%) rename tests/rustdoc/{issue-31808.rs => ice-assoc-const-for-primitive-31808.rs} (100%) rename tests/rustdoc/{issue-33592.rs => impl-type-parameter-33592.rs} (100%) rename tests/rustdoc/{ => inline_cross}/auxiliary/issue-29584.rs (100%) rename tests/rustdoc/{issue-29584.rs => inline_cross/doc-hidden-extern-trait-impl-29584.rs} (100%) rename tests/rustdoc/{issue-33178.rs => link-extern-crate-33178.rs} (100%) rename tests/rustdoc/{issue-30109.rs => link-extern-crate-item-30109.rs} (100%) rename tests/rustdoc/{issue-33178-1.rs => link-extern-crate-title-33178.rs} (100%) rename tests/rustdoc/{issue-32395.rs => render-enum-variant-structlike-32395.rs} (100%) rename tests/rustdoc/{issue-34274.rs => src-links-inlined-34274.rs} (100%) rename tests/rustdoc/{issue-32374.rs => staged-api-deprecated-unstable-32374.rs} (100%) rename tests/rustdoc/{issue-31899.rs => summary-codeblock-31899.rs} (100%) rename tests/rustdoc/{issue-30366.rs => summary-reference-link-30366.rs} (100%) rename tests/rustdoc/{issue-32077-type-alias-impls.rs => type-alias-impls-32077.rs} (100%) diff --git a/tests/rustdoc/issue-29503.rs b/tests/rustdoc/blanket-impl-29503.rs similarity index 100% rename from tests/rustdoc/issue-29503.rs rename to tests/rustdoc/blanket-impl-29503.rs diff --git a/tests/rustdoc/issue-33302.rs b/tests/rustdoc/const-rendering-macros-33302.rs similarity index 100% rename from tests/rustdoc/issue-33302.rs rename to tests/rustdoc/const-rendering-macros-33302.rs diff --git a/tests/rustdoc/issue-32890.rs b/tests/rustdoc/disambiguate-anchors-32890.rs similarity index 100% rename from tests/rustdoc/issue-32890.rs rename to tests/rustdoc/disambiguate-anchors-32890.rs diff --git a/tests/rustdoc/issue-29449.rs b/tests/rustdoc/disambiguate-anchors-header-29449.rs similarity index 100% rename from tests/rustdoc/issue-29449.rs rename to tests/rustdoc/disambiguate-anchors-header-29449.rs diff --git a/tests/rustdoc/issue-33069.rs b/tests/rustdoc/doc-hidden-trait-implementors-33069.rs similarity index 100% rename from tests/rustdoc/issue-33069.rs rename to tests/rustdoc/doc-hidden-trait-implementors-33069.rs diff --git a/tests/rustdoc/issue-30252.rs b/tests/rustdoc/doctest-cfg-feature-30252.rs similarity index 100% rename from tests/rustdoc/issue-30252.rs rename to tests/rustdoc/doctest-cfg-feature-30252.rs diff --git a/tests/rustdoc/issue-32556.rs b/tests/rustdoc/doctest-ignore-32556.rs similarity index 100% rename from tests/rustdoc/issue-32556.rs rename to tests/rustdoc/doctest-ignore-32556.rs diff --git a/tests/rustdoc/issue-34025.rs b/tests/rustdoc/hidden-extern-34025.rs similarity index 100% rename from tests/rustdoc/issue-34025.rs rename to tests/rustdoc/hidden-extern-34025.rs diff --git a/tests/rustdoc/issue-31808.rs b/tests/rustdoc/ice-assoc-const-for-primitive-31808.rs similarity index 100% rename from tests/rustdoc/issue-31808.rs rename to tests/rustdoc/ice-assoc-const-for-primitive-31808.rs diff --git a/tests/rustdoc/issue-33592.rs b/tests/rustdoc/impl-type-parameter-33592.rs similarity index 100% rename from tests/rustdoc/issue-33592.rs rename to tests/rustdoc/impl-type-parameter-33592.rs diff --git a/tests/rustdoc/auxiliary/issue-29584.rs b/tests/rustdoc/inline_cross/auxiliary/issue-29584.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-29584.rs rename to tests/rustdoc/inline_cross/auxiliary/issue-29584.rs diff --git a/tests/rustdoc/issue-29584.rs b/tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs similarity index 100% rename from tests/rustdoc/issue-29584.rs rename to tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs diff --git a/tests/rustdoc/issue-33178.rs b/tests/rustdoc/link-extern-crate-33178.rs similarity index 100% rename from tests/rustdoc/issue-33178.rs rename to tests/rustdoc/link-extern-crate-33178.rs diff --git a/tests/rustdoc/issue-30109.rs b/tests/rustdoc/link-extern-crate-item-30109.rs similarity index 100% rename from tests/rustdoc/issue-30109.rs rename to tests/rustdoc/link-extern-crate-item-30109.rs diff --git a/tests/rustdoc/issue-33178-1.rs b/tests/rustdoc/link-extern-crate-title-33178.rs similarity index 100% rename from tests/rustdoc/issue-33178-1.rs rename to tests/rustdoc/link-extern-crate-title-33178.rs diff --git a/tests/rustdoc/issue-32395.rs b/tests/rustdoc/render-enum-variant-structlike-32395.rs similarity index 100% rename from tests/rustdoc/issue-32395.rs rename to tests/rustdoc/render-enum-variant-structlike-32395.rs diff --git a/tests/rustdoc/issue-34274.rs b/tests/rustdoc/src-links-inlined-34274.rs similarity index 100% rename from tests/rustdoc/issue-34274.rs rename to tests/rustdoc/src-links-inlined-34274.rs diff --git a/tests/rustdoc/issue-32374.rs b/tests/rustdoc/staged-api-deprecated-unstable-32374.rs similarity index 100% rename from tests/rustdoc/issue-32374.rs rename to tests/rustdoc/staged-api-deprecated-unstable-32374.rs diff --git a/tests/rustdoc/issue-31899.rs b/tests/rustdoc/summary-codeblock-31899.rs similarity index 100% rename from tests/rustdoc/issue-31899.rs rename to tests/rustdoc/summary-codeblock-31899.rs diff --git a/tests/rustdoc/issue-30366.rs b/tests/rustdoc/summary-reference-link-30366.rs similarity index 100% rename from tests/rustdoc/issue-30366.rs rename to tests/rustdoc/summary-reference-link-30366.rs diff --git a/tests/rustdoc/issue-32077-type-alias-impls.rs b/tests/rustdoc/type-alias-impls-32077.rs similarity index 100% rename from tests/rustdoc/issue-32077-type-alias-impls.rs rename to tests/rustdoc/type-alias-impls-32077.rs From 43b493ebc06f298c8d781f3f0b5a21acbfebd013 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 16 Oct 2023 16:12:17 -0700 Subject: [PATCH 34/94] Add URL to test cases --- tests/rustdoc/blanket-impl-29503.rs | 1 + tests/rustdoc/const-rendering-macros-33302.rs | 1 + tests/rustdoc/disambiguate-anchors-32890.rs | 1 + tests/rustdoc/disambiguate-anchors-header-29449.rs | 1 + tests/rustdoc/doc-hidden-trait-implementors-33069.rs | 1 + tests/rustdoc/doctest-cfg-feature-30252.rs | 1 + tests/rustdoc/doctest-ignore-32556.rs | 1 + tests/rustdoc/hidden-extern-34025.rs | 1 + tests/rustdoc/ice-assoc-const-for-primitive-31808.rs | 1 + tests/rustdoc/impl-type-parameter-33592.rs | 1 + tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs | 1 + tests/rustdoc/link-extern-crate-33178.rs | 1 + tests/rustdoc/link-extern-crate-item-30109.rs | 1 + tests/rustdoc/link-extern-crate-title-33178.rs | 1 + tests/rustdoc/render-enum-variant-structlike-32395.rs | 1 + tests/rustdoc/src-links-inlined-34274.rs | 1 + tests/rustdoc/staged-api-deprecated-unstable-32374.rs | 1 + tests/rustdoc/summary-codeblock-31899.rs | 1 + tests/rustdoc/summary-reference-link-30366.rs | 1 + tests/rustdoc/type-alias-impls-32077.rs | 1 + 20 files changed, 20 insertions(+) diff --git a/tests/rustdoc/blanket-impl-29503.rs b/tests/rustdoc/blanket-impl-29503.rs index 310acd09a823..d6a132e1c263 100644 --- a/tests/rustdoc/blanket-impl-29503.rs +++ b/tests/rustdoc/blanket-impl-29503.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/29503 #![crate_name="issue_29503"] use std::fmt; diff --git a/tests/rustdoc/const-rendering-macros-33302.rs b/tests/rustdoc/const-rendering-macros-33302.rs index b4e6cc7aaac2..0f5cb921411e 100644 --- a/tests/rustdoc/const-rendering-macros-33302.rs +++ b/tests/rustdoc/const-rendering-macros-33302.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/33302 #![crate_name="issue_33302"] // Ensure constant and array length values are not taken from source diff --git a/tests/rustdoc/disambiguate-anchors-32890.rs b/tests/rustdoc/disambiguate-anchors-32890.rs index dfac0ef22b7f..d88601d65d38 100644 --- a/tests/rustdoc/disambiguate-anchors-32890.rs +++ b/tests/rustdoc/disambiguate-anchors-32890.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/32890 #![crate_name="issue_32890"] // @has issue_32890/struct.Foo.html diff --git a/tests/rustdoc/disambiguate-anchors-header-29449.rs b/tests/rustdoc/disambiguate-anchors-header-29449.rs index 0b9b29a69eef..38a4954fc139 100644 --- a/tests/rustdoc/disambiguate-anchors-header-29449.rs +++ b/tests/rustdoc/disambiguate-anchors-header-29449.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/29449 #![crate_name="issue_29449"] // @has issue_29449/struct.Foo.html diff --git a/tests/rustdoc/doc-hidden-trait-implementors-33069.rs b/tests/rustdoc/doc-hidden-trait-implementors-33069.rs index 9c0e0014bd1a..35570668ea16 100644 --- a/tests/rustdoc/doc-hidden-trait-implementors-33069.rs +++ b/tests/rustdoc/doc-hidden-trait-implementors-33069.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/33069 #![crate_name="issue_33069"] pub trait Bar {} diff --git a/tests/rustdoc/doctest-cfg-feature-30252.rs b/tests/rustdoc/doctest-cfg-feature-30252.rs index 749c63d741c6..ceb8076fe352 100644 --- a/tests/rustdoc/doctest-cfg-feature-30252.rs +++ b/tests/rustdoc/doctest-cfg-feature-30252.rs @@ -1,5 +1,6 @@ // compile-flags:--test --cfg feature="bar" +// https://github.com/rust-lang/rust/issues/30252 #![crate_name="issue_30252"] /// ```rust diff --git a/tests/rustdoc/doctest-ignore-32556.rs b/tests/rustdoc/doctest-ignore-32556.rs index 369aef72e190..99da9358bd6b 100644 --- a/tests/rustdoc/doctest-ignore-32556.rs +++ b/tests/rustdoc/doctest-ignore-32556.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/32556 #![crate_name="issue_32556"] /// Blah blah blah diff --git a/tests/rustdoc/hidden-extern-34025.rs b/tests/rustdoc/hidden-extern-34025.rs index 9b9f21cb3169..81ccf2a0e5cc 100644 --- a/tests/rustdoc/hidden-extern-34025.rs +++ b/tests/rustdoc/hidden-extern-34025.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/34025 #![crate_name = "foo"] // @!has 'foo/sys/index.html' diff --git a/tests/rustdoc/ice-assoc-const-for-primitive-31808.rs b/tests/rustdoc/ice-assoc-const-for-primitive-31808.rs index 58f9daaff591..9c0e404cf761 100644 --- a/tests/rustdoc/ice-assoc-const-for-primitive-31808.rs +++ b/tests/rustdoc/ice-assoc-const-for-primitive-31808.rs @@ -1,5 +1,6 @@ // Test that associated item impls on primitive types don't crash rustdoc +// https://github.com/rust-lang/rust/issues/31808 #![crate_name="issue_31808"] pub trait Foo { diff --git a/tests/rustdoc/impl-type-parameter-33592.rs b/tests/rustdoc/impl-type-parameter-33592.rs index 7a128f0b897e..77f53710e5e7 100644 --- a/tests/rustdoc/impl-type-parameter-33592.rs +++ b/tests/rustdoc/impl-type-parameter-33592.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/33592 #![crate_name = "foo"] pub trait Foo {} diff --git a/tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs b/tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs index 6e3feafc7ad6..b246e94e048d 100644 --- a/tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs +++ b/tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs @@ -1,6 +1,7 @@ // aux-build:issue-29584.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/29584 #![crate_name="issue_29584"] extern crate issue_29584; diff --git a/tests/rustdoc/link-extern-crate-33178.rs b/tests/rustdoc/link-extern-crate-33178.rs index fb44d8efc8c8..6a63712c4a78 100644 --- a/tests/rustdoc/link-extern-crate-33178.rs +++ b/tests/rustdoc/link-extern-crate-33178.rs @@ -3,6 +3,7 @@ // build-aux-docs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/33178 #![crate_name="issue_33178"] // @has issue_33178/index.html diff --git a/tests/rustdoc/link-extern-crate-item-30109.rs b/tests/rustdoc/link-extern-crate-item-30109.rs index ff9a22b5f7b3..c83234352ad3 100644 --- a/tests/rustdoc/link-extern-crate-item-30109.rs +++ b/tests/rustdoc/link-extern-crate-item-30109.rs @@ -2,6 +2,7 @@ // aux-build:issue-30109-1.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/30109 #![crate_name="issue_30109"] pub mod quux { diff --git a/tests/rustdoc/link-extern-crate-title-33178.rs b/tests/rustdoc/link-extern-crate-title-33178.rs index 24740c12952c..d2f115a386e9 100644 --- a/tests/rustdoc/link-extern-crate-title-33178.rs +++ b/tests/rustdoc/link-extern-crate-title-33178.rs @@ -2,6 +2,7 @@ // aux-build:variant-struct.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/33178 #![crate_name="issue_33178_1"] // @has issue_33178_1/index.html diff --git a/tests/rustdoc/render-enum-variant-structlike-32395.rs b/tests/rustdoc/render-enum-variant-structlike-32395.rs index d419c75b71c7..2200d8ec6377 100644 --- a/tests/rustdoc/render-enum-variant-structlike-32395.rs +++ b/tests/rustdoc/render-enum-variant-structlike-32395.rs @@ -2,6 +2,7 @@ // build-aux-docs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/32395 #![crate_name="issue_32395"] // @has variant_struct/enum.Foo.html diff --git a/tests/rustdoc/src-links-inlined-34274.rs b/tests/rustdoc/src-links-inlined-34274.rs index ce5be84a5491..a3c9bf7e45c5 100644 --- a/tests/rustdoc/src-links-inlined-34274.rs +++ b/tests/rustdoc/src-links-inlined-34274.rs @@ -2,6 +2,7 @@ // build-aux-docs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/34274 #![crate_name = "foo"] extern crate issue_34274; diff --git a/tests/rustdoc/staged-api-deprecated-unstable-32374.rs b/tests/rustdoc/staged-api-deprecated-unstable-32374.rs index 36070dbb731d..d282dea907e8 100644 --- a/tests/rustdoc/staged-api-deprecated-unstable-32374.rs +++ b/tests/rustdoc/staged-api-deprecated-unstable-32374.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/32374 #![feature(staged_api)] #![doc(issue_tracker_base_url = "https://issue_url/")] #![unstable(feature = "test", issue = "32374")] diff --git a/tests/rustdoc/summary-codeblock-31899.rs b/tests/rustdoc/summary-codeblock-31899.rs index 570ab59bbe98..c1b33058c9e7 100644 --- a/tests/rustdoc/summary-codeblock-31899.rs +++ b/tests/rustdoc/summary-codeblock-31899.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/31899 #![crate_name="issue_31899"] // @has issue_31899/index.html diff --git a/tests/rustdoc/summary-reference-link-30366.rs b/tests/rustdoc/summary-reference-link-30366.rs index 0fa5dc6fe7f4..5b9854c53903 100644 --- a/tests/rustdoc/summary-reference-link-30366.rs +++ b/tests/rustdoc/summary-reference-link-30366.rs @@ -1,5 +1,6 @@ // @has issue_30366/index.html '//a/@href' 'http://www.rust-lang.org/' +// https://github.com/rust-lang/rust/issues/30366 #![crate_name="issue_30366"] /// Describe it. [Link somewhere][1]. diff --git a/tests/rustdoc/type-alias-impls-32077.rs b/tests/rustdoc/type-alias-impls-32077.rs index 664b678093e9..7bb763f86afb 100644 --- a/tests/rustdoc/type-alias-impls-32077.rs +++ b/tests/rustdoc/type-alias-impls-32077.rs @@ -1,5 +1,6 @@ // Regression test for . +// https://github.com/rust-lang/rust/issues/32077 #![crate_name = "foo"] pub struct GenericStruct(T); From 94b39e8c86f3b07e39e8541ef4417c260ec13eab Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 16 Oct 2023 18:02:11 -0700 Subject: [PATCH 35/94] rustdoc: move ICE test to rustdoc-ui --- .../ice-assoc-const-for-primitive-31808.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{rustdoc => rustdoc-ui}/ice-assoc-const-for-primitive-31808.rs (100%) diff --git a/tests/rustdoc/ice-assoc-const-for-primitive-31808.rs b/tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs similarity index 100% rename from tests/rustdoc/ice-assoc-const-for-primitive-31808.rs rename to tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs From c0b6a5d3406546e89785e0512cf24ab88b6564bc Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 16 Oct 2023 18:03:22 -0700 Subject: [PATCH 36/94] rustdoc: add `check-pass` to ICE test with no expected output --- tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs b/tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs index 9c0e404cf761..6e4709403a4d 100644 --- a/tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs +++ b/tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs @@ -1,3 +1,5 @@ +// check-pass + // Test that associated item impls on primitive types don't crash rustdoc // https://github.com/rust-lang/rust/issues/31808 From b0e1a52e37d9690db292af841181a894599c41ee Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 17 Oct 2023 11:37:58 +1100 Subject: [PATCH 37/94] Make `handle_options` public again. --- compiler/rustc_driver_impl/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 5bb7c41677cd..a509412074e4 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1184,7 +1184,11 @@ fn print_flag_list( /// /// So with all that in mind, the comments below have some more detail about the /// contortions done here to get things to work out correctly. -fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option { +/// +/// This does not need to be `pub` for rustc itself, but @chaosite needs it to +/// be public when using rustc as a library, see +/// +pub fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option { if args.is_empty() { // user did not write `-v` nor `-Z unstable-options`, so do not // include that extra information. From 8769e02d0b17e18e0a52b521a82da4bcae2e6385 Mon Sep 17 00:00:00 2001 From: Arthur Lafrance Date: Sat, 23 Sep 2023 23:50:47 -0700 Subject: [PATCH 38/94] implement the basics of the lint static analysis --- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint/src/span_use_eq_ctxt.rs | 38 +++++++++++++++++++++ compiler/rustc_span/src/span_encoding.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + 4 files changed, 41 insertions(+) create mode 100644 compiler/rustc_lint/src/span_use_eq_ctxt.rs diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index b9e455e6c2a3..ca1f620b7c76 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -83,6 +83,7 @@ mod passes; mod ptr_nulls; mod redundant_semicolon; mod reference_casting; +mod span_use_eq_ctxt; mod traits; mod types; mod unused; diff --git a/compiler/rustc_lint/src/span_use_eq_ctxt.rs b/compiler/rustc_lint/src/span_use_eq_ctxt.rs new file mode 100644 index 000000000000..19fea01bf4f7 --- /dev/null +++ b/compiler/rustc_lint/src/span_use_eq_ctxt.rs @@ -0,0 +1,38 @@ +use crate::{LateContext, LateLintPass}; +use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind}; +use rustc_span::sym; + +declare_lint! { + pub SPAN_USE_EQ_CTXT, + Warn, // is this the right level? + "Use of `==` with `Span::ctxt` rather than `Span::eq_ctxt`" +} + +declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]); + +impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { + if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind { + if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) { + todo!(); // emit lint + } + } + } +} + +fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + match &expr.kind { + ExprKind::MethodCall(..) => { + // i gave a method a diagnostic item -- FIXME: switch to a diagnostic + // item for the Span type and check: + // * method call path == "ctxt" + // * receiver type matches Span diag item + // also FIXME(todo) remove old SpanCtxt diagnostic item + cx.typeck_results() + .type_dependent_def_id(expr.hir_id) + .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, did)) + } + + _ => false, + } +} diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index bfc9e125362c..69ad11e23f02 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -212,6 +212,7 @@ impl Span { /// This function is used as a fast path when decoding the full `SpanData` is not necessary. /// It's a cut-down version of `data_untracked`. + #[rustc_diagnostic_item = "SpanCtxt"] #[inline] pub fn ctxt(self) -> SyntaxContext { if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ea261923c654..be8c65862dc2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -303,6 +303,7 @@ symbols! { SliceIndex, SliceIter, Some, + SpanCtxt, String, StructuralEq, StructuralPartialEq, From f77dea89e183b638841d42d4d7bea48058a98e76 Mon Sep 17 00:00:00 2001 From: Arthur Lafrance Date: Mon, 25 Sep 2023 00:15:00 -0700 Subject: [PATCH 39/94] basic lint v2 implemented --- compiler/rustc_lint/messages.ftl | 2 + compiler/rustc_lint/src/internal.rs | 45 ++++++++++++++++++- compiler/rustc_lint/src/lib.rs | 4 +- compiler/rustc_lint/src/lints.rs | 6 +++ compiler/rustc_lint/src/span_use_eq_ctxt.rs | 38 ---------------- compiler/rustc_span/src/span_encoding.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- .../internal-lints/span_use_eq_ctxt.rs | 13 ++++++ 8 files changed, 69 insertions(+), 43 deletions(-) delete mode 100644 compiler/rustc_lint/src/span_use_eq_ctxt.rs create mode 100644 tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 197fe6552d79..261451e530e6 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -494,6 +494,8 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` +lint_span_use_eq_ctxt = use `eq_ctxt()` not `ctxt() == ctxt()` + lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target .label = target type is set here diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index fc2d3d0a2544..c2aa768e9457 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -3,14 +3,14 @@ use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, - QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, + QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, UntranslatableDiagnosticTrivial, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_hir::def::Res; use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath}; -use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind}; +use rustc_hir::{BinOp, BinOpKind, HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; @@ -537,3 +537,44 @@ impl LateLintPass<'_> for BadOptAccess { } } } + +// some things i'm not sure about: +// * is Warn the right level? +// * the way i verify that the right method is being called (path + diag item check) + +declare_tool_lint! { + pub rustc::SPAN_USE_EQ_CTXT, + Warn, // is this the right level? + "Use of `==` with `Span::ctxt` rather than `Span::eq_ctxt`", + report_in_external_macro: true +} + +declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]); + +impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { + if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind { + if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) { + cx.emit_spanned_lint( + SPAN_USE_EQ_CTXT, + expr.span, + SpanUseEqCtxtDiag { msg: "fail" }, + ); + } + } + } +} + +fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + match &expr.kind { + ExprKind::MethodCall(path, receiver, _, _) => { + path.ident.name.as_str() == "ctxt" + && cx + .typeck_results() + .type_dependent_def_id(receiver.hir_id) + .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::Span, did)) + } + + _ => false, + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index ca1f620b7c76..d61c59af1e05 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -83,7 +83,6 @@ mod passes; mod ptr_nulls; mod redundant_semicolon; mod reference_casting; -mod span_use_eq_ctxt; mod traits; mod types; mod unused; @@ -532,6 +531,8 @@ fn register_internals(store: &mut LintStore) { store.register_late_mod_pass(|_| Box::new(BadOptAccess)); store.register_lints(&PassByValue::get_lints()); store.register_late_mod_pass(|_| Box::new(PassByValue)); + store.register_lints(&SpanUseEqCtxt::get_lints()); + store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt)); // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and // these lints will trigger all of the time - change this once migration to diagnostic structs @@ -549,6 +550,7 @@ fn register_internals(store: &mut LintStore) { LintId::of(USAGE_OF_QUALIFIED_TY), LintId::of(EXISTING_DOC_KEYWORD), LintId::of(BAD_OPT_ACCESS), + LintId::of(SPAN_USE_EQ_CTXT), ], ); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 594ef97b3ffb..a02bee506dfa 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -900,6 +900,12 @@ pub struct QueryInstability { pub query: Symbol, } +#[derive(LintDiagnostic)] +#[diag(lint_span_use_eq_ctxt)] +pub struct SpanUseEqCtxtDiag<'a> { + pub msg: &'a str, +} + #[derive(LintDiagnostic)] #[diag(lint_tykind_kind)] pub struct TykindKind { diff --git a/compiler/rustc_lint/src/span_use_eq_ctxt.rs b/compiler/rustc_lint/src/span_use_eq_ctxt.rs deleted file mode 100644 index 19fea01bf4f7..000000000000 --- a/compiler/rustc_lint/src/span_use_eq_ctxt.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::{LateContext, LateLintPass}; -use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind}; -use rustc_span::sym; - -declare_lint! { - pub SPAN_USE_EQ_CTXT, - Warn, // is this the right level? - "Use of `==` with `Span::ctxt` rather than `Span::eq_ctxt`" -} - -declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]); - -impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { - if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind { - if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) { - todo!(); // emit lint - } - } - } -} - -fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - match &expr.kind { - ExprKind::MethodCall(..) => { - // i gave a method a diagnostic item -- FIXME: switch to a diagnostic - // item for the Span type and check: - // * method call path == "ctxt" - // * receiver type matches Span diag item - // also FIXME(todo) remove old SpanCtxt diagnostic item - cx.typeck_results() - .type_dependent_def_id(expr.hir_id) - .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, did)) - } - - _ => false, - } -} diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index 69ad11e23f02..7c7f8448c978 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -75,6 +75,7 @@ use rustc_data_structures::fx::FxIndexSet; /// the dependency to the parent definition's span. This is performed /// using the callback `SPAN_TRACK` to access the query engine. /// +#[cfg_attr(not(test), rustc_diagnostic_item = "Span")] #[derive(Clone, Copy, Eq, PartialEq, Hash)] #[rustc_pass_by_value] pub struct Span { @@ -212,7 +213,6 @@ impl Span { /// This function is used as a fast path when decoding the full `SpanData` is not necessary. /// It's a cut-down version of `data_untracked`. - #[rustc_diagnostic_item = "SpanCtxt"] #[inline] pub fn ctxt(self) -> SyntaxContext { if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index be8c65862dc2..9598b2d0310a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -303,7 +303,7 @@ symbols! { SliceIndex, SliceIter, Some, - SpanCtxt, + Span, String, StructuralEq, StructuralPartialEq, diff --git a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs new file mode 100644 index 000000000000..5b4c59a2e8a0 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs @@ -0,0 +1,13 @@ +// compile-flags: -Z unstable-options + +#![feature(rustc_private)] +#![deny(rustc::span_use_eq_ctxt)] + +extern crate rustc_span; +use rustc_span::Span; + +pub fn f(s: Span, t: Span) -> bool { + s.ctxt() == t.ctxt() //~ ERROR use of span ctxt +} + +fn main() {} From 5895102c4dab67e7962bd76e1204bcf0fab467c5 Mon Sep 17 00:00:00 2001 From: Arthur Lafrance Date: Mon, 16 Oct 2023 01:05:11 -0700 Subject: [PATCH 40/94] debug Span::ctxt() call detection --- compiler/rustc_hir_typeck/src/callee.rs | 2 +- compiler/rustc_lint/messages.ftl | 2 +- compiler/rustc_lint/src/internal.rs | 23 +++++-------------- compiler/rustc_lint/src/lints.rs | 4 +--- .../rustc_mir_transform/src/coverage/spans.rs | 2 +- compiler/rustc_span/src/span_encoding.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- .../internal-lints/span_use_eq_ctxt.rs | 6 ++--- .../internal-lints/span_use_eq_ctxt.stderr | 14 +++++++++++ 9 files changed, 29 insertions(+), 28 deletions(-) create mode 100644 tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 512d73fc1036..1c23ccd15794 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -650,7 +650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .sess .source_map() .is_multiline(call_expr.span.with_lo(callee_expr.span.hi())) - && call_expr.span.ctxt() == callee_expr.span.ctxt(); + && call_expr.span.eq_ctxt(callee_expr.span); if call_is_multiline { err.span_suggestion( callee_expr.span.shrink_to_hi(), diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 261451e530e6..4c4d2933bf4f 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -494,7 +494,7 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` -lint_span_use_eq_ctxt = use `eq_ctxt()` not `ctxt() == ctxt()` +lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target .label = target type is set here diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index c2aa768e9457..34f241e8c8d2 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -538,13 +538,9 @@ impl LateLintPass<'_> for BadOptAccess { } } -// some things i'm not sure about: -// * is Warn the right level? -// * the way i verify that the right method is being called (path + diag item check) - declare_tool_lint! { pub rustc::SPAN_USE_EQ_CTXT, - Warn, // is this the right level? + Allow, "Use of `==` with `Span::ctxt` rather than `Span::eq_ctxt`", report_in_external_macro: true } @@ -555,11 +551,7 @@ impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind { if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) { - cx.emit_spanned_lint( - SPAN_USE_EQ_CTXT, - expr.span, - SpanUseEqCtxtDiag { msg: "fail" }, - ); + cx.emit_spanned_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag); } } } @@ -567,13 +559,10 @@ impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match &expr.kind { - ExprKind::MethodCall(path, receiver, _, _) => { - path.ident.name.as_str() == "ctxt" - && cx - .typeck_results() - .type_dependent_def_id(receiver.hir_id) - .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::Span, did)) - } + ExprKind::MethodCall(..) => cx + .typeck_results() + .type_dependent_def_id(expr.hir_id) + .is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)), _ => false, } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a02bee506dfa..4eaf8bbf5ded 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -902,9 +902,7 @@ pub struct QueryInstability { #[derive(LintDiagnostic)] #[diag(lint_span_use_eq_ctxt)] -pub struct SpanUseEqCtxtDiag<'a> { - pub msg: &'a str, -} +pub struct SpanUseEqCtxtDiag; #[derive(LintDiagnostic)] #[diag(lint_tykind_kind)] diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 1d1be8f24927..f1a0f762041c 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -404,7 +404,7 @@ impl<'a> CoverageSpansGenerator<'a> { let Some(visible_macro) = curr.visible_macro(self.body_span) else { return }; if let Some(prev) = &self.some_prev - && prev.expn_span.ctxt() == curr.expn_span.ctxt() + && prev.expn_span.eq_ctxt(curr.expn_span) { return; } diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index 7c7f8448c978..f7d17a267d69 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -75,7 +75,6 @@ use rustc_data_structures::fx::FxIndexSet; /// the dependency to the parent definition's span. This is performed /// using the callback `SPAN_TRACK` to access the query engine. /// -#[cfg_attr(not(test), rustc_diagnostic_item = "Span")] #[derive(Clone, Copy, Eq, PartialEq, Hash)] #[rustc_pass_by_value] pub struct Span { @@ -213,6 +212,7 @@ impl Span { /// This function is used as a fast path when decoding the full `SpanData` is not necessary. /// It's a cut-down version of `data_untracked`. + #[cfg_attr(not(test), rustc_diagnostic_item = "SpanCtxt")] #[inline] pub fn ctxt(self) -> SyntaxContext { if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9598b2d0310a..be8c65862dc2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -303,7 +303,7 @@ symbols! { SliceIndex, SliceIter, Some, - Span, + SpanCtxt, String, StructuralEq, StructuralPartialEq, diff --git a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs index 5b4c59a2e8a0..39980ee7c672 100644 --- a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs +++ b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs @@ -1,13 +1,13 @@ +// Test the `rustc::span_use_eq_ctxt` internal lint // compile-flags: -Z unstable-options #![feature(rustc_private)] #![deny(rustc::span_use_eq_ctxt)] +#![crate_type = "lib"] extern crate rustc_span; use rustc_span::Span; pub fn f(s: Span, t: Span) -> bool { - s.ctxt() == t.ctxt() //~ ERROR use of span ctxt + s.ctxt() == t.ctxt() //~ ERROR use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` } - -fn main() {} diff --git a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr new file mode 100644 index 000000000000..b33f62125454 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr @@ -0,0 +1,14 @@ +error: use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` + --> $DIR/span_use_eq_ctxt.rs:12:5 + | +LL | s.ctxt() == t.ctxt() + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/span_use_eq_ctxt.rs:5:9 + | +LL | #![deny(rustc::span_use_eq_ctxt)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 52ad8199d502cdce296a2145cad2650795a2f3f6 Mon Sep 17 00:00:00 2001 From: Arthur Lafrance Date: Mon, 16 Oct 2023 01:17:52 -0700 Subject: [PATCH 41/94] tweak pass description and fix lint fail post-rebase --- compiler/rustc_lint/src/internal.rs | 2 +- compiler/rustc_passes/src/loops.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 34f241e8c8d2..2d86129c480c 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -541,7 +541,7 @@ impl LateLintPass<'_> for BadOptAccess { declare_tool_lint! { pub rustc::SPAN_USE_EQ_CTXT, Allow, - "Use of `==` with `Span::ctxt` rather than `Span::eq_ctxt`", + "forbid uses of `==` with `Span::ctxt`, suggest `Span::eq_ctxt` instead", report_in_external_macro: true } diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 4590ab9e4f57..25e131d7477f 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -231,7 +231,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { AsyncClosure(closure_span) => { self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name }); } - UnlabeledBlock(block_span) if is_break && block_span.ctxt() == break_span.ctxt() => { + UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => { let suggestion = Some(OutsideLoopSuggestion { block_span, break_span }); self.sess.emit_err(OutsideLoop { span, name, is_break, suggestion }); } From e89d4d4871d7ecd5f59136638250bca419628baa Mon Sep 17 00:00:00 2001 From: Arthur Lafrance Date: Mon, 16 Oct 2023 13:52:50 -0700 Subject: [PATCH 42/94] fix lint failures in clippy --- src/tools/clippy/clippy_lints/src/dereference.rs | 2 +- src/tools/clippy/clippy_lints/src/entry.rs | 2 +- src/tools/clippy/clippy_lints/src/formatting.rs | 2 +- src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs | 2 +- src/tools/clippy/clippy_lints/src/manual_let_else.rs | 2 +- .../clippy/clippy_lints/src/matches/collapsible_match.rs | 2 +- src/tools/clippy/clippy_lints/src/matches/manual_utils.rs | 4 ++-- src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs | 2 +- src/tools/clippy/clippy_lints/src/needless_question_mark.rs | 2 +- .../clippy/clippy_lints/src/non_octal_unix_permissions.rs | 4 ++-- src/tools/clippy/clippy_lints/src/redundant_async_block.rs | 2 +- src/tools/clippy/clippy_lints/src/reference.rs | 2 +- .../clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs | 2 +- src/tools/clippy/clippy_utils/src/macros.rs | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 14877385646a..5134cf66050c 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -701,7 +701,7 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool { fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { if let Some(parent) = get_parent_expr(cx, e) - && parent.span.ctxt() == e.span.ctxt() + && parent.span.eq_ctxt(e.span) { match parent.kind { ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _) diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index 6197b5b19eb4..70a467dde613 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -241,7 +241,7 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio }, ], _, - ) if key_span.ctxt() == expr.span.ctxt() => { + ) if key_span.eq_ctxt(expr.span) => { let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; let expr = ContainsExpr { negated, diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs index d03480c21084..4ebf0e9667df 100644 --- a/src/tools/clippy/clippy_lints/src/formatting.rs +++ b/src/tools/clippy/clippy_lints/src/formatting.rs @@ -274,7 +274,7 @@ fn check_array(cx: &EarlyContext<'_>, expr: &Expr) { for element in array { if_chain! { if let ExprKind::Binary(ref op, ref lhs, _) = element.kind; - if has_unary_equivalent(op.node) && lhs.span.ctxt() == op.span.ctxt(); + if has_unary_equivalent(op.node) && lhs.span.eq_ctxt(op.span); let space_span = lhs.span.between(op.span); if let Some(space_snippet) = snippet_opt(cx, space_span); let lint_span = lhs.span.with_lo(lhs.span.hi()); diff --git a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs index 4e9d77ea156a..79d728a021c3 100644 --- a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs @@ -31,7 +31,7 @@ impl LateLintPass<'_> for UnderscoreTyped { if !in_external_macro(cx.tcx.sess, local.span); if let Some(ty) = local.ty; // Ensure that it has a type defined if let TyKind::Infer = &ty.kind; // that type is '_' - if local.span.ctxt() == ty.span.ctxt(); + if local.span.eq_ctxt(ty.span); then { // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized, // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty` diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 2117308cd400..86bbdb4ea199 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -59,7 +59,7 @@ impl<'tcx> QuestionMark { let Some(init) = local.init && local.els.is_none() && local.ty.is_none() && - init.span.ctxt() == stmt.span.ctxt() && + init.span.eq_ctxt(stmt.span) && let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) { match if_let_or_match { diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs index 33a052c41a38..29b935fb61a8 100644 --- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs @@ -57,7 +57,7 @@ fn check_arm<'tcx>( } }, }; - if outer_pat.span.ctxt() == inner_scrutinee.span.ctxt(); + if outer_pat.span.eq_ctxt(inner_scrutinee.span); // match expression must be a local binding // match { .. } if let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee)); diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index 6b611f567ae2..781ee138c76f 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -119,7 +119,7 @@ where // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); - let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX { + let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_POSTFIX { format!("({scrutinee_str})") } else { scrutinee_str.into() @@ -130,7 +130,7 @@ where if_chain! { if !some_expr.needs_unsafe_block; if let Some(func) = can_pass_as_func(cx, id, some_expr.expr); - if func.span.ctxt() == some_expr.expr.span.ctxt(); + if func.span.eq_ctxt(some_expr.expr.span); then { snippet_with_applicability(cx, func.span, "..", &mut app).into_owned() } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs index 5464e455dea4..e70a1bc98799 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs @@ -56,7 +56,7 @@ pub(super) fn check<'tcx>( // lint, with note if neither arg is > 1 line and both map() and // unwrap_or_else() have the same span let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; - let same_span = map_arg.span.ctxt() == unwrap_arg.span.ctxt(); + let same_span = map_arg.span.eq_ctxt(unwrap_arg.span); if same_span && !multiline { let var_snippet = snippet(cx, recv.span, ".."); span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index 7b0f7eaf1f06..0e834fb3ac76 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -125,7 +125,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind; if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind; if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind; - if expr.span.ctxt() == inner_expr.span.ctxt(); + if expr.span.eq_ctxt(inner_expr.span); let expr_ty = cx.typeck_results().expr_ty(expr); let inner_ty = cx.typeck_results().expr_ty(inner_expr); if expr_ty == inner_ty; diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs index d47728f190ab..e94e45899660 100644 --- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs +++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs @@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions { || (path.ident.name == sym!(set_mode) && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did())); if let ExprKind::Lit(_) = param.kind; - if param.span.ctxt() == expr.span.ctxt(); + if param.span.eq_ctxt(expr.span); then { let Some(snip) = snippet_opt(cx, param.span) else { @@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions { if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE); if let ExprKind::Lit(_) = param.kind; - if param.span.ctxt() == expr.span.ctxt(); + if param.span.eq_ctxt(expr.span); if let Some(snip) = snippet_opt(cx, param.span); if !snip.starts_with("0o"); then { diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index 534b2762ba76..8193057a6eb2 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock { let Some(body_expr) = desugar_async_block(cx, expr) && let Some(expr) = desugar_await(peel_blocks(body_expr)) && // The await prefix must not come from a macro as its content could change in the future. - expr.span.ctxt() == body_expr.span.ctxt() && + expr.span.eq_ctxt(body_expr.span) && // An async block does not have immediate side-effects from a `.await` point-of-view. (!expr.can_have_side_effects() || desugar_async_block(cx, expr).is_some()) && let Some(shortened_span) = walk_span_to_context(expr.span, span.ctxt()) diff --git a/src/tools/clippy/clippy_lints/src/reference.rs b/src/tools/clippy/clippy_lints/src/reference.rs index db870ec4c5b6..12da29f11089 100644 --- a/src/tools/clippy/clippy_lints/src/reference.rs +++ b/src/tools/clippy/clippy_lints/src/reference.rs @@ -50,7 +50,7 @@ impl EarlyLintPass for DerefAddrOf { if_chain! { if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind; if let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind; - if deref_target.span.ctxt() == e.span.ctxt(); + if deref_target.span.eq_ctxt(e.span); if !addrof_target.span.from_expansion(); then { let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs index 8e156b8829b9..39cd289b67ad 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs @@ -33,7 +33,7 @@ impl LateLintPass<'_> for ConfusingXorAndPow { if !in_external_macro(cx.sess(), expr.span) && let ExprKind::Binary(op, left, right) = &expr.kind && op.node == BinOpKind::BitXor - && left.span.ctxt() == right.span.ctxt() + && left.span.eq_ctxt(right.span) && let ExprKind::Lit(lit_left) = &left.kind && let ExprKind::Lit(lit_right) = &right.kind && matches!(lit_right.node, LitKind::Int(..) | LitKind::Float(..)) diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs index eaf590f6ad77..46ce4ffdce5d 100644 --- a/src/tools/clippy/clippy_utils/src/macros.rs +++ b/src/tools/clippy/clippy_utils/src/macros.rs @@ -245,7 +245,7 @@ impl<'a> PanicExpn<'a> { return None; }; let result = match name { - "panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty, + "panic" if arg.span.eq_ctxt(expr.span) => Self::Empty, "panic" | "panic_str" => Self::Str(arg), "panic_display" | "panic_cold_display" => { let ExprKind::AddrOf(_, _, e) = &arg.kind else { From 4175c9b59546b78d7bab2d17a5e8c87fc633b4a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 16 Oct 2023 17:08:14 +1100 Subject: [PATCH 43/94] Remove unused features from `rustc_data_structures`. --- compiler/rustc_data_structures/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 461ec3a90ed9..1d1a5b4d5ee4 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -8,7 +8,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] -#![feature(associated_type_bounds)] #![feature(auto_traits)] #![feature(cell_leak)] #![feature(core_intrinsics)] @@ -25,7 +24,6 @@ #![feature(negative_impls)] #![feature(test)] #![feature(thread_id_value)] -#![feature(vec_into_raw_parts)] #![feature(allocator_api)] #![feature(get_mut_unchecked)] #![feature(lint_reasons)] From 847c8ba70df6fd5772ad7e7f0df8cc3617812ea3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 16 Oct 2023 16:50:25 +1100 Subject: [PATCH 44/94] Remove `IdFunctor` trait. It's defined in `rustc_data_structures` but is only used in `rustc_type_ir`. The code is shorter and easier to read if we remove this layer of abstraction and just do the things directly where they are needed. --- compiler/rustc_data_structures/src/functor.rs | 116 ------------------ compiler/rustc_data_structures/src/lib.rs | 3 - compiler/rustc_type_ir/src/lib.rs | 2 + .../rustc_type_ir/src/structural_impls.rs | 52 +++++++- 4 files changed, 48 insertions(+), 125 deletions(-) delete mode 100644 compiler/rustc_data_structures/src/functor.rs diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs deleted file mode 100644 index e3fcaccb1bd5..000000000000 --- a/compiler/rustc_data_structures/src/functor.rs +++ /dev/null @@ -1,116 +0,0 @@ -use rustc_index::{Idx, IndexVec}; -use std::{mem, rc::Rc, sync::Arc}; - -pub trait IdFunctor: Sized { - type Inner; - - fn try_map_id(self, f: F) -> Result - where - F: FnMut(Self::Inner) -> Result; -} - -impl IdFunctor for Box { - type Inner = T; - - #[inline] - fn try_map_id(self, mut f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - let raw = Box::into_raw(self); - Ok(unsafe { - // SAFETY: The raw pointer points to a valid value of type `T`. - let value = raw.read(); - // SAFETY: Converts `Box` to `Box>` which is the - // inverse of `Box::assume_init()` and should be safe. - let raw: Box> = Box::from_raw(raw.cast()); - // SAFETY: Write the mapped value back into the `Box`. - Box::write(raw, f(value)?) - }) - } -} - -impl IdFunctor for Vec { - type Inner = T; - - #[inline] - fn try_map_id(self, f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - self.into_iter().map(f).collect() - } -} - -impl IdFunctor for Box<[T]> { - type Inner = T; - - #[inline] - fn try_map_id(self, f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - Vec::from(self).try_map_id(f).map(Into::into) - } -} - -impl IdFunctor for IndexVec { - type Inner = T; - - #[inline] - fn try_map_id(self, f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - self.raw.try_map_id(f).map(IndexVec::from_raw) - } -} - -macro_rules! rc { - ($($rc:ident),+) => {$( - impl IdFunctor for $rc { - type Inner = T; - - #[inline] - fn try_map_id(mut self, mut f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - // We merely want to replace the contained `T`, if at all possible, - // so that we don't needlessly allocate a new `$rc` or indeed clone - // the contained type. - unsafe { - // First step is to ensure that we have a unique reference to - // the contained type, which `$rc::make_mut` will accomplish (by - // allocating a new `$rc` and cloning the `T` only if required). - // This is done *before* casting to `$rc>` so that - // panicking during `make_mut` does not leak the `T`. - $rc::make_mut(&mut self); - - // Casting to `$rc>` is safe because `ManuallyDrop` - // is `repr(transparent)`. - let ptr = $rc::into_raw(self).cast::>(); - let mut unique = $rc::from_raw(ptr); - - // Call to `$rc::make_mut` above guarantees that `unique` is the - // sole reference to the contained value, so we can avoid doing - // a checked `get_mut` here. - let slot = $rc::get_mut_unchecked(&mut unique); - - // Semantically move the contained type out from `unique`, fold - // it, then move the folded value back into `unique`. Should - // folding fail, `ManuallyDrop` ensures that the "moved-out" - // value is not re-dropped. - let owned = mem::ManuallyDrop::take(slot); - let folded = f(owned)?; - *slot = mem::ManuallyDrop::new(folded); - - // Cast back to `$rc`. - Ok($rc::from_raw($rc::into_raw(unique).cast())) - } - } - } - )+}; -} - -rc! { Rc, Arc } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 1d1a5b4d5ee4..4dd4ade4e6be 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -18,14 +18,12 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(type_alias_impl_trait)] -#![feature(new_uninit)] #![feature(lazy_cell)] #![feature(rustc_attrs)] #![feature(negative_impls)] #![feature(test)] #![feature(thread_id_value)] #![feature(allocator_api)] -#![feature(get_mut_unchecked)] #![feature(lint_reasons)] #![feature(unwrap_infallible)] #![feature(strict_provenance)] @@ -61,7 +59,6 @@ pub mod binary_search_util; pub mod captures; pub mod flat_map_in_place; pub mod flock; -pub mod functor; pub mod fx; pub mod graph; pub mod intern; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 5df068de1f84..9f8d9f02ec24 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,7 +1,9 @@ #![feature(associated_type_defaults)] #![feature(fmt_helpers_for_derive)] +#![feature(get_mut_unchecked)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(new_uninit)] #![feature(rustc_attrs)] #![feature(unwrap_infallible)] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index f1037fe0bafa..18ff33f6997f 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -5,12 +5,12 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; use crate::{ConstKind, FloatTy, InferTy, IntTy, Interner, UintTy, UniverseIndex}; -use rustc_data_structures::functor::IdFunctor; use rustc_data_structures::sync::Lrc; use rustc_index::{Idx, IndexVec}; use core::fmt; use std::marker::PhantomData; +use std::mem; use std::ops::ControlFlow; /////////////////////////////////////////////////////////////////////////// @@ -108,8 +108,39 @@ impl, E: TypeVisitable> TypeVisitable for } impl> TypeFoldable for Lrc { - fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|value| value.try_fold_with(folder)) + fn try_fold_with>(mut self, folder: &mut F) -> Result { + // We merely want to replace the contained `T`, if at all possible, + // so that we don't needlessly allocate a new `Lrc` or indeed clone + // the contained type. + unsafe { + // First step is to ensure that we have a unique reference to + // the contained type, which `Lrc::make_mut` will accomplish (by + // allocating a new `Lrc` and cloning the `T` only if required). + // This is done *before* casting to `Lrc>` so that + // panicking during `make_mut` does not leak the `T`. + Lrc::make_mut(&mut self); + + // Casting to `Lrc>` is safe because `ManuallyDrop` + // is `repr(transparent)`. + let ptr = Lrc::into_raw(self).cast::>(); + let mut unique = Lrc::from_raw(ptr); + + // Call to `Lrc::make_mut` above guarantees that `unique` is the + // sole reference to the contained value, so we can avoid doing + // a checked `get_mut` here. + let slot = Lrc::get_mut_unchecked(&mut unique); + + // Semantically move the contained type out from `unique`, fold + // it, then move the folded value back into `unique`. Should + // folding fail, `ManuallyDrop` ensures that the "moved-out" + // value is not re-dropped. + let owned = mem::ManuallyDrop::take(slot); + let folded = owned.try_fold_with(folder)?; + *slot = mem::ManuallyDrop::new(folded); + + // Cast back to `Lrc`. + Ok(Lrc::from_raw(Lrc::into_raw(unique).cast())) + } } } @@ -121,7 +152,16 @@ impl> TypeVisitable for Lrc { impl> TypeFoldable for Box { fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|value| value.try_fold_with(folder)) + let raw = Box::into_raw(self); + Ok(unsafe { + // SAFETY: The raw pointer points to a valid value of type `T`. + let value = raw.read(); + // SAFETY: Converts `Box` to `Box>` which is the + // inverse of `Box::assume_init()` and should be safe. + let raw: Box> = Box::from_raw(raw.cast()); + // SAFETY: Write the mapped value back into the `Box`. + Box::write(raw, value.try_fold_with(folder)?) + }) } } @@ -133,7 +173,7 @@ impl> TypeVisitable for Box { impl> TypeFoldable for Vec { fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|t| t.try_fold_with(folder)) + self.into_iter().map(|t| t.try_fold_with(folder)).collect() } } @@ -161,7 +201,7 @@ impl> TypeVisitable for Box<[T]> { impl, Ix: Idx> TypeFoldable for IndexVec { fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|x| x.try_fold_with(folder)) + self.raw.try_fold_with(folder).map(IndexVec::from_raw) } } From 178ba0e85cc07995d9ac420875995efa26585b59 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 17 Oct 2023 13:44:25 +1100 Subject: [PATCH 45/94] Rewrite `Box::try_fold_with`. It can be written more simply, without needing `unsafe`. --- compiler/rustc_type_ir/src/structural_impls.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 18ff33f6997f..08af96ea15f0 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -151,17 +151,9 @@ impl> TypeVisitable for Lrc { } impl> TypeFoldable for Box { - fn try_fold_with>(self, folder: &mut F) -> Result { - let raw = Box::into_raw(self); - Ok(unsafe { - // SAFETY: The raw pointer points to a valid value of type `T`. - let value = raw.read(); - // SAFETY: Converts `Box` to `Box>` which is the - // inverse of `Box::assume_init()` and should be safe. - let raw: Box> = Box::from_raw(raw.cast()); - // SAFETY: Write the mapped value back into the `Box`. - Box::write(raw, value.try_fold_with(folder)?) - }) + fn try_fold_with>(mut self, folder: &mut F) -> Result { + *self = (*self).try_fold_with(folder)?; + Ok(self) } } From e494df436df105f8a3d767dfcd8e51c597c0fca5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 17 Oct 2023 07:56:49 +0200 Subject: [PATCH 46/94] remove 128bit atomics, they are anyway not exposed on those targets --- library/core/src/sync/atomic.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 5a429826c0d4..073488817c48 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -103,8 +103,7 @@ //! | `target_arch` | Size limit | //! |---------------|---------| //! | `x86`, `arm`, `mips`, `mips32r6, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes | -//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64` | 8 bytes | -//! | `s390x`, `powerpc64` with `target_feature = "quadword-atomics"` | 16 bytes | +//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64`, `s390x` | 8 bytes | //! //! Atomics loads that are larger than this limit as well as atomic loads with ordering other //! than `Relaxed`, as well as *all* atomic loads on targets not listed in the table, might still be From acef1c2c576c778e7a3c8e249298eb10450ae7e8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 7 Oct 2023 23:33:27 +0300 Subject: [PATCH 47/94] reorganize bootstrap bins and helper module utilizations Signed-off-by: onur-ozkan --- src/bootstrap/bin/_helper.rs | 25 ------------------- src/bootstrap/{ => src}/bin/main.rs | 0 src/bootstrap/{ => src}/bin/rustc.rs | 15 +++++++---- src/bootstrap/{ => src}/bin/rustdoc.rs | 14 +++++++---- .../{ => src}/bin/sccache-plus-cl.rs | 0 5 files changed, 19 insertions(+), 35 deletions(-) delete mode 100644 src/bootstrap/bin/_helper.rs rename src/bootstrap/{ => src}/bin/main.rs (100%) rename src/bootstrap/{ => src}/bin/rustc.rs (98%) rename src/bootstrap/{ => src}/bin/rustdoc.rs (90%) rename src/bootstrap/{ => src}/bin/sccache-plus-cl.rs (100%) diff --git a/src/bootstrap/bin/_helper.rs b/src/bootstrap/bin/_helper.rs deleted file mode 100644 index 46c574c5bf45..000000000000 --- a/src/bootstrap/bin/_helper.rs +++ /dev/null @@ -1,25 +0,0 @@ -/// Parses the value of the "RUSTC_VERBOSE" environment variable and returns it as a `usize`. -/// If it was not defined, returns 0 by default. -/// -/// Panics if "RUSTC_VERBOSE" is defined with the value that is not an unsigned integer. -fn parse_rustc_verbose() -> usize { - use std::str::FromStr; - - match std::env::var("RUSTC_VERBOSE") { - Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"), - Err(_) => 0, - } -} - -/// Parses the value of the "RUSTC_STAGE" environment variable and returns it as a `String`. -/// -/// If "RUSTC_STAGE" was not set, the program will be terminated with 101. -#[allow(unused)] -fn parse_rustc_stage() -> String { - std::env::var("RUSTC_STAGE").unwrap_or_else(|_| { - // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead. - eprintln!("rustc shim: fatal: RUSTC_STAGE was not set"); - eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap"); - exit(101); - }) -} diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/src/bin/main.rs similarity index 100% rename from src/bootstrap/bin/main.rs rename to src/bootstrap/src/bin/main.rs diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs similarity index 98% rename from src/bootstrap/bin/rustc.rs rename to src/bootstrap/src/bin/rustc.rs index 6cc5162120a9..b050713265bf 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -15,19 +15,24 @@ //! switching compilers for the bootstrap and for build scripts will probably //! never get replaced. -include!("../dylib_util.rs"); -include!("./_helper.rs"); - use std::env; use std::path::PathBuf; -use std::process::{exit, Child, Command}; +use std::process::{Child, Command}; use std::time::Instant; +use dylib_util::{dylib_path, dylib_path_var}; + +#[path = "../utils/bin_helpers.rs"] +mod bin_helpers; + +#[path = "../utils/dylib_util.rs"] +mod dylib_util; + fn main() { let args = env::args_os().skip(1).collect::>(); let arg = |name| args.windows(2).find(|args| args[0] == name).and_then(|args| args[1].to_str()); - let verbose = parse_rustc_verbose(); + let verbose = bin_helpers::parse_rustc_verbose(); // Detect whether or not we're a build script depending on whether --target // is passed (a bit janky...) diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/src/bin/rustdoc.rs similarity index 90% rename from src/bootstrap/bin/rustdoc.rs rename to src/bootstrap/src/bin/rustdoc.rs index 6561c1c1933c..85d685475b40 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/src/bin/rustdoc.rs @@ -5,17 +5,21 @@ use std::env; use std::ffi::OsString; use std::path::PathBuf; -use std::process::{exit, Command}; +use std::process::Command; -include!("../dylib_util.rs"); +use dylib_util::{dylib_path, dylib_path_var}; -include!("./_helper.rs"); +#[path = "../utils/bin_helpers.rs"] +mod bin_helpers; + +#[path = "../utils/dylib_util.rs"] +mod dylib_util; fn main() { let args = env::args_os().skip(1).collect::>(); - let stage = parse_rustc_stage(); - let verbose = parse_rustc_verbose(); + let stage = bin_helpers::parse_rustc_stage(); + let verbose = bin_helpers::parse_rustc_verbose(); let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set"); let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set"); diff --git a/src/bootstrap/bin/sccache-plus-cl.rs b/src/bootstrap/src/bin/sccache-plus-cl.rs similarity index 100% rename from src/bootstrap/bin/sccache-plus-cl.rs rename to src/bootstrap/src/bin/sccache-plus-cl.rs From c68ab9347ee7d9bf8c93dfb444b9ec5ec0ccc43f Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 7 Oct 2023 23:35:02 +0300 Subject: [PATCH 48/94] improve bootstrap tests structure Signed-off-by: onur-ozkan --- .../{builder/tests.rs => src/tests/builder.rs} | 10 +++++----- src/bootstrap/{config/tests.rs => src/tests/config.rs} | 10 +++++----- src/bootstrap/{setup/tests.rs => src/tests/setup.rs} | 0 3 files changed, 10 insertions(+), 10 deletions(-) rename src/bootstrap/{builder/tests.rs => src/tests/builder.rs} (99%) rename src/bootstrap/{config/tests.rs => src/tests/config.rs} (97%) rename src/bootstrap/{setup/tests.rs => src/tests/setup.rs} (100%) diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/src/tests/builder.rs similarity index 99% rename from src/bootstrap/builder/tests.rs rename to src/bootstrap/src/tests/builder.rs index 0294102286e9..96139f7b099c 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/src/tests/builder.rs @@ -1,6 +1,6 @@ use super::*; -use crate::config::{Config, DryRun, TargetSelection}; -use crate::doc::DocumentationFormat; +use crate::core::config::{Config, DryRun, TargetSelection}; +use crate::core::build_steps::doc::DocumentationFormat; use std::thread; fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config { @@ -158,7 +158,7 @@ fn alias_and_path_for_library() { #[test] fn test_beta_rev_parsing() { - use crate::extract_beta_rev; + use crate::utils::helpers::extract_beta_rev; // single digit revision assert_eq!(extract_beta_rev("1.99.9-beta.7 (xxxxxx)"), Some("7".to_string())); @@ -174,7 +174,7 @@ fn test_beta_rev_parsing() { mod defaults { use super::{configure, first, run_build}; - use crate::builder::*; + use crate::core::builder::*; use crate::Config; use pretty_assertions::assert_eq; @@ -285,7 +285,7 @@ mod defaults { mod dist { use super::{first, run_build, Config}; - use crate::builder::*; + use crate::core::builder::*; use pretty_assertions::assert_eq; fn configure(host: &[&str], target: &[&str]) -> Config { diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/src/tests/config.rs similarity index 97% rename from src/bootstrap/config/tests.rs rename to src/bootstrap/src/tests/config.rs index ae8363b6de9c..59bd52a94dc8 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/src/tests/config.rs @@ -1,6 +1,6 @@ -use crate::config::TomlConfig; - +use crate::core::config::TomlConfig; use super::{Config, Flags}; + use clap::CommandFactory; use serde::Deserialize; use std::{ @@ -18,7 +18,7 @@ fn parse(config: &str) -> Config { #[test] fn download_ci_llvm() { - if crate::llvm::is_ci_llvm_modified(&parse("")) { + if crate::core::build_steps::llvm::is_ci_llvm_modified(&parse("")) { eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change"); return; } @@ -137,7 +137,7 @@ build-config = {} assert_eq!(config.change_id, Some(1), "setting top-level value"); assert_eq!( config.rust_lto, - crate::config::RustcLto::Fat, + crate::core::config::RustcLto::Fat, "setting string value without quotes" ); assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes"); @@ -175,7 +175,7 @@ fn profile_user_dist() { "profile = \"user\"".to_owned() } else { assert!(file.ends_with("config.dist.toml")); - std::fs::read_to_string(dbg!(file)).unwrap() + std::fs::read_to_string(file).unwrap() }; toml::from_str(&contents) .and_then(|table: toml::Value| TomlConfig::deserialize(table)) diff --git a/src/bootstrap/setup/tests.rs b/src/bootstrap/src/tests/setup.rs similarity index 100% rename from src/bootstrap/setup/tests.rs rename to src/bootstrap/src/tests/setup.rs From 2bce0207d4b16393937b268ce7676c6b83813867 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 7 Oct 2023 23:37:06 +0300 Subject: [PATCH 49/94] move bootstrap core implementation to bootstrap/src/core module Signed-off-by: onur-ozkan --- .../{ => src/core/build_steps}/check.rs | 22 +- .../{ => src/core/build_steps}/clean.rs | 6 +- .../{ => src/core/build_steps}/compile.rs | 28 +- .../{ => src/core/build_steps}/dist.rs | 30 +- .../{ => src/core/build_steps}/doc.rs | 14 +- .../{ => src/core/build_steps}/format.rs | 4 +- .../{ => src/core/build_steps}/install.rs | 12 +- .../{ => src/core/build_steps}/llvm.rs | 27 +- src/bootstrap/src/core/build_steps/mod.rs | 15 + .../{ => src/core/build_steps}/run.rs | 16 +- .../{ => src/core/build_steps}/setup.rs | 5 +- .../{ => src/core/build_steps}/suggest.rs | 11 +- .../core/build_steps}/synthetic_targets.rs | 6 +- .../{ => src/core/build_steps}/test.rs | 106 ++-- .../{ => src/core/build_steps}/tool.rs | 12 +- .../{ => src/core/build_steps}/toolstate.rs | 4 +- src/bootstrap/{ => src/core}/builder.rs | 38 +- src/bootstrap/{ => src/core/config}/config.rs | 29 +- src/bootstrap/src/core/config/flags.rs | 565 ++++++++++++++++++ src/bootstrap/src/core/config/mod.rs | 4 + src/bootstrap/{ => src/core}/download.rs | 11 +- src/bootstrap/{ => src/core}/metadata.rs | 4 +- src/bootstrap/src/core/mod.rs | 6 + src/bootstrap/{ => src/core}/sanity.rs | 6 +- 24 files changed, 792 insertions(+), 189 deletions(-) rename src/bootstrap/{ => src/core/build_steps}/check.rs (96%) rename src/bootstrap/{ => src/core/build_steps}/clean.rs (98%) rename src/bootstrap/{ => src/core/build_steps}/compile.rs (98%) rename src/bootstrap/{ => src/core/build_steps}/dist.rs (98%) rename src/bootstrap/{ => src/core/build_steps}/doc.rs (98%) rename src/bootstrap/{ => src/core/build_steps}/format.rs (99%) rename src/bootstrap/{ => src/core/build_steps}/install.rs (98%) rename src/bootstrap/{ => src/core/build_steps}/llvm.rs (98%) create mode 100644 src/bootstrap/src/core/build_steps/mod.rs rename src/bootstrap/{ => src/core/build_steps}/run.rs (96%) rename src/bootstrap/{ => src/core/build_steps}/setup.rs (99%) rename src/bootstrap/{ => src/core/build_steps}/suggest.rs (93%) rename src/bootstrap/{ => src/core/build_steps}/synthetic_targets.rs (95%) rename src/bootstrap/{ => src/core/build_steps}/test.rs (97%) rename src/bootstrap/{ => src/core/build_steps}/tool.rs (99%) rename src/bootstrap/{ => src/core/build_steps}/toolstate.rs (99%) rename src/bootstrap/{ => src/core}/builder.rs (99%) rename src/bootstrap/{ => src/core/config}/config.rs (98%) create mode 100644 src/bootstrap/src/core/config/flags.rs create mode 100644 src/bootstrap/src/core/config/mod.rs rename src/bootstrap/{ => src/core}/download.rs (99%) rename src/bootstrap/{ => src/core}/metadata.rs (98%) create mode 100644 src/bootstrap/src/core/mod.rs rename src/bootstrap/{ => src/core}/sanity.rs (98%) diff --git a/src/bootstrap/check.rs b/src/bootstrap/src/core/build_steps/check.rs similarity index 96% rename from src/bootstrap/check.rs rename to src/bootstrap/src/core/build_steps/check.rs index b417abc00f5b..121925b56a05 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -1,10 +1,12 @@ //! Implementation of compiling the compiler and standard library, in "check"-based modes. -use crate::builder::{crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; -use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo}; -use crate::config::TargetSelection; -use crate::tool::{prepare_tool_cargo, SourceType}; +use crate::core::build_steps::compile::{ + add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, +}; +use crate::core::build_steps::tool::{prepare_tool_cargo, SourceType}; +use crate::core::builder::{crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step}; +use crate::core::config::TargetSelection; +use crate::utils::cache::Interned; use crate::INTERNER; use crate::{Compiler, Mode, Subcommand}; use std::path::{Path, PathBuf}; @@ -16,7 +18,7 @@ pub struct Std { /// /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`]. /// - /// [`compile::Rustc`]: crate::compile::Rustc + /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc crates: Interned>, } @@ -193,7 +195,7 @@ pub struct Rustc { /// /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`]. /// - /// [`compile::Rustc`]: crate::compile::Rustc + /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc crates: Interned>, } @@ -237,8 +239,8 @@ impl Step for Rustc { // the sysroot for the compiler to find. Otherwise, we're going to // fail when building crates that need to generate code (e.g., build // scripts and their dependencies). - builder.ensure(crate::compile::Std::new(compiler, compiler.host)); - builder.ensure(crate::compile::Std::new(compiler, target)); + builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host)); + builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target)); } else { builder.ensure(Std::new(target)); } @@ -387,7 +389,7 @@ impl Step for RustAnalyzer { &["rust-analyzer/in-rust-tree".to_owned()], ); - cargo.allow_features(crate::tool::RustAnalyzer::ALLOW_FEATURES); + cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES); // For ./x.py clippy, don't check those targets because // linting tests and benchmarks can produce very noisy results diff --git a/src/bootstrap/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs similarity index 98% rename from src/bootstrap/clean.rs rename to src/bootstrap/src/core/build_steps/clean.rs index 7389816b44c7..679770ce0ec7 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -9,9 +9,9 @@ use std::fs; use std::io::{self, ErrorKind}; use std::path::Path; -use crate::builder::{crate_description, Builder, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; -use crate::util::t; +use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step}; +use crate::utils::cache::Interned; +use crate::utils::helpers::t; use crate::{Build, Compiler, Mode, Subcommand}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs similarity index 98% rename from src/bootstrap/compile.rs rename to src/bootstrap/src/core/build_steps/compile.rs index 623fa5fa111a..441931e415cc 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -19,16 +19,17 @@ use std::str; use serde_derive::Deserialize; -use crate::builder::crate_description; -use crate::builder::Cargo; -use crate::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; -use crate::cache::{Interned, INTERNER}; -use crate::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; -use crate::dist; -use crate::llvm; -use crate::tool::SourceType; -use crate::util::get_clang_cl_resource_dir; -use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date}; +use crate::core::build_steps::dist; +use crate::core::build_steps::llvm; +use crate::core::build_steps::tool::SourceType; +use crate::core::builder::crate_description; +use crate::core::builder::Cargo; +use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; +use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::helpers::{ + exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date, +}; use crate::LLVM_TOOLS; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; use filetime::FileTime; @@ -510,7 +511,7 @@ impl Step for StdLink { let (libdir, hostdir) = if self.force_recompile && builder.download_rustc() { // NOTE: copies part of `sysroot_libdir` to avoid having to add a new `force_recompile` argument there too let lib = builder.sysroot_libdir_relative(self.compiler); - let sysroot = builder.ensure(crate::compile::Sysroot { + let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot { compiler: self.compiler, force_recompile: self.force_recompile, }); @@ -1016,7 +1017,8 @@ pub fn rustc_cargo_env( // detected that LLVM is already built and good to go which helps prevent // busting caches (e.g. like #71152). if builder.config.llvm_enabled() { - let building_is_expensive = crate::llvm::prebuilt_llvm_config(builder, target).is_err(); + let building_is_expensive = + crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target).is_err(); // `top_stage == stage` might be false for `check --stage 1`, if we are building the stage 1 compiler let can_skip_build = builder.kind == Kind::Check && builder.top_stage == stage; let should_skip_build = building_is_expensive && can_skip_build; @@ -1684,7 +1686,7 @@ impl Step for Assemble { builder.copy(&lld_install.join("bin").join(&src_exe), &libdir_bin.join(&dst_exe)); let self_contained_lld_dir = libdir_bin.join("gcc-ld"); t!(fs::create_dir(&self_contained_lld_dir)); - let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper { + let lld_wrapper_exe = builder.ensure(crate::core::build_steps::tool::LldWrapper { compiler: build_compiler, target: target_compiler.host, }); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs similarity index 98% rename from src/bootstrap/dist.rs rename to src/bootstrap/src/core/build_steps/dist.rs index 7bb59e5a611e..47f41ab288d5 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -19,16 +19,16 @@ use std::process::Command; use object::read::archive::ArchiveFile; use object::BinaryFormat; -use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; -use crate::cache::{Interned, INTERNER}; -use crate::channel; -use crate::compile; -use crate::config::TargetSelection; -use crate::doc::DocumentationFormat; -use crate::llvm; -use crate::tarball::{GeneratedTarball, OverlayKind, Tarball}; -use crate::tool::{self, Tool}; -use crate::util::{exe, is_dylib, output, t, timeit}; +use crate::core::build_steps::compile; +use crate::core::build_steps::doc::DocumentationFormat; +use crate::core::build_steps::llvm; +use crate::core::build_steps::tool::{self, Tool}; +use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; +use crate::core::config::TargetSelection; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::channel; +use crate::utils::helpers::{exe, is_dylib, output, t, timeit}; +use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball}; use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS}; pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { @@ -104,7 +104,7 @@ impl Step for JsonDocs { /// Builds the `rust-docs-json` installer component. fn run(self, builder: &Builder<'_>) -> Option { let host = self.host; - builder.ensure(crate::doc::Std::new( + builder.ensure(crate::core::build_steps::doc::Std::new( builder.top_stage, host, builder, @@ -488,7 +488,7 @@ impl Step for Rustc { let man_src = builder.src.join("src/doc/man"); let man_dst = image.join("share/man/man1"); - // don't use our `bootstrap::util::{copy, cp_r}`, because those try + // don't use our `bootstrap::{copy, cp_r}`, because those try // to hardlink, and we don't want to edit the source templates for file_entry in builder.read_dir(&man_src) { let page_src = file_entry.path(); @@ -2060,7 +2060,7 @@ impl Step for LlvmTools { } } - builder.ensure(crate::llvm::Llvm { target }); + builder.ensure(crate::core::build_steps::llvm::Llvm { target }); let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple); tarball.set_overlay(OverlayKind::LLVM); @@ -2119,10 +2119,10 @@ impl Step for RustDev { let mut tarball = Tarball::new(builder, "rust-dev", &target.triple); tarball.set_overlay(OverlayKind::LLVM); - builder.ensure(crate::llvm::Llvm { target }); + builder.ensure(crate::core::build_steps::llvm::Llvm { target }); // We want to package `lld` to use it with `download-ci-llvm`. - builder.ensure(crate::llvm::Lld { target }); + builder.ensure(crate::core::build_steps::llvm::Lld { target }); let src_bindir = builder.llvm_out(target).join("bin"); // If updating this list, you likely want to change diff --git a/src/bootstrap/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs similarity index 98% rename from src/bootstrap/doc.rs rename to src/bootstrap/src/core/build_steps/doc.rs index 505f06ed12d7..628a4ece8e90 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -10,13 +10,13 @@ use std::fs; use std::path::{Path, PathBuf}; -use crate::builder::crate_description; -use crate::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; -use crate::cache::{Interned, INTERNER}; -use crate::compile; -use crate::config::{Config, TargetSelection}; -use crate::tool::{self, prepare_tool_cargo, SourceType, Tool}; -use crate::util::{dir_is_empty, symlink_dir, t, up_to_date}; +use crate::core::build_steps::compile; +use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool}; +use crate::core::builder::crate_description; +use crate::core::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; +use crate::core::config::{Config, TargetSelection}; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::helpers::{dir_is_empty, symlink_dir, t, up_to_date}; use crate::Mode; macro_rules! submodule_helper { diff --git a/src/bootstrap/format.rs b/src/bootstrap/src/core/build_steps/format.rs similarity index 99% rename from src/bootstrap/format.rs rename to src/bootstrap/src/core/build_steps/format.rs index 11f2762f7666..0e260e69c85a 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -1,7 +1,7 @@ //! Runs rustfmt on the repository. -use crate::builder::Builder; -use crate::util::{output, program_out_of_date, t}; +use crate::core::builder::Builder; +use crate::utils::helpers::{output, program_out_of_date, t}; use build_helper::ci::CiEnv; use build_helper::git::get_git_modified_files; use ignore::WalkBuilder; diff --git a/src/bootstrap/install.rs b/src/bootstrap/src/core/build_steps/install.rs similarity index 98% rename from src/bootstrap/install.rs rename to src/bootstrap/src/core/build_steps/install.rs index 885b3a782367..391995b7c3b8 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -8,15 +8,13 @@ use std::fs; use std::path::{Component, Path, PathBuf}; use std::process::Command; -use crate::util::t; - -use crate::dist; -use crate::tarball::GeneratedTarball; +use crate::core::build_steps::dist; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::config::{Config, TargetSelection}; +use crate::utils::helpers::t; +use crate::utils::tarball::GeneratedTarball; use crate::{Compiler, Kind}; -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::config::{Config, TargetSelection}; - #[cfg(target_os = "illumos")] const SHELL: &str = "bash"; #[cfg(not(target_os = "illumos"))] diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs similarity index 98% rename from src/bootstrap/llvm.rs rename to src/bootstrap/src/core/build_steps/llvm.rs index 4556831589bd..24351118a5aa 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -16,11 +16,10 @@ use std::io; use std::path::{Path, PathBuf}; use std::process::Command; -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::channel; -use crate::config::{Config, TargetSelection}; -use crate::util::get_clang_cl_resource_dir; -use crate::util::{self, exe, output, t, up_to_date}; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::config::{Config, TargetSelection}; +use crate::utils::channel; +use crate::utils::helpers::{self, exe, get_clang_cl_resource_dir, output, t, up_to_date}; use crate::{CLang, GitRepo, Kind}; use build_helper::ci::CiEnv; @@ -281,7 +280,7 @@ impl Step for Llvm { let _guard = builder.msg_unstaged(Kind::Build, "LLVM", target); t!(stamp.remove()); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); t!(fs::create_dir_all(&out_dir)); // https://llvm.org/docs/CMake.html @@ -410,7 +409,7 @@ impl Step for Llvm { let mut enabled_llvm_projects = Vec::new(); - if util::forcing_clang_based_tests() { + if helpers::forcing_clang_based_tests() { enabled_llvm_projects.push("clang"); enabled_llvm_projects.push("compiler-rt"); } @@ -528,8 +527,12 @@ impl Step for Llvm { // If the shared library exists in LLVM's `/build/lib/` or `/lib/` folders, strip its // debuginfo. - crate::compile::strip_debug(builder, target, &out_dir.join("lib").join(&lib_name)); - crate::compile::strip_debug( + crate::core::build_steps::compile::strip_debug( + builder, + target, + &out_dir.join("lib").join(&lib_name), + ); + crate::core::build_steps::compile::strip_debug( builder, target, &out_dir.join("build").join("lib").join(&lib_name), @@ -846,7 +849,7 @@ impl Step for Lld { } let _guard = builder.msg_unstaged(Kind::Build, "LLD", target); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); t!(fs::create_dir_all(&out_dir)); let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/lld")); @@ -877,7 +880,7 @@ impl Step for Lld { // `LD_LIBRARY_PATH` overrides) // if builder.config.rpath_enabled(target) - && util::use_host_linker(target) + && helpers::use_host_linker(target) && builder.config.llvm_link_shared() && target.contains("linux") { @@ -970,7 +973,7 @@ impl Step for Sanitizers { let _guard = builder.msg_unstaged(Kind::Build, "sanitizers", self.target); t!(stamp.remove()); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let mut cfg = cmake::Config::new(&compiler_rt_dir); cfg.profile("Release"); diff --git a/src/bootstrap/src/core/build_steps/mod.rs b/src/bootstrap/src/core/build_steps/mod.rs new file mode 100644 index 000000000000..50d83789be82 --- /dev/null +++ b/src/bootstrap/src/core/build_steps/mod.rs @@ -0,0 +1,15 @@ +pub(crate) mod check; +pub(crate) mod clean; +pub(crate) mod compile; +pub(crate) mod dist; +pub(crate) mod doc; +pub(crate) mod format; +pub(crate) mod install; +pub(crate) mod llvm; +pub(crate) mod run; +pub(crate) mod setup; +pub(crate) mod suggest; +pub(crate) mod synthetic_targets; +pub(crate) mod test; +pub(crate) mod tool; +pub(crate) mod toolstate; diff --git a/src/bootstrap/run.rs b/src/bootstrap/src/core/build_steps/run.rs similarity index 96% rename from src/bootstrap/run.rs rename to src/bootstrap/src/core/build_steps/run.rs index f253f5225a10..29272bebf996 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -1,13 +1,15 @@ use std::path::PathBuf; use std::process::Command; -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::config::TargetSelection; -use crate::dist::distdir; -use crate::flags::get_completion; -use crate::test; -use crate::tool::{self, SourceType, Tool}; -use crate::util::output; +use clap_complete::shells; + +use crate::core::build_steps::dist::distdir; +use crate::core::build_steps::test; +use crate::core::build_steps::tool::{self, SourceType, Tool}; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::config::flags::get_completion; +use crate::core::config::TargetSelection; +use crate::utils::helpers::output; use crate::Mode; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs similarity index 99% rename from src/bootstrap/setup.rs rename to src/bootstrap/src/core/build_steps/setup.rs index 14ec33147fb9..ebe093674fc7 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -1,4 +1,4 @@ -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::Config; use crate::{t, CONFIG_CHANGE_HISTORY}; use sha2::Digest; @@ -12,6 +12,7 @@ use std::str::FromStr; use std::{fmt, fs, io}; #[cfg(test)] +#[path = "../../tests/setup.rs"] mod tests; #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] @@ -35,7 +36,7 @@ static SETTINGS_HASHES: &[&str] = &[ "47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923", "b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a", ]; -static RUST_ANALYZER_SETTINGS: &str = include_str!("../etc/rust_analyzer_settings.json"); +static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json"); impl Profile { fn include_path(&self, src_path: &Path) -> PathBuf { diff --git a/src/bootstrap/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs similarity index 93% rename from src/bootstrap/suggest.rs rename to src/bootstrap/src/core/build_steps/suggest.rs index f225104bda92..82fb10cebe07 100644 --- a/src/bootstrap/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -1,12 +1,11 @@ #![cfg_attr(feature = "build-metrics", allow(unused))] +use clap::Parser; +use std::path::PathBuf; use std::str::FromStr; -use std::path::PathBuf; - -use clap::Parser; - -use crate::{builder::Builder, tool::Tool}; +use crate::core::build_steps::tool::Tool; +use crate::core::builder::Builder; /// Suggests a list of possible `x.py` commands to run based on modified files in branch. pub fn suggest(builder: &Builder<'_>, run: bool) { @@ -62,7 +61,7 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { for sug in suggestions { let mut build: crate::Build = builder.build.clone(); build.config.paths = sug.2; - build.config.cmd = crate::flags::Flags::parse_from(["x.py", sug.0]).cmd; + build.config.cmd = crate::core::config::flags::Flags::parse_from(["x.py", sug.0]).cmd; if let Some(stage) = sug.1 { build.config.stage = stage; } diff --git a/src/bootstrap/synthetic_targets.rs b/src/bootstrap/src/core/build_steps/synthetic_targets.rs similarity index 95% rename from src/bootstrap/synthetic_targets.rs rename to src/bootstrap/src/core/build_steps/synthetic_targets.rs index 7eeac9025c9b..d2c65b740dad 100644 --- a/src/bootstrap/synthetic_targets.rs +++ b/src/bootstrap/src/core/build_steps/synthetic_targets.rs @@ -7,8 +7,8 @@ //! one of the target specs already defined in this module, or create new ones by adding a new step //! that calls create_synthetic_target. -use crate::builder::{Builder, ShouldRun, Step}; -use crate::config::TargetSelection; +use crate::core::builder::{Builder, ShouldRun, Step}; +use crate::core::config::TargetSelection; use crate::Compiler; use std::process::{Command, Stdio}; @@ -76,7 +76,7 @@ fn create_synthetic_target( std::fs::write(&path, &serde_json::to_vec_pretty(&spec).unwrap()).unwrap(); let target = TargetSelection::create_synthetic(&name, path.to_str().unwrap()); - crate::cc_detect::find_target(builder, target); + crate::utils::cc_detect::find_target(builder, target); target } diff --git a/src/bootstrap/test.rs b/src/bootstrap/src/core/build_steps/test.rs similarity index 97% rename from src/bootstrap/test.rs rename to src/bootstrap/src/core/build_steps/test.rs index fb8ec0355c24..831a86940fb4 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -13,21 +13,24 @@ use std::process::{Command, Stdio}; use clap_complete::shells; -use crate::builder::crate_description; -use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; -use crate::cache::INTERNER; -use crate::compile; -use crate::config::TargetSelection; -use crate::dist; -use crate::doc::DocumentationFormat; -use crate::flags::Subcommand; -use crate::llvm; -use crate::render_tests::add_flags_and_try_run_tests; -use crate::synthetic_targets::MirOptPanicAbortSyntheticTarget; -use crate::tool::{self, SourceType, Tool}; -use crate::toolstate::ToolState; -use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t, up_to_date}; +use crate::core::build_steps::compile; +use crate::core::build_steps::dist; +use crate::core::build_steps::doc::DocumentationFormat; +use crate::core::build_steps::llvm; +use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget; +use crate::core::build_steps::tool::{self, SourceType, Tool}; +use crate::core::build_steps::toolstate::ToolState; +use crate::core::builder::crate_description; +use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; +use crate::core::config::flags::get_completion; +use crate::core::config::flags::Subcommand; +use crate::core::config::TargetSelection; +use crate::utils; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::helpers::{ + self, add_link_lib_path, dylib_path, dylib_path_var, output, t, up_to_date, +}; +use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests}; use crate::{envify, CLang, DocTests, GitRepo, Mode}; const ADB_TEST_DIR: &str = "/data/local/tmp/work"; @@ -167,7 +170,7 @@ You can skip linkcheck with --skip src/tools/linkchecker" // Run the linkchecker. let _guard = builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run_delaying_failure(linkchecker.arg(builder.out.join(host.triple).join("doc"))); } @@ -219,7 +222,11 @@ impl Step for HtmlCheck { } // Ensure that a few different kinds of documentation are available. builder.default_doc(&[]); - builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder)); + builder.ensure(crate::core::build_steps::doc::Rustc::new( + builder.top_stage, + self.target, + builder, + )); builder.run_delaying_failure( builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)), @@ -260,7 +267,7 @@ impl Step for Cargotest { let out_dir = builder.out.join("ct"); t!(fs::create_dir_all(&out_dir)); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let mut cmd = builder.tool_cmd(Tool::CargoTest); builder.run_delaying_failure( cmd.arg(&cargo) @@ -328,7 +335,7 @@ impl Step for Cargo { builder, ); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); add_flags_and_try_run_tests(builder, &mut cargo); } } @@ -642,7 +649,7 @@ impl Step for Miri { // does not understand the flags added by `add_flags_and_try_run_test`. let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder); { - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run(&mut cargo); } @@ -658,7 +665,7 @@ impl Step for Miri { let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder); { - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run(&mut cargo); } } @@ -698,7 +705,7 @@ impl Step for Miri { let mut cargo = Command::from(cargo); { - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run(&mut cargo); } } @@ -859,7 +866,7 @@ impl Step for RustdocTheme { if builder.is_fuse_ld_lld(self.compiler.host) { cmd.env( "RUSTDOC_LLD_NO_THREADS", - util::lld_flag_no_threads(self.compiler.host.contains("windows")), + helpers::lld_flag_no_threads(self.compiler.host.contains("windows")), ); } builder.run_delaying_failure(&mut cmd); @@ -900,7 +907,8 @@ impl Step for RustdocJSStd { .arg("--test-folder") .arg(builder.src.join("tests/rustdoc-js-std")); for path in &builder.paths { - if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder) { + if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder) + { if !p.ends_with(".js") { eprintln!("A non-js file was given: `{}`", path.display()); panic!("Cannot run rustdoc-js-std tests"); @@ -908,7 +916,7 @@ impl Step for RustdocJSStd { command.arg("--test-file").arg(path); } } - builder.ensure(crate::doc::Std::new( + builder.ensure(crate::core::build_steps::doc::Std::new( builder.top_stage, self.target, builder, @@ -1035,7 +1043,7 @@ impl Step for RustdocGUI { .env("RUSTC", builder.rustc(self.compiler)); for path in &builder.paths { - if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) { + if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) { if !p.ends_with(".goml") { eprintln!("A non-goml file was given: `{}`", path.display()); panic!("Cannot run rustdoc-gui tests"); @@ -1058,7 +1066,7 @@ impl Step for RustdocGUI { cmd.arg("--npm").arg(npm); } - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let _guard = builder.msg_sysroot_tool( Kind::Test, self.compiler.stage, @@ -1066,7 +1074,7 @@ impl Step for RustdocGUI { self.compiler.host, self.target, ); - crate::render_tests::try_run_tests(builder, &mut cmd, true); + try_run_tests(builder, &mut cmd, true); } } @@ -1126,7 +1134,7 @@ help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to ); crate::exit!(1); } - crate::format::format(&builder, !builder.config.cmd.bless(), &[]); + crate::core::build_steps::format::format(&builder, !builder.config.cmd.bless(), &[]); } builder.info("tidy check"); @@ -1138,10 +1146,10 @@ help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"] .map(|filename| builder.src.join("src/etc/completions").join(filename)); if builder.config.cmd.bless() { - builder.ensure(crate::run::GenerateCompletions); - } else if crate::flags::get_completion(shells::Bash, &bash).is_some() - || crate::flags::get_completion(shells::Fish, &fish).is_some() - || crate::flags::get_completion(shells::PowerShell, &powershell).is_some() + builder.ensure(crate::core::build_steps::run::GenerateCompletions); + } else if get_completion(shells::Bash, &bash).is_some() + || get_completion(shells::Fish, &fish).is_some() + || get_completion(shells::PowerShell, &powershell).is_some() || crate::flags::get_completion(shells::Zsh, &zsh).is_some() { eprintln!( @@ -1403,10 +1411,10 @@ impl Step for MirOpt { // have been detected by bootstrap if the target we're testing wasn't in the // --target flags. if !builder.cc.borrow().contains_key(&target_32bit) { - crate::cc_detect::find_target(builder, target_32bit); + utils::cc_detect::find_target(builder, target_32bit); } if !builder.cc.borrow().contains_key(&target_64bit) { - crate::cc_detect::find_target(builder, target_64bit); + utils::cc_detect::find_target(builder, target_64bit); } vec![target_32bit, target_64bit] @@ -1679,7 +1687,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the } } - if util::forcing_clang_based_tests() { + if helpers::forcing_clang_based_tests() { let clang_exe = builder.llvm_out(target).join("bin").join("clang"); cmd.arg("--run-clang-based-tests-with").arg(clang_exe); } @@ -1698,7 +1706,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the // Get test-args by striping suite path let mut test_args: Vec<&str> = paths .iter() - .filter_map(|p| util::is_valid_test_suite_arg(p, suite_path, builder)) + .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder)) .collect(); test_args.append(&mut builder.config.test_args()); @@ -1887,7 +1895,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the compiler.host, target, ); - crate::render_tests::try_run_tests(builder, &mut cmd, false); + try_run_tests(builder, &mut cmd, false); if let Some(compare_mode) = compare_mode { cmd.arg("--compare-mode").arg(compare_mode); @@ -1909,8 +1917,8 @@ note: if you're sure you want to do this, please open an issue as to why. In the "Check compiletest suite={} mode={} compare_mode={} ({} -> {})", suite, mode, compare_mode, &compiler.host, target )); - let _time = util::timeit(&builder); - crate::render_tests::try_run_tests(builder, &mut cmd, false); + let _time = helpers::timeit(&builder); + try_run_tests(builder, &mut cmd, false); } } } @@ -1981,7 +1989,7 @@ impl BookTest { compiler.host, compiler.host, ); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let toolstate = if builder.run_delaying_failure(&mut rustbook_cmd) { ToolState::TestPass } else { @@ -2003,7 +2011,7 @@ impl BookTest { // Do a breadth-first traversal of the `src/doc` directory and just run // tests for all files that end in `*.md` let mut stack = vec![builder.src.join(self.path)]; - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let mut files = Vec::new(); while let Some(p) = stack.pop() { if p.is_dir() { @@ -2114,7 +2122,7 @@ impl Step for ErrorIndex { let guard = builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run_quiet(&mut tool); drop(guard); // The tests themselves need to link to std, so make sure it is @@ -2236,7 +2244,7 @@ fn run_cargo_test<'a>( ) -> bool { let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let _group = description.into().and_then(|what| { builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target) }); @@ -2631,7 +2639,7 @@ impl Step for RemoteCopyLibs { for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) { let f = t!(f); let name = f.file_name().into_string().unwrap(); - if util::is_dylib(&name) { + if helpers::is_dylib(&name) { builder.run(Command::new(&tool).arg("push").arg(f.path())); } } @@ -2676,7 +2684,9 @@ impl Step for Distcheck { .current_dir(&dir), ); builder.run( - Command::new(util::make(&builder.config.build.triple)).arg("check").current_dir(&dir), + Command::new(helpers::make(&builder.config.build.triple)) + .arg("check") + .current_dir(&dir), ); // Now make sure that rust-src has all of libstd's dependencies @@ -2833,7 +2843,7 @@ impl Step for LintDocs { /// Tests that the lint examples in the rustc book generate the correct /// lints and have the expected format. fn run(self, builder: &Builder<'_>) { - builder.ensure(crate::doc::RustcBook { + builder.ensure(crate::core::build_steps::doc::RustcBook { compiler: self.compiler, target: self.target, validate: true, @@ -3052,7 +3062,7 @@ impl Step for CodegenCranelift { &compiler.host, target )); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); // FIXME handle vendoring for source tarballs before removing the --skip-test below let download_dir = builder.out.join("cg_clif_download"); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs similarity index 99% rename from src/bootstrap/tool.rs rename to src/bootstrap/src/core/build_steps/tool.rs index f094dd9d7c90..5702fa62d7cc 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -3,12 +3,12 @@ use std::fs; use std::path::PathBuf; use std::process::Command; -use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; -use crate::channel::GitInfo; -use crate::compile; -use crate::config::TargetSelection; -use crate::toolstate::ToolState; -use crate::util::{add_dylib_path, exe, t}; +use crate::core::build_steps::compile; +use crate::core::build_steps::toolstate::ToolState; +use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; +use crate::core::config::TargetSelection; +use crate::utils::channel::GitInfo; +use crate::utils::helpers::{add_dylib_path, exe, t}; use crate::Compiler; use crate::Mode; use crate::{gha, Kind}; diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/src/core/build_steps/toolstate.rs similarity index 99% rename from src/bootstrap/toolstate.rs rename to src/bootstrap/src/core/build_steps/toolstate.rs index 308023537d58..f892577ccbf7 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/src/core/build_steps/toolstate.rs @@ -1,5 +1,5 @@ -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::util::t; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::utils::helpers::t; use serde_derive::{Deserialize, Serialize}; use std::collections::HashMap; use std::env; diff --git a/src/bootstrap/builder.rs b/src/bootstrap/src/core/builder.rs similarity index 99% rename from src/bootstrap/builder.rs rename to src/bootstrap/src/core/builder.rs index c714b09ec3ce..039a87e760d7 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -12,20 +12,15 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{Duration, Instant}; -use crate::cache::{Cache, Interned, INTERNER}; -use crate::config::{DryRun, SplitDebuginfo, TargetSelection}; -use crate::doc; -use crate::flags::{Color, Subcommand}; -use crate::install; -use crate::llvm; -use crate::run; -use crate::setup; -use crate::test; -use crate::tool::{self, SourceType}; -use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t}; +use crate::core::build_steps::llvm; +use crate::core::build_steps::tool::{self, SourceType}; +use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, setup, test}; +use crate::core::config::flags::{Color, Subcommand}; +use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection}; +use crate::utils::cache::{Cache, Interned, INTERNER}; +use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t}; +use crate::Crate; use crate::EXTRA_CHECK_CFGS; -use crate::{check, compile, Crate}; -use crate::{clean, dist}; use crate::{Build, CLang, DocTests, GitRepo, Mode}; pub use crate::Compiler; @@ -36,6 +31,10 @@ pub use crate::Compiler; use clap::ValueEnum; use once_cell::sync::{Lazy, OnceCell}; +#[cfg(test)] +#[path = "../tests/builder.rs"] +mod tests; + pub struct Builder<'a> { pub build: &'a Build, pub top_stage: u32, @@ -723,7 +722,7 @@ impl<'a> Builder<'a> { check::Bootstrap ), Kind::Test => describe!( - crate::toolstate::ToolStateCheck, + crate::core::build_steps::toolstate::ToolStateCheck, test::ExpandYamlAnchors, test::Tidy, test::Ui, @@ -1297,8 +1296,8 @@ impl<'a> Builder<'a> { // See comment in rustc_llvm/build.rs for why this is necessary, largely llvm-config // needs to not accidentally link to libLLVM in stage0/lib. - cargo.env("REAL_LIBRARY_PATH_VAR", &util::dylib_path_var()); - if let Some(e) = env::var_os(util::dylib_path_var()) { + cargo.env("REAL_LIBRARY_PATH_VAR", &helpers::dylib_path_var()); + if let Some(e) = env::var_os(helpers::dylib_path_var()) { cargo.env("REAL_LIBRARY_PATH", e); } @@ -1311,7 +1310,7 @@ impl<'a> Builder<'a> { // rustc_llvm. But if LLVM is stale, that'll be a tiny amount // of work comparatively, and we'd likely need to rebuild it anyway, // so that's okay. - if crate::llvm::prebuilt_llvm_config(self, target).is_err() { + if crate::core::build_steps::llvm::prebuilt_llvm_config(self, target).is_err() { cargo.env("RUST_CHECK", "1"); } } @@ -1643,7 +1642,7 @@ impl<'a> Builder<'a> { // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it // fun to pass a flag to a tool to pass a flag to pass a flag to a tool // to change a flag in a binary? - if self.config.rpath_enabled(target) && util::use_host_linker(target) { + if self.config.rpath_enabled(target) && helpers::use_host_linker(target) { let libdir = self.sysroot_libdir_relative(compiler).to_str().unwrap(); let rpath = if target.contains("apple") { // Note that we need to take one extra step on macOS to also pass @@ -2197,9 +2196,6 @@ impl<'a> Builder<'a> { } } -#[cfg(test)] -mod tests; - /// Represents flag values in `String` form with whitespace delimiter to pass it to the compiler later. /// /// `-Z crate-attr` flags will be applied recursively on the target code using the `rustc_parse::parser::Parser`. diff --git a/src/bootstrap/config.rs b/src/bootstrap/src/core/config/config.rs similarity index 98% rename from src/bootstrap/config.rs rename to src/bootstrap/src/core/config/config.rs index 759d874a089a..7ca1bbad9684 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -4,6 +4,7 @@ //! how the build runs. #[cfg(test)] +#[path = "../../tests/config.rs"] mod tests; use std::cell::{Cell, RefCell}; @@ -17,19 +18,20 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; -use crate::cache::{Interned, INTERNER}; -use crate::cc_detect::{ndk_compiler, Language}; -use crate::channel::{self, GitInfo}; -use crate::compile::CODEGEN_BACKEND_PREFIX; -pub use crate::flags::Subcommand; -use crate::flags::{Color, Flags, Warnings}; -use crate::util::{exe, output, t}; +use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX; +use crate::core::config::flags::{Color, Flags, Warnings}; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::cc_detect::{ndk_compiler, Language}; +use crate::utils::channel::{self, GitInfo}; +use crate::utils::helpers::{exe, output, t}; use build_helper::exit; use once_cell::sync::OnceCell; use semver::Version; use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; +pub use crate::core::config::flags::Subcommand; + macro_rules! check_ci_llvm { ($name:expr) => { assert!( @@ -547,7 +549,7 @@ impl Target { /// `Config` structure. #[derive(Deserialize, Default)] #[serde(deny_unknown_fields, rename_all = "kebab-case")] -struct TomlConfig { +pub(crate) struct TomlConfig { changelog_seen: Option, // FIXME: Deprecated field. Remove it at 2024. change_id: Option, build: Option, @@ -1269,7 +1271,7 @@ impl Config { // To avoid writing to random places on the file system, `config.out` needs to be an absolute path. if !config.out.is_absolute() { // `canonicalize` requires the path to already exist. Use our vendored copy of `absolute` instead. - config.out = crate::util::absolute(&config.out); + config.out = crate::utils::helpers::absolute(&config.out); } config.initial_rustc = if let Some(rustc) = build.rustc { @@ -1527,11 +1529,12 @@ impl Config { config.llvm_from_ci = match llvm.download_ci_llvm { Some(StringOrBool::String(s)) => { assert_eq!(s, "if-available", "unknown option `{s}` for download-ci-llvm"); - crate::llvm::is_ci_llvm_available(&config, asserts) + crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts) } Some(StringOrBool::Bool(b)) => b, None => { - config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, asserts) + config.channel == "dev" + && crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts) } }; @@ -1573,8 +1576,8 @@ impl Config { config.llvm_link_shared.set(Some(true)); } } else { - config.llvm_from_ci = - config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, false); + config.llvm_from_ci = config.channel == "dev" + && crate::core::build_steps::llvm::is_ci_llvm_available(&config, false); } if let Some(t) = toml.target { diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs new file mode 100644 index 000000000000..92aea76382ab --- /dev/null +++ b/src/bootstrap/src/core/config/flags.rs @@ -0,0 +1,565 @@ +//! Command-line interface of the rustbuild build system. +//! +//! This module implements the command-line parsing of the build system which +//! has various flags to configure how it's run. + +use std::path::{Path, PathBuf}; + +use clap::{CommandFactory, Parser, ValueEnum}; + +use crate::core::build_steps::setup::Profile; +use crate::core::builder::{Builder, Kind}; +use crate::core::config::{target_selection_list, Config, TargetSelectionList}; +use crate::{Build, DocTests}; + +#[derive(Copy, Clone, Default, Debug, ValueEnum)] +pub enum Color { + Always, + Never, + #[default] + Auto, +} + +/// Whether to deny warnings, emit them as warnings, or use the default behavior +#[derive(Copy, Clone, Default, Debug, ValueEnum)] +pub enum Warnings { + Deny, + Warn, + #[default] + Default, +} + +/// Deserialized version of all flags for this compile. +#[derive(Debug, Parser)] +#[clap( + override_usage = "x.py [options] [...]", + disable_help_subcommand(true), + about = "", + next_line_help(false) +)] +pub struct Flags { + #[command(subcommand)] + pub cmd: Subcommand, + + #[arg(global(true), short, long, action = clap::ArgAction::Count)] + /// use verbose output (-vv for very verbose) + pub verbose: u8, // each extra -v after the first is passed to Cargo + #[arg(global(true), short, long)] + /// use incremental compilation + pub incremental: bool, + #[arg(global(true), long, value_hint = clap::ValueHint::FilePath, value_name = "FILE")] + /// TOML configuration file for build + pub config: Option, + #[arg(global(true), long, value_hint = clap::ValueHint::DirPath, value_name = "DIR")] + /// Build directory, overrides `build.build-dir` in `config.toml` + pub build_dir: Option, + + #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "BUILD")] + /// build target of the stage0 compiler + pub build: Option, + + #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "HOST", value_parser = target_selection_list)] + /// host targets to build + pub host: Option, + + #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "TARGET", value_parser = target_selection_list)] + /// target targets to build + pub target: Option, + + #[arg(global(true), long, value_name = "PATH")] + /// build paths to exclude + pub exclude: Vec, // keeping for client backward compatibility + #[arg(global(true), long, value_name = "PATH")] + /// build paths to skip + pub skip: Vec, + #[arg(global(true), long)] + /// include default paths in addition to the provided ones + pub include_default_paths: bool, + + #[arg(global(true), value_hint = clap::ValueHint::Other, long)] + pub rustc_error_format: Option, + + #[arg(global(true), long, value_hint = clap::ValueHint::CommandString, value_name = "CMD")] + /// command to run on failure + pub on_fail: Option, + #[arg(global(true), long)] + /// dry run; don't build anything + pub dry_run: bool, + #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")] + /// stage to build (indicates compiler to use/test, e.g., stage 0 uses the + /// bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.) + pub stage: Option, + + #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")] + /// stage(s) to keep without recompiling + /// (pass multiple times to keep e.g., both stages 0 and 1) + pub keep_stage: Vec, + #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")] + /// stage(s) of the standard library to keep without recompiling + /// (pass multiple times to keep e.g., both stages 0 and 1) + pub keep_stage_std: Vec, + #[arg(global(true), long, value_hint = clap::ValueHint::DirPath, value_name = "DIR")] + /// path to the root of the rust checkout + pub src: Option, + + #[arg( + global(true), + short, + long, + value_hint = clap::ValueHint::Other, + default_value_t = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get), + value_name = "JOBS" + )] + /// number of jobs to run in parallel + pub jobs: usize, + // This overrides the deny-warnings configuration option, + // which passes -Dwarnings to the compiler invocations. + #[arg(global(true), long)] + #[clap(value_enum, default_value_t=Warnings::Default, value_name = "deny|warn")] + /// if value is deny, will deny warnings + /// if value is warn, will emit warnings + /// otherwise, use the default configured behaviour + pub warnings: Warnings, + + #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "FORMAT")] + /// rustc error format + pub error_format: Option, + #[arg(global(true), long)] + /// use message-format=json + pub json_output: bool, + + #[arg(global(true), long, value_name = "STYLE")] + #[clap(value_enum, default_value_t = Color::Auto)] + /// whether to use color in cargo and rustc output + pub color: Color, + + /// whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml + #[arg(global(true), long, value_name = "VALUE")] + pub llvm_skip_rebuild: Option, + /// generate PGO profile with rustc build + #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")] + pub rust_profile_generate: Option, + /// use PGO profile for rustc build + #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")] + pub rust_profile_use: Option, + /// use PGO profile for LLVM build + #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")] + pub llvm_profile_use: Option, + // LLVM doesn't support a custom location for generating profile + // information. + // + // llvm_out/build/profiles/ is the location this writes to. + /// generate PGO profile with llvm built for rustc + #[arg(global(true), long)] + pub llvm_profile_generate: bool, + /// Additional reproducible artifacts that should be added to the reproducible artifacts archive. + #[arg(global(true), long)] + pub reproducible_artifact: Vec, + #[arg(global(true))] + /// paths for the subcommand + pub paths: Vec, + /// override options in config.toml + #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "section.option=value")] + pub set: Vec, + /// arguments passed to subcommands + #[arg(global(true), last(true), value_name = "ARGS")] + pub free_args: Vec, +} + +impl Flags { + pub fn parse(args: &[String]) -> Self { + let first = String::from("x.py"); + let it = std::iter::once(&first).chain(args.iter()); + // We need to check for ` -h -v`, in which case we list the paths + #[derive(Parser)] + #[clap(disable_help_flag(true))] + struct HelpVerboseOnly { + #[arg(short, long)] + help: bool, + #[arg(global(true), short, long, action = clap::ArgAction::Count)] + pub verbose: u8, + #[arg(value_enum)] + cmd: Kind, + } + if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) = + HelpVerboseOnly::try_parse_from(it.clone()) + { + println!("note: updating submodules before printing available paths"); + let config = Config::parse(&[String::from("build")]); + let build = Build::new(config); + let paths = Builder::get_help(&build, subcommand); + if let Some(s) = paths { + println!("{s}"); + } else { + panic!("No paths available for subcommand `{}`", subcommand.as_str()); + } + crate::exit!(0); + } + + Flags::parse_from(it) + } +} + +#[derive(Debug, Clone, Default, clap::Subcommand)] +pub enum Subcommand { + #[clap(aliases = ["b"], long_about = "\n + Arguments: + This subcommand accepts a number of paths to directories to the crates + and/or artifacts to compile. For example, for a quick build of a usable + compiler: + ./x.py build --stage 1 library/std + This will build a compiler and standard library from the local source code. + Once this is done, build/$ARCH/stage1 contains a usable compiler. + If no arguments are passed then the default artifacts for that stage are + compiled. For example: + ./x.py build --stage 0 + ./x.py build ")] + /// Compile either the compiler or libraries + #[default] + Build, + #[clap(aliases = ["c"], long_about = "\n + Arguments: + This subcommand accepts a number of paths to directories to the crates + and/or artifacts to compile. For example: + ./x.py check library/std + If no arguments are passed then many artifacts are checked.")] + /// Compile either the compiler or libraries, using cargo check + Check { + #[arg(long)] + /// Check all targets + all_targets: bool, + }, + /// Run Clippy (uses rustup/cargo-installed clippy binary) + #[clap(long_about = "\n + Arguments: + This subcommand accepts a number of paths to directories to the crates + and/or artifacts to run clippy against. For example: + ./x.py clippy library/core + ./x.py clippy library/core library/proc_macro")] + Clippy { + #[arg(long)] + fix: bool, + /// clippy lints to allow + #[arg(global(true), short = 'A', action = clap::ArgAction::Append, value_name = "LINT")] + allow: Vec, + /// clippy lints to deny + #[arg(global(true), short = 'D', action = clap::ArgAction::Append, value_name = "LINT")] + deny: Vec, + /// clippy lints to warn on + #[arg(global(true), short = 'W', action = clap::ArgAction::Append, value_name = "LINT")] + warn: Vec, + /// clippy lints to forbid + #[arg(global(true), short = 'F', action = clap::ArgAction::Append, value_name = "LINT")] + forbid: Vec, + }, + /// Run cargo fix + #[clap(long_about = "\n + Arguments: + This subcommand accepts a number of paths to directories to the crates + and/or artifacts to run `cargo fix` against. For example: + ./x.py fix library/core + ./x.py fix library/core library/proc_macro")] + Fix, + #[clap( + name = "fmt", + long_about = "\n + Arguments: + This subcommand optionally accepts a `--check` flag which succeeds if formatting is correct and + fails if it is not. For example: + ./x.py fmt + ./x.py fmt --check" + )] + /// Run rustfmt + Format { + /// check formatting instead of applying + #[arg(long)] + check: bool, + }, + #[clap(aliases = ["d"], long_about = "\n + Arguments: + This subcommand accepts a number of paths to directories of documentation + to build. For example: + ./x.py doc src/doc/book + ./x.py doc src/doc/nomicon + ./x.py doc src/doc/book library/std + ./x.py doc library/std --json + ./x.py doc library/std --open + If no arguments are passed then everything is documented: + ./x.py doc + ./x.py doc --stage 1")] + /// Build documentation + Doc { + #[arg(long)] + /// open the docs in a browser + open: bool, + #[arg(long)] + /// render the documentation in JSON format in addition to the usual HTML format + json: bool, + }, + #[clap(aliases = ["t"], long_about = "\n + Arguments: + This subcommand accepts a number of paths to test directories that + should be compiled and run. For example: + ./x.py test tests/ui + ./x.py test library/std --test-args hash_map + ./x.py test library/std --stage 0 --no-doc + ./x.py test tests/ui --bless + ./x.py test tests/ui --compare-mode next-solver + Note that `test tests/* --stage N` does NOT depend on `build compiler/rustc --stage N`; + just like `build library/std --stage N` it tests the compiler produced by the previous + stage. + Execute tool tests with a tool name argument: + ./x.py test tidy + If no arguments are passed then the complete artifacts for that stage are + compiled and tested. + ./x.py test + ./x.py test --stage 1")] + /// Build and run some test suites + Test { + #[arg(long)] + /// run all tests regardless of failure + no_fail_fast: bool, + #[arg(long, value_name = "SUBSTRING")] + /// skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times + skip: Vec, + #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] + /// extra arguments to be passed for the test tool being used + /// (e.g. libtest, compiletest or rustdoc) + test_args: Vec, + /// extra options to pass the compiler when running tests + #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] + rustc_args: Vec, + #[arg(long)] + /// do not run doc tests + no_doc: bool, + #[arg(long)] + /// only run doc tests + doc: bool, + #[arg(long)] + /// whether to automatically update stderr/stdout files + bless: bool, + #[arg(long)] + /// comma-separated list of other files types to check (accepts py, py:lint, + /// py:fmt, shell) + extra_checks: Option, + #[arg(long)] + /// rerun tests even if the inputs are unchanged + force_rerun: bool, + #[arg(long)] + /// only run tests that result has been changed + only_modified: bool, + #[arg(long, value_name = "COMPARE MODE")] + /// mode describing what file the actual ui output will be compared to + compare_mode: Option, + #[arg(long, value_name = "check | build | run")] + /// force {check,build,run}-pass tests to this mode. + pass: Option, + #[arg(long, value_name = "auto | always | never")] + /// whether to execute run-* tests + run: Option, + #[arg(long)] + /// enable this to generate a Rustfix coverage file, which is saved in + /// `//rustfix_missing_coverage.txt` + rustfix_coverage: bool, + }, + /// Build and run some benchmarks + Bench { + #[arg(long, allow_hyphen_values(true))] + test_args: Vec, + }, + /// Clean out build directories + Clean { + #[arg(long)] + /// Clean the entire build directory (not used by default) + all: bool, + #[arg(long, value_name = "N")] + /// Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used. + stage: Option, + }, + /// Build distribution artifacts + Dist, + /// Install distribution artifacts + Install, + #[clap(aliases = ["r"], long_about = "\n + Arguments: + This subcommand accepts a number of paths to tools to build and run. For + example: + ./x.py run src/tools/expand-yaml-anchors + At least a tool needs to be called.")] + /// Run tools contained in this repository + Run { + /// arguments for the tool + #[arg(long, allow_hyphen_values(true))] + args: Vec, + }, + /// Set up the environment for development + #[clap(long_about = format!( + "\n +x.py setup creates a `config.toml` which changes the defaults for x.py itself, +as well as setting up a git pre-push hook, VS Code config and toolchain link. +Arguments: + This subcommand accepts a 'profile' to use for builds. For example: + ./x.py setup library + The profile is optional and you will be prompted interactively if it is not given. + The following profiles are available: +{} + To only set up the git hook, VS Code config or toolchain link, you may use + ./x.py setup hook + ./x.py setup vscode + ./x.py setup link", Profile::all_for_help(" ").trim_end()))] + Setup { + /// Either the profile for `config.toml` or another setup action. + /// May be omitted to set up interactively + #[arg(value_name = "|hook|vscode|link")] + profile: Option, + }, + /// Suggest a subset of tests to run, based on modified files + #[clap(long_about = "\n")] + Suggest { + /// run suggested tests + #[arg(long)] + run: bool, + }, +} + +impl Subcommand { + pub fn kind(&self) -> Kind { + match self { + Subcommand::Bench { .. } => Kind::Bench, + Subcommand::Build { .. } => Kind::Build, + Subcommand::Check { .. } => Kind::Check, + Subcommand::Clippy { .. } => Kind::Clippy, + Subcommand::Doc { .. } => Kind::Doc, + Subcommand::Fix { .. } => Kind::Fix, + Subcommand::Format { .. } => Kind::Format, + Subcommand::Test { .. } => Kind::Test, + Subcommand::Clean { .. } => Kind::Clean, + Subcommand::Dist { .. } => Kind::Dist, + Subcommand::Install { .. } => Kind::Install, + Subcommand::Run { .. } => Kind::Run, + Subcommand::Setup { .. } => Kind::Setup, + Subcommand::Suggest { .. } => Kind::Suggest, + } + } + + pub fn rustc_args(&self) -> Vec<&str> { + match *self { + Subcommand::Test { ref rustc_args, .. } => { + rustc_args.iter().flat_map(|s| s.split_whitespace()).collect() + } + _ => vec![], + } + } + + pub fn fail_fast(&self) -> bool { + match *self { + Subcommand::Test { no_fail_fast, .. } => !no_fail_fast, + _ => false, + } + } + + pub fn doc_tests(&self) -> DocTests { + match *self { + Subcommand::Test { doc, no_doc, .. } => { + if doc { + DocTests::Only + } else if no_doc { + DocTests::No + } else { + DocTests::Yes + } + } + _ => DocTests::Yes, + } + } + + pub fn bless(&self) -> bool { + match *self { + Subcommand::Test { bless, .. } => bless, + _ => false, + } + } + + pub fn extra_checks(&self) -> Option<&str> { + match *self { + Subcommand::Test { ref extra_checks, .. } => extra_checks.as_ref().map(String::as_str), + _ => None, + } + } + + pub fn only_modified(&self) -> bool { + match *self { + Subcommand::Test { only_modified, .. } => only_modified, + _ => false, + } + } + + pub fn force_rerun(&self) -> bool { + match *self { + Subcommand::Test { force_rerun, .. } => force_rerun, + _ => false, + } + } + + pub fn rustfix_coverage(&self) -> bool { + match *self { + Subcommand::Test { rustfix_coverage, .. } => rustfix_coverage, + _ => false, + } + } + + pub fn compare_mode(&self) -> Option<&str> { + match *self { + Subcommand::Test { ref compare_mode, .. } => compare_mode.as_ref().map(|s| &s[..]), + _ => None, + } + } + + pub fn pass(&self) -> Option<&str> { + match *self { + Subcommand::Test { ref pass, .. } => pass.as_ref().map(|s| &s[..]), + _ => None, + } + } + + pub fn run(&self) -> Option<&str> { + match *self { + Subcommand::Test { ref run, .. } => run.as_ref().map(|s| &s[..]), + _ => None, + } + } + + pub fn open(&self) -> bool { + match *self { + Subcommand::Doc { open, .. } => open, + _ => false, + } + } + + pub fn json(&self) -> bool { + match *self { + Subcommand::Doc { json, .. } => json, + _ => false, + } + } +} + +/// Returns the shell completion for a given shell, if the result differs from the current +/// content of `path`. If `path` does not exist, always returns `Some`. +pub fn get_completion(shell: G, path: &Path) -> Option { + let mut cmd = Flags::command(); + let current = if !path.exists() { + String::new() + } else { + std::fs::read_to_string(path).unwrap_or_else(|_| { + eprintln!("couldn't read {}", path.display()); + crate::exit!(1) + }) + }; + let mut buf = Vec::new(); + clap_complete::generate(shell, &mut cmd, "x.py", &mut buf); + if buf == current.as_bytes() { + return None; + } + Some(String::from_utf8(buf).expect("completion script should be UTF-8")) +} diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs new file mode 100644 index 000000000000..9c6861826d60 --- /dev/null +++ b/src/bootstrap/src/core/config/mod.rs @@ -0,0 +1,4 @@ +pub(crate) mod config; +pub(crate) mod flags; + +pub use config::*; diff --git a/src/bootstrap/download.rs b/src/bootstrap/src/core/download.rs similarity index 99% rename from src/bootstrap/download.rs rename to src/bootstrap/src/core/download.rs index 2a0dec755996..5541a2f3e35e 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -11,13 +11,10 @@ use build_helper::ci::CiEnv; use once_cell::sync::OnceCell; use xz2::bufread::XzDecoder; -use crate::{ - config::RustfmtMetadata, - llvm::detect_llvm_sha, - t, - util::{check_run, exe, program_out_of_date}, - Config, -}; +use crate::core::build_steps::llvm::detect_llvm_sha; +use crate::core::config::RustfmtMetadata; +use crate::utils::helpers::{check_run, exe, program_out_of_date}; +use crate::{t, Config}; static SHOULD_FIX_BINS_AND_DYLIBS: OnceCell = OnceCell::new(); diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/src/core/metadata.rs similarity index 98% rename from src/bootstrap/metadata.rs rename to src/bootstrap/src/core/metadata.rs index 3b20ceac8759..5802082326a8 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -3,8 +3,8 @@ use std::process::Command; use serde_derive::Deserialize; -use crate::cache::INTERNER; -use crate::util::output; +use crate::utils::cache::INTERNER; +use crate::utils::helpers::output; use crate::{t, Build, Crate}; /// For more information, see the output of diff --git a/src/bootstrap/src/core/mod.rs b/src/bootstrap/src/core/mod.rs new file mode 100644 index 000000000000..9e18d6704d4f --- /dev/null +++ b/src/bootstrap/src/core/mod.rs @@ -0,0 +1,6 @@ +pub(crate) mod build_steps; +pub(crate) mod builder; +pub(crate) mod config; +pub(crate) mod download; +pub(crate) mod metadata; +pub(crate) mod sanity; diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/src/core/sanity.rs similarity index 98% rename from src/bootstrap/sanity.rs rename to src/bootstrap/src/core/sanity.rs index 0febdf250d3f..eec3be66a128 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -15,9 +15,9 @@ use std::fs; use std::path::PathBuf; use std::process::Command; -use crate::cache::INTERNER; -use crate::config::Target; -use crate::util::output; +use crate::core::config::Target; +use crate::utils::cache::INTERNER; +use crate::utils::helpers::output; use crate::Build; pub struct Finder { From 9f381fe3452a0b938e91dc1d10c492d0635b8bad Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 7 Oct 2023 23:37:55 +0300 Subject: [PATCH 50/94] move bootstrap utils into bootstrap/src/utils module Signed-off-by: onur-ozkan --- src/bootstrap/Cargo.toml | 10 +- src/bootstrap/flags.rs | 568 ------------------ src/bootstrap/job.rs | 143 ----- src/bootstrap/src/core/config/flags.rs | 3 + src/bootstrap/{ => src}/lib.rs | 148 ++--- src/bootstrap/src/utils/bin_helpers.rs | 28 + src/bootstrap/{ => src/utils}/cache.rs | 2 +- src/bootstrap/{ => src/utils}/cc_detect.rs | 4 +- src/bootstrap/{ => src/utils}/channel.rs | 3 +- src/bootstrap/{ => src/utils}/dylib_util.rs | 11 +- .../{util.rs => src/utils/helpers.rs} | 36 +- src/bootstrap/src/utils/job.rs | 161 +++++ src/bootstrap/{ => src/utils}/metrics.rs | 4 +- src/bootstrap/src/utils/mod.rs | 14 + src/bootstrap/{ => src/utils}/render_tests.rs | 2 +- src/bootstrap/{ => src/utils}/tarball.rs | 19 +- 16 files changed, 296 insertions(+), 860 deletions(-) delete mode 100644 src/bootstrap/flags.rs delete mode 100644 src/bootstrap/job.rs rename src/bootstrap/{ => src}/lib.rs (95%) create mode 100644 src/bootstrap/src/utils/bin_helpers.rs rename src/bootstrap/{ => src/utils}/cache.rs (99%) rename src/bootstrap/{ => src/utils}/cc_detect.rs (99%) rename src/bootstrap/{ => src/utils}/channel.rs (99%) rename src/bootstrap/{ => src/utils}/dylib_util.rs (62%) rename src/bootstrap/{util.rs => src/utils/helpers.rs} (95%) create mode 100644 src/bootstrap/src/utils/job.rs rename src/bootstrap/{ => src/utils}/metrics.rs (99%) create mode 100644 src/bootstrap/src/utils/mod.rs rename src/bootstrap/{ => src/utils}/render_tests.rs (99%) rename src/bootstrap/{ => src/utils}/tarball.rs (95%) diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 006a992eb3c3..e236421b7f5f 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -9,27 +9,27 @@ default-run = "bootstrap" build-metrics = ["sysinfo"] [lib] -path = "lib.rs" +path = "src/lib.rs" doctest = false [[bin]] name = "bootstrap" -path = "bin/main.rs" +path = "src/bin/main.rs" test = false [[bin]] name = "rustc" -path = "bin/rustc.rs" +path = "src/bin/rustc.rs" test = false [[bin]] name = "rustdoc" -path = "bin/rustdoc.rs" +path = "src/bin/rustdoc.rs" test = false [[bin]] name = "sccache-plus-cl" -path = "bin/sccache-plus-cl.rs" +path = "src/bin/sccache-plus-cl.rs" test = false [dependencies] diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs deleted file mode 100644 index 5a6a5f37fc6f..000000000000 --- a/src/bootstrap/flags.rs +++ /dev/null @@ -1,568 +0,0 @@ -//! Command-line interface of the rustbuild build system. -//! -//! This module implements the command-line parsing of the build system which -//! has various flags to configure how it's run. - -use std::path::{Path, PathBuf}; - -use clap::{CommandFactory, Parser, ValueEnum}; - -use crate::builder::{Builder, Kind}; -use crate::config::{target_selection_list, Config, TargetSelectionList}; -use crate::setup::Profile; -use crate::{Build, DocTests}; - -#[derive(Copy, Clone, Default, Debug, ValueEnum)] -pub enum Color { - Always, - Never, - #[default] - Auto, -} - -/// Whether to deny warnings, emit them as warnings, or use the default behavior -#[derive(Copy, Clone, Default, Debug, ValueEnum)] -pub enum Warnings { - Deny, - Warn, - #[default] - Default, -} - -/// Deserialized version of all flags for this compile. -#[derive(Debug, Parser)] -#[clap( - override_usage = "x.py [options] [...]", - disable_help_subcommand(true), - about = "", - next_line_help(false) -)] -pub struct Flags { - #[command(subcommand)] - pub cmd: Subcommand, - - #[arg(global(true), short, long, action = clap::ArgAction::Count)] - /// use verbose output (-vv for very verbose) - pub verbose: u8, // each extra -v after the first is passed to Cargo - #[arg(global(true), short, long)] - /// use incremental compilation - pub incremental: bool, - #[arg(global(true), long, value_hint = clap::ValueHint::FilePath, value_name = "FILE")] - /// TOML configuration file for build - pub config: Option, - #[arg(global(true), long, value_hint = clap::ValueHint::DirPath, value_name = "DIR")] - /// Build directory, overrides `build.build-dir` in `config.toml` - pub build_dir: Option, - - #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "BUILD")] - /// build target of the stage0 compiler - pub build: Option, - - #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "HOST", value_parser = target_selection_list)] - /// host targets to build - pub host: Option, - - #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "TARGET", value_parser = target_selection_list)] - /// target targets to build - pub target: Option, - - #[arg(global(true), long, value_name = "PATH")] - /// build paths to exclude - pub exclude: Vec, // keeping for client backward compatibility - #[arg(global(true), long, value_name = "PATH")] - /// build paths to skip - pub skip: Vec, - #[arg(global(true), long)] - /// include default paths in addition to the provided ones - pub include_default_paths: bool, - - #[arg(global(true), value_hint = clap::ValueHint::Other, long)] - pub rustc_error_format: Option, - - #[arg(global(true), long, value_hint = clap::ValueHint::CommandString, value_name = "CMD")] - /// command to run on failure - pub on_fail: Option, - #[arg(global(true), long)] - /// dry run; don't build anything - pub dry_run: bool, - #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")] - /// stage to build (indicates compiler to use/test, e.g., stage 0 uses the - /// bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.) - pub stage: Option, - - #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")] - /// stage(s) to keep without recompiling - /// (pass multiple times to keep e.g., both stages 0 and 1) - pub keep_stage: Vec, - #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")] - /// stage(s) of the standard library to keep without recompiling - /// (pass multiple times to keep e.g., both stages 0 and 1) - pub keep_stage_std: Vec, - #[arg(global(true), long, value_hint = clap::ValueHint::DirPath, value_name = "DIR")] - /// path to the root of the rust checkout - pub src: Option, - - #[arg( - global(true), - short, - long, - value_hint = clap::ValueHint::Other, - default_value_t = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get), - value_name = "JOBS" - )] - /// number of jobs to run in parallel - pub jobs: usize, - // This overrides the deny-warnings configuration option, - // which passes -Dwarnings to the compiler invocations. - #[arg(global(true), long)] - #[clap(value_enum, default_value_t=Warnings::Default, value_name = "deny|warn")] - /// if value is deny, will deny warnings - /// if value is warn, will emit warnings - /// otherwise, use the default configured behaviour - pub warnings: Warnings, - - #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "FORMAT")] - /// rustc error format - pub error_format: Option, - #[arg(global(true), long)] - /// use message-format=json - pub json_output: bool, - - #[arg(global(true), long, value_name = "STYLE")] - #[clap(value_enum, default_value_t = Color::Auto)] - /// whether to use color in cargo and rustc output - pub color: Color, - - /// whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml - #[arg(global(true), long, value_name = "VALUE")] - pub llvm_skip_rebuild: Option, - /// generate PGO profile with rustc build - #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")] - pub rust_profile_generate: Option, - /// use PGO profile for rustc build - #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")] - pub rust_profile_use: Option, - /// use PGO profile for LLVM build - #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")] - pub llvm_profile_use: Option, - // LLVM doesn't support a custom location for generating profile - // information. - // - // llvm_out/build/profiles/ is the location this writes to. - /// generate PGO profile with llvm built for rustc - #[arg(global(true), long)] - pub llvm_profile_generate: bool, - /// Enable BOLT link flags - #[arg(global(true), long)] - pub enable_bolt_settings: bool, - /// Additional reproducible artifacts that should be added to the reproducible artifacts archive. - #[arg(global(true), long)] - pub reproducible_artifact: Vec, - #[arg(global(true))] - /// paths for the subcommand - pub paths: Vec, - /// override options in config.toml - #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "section.option=value")] - pub set: Vec, - /// arguments passed to subcommands - #[arg(global(true), last(true), value_name = "ARGS")] - pub free_args: Vec, -} - -impl Flags { - pub fn parse(args: &[String]) -> Self { - let first = String::from("x.py"); - let it = std::iter::once(&first).chain(args.iter()); - // We need to check for ` -h -v`, in which case we list the paths - #[derive(Parser)] - #[clap(disable_help_flag(true))] - struct HelpVerboseOnly { - #[arg(short, long)] - help: bool, - #[arg(global(true), short, long, action = clap::ArgAction::Count)] - pub verbose: u8, - #[arg(value_enum)] - cmd: Kind, - } - if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) = - HelpVerboseOnly::try_parse_from(it.clone()) - { - println!("note: updating submodules before printing available paths"); - let config = Config::parse(&[String::from("build")]); - let build = Build::new(config); - let paths = Builder::get_help(&build, subcommand); - if let Some(s) = paths { - println!("{s}"); - } else { - panic!("No paths available for subcommand `{}`", subcommand.as_str()); - } - crate::exit!(0); - } - - Flags::parse_from(it) - } -} - -#[derive(Debug, Clone, Default, clap::Subcommand)] -pub enum Subcommand { - #[clap(aliases = ["b"], long_about = "\n - Arguments: - This subcommand accepts a number of paths to directories to the crates - and/or artifacts to compile. For example, for a quick build of a usable - compiler: - ./x.py build --stage 1 library/std - This will build a compiler and standard library from the local source code. - Once this is done, build/$ARCH/stage1 contains a usable compiler. - If no arguments are passed then the default artifacts for that stage are - compiled. For example: - ./x.py build --stage 0 - ./x.py build ")] - /// Compile either the compiler or libraries - #[default] - Build, - #[clap(aliases = ["c"], long_about = "\n - Arguments: - This subcommand accepts a number of paths to directories to the crates - and/or artifacts to compile. For example: - ./x.py check library/std - If no arguments are passed then many artifacts are checked.")] - /// Compile either the compiler or libraries, using cargo check - Check { - #[arg(long)] - /// Check all targets - all_targets: bool, - }, - /// Run Clippy (uses rustup/cargo-installed clippy binary) - #[clap(long_about = "\n - Arguments: - This subcommand accepts a number of paths to directories to the crates - and/or artifacts to run clippy against. For example: - ./x.py clippy library/core - ./x.py clippy library/core library/proc_macro")] - Clippy { - #[arg(long)] - fix: bool, - /// clippy lints to allow - #[arg(global(true), short = 'A', action = clap::ArgAction::Append, value_name = "LINT")] - allow: Vec, - /// clippy lints to deny - #[arg(global(true), short = 'D', action = clap::ArgAction::Append, value_name = "LINT")] - deny: Vec, - /// clippy lints to warn on - #[arg(global(true), short = 'W', action = clap::ArgAction::Append, value_name = "LINT")] - warn: Vec, - /// clippy lints to forbid - #[arg(global(true), short = 'F', action = clap::ArgAction::Append, value_name = "LINT")] - forbid: Vec, - }, - /// Run cargo fix - #[clap(long_about = "\n - Arguments: - This subcommand accepts a number of paths to directories to the crates - and/or artifacts to run `cargo fix` against. For example: - ./x.py fix library/core - ./x.py fix library/core library/proc_macro")] - Fix, - #[clap( - name = "fmt", - long_about = "\n - Arguments: - This subcommand optionally accepts a `--check` flag which succeeds if formatting is correct and - fails if it is not. For example: - ./x.py fmt - ./x.py fmt --check" - )] - /// Run rustfmt - Format { - /// check formatting instead of applying - #[arg(long)] - check: bool, - }, - #[clap(aliases = ["d"], long_about = "\n - Arguments: - This subcommand accepts a number of paths to directories of documentation - to build. For example: - ./x.py doc src/doc/book - ./x.py doc src/doc/nomicon - ./x.py doc src/doc/book library/std - ./x.py doc library/std --json - ./x.py doc library/std --open - If no arguments are passed then everything is documented: - ./x.py doc - ./x.py doc --stage 1")] - /// Build documentation - Doc { - #[arg(long)] - /// open the docs in a browser - open: bool, - #[arg(long)] - /// render the documentation in JSON format in addition to the usual HTML format - json: bool, - }, - #[clap(aliases = ["t"], long_about = "\n - Arguments: - This subcommand accepts a number of paths to test directories that - should be compiled and run. For example: - ./x.py test tests/ui - ./x.py test library/std --test-args hash_map - ./x.py test library/std --stage 0 --no-doc - ./x.py test tests/ui --bless - ./x.py test tests/ui --compare-mode next-solver - Note that `test tests/* --stage N` does NOT depend on `build compiler/rustc --stage N`; - just like `build library/std --stage N` it tests the compiler produced by the previous - stage. - Execute tool tests with a tool name argument: - ./x.py test tidy - If no arguments are passed then the complete artifacts for that stage are - compiled and tested. - ./x.py test - ./x.py test --stage 1")] - /// Build and run some test suites - Test { - #[arg(long)] - /// run all tests regardless of failure - no_fail_fast: bool, - #[arg(long, value_name = "SUBSTRING")] - /// skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times - skip: Vec, - #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] - /// extra arguments to be passed for the test tool being used - /// (e.g. libtest, compiletest or rustdoc) - test_args: Vec, - /// extra options to pass the compiler when running tests - #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] - rustc_args: Vec, - #[arg(long)] - /// do not run doc tests - no_doc: bool, - #[arg(long)] - /// only run doc tests - doc: bool, - #[arg(long)] - /// whether to automatically update stderr/stdout files - bless: bool, - #[arg(long)] - /// comma-separated list of other files types to check (accepts py, py:lint, - /// py:fmt, shell) - extra_checks: Option, - #[arg(long)] - /// rerun tests even if the inputs are unchanged - force_rerun: bool, - #[arg(long)] - /// only run tests that result has been changed - only_modified: bool, - #[arg(long, value_name = "COMPARE MODE")] - /// mode describing what file the actual ui output will be compared to - compare_mode: Option, - #[arg(long, value_name = "check | build | run")] - /// force {check,build,run}-pass tests to this mode. - pass: Option, - #[arg(long, value_name = "auto | always | never")] - /// whether to execute run-* tests - run: Option, - #[arg(long)] - /// enable this to generate a Rustfix coverage file, which is saved in - /// `//rustfix_missing_coverage.txt` - rustfix_coverage: bool, - }, - /// Build and run some benchmarks - Bench { - #[arg(long, allow_hyphen_values(true))] - test_args: Vec, - }, - /// Clean out build directories - Clean { - #[arg(long)] - /// Clean the entire build directory (not used by default) - all: bool, - #[arg(long, value_name = "N")] - /// Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used. - stage: Option, - }, - /// Build distribution artifacts - Dist, - /// Install distribution artifacts - Install, - #[clap(aliases = ["r"], long_about = "\n - Arguments: - This subcommand accepts a number of paths to tools to build and run. For - example: - ./x.py run src/tools/expand-yaml-anchors - At least a tool needs to be called.")] - /// Run tools contained in this repository - Run { - /// arguments for the tool - #[arg(long, allow_hyphen_values(true))] - args: Vec, - }, - /// Set up the environment for development - #[clap(long_about = format!( - "\n -x.py setup creates a `config.toml` which changes the defaults for x.py itself, -as well as setting up a git pre-push hook, VS Code config and toolchain link. -Arguments: - This subcommand accepts a 'profile' to use for builds. For example: - ./x.py setup library - The profile is optional and you will be prompted interactively if it is not given. - The following profiles are available: -{} - To only set up the git hook, VS Code config or toolchain link, you may use - ./x.py setup hook - ./x.py setup vscode - ./x.py setup link", Profile::all_for_help(" ").trim_end()))] - Setup { - /// Either the profile for `config.toml` or another setup action. - /// May be omitted to set up interactively - #[arg(value_name = "|hook|vscode|link")] - profile: Option, - }, - /// Suggest a subset of tests to run, based on modified files - #[clap(long_about = "\n")] - Suggest { - /// run suggested tests - #[arg(long)] - run: bool, - }, -} - -impl Subcommand { - pub fn kind(&self) -> Kind { - match self { - Subcommand::Bench { .. } => Kind::Bench, - Subcommand::Build { .. } => Kind::Build, - Subcommand::Check { .. } => Kind::Check, - Subcommand::Clippy { .. } => Kind::Clippy, - Subcommand::Doc { .. } => Kind::Doc, - Subcommand::Fix { .. } => Kind::Fix, - Subcommand::Format { .. } => Kind::Format, - Subcommand::Test { .. } => Kind::Test, - Subcommand::Clean { .. } => Kind::Clean, - Subcommand::Dist { .. } => Kind::Dist, - Subcommand::Install { .. } => Kind::Install, - Subcommand::Run { .. } => Kind::Run, - Subcommand::Setup { .. } => Kind::Setup, - Subcommand::Suggest { .. } => Kind::Suggest, - } - } - - pub fn rustc_args(&self) -> Vec<&str> { - match *self { - Subcommand::Test { ref rustc_args, .. } => { - rustc_args.iter().flat_map(|s| s.split_whitespace()).collect() - } - _ => vec![], - } - } - - pub fn fail_fast(&self) -> bool { - match *self { - Subcommand::Test { no_fail_fast, .. } => !no_fail_fast, - _ => false, - } - } - - pub fn doc_tests(&self) -> DocTests { - match *self { - Subcommand::Test { doc, no_doc, .. } => { - if doc { - DocTests::Only - } else if no_doc { - DocTests::No - } else { - DocTests::Yes - } - } - _ => DocTests::Yes, - } - } - - pub fn bless(&self) -> bool { - match *self { - Subcommand::Test { bless, .. } => bless, - _ => false, - } - } - - pub fn extra_checks(&self) -> Option<&str> { - match *self { - Subcommand::Test { ref extra_checks, .. } => extra_checks.as_ref().map(String::as_str), - _ => None, - } - } - - pub fn only_modified(&self) -> bool { - match *self { - Subcommand::Test { only_modified, .. } => only_modified, - _ => false, - } - } - - pub fn force_rerun(&self) -> bool { - match *self { - Subcommand::Test { force_rerun, .. } => force_rerun, - _ => false, - } - } - - pub fn rustfix_coverage(&self) -> bool { - match *self { - Subcommand::Test { rustfix_coverage, .. } => rustfix_coverage, - _ => false, - } - } - - pub fn compare_mode(&self) -> Option<&str> { - match *self { - Subcommand::Test { ref compare_mode, .. } => compare_mode.as_ref().map(|s| &s[..]), - _ => None, - } - } - - pub fn pass(&self) -> Option<&str> { - match *self { - Subcommand::Test { ref pass, .. } => pass.as_ref().map(|s| &s[..]), - _ => None, - } - } - - pub fn run(&self) -> Option<&str> { - match *self { - Subcommand::Test { ref run, .. } => run.as_ref().map(|s| &s[..]), - _ => None, - } - } - - pub fn open(&self) -> bool { - match *self { - Subcommand::Doc { open, .. } => open, - _ => false, - } - } - - pub fn json(&self) -> bool { - match *self { - Subcommand::Doc { json, .. } => json, - _ => false, - } - } -} - -/// Returns the shell completion for a given shell, if the result differs from the current -/// content of `path`. If `path` does not exist, always returns `Some`. -pub fn get_completion(shell: G, path: &Path) -> Option { - let mut cmd = Flags::command(); - let current = if !path.exists() { - String::new() - } else { - std::fs::read_to_string(path).unwrap_or_else(|_| { - eprintln!("couldn't read {}", path.display()); - crate::exit!(1) - }) - }; - let mut buf = Vec::new(); - clap_complete::generate(shell, &mut cmd, "x.py", &mut buf); - if buf == current.as_bytes() { - return None; - } - Some(String::from_utf8(buf).expect("completion script should be UTF-8")) -} diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs deleted file mode 100644 index b0a97b540ec7..000000000000 --- a/src/bootstrap/job.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! Job management on Windows for bootstrapping -//! -//! Most of the time when you're running a build system (e.g., make) you expect -//! Ctrl-C or abnormal termination to actually terminate the entire tree of -//! process in play, not just the one at the top. This currently works "by -//! default" on Unix platforms because Ctrl-C actually sends a signal to the -//! *process group* rather than the parent process, so everything will get torn -//! down. On Windows, however, this does not happen and Ctrl-C just kills the -//! parent process. -//! -//! To achieve the same semantics on Windows we use Job Objects to ensure that -//! all processes die at the same time. Job objects have a mode of operation -//! where when all handles to the object are closed it causes all child -//! processes associated with the object to be terminated immediately. -//! Conveniently whenever a process in the job object spawns a new process the -//! child will be associated with the job object as well. This means if we add -//! ourselves to the job object we create then everything will get torn down! -//! -//! Unfortunately most of the time the build system is actually called from a -//! python wrapper (which manages things like building the build system) so this -//! all doesn't quite cut it so far. To go the last mile we duplicate the job -//! object handle into our parent process (a python process probably) and then -//! close our own handle. This means that the only handle to the job object -//! resides in the parent python process, so when python dies the whole build -//! system dies (as one would probably expect!). -//! -//! Note that this module has a #[cfg(windows)] above it as none of this logic -//! is required on Unix. - -use crate::Build; -use std::env; -use std::ffi::c_void; -use std::io; -use std::mem; - -use windows::{ - core::PCWSTR, - Win32::Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE}, - Win32::System::Diagnostics::Debug::{SetErrorMode, SEM_NOGPFAULTERRORBOX, THREAD_ERROR_MODE}, - Win32::System::JobObjects::{ - AssignProcessToJobObject, CreateJobObjectW, JobObjectExtendedLimitInformation, - SetInformationJobObject, JOBOBJECT_EXTENDED_LIMIT_INFORMATION, - JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS, - }, - Win32::System::Threading::{ - GetCurrentProcess, OpenProcess, BELOW_NORMAL_PRIORITY_CLASS, PROCESS_DUP_HANDLE, - }, -}; - -pub unsafe fn setup(build: &mut Build) { - // Enable the Windows Error Reporting dialog which msys disables, - // so we can JIT debug rustc - let mode = SetErrorMode(THREAD_ERROR_MODE::default()); - let mode = THREAD_ERROR_MODE(mode); - SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX); - - // Create a new job object for us to use - let job = CreateJobObjectW(None, PCWSTR::null()).unwrap(); - - // Indicate that when all handles to the job object are gone that all - // process in the object should be killed. Note that this includes our - // entire process tree by default because we've added ourselves and our - // children will reside in the job by default. - let mut info = JOBOBJECT_EXTENDED_LIMIT_INFORMATION::default(); - info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - if build.config.low_priority { - info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS; - info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS.0; - } - let r = SetInformationJobObject( - job, - JobObjectExtendedLimitInformation, - &info as *const _ as *const c_void, - mem::size_of_val(&info) as u32, - ) - .ok(); - assert!(r.is_ok(), "{}", io::Error::last_os_error()); - - // Assign our process to this job object. Note that if this fails, one very - // likely reason is that we are ourselves already in a job object! This can - // happen on the build bots that we've got for Windows, or if just anyone - // else is instrumenting the build. In this case we just bail out - // immediately and assume that they take care of it. - // - // Also note that nested jobs (why this might fail) are supported in recent - // versions of Windows, but the version of Windows that our bots are running - // at least don't support nested job objects. - let r = AssignProcessToJobObject(job, GetCurrentProcess()).ok(); - if r.is_err() { - CloseHandle(job); - return; - } - - // If we've got a parent process (e.g., the python script that called us) - // then move ownership of this job object up to them. That way if the python - // script is killed (e.g., via ctrl-c) then we'll all be torn down. - // - // If we don't have a parent (e.g., this was run directly) then we - // intentionally leak the job object handle. When our process exits - // (normally or abnormally) it will close the handle implicitly, causing all - // processes in the job to be cleaned up. - let pid = match env::var("BOOTSTRAP_PARENT_ID") { - Ok(s) => s, - Err(..) => return, - }; - - let parent = match OpenProcess(PROCESS_DUP_HANDLE, false, pid.parse().unwrap()).ok() { - Some(parent) => parent, - _ => { - // If we get a null parent pointer here, it is possible that either - // we have an invalid pid or the parent process has been closed. - // Since the first case rarely happens - // (only when wrongly setting the environmental variable), - // it might be better to improve the experience of the second case - // when users have interrupted the parent process and we haven't finish - // duplicating the handle yet. We just need close the job object if that occurs. - CloseHandle(job); - return; - } - }; - - let mut parent_handle = HANDLE::default(); - let r = DuplicateHandle( - GetCurrentProcess(), - job, - parent, - &mut parent_handle, - 0, - false, - DUPLICATE_SAME_ACCESS, - ) - .ok(); - - // If this failed, well at least we tried! An example of DuplicateHandle - // failing in the past has been when the wrong python2 package spawned this - // build system (e.g., the `python2` package in MSYS instead of - // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure - // mode" here is that we only clean everything up when the build system - // dies, not when the python parent does, so not too bad. - if r.is_err() { - CloseHandle(job); - } -} diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 92aea76382ab..dea553035449 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -152,6 +152,9 @@ pub struct Flags { /// generate PGO profile with llvm built for rustc #[arg(global(true), long)] pub llvm_profile_generate: bool, + /// Enable BOLT link flags + #[arg(global(true), long)] + pub enable_bolt_settings: bool, /// Additional reproducible artifacts that should be added to the reproducible artifacts archive. #[arg(global(true), long)] pub reproducible_artifact: Vec, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/src/lib.rs similarity index 95% rename from src/bootstrap/lib.rs rename to src/bootstrap/src/lib.rs index a9a81cb25f6f..97c743074af4 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -28,70 +28,28 @@ use std::str; use build_helper::ci::{gha, CiEnv}; use build_helper::exit; -use channel::GitInfo; -use config::{DryRun, Target}; use filetime::FileTime; use once_cell::sync::OnceCell; +use termcolor::{ColorChoice, StandardStream, WriteColor}; +use utils::channel::GitInfo; -use crate::builder::Kind; -use crate::config::{LlvmLibunwind, TargetSelection}; -use crate::util::{ - dir_is_empty, exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, +use crate::core::builder; +use crate::core::builder::Kind; +use crate::core::config::flags; +use crate::core::config::{DryRun, Target}; +use crate::core::config::{LlvmLibunwind, TargetSelection}; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::helpers::{ + self, dir_is_empty, exe, libdir, mtime, output, run, run_suppressed, symlink_dir, + try_run_suppressed, }; -mod builder; -mod cache; -mod cc_detect; -mod channel; -mod check; -mod clean; -mod compile; -mod config; -mod dist; -mod doc; -mod download; -mod flags; -mod format; -mod install; -mod llvm; -mod metadata; -mod render_tests; -mod run; -mod sanity; -mod setup; -mod suggest; -mod synthetic_targets; -mod tarball; -mod test; -mod tool; -mod toolstate; -pub mod util; +mod core; +mod utils; -#[cfg(feature = "build-metrics")] -mod metrics; - -#[cfg(windows)] -mod job; - -#[cfg(all(unix, not(target_os = "haiku")))] -mod job { - pub unsafe fn setup(build: &mut crate::Build) { - if build.config.low_priority { - libc::setpriority(libc::PRIO_PGRP as _, 0, 10); - } - } -} - -#[cfg(any(target_os = "haiku", target_os = "hermit", not(any(unix, windows))))] -mod job { - pub unsafe fn setup(_build: &mut crate::Build) {} -} - -pub use crate::builder::PathSet; -use crate::cache::{Interned, INTERNER}; -pub use crate::config::Config; -pub use crate::flags::Subcommand; -use termcolor::{ColorChoice, StandardStream, WriteColor}; +pub use crate::core::builder::PathSet; +pub use crate::core::config::flags::Subcommand; +pub use crate::core::config::Config; const LLVM_TOOLS: &[&str] = &[ "llvm-cov", // used to generate coverage report @@ -210,12 +168,12 @@ pub struct Build { src: PathBuf, out: PathBuf, bootstrap_out: PathBuf, - cargo_info: channel::GitInfo, - rust_analyzer_info: channel::GitInfo, - clippy_info: channel::GitInfo, - miri_info: channel::GitInfo, - rustfmt_info: channel::GitInfo, - in_tree_llvm_info: channel::GitInfo, + cargo_info: GitInfo, + rust_analyzer_info: GitInfo, + clippy_info: GitInfo, + miri_info: GitInfo, + rustfmt_info: GitInfo, + in_tree_llvm_info: GitInfo, local_rebuild: bool, fail_fast: bool, doc_tests: DocTests, @@ -248,7 +206,7 @@ pub struct Build { prerelease_version: Cell>, #[cfg(feature = "build-metrics")] - metrics: metrics::BuildMetrics, + metrics: crate::utils::metrics::BuildMetrics, } #[derive(Debug, Clone)] @@ -372,16 +330,15 @@ impl Build { let is_sudo = false; let omit_git_hash = config.omit_git_hash; - let rust_info = channel::GitInfo::new(omit_git_hash, &src); - let cargo_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/cargo")); - let rust_analyzer_info = - channel::GitInfo::new(omit_git_hash, &src.join("src/tools/rust-analyzer")); - let clippy_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/clippy")); - let miri_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/miri")); - let rustfmt_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt")); + let rust_info = GitInfo::new(omit_git_hash, &src); + let cargo_info = GitInfo::new(omit_git_hash, &src.join("src/tools/cargo")); + let rust_analyzer_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rust-analyzer")); + let clippy_info = GitInfo::new(omit_git_hash, &src.join("src/tools/clippy")); + let miri_info = GitInfo::new(omit_git_hash, &src.join("src/tools/miri")); + let rustfmt_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt")); // we always try to use git for LLVM builds - let in_tree_llvm_info = channel::GitInfo::new(false, &src.join("src/llvm-project")); + let in_tree_llvm_info = GitInfo::new(false, &src.join("src/llvm-project")); let initial_target_libdir_str = if config.dry_run() { "/dummy/lib/path/to/lib/".to_string() @@ -474,7 +431,7 @@ impl Build { prerelease_version: Cell::new(None), #[cfg(feature = "build-metrics")] - metrics: metrics::BuildMetrics::init(), + metrics: crate::utils::metrics::BuildMetrics::init(), }; // If local-rust is the same major.minor as the current version, then force a @@ -493,7 +450,7 @@ impl Build { } build.verbose("finding compilers"); - cc_detect::find(&build); + utils::cc_detect::find(&build); // When running `setup`, the profile is about to change, so any requirements we have now may // be different on the next invocation. Don't check for them until the next time x.py is // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing. @@ -501,7 +458,7 @@ impl Build { // Similarly, for `setup` we don't actually need submodules or cargo metadata. if !matches!(build.config.cmd, Subcommand::Setup { .. }) { build.verbose("running sanity check"); - sanity::check(&mut build); + crate::core::sanity::check(&mut build); // Make sure we update these before gathering metadata so we don't get an error about missing // Cargo.toml files. @@ -513,7 +470,7 @@ impl Build { build.update_existing_submodules(); build.verbose("learning about cargo"); - metadata::build(&mut build); + crate::core::metadata::build(&mut build); } // Make a symbolic link so we can use a consistent directory in the documentation. @@ -549,7 +506,7 @@ impl Build { // NOTE: The check for the empty directory is here because when running x.py the first time, // the submodule won't be checked out. Check it out now so we can build it. - if !channel::GitInfo::new(false, &absolute_path).is_managed_git_subrepository() + if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository() && !dir_is_empty(&absolute_path) { return; @@ -663,7 +620,7 @@ impl Build { // Sample output: `submodule.src/rust-installer.path src/tools/rust-installer` let submodule = Path::new(line.splitn(2, ' ').nth(1).unwrap()); // Don't update the submodule unless it's already been cloned. - if channel::GitInfo::new(false, submodule).is_managed_git_subrepository() { + if GitInfo::new(false, submodule).is_managed_git_subrepository() { self.update_submodule(submodule); } } @@ -672,7 +629,7 @@ impl Build { /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { unsafe { - job::setup(self); + crate::utils::job::setup(self); } // Download rustfmt early so that it can be used in rust-analyzer configs. @@ -681,10 +638,14 @@ impl Build { // hardcoded subcommands match &self.config.cmd { Subcommand::Format { check } => { - return format::format(&builder::Builder::new(&self), *check, &self.config.paths); + return core::build_steps::format::format( + &builder::Builder::new(&self), + *check, + &self.config.paths, + ); } Subcommand::Suggest { run } => { - return suggest::suggest(&builder::Builder::new(&self), *run); + return core::build_steps::suggest::suggest(&builder::Builder::new(&self), *run); } _ => (), } @@ -1065,7 +1026,7 @@ impl Build { /// Return a `Group` guard for a [`Step`] that is built for each `--stage`. /// - /// [`Step`]: crate::builder::Step + /// [`Step`]: crate::core::builder::Step #[must_use = "Groups should not be dropped until the Step finishes running"] #[track_caller] fn msg( @@ -1093,7 +1054,7 @@ impl Build { /// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`. /// - /// [`Step`]: crate::builder::Step + /// [`Step`]: crate::core::builder::Step #[must_use = "Groups should not be dropped until the Step finishes running"] #[track_caller] fn msg_unstaged( @@ -1253,7 +1214,7 @@ impl Build { // that are only existed in CXX libraries Some(self.cxx.borrow()[&target].path().into()) } else if target != self.config.build - && util::use_host_linker(target) + && helpers::use_host_linker(target) && !target.contains("msvc") { Some(self.cc(target)) @@ -1278,7 +1239,7 @@ impl Build { options[0] = Some("-Clink-arg=-fuse-ld=lld".to_string()); } - let no_threads = util::lld_flag_no_threads(target.contains("windows")); + let no_threads = helpers::lld_flag_no_threads(target.contains("windows")); options[1] = Some(format!("-Clink-arg=-Wl,{no_threads}")); } @@ -1418,7 +1379,7 @@ impl Build { fn extract_beta_rev_from_file>(version_file: P) -> Option { let version = fs::read_to_string(version_file).ok()?; - extract_beta_rev(&version) + helpers::extract_beta_rev(&version) } if let Some(s) = self.prerelease_version.get() { @@ -1732,7 +1693,7 @@ impl Build { /// Returns if config.ninja is enabled, and checks for ninja existence, /// exiting with a nicer error message if not. fn ninja(&self) -> bool { - let mut cmd_finder = crate::sanity::Finder::new(); + let mut cmd_finder = crate::core::sanity::Finder::new(); if self.config.ninja_in_file { // Some Linux distros rename `ninja` to `ninja-build`. @@ -1798,17 +1759,6 @@ to download LLVM rather than building it. } } -/// Extract the beta revision from the full version string. -/// -/// The full version string looks like "a.b.c-beta.y". And we need to extract -/// the "y" part from the string. -pub fn extract_beta_rev(version: &str) -> Option { - let parts = version.splitn(2, "-beta.").collect::>(); - let count = parts.get(1).and_then(|s| s.find(' ').map(|p| (&s[..p]).to_string())); - - count -} - #[cfg(unix)] fn chmod(path: &Path, perms: u32) { use std::os::unix::fs::*; diff --git a/src/bootstrap/src/utils/bin_helpers.rs b/src/bootstrap/src/utils/bin_helpers.rs new file mode 100644 index 000000000000..ab41a6b96002 --- /dev/null +++ b/src/bootstrap/src/utils/bin_helpers.rs @@ -0,0 +1,28 @@ +//! This file is meant to be included directly from bootstrap shims to avoid a +//! dependency on the bootstrap library. This reduces the binary size and +//! improves compilation time by reducing the linking time. + +/// Parses the value of the "RUSTC_VERBOSE" environment variable and returns it as a `usize`. +/// If it was not defined, returns 0 by default. +/// +/// Panics if "RUSTC_VERBOSE" is defined with the value that is not an unsigned integer. +pub(crate) fn parse_rustc_verbose() -> usize { + use std::str::FromStr; + + match std::env::var("RUSTC_VERBOSE") { + Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"), + Err(_) => 0, + } +} + +/// Parses the value of the "RUSTC_STAGE" environment variable and returns it as a `String`. +/// +/// If "RUSTC_STAGE" was not set, the program will be terminated with 101. +pub(crate) fn parse_rustc_stage() -> String { + std::env::var("RUSTC_STAGE").unwrap_or_else(|_| { + // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead. + eprintln!("rustc shim: fatal: RUSTC_STAGE was not set"); + eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap"); + std::process::exit(101); + }) +} diff --git a/src/bootstrap/cache.rs b/src/bootstrap/src/utils/cache.rs similarity index 99% rename from src/bootstrap/cache.rs rename to src/bootstrap/src/utils/cache.rs index 53e4ff03431f..1b2aa9c234bb 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/src/utils/cache.rs @@ -14,7 +14,7 @@ use std::sync::Mutex; // FIXME: replace with std::lazy after it gets stabilized and reaches beta use once_cell::sync::Lazy; -use crate::builder::Step; +use crate::core::builder::Step; pub struct Interned(usize, PhantomData<*const T>); diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs similarity index 99% rename from src/bootstrap/cc_detect.rs rename to src/bootstrap/src/utils/cc_detect.rs index 2496c2a9db52..3d3f93f7720e 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -26,8 +26,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::{env, iter}; -use crate::config::{Target, TargetSelection}; -use crate::util::output; +use crate::core::config::{Target, TargetSelection}; +use crate::utils::helpers::output; use crate::{Build, CLang, GitRepo}; // The `cc` crate doesn't provide a way to obtain a path to the detected archiver, diff --git a/src/bootstrap/channel.rs b/src/bootstrap/src/utils/channel.rs similarity index 99% rename from src/bootstrap/channel.rs rename to src/bootstrap/src/utils/channel.rs index 87018574048a..e59d7f22aaae 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/src/utils/channel.rs @@ -9,8 +9,7 @@ use std::fs; use std::path::Path; use std::process::Command; -use crate::util::output; -use crate::util::t; +use crate::utils::helpers::{output, t}; use crate::Build; #[derive(Clone, Default)] diff --git a/src/bootstrap/dylib_util.rs b/src/bootstrap/src/utils/dylib_util.rs similarity index 62% rename from src/bootstrap/dylib_util.rs rename to src/bootstrap/src/utils/dylib_util.rs index b14c0bed66c2..279a6a010f1d 100644 --- a/src/bootstrap/dylib_util.rs +++ b/src/bootstrap/src/utils/dylib_util.rs @@ -1,7 +1,4 @@ -// Various utilities for working with dylib paths. -// -// This file is meant to be included directly to avoid a dependency on the bootstrap library from -// the rustc and rustdoc wrappers. This improves compilation time by reducing the linking time. +//! Various utilities for working with dylib paths. /// Returns the environment variable which the dynamic library lookup path /// resides in for this platform. @@ -21,10 +18,10 @@ pub fn dylib_path_var() -> &'static str { /// Parses the `dylib_path_var()` environment variable, returning a list of /// paths that are members of this lookup path. -pub fn dylib_path() -> Vec { - let var = match env::var_os(dylib_path_var()) { +pub fn dylib_path() -> Vec { + let var = match std::env::var_os(dylib_path_var()) { Some(v) => v, None => return vec![], }; - env::split_paths(&var).collect() + std::env::split_paths(&var).collect() } diff --git a/src/bootstrap/util.rs b/src/bootstrap/src/utils/helpers.rs similarity index 95% rename from src/bootstrap/util.rs rename to src/bootstrap/src/utils/helpers.rs index 3c4a21434c00..90db0a896548 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -12,10 +12,12 @@ use std::process::{Command, Stdio}; use std::str; use std::time::{Instant, SystemTime, UNIX_EPOCH}; -use crate::builder::Builder; -use crate::config::{Config, TargetSelection}; +use crate::core::builder::Builder; +use crate::core::config::{Config, TargetSelection}; use crate::OnceCell; +pub use crate::utils::dylib_util::{dylib_path, dylib_path_var}; + /// A helper macro to `unwrap` a result except also print out details like: /// /// * The file/line of the panic @@ -81,8 +83,6 @@ pub fn add_dylib_path(path: Vec, cmd: &mut Command) { cmd.env(dylib_path_var(), t!(env::join_paths(list))); } -include!("dylib_util.rs"); - /// Adds a list of lookup paths to `cmd`'s link library lookup path. pub fn add_link_lib_path(path: Vec, cmd: &mut Command) { let mut list = link_lib_path(); @@ -293,23 +293,6 @@ pub fn output(cmd: &mut Command) -> String { String::from_utf8(output.stdout).unwrap() } -pub fn output_result(cmd: &mut Command) -> Result { - let output = match cmd.stderr(Stdio::inherit()).output() { - Ok(status) => status, - Err(e) => return Err(format!("failed to run command: {cmd:?}: {e}")), - }; - if !output.status.success() { - return Err(format!( - "command did not execute successfully: {:?}\n\ - expected success, got: {}\n{}", - cmd, - output.status, - String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? - )); - } - Ok(String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?) -} - /// Returns the last-modified time for `path`, or zero if it doesn't exist. pub fn mtime(path: &Path) -> SystemTime { fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH) @@ -495,3 +478,14 @@ pub fn lld_flag_no_threads(is_windows: bool) -> &'static str { pub fn dir_is_empty(dir: &Path) -> bool { t!(std::fs::read_dir(dir)).next().is_none() } + +/// Extract the beta revision from the full version string. +/// +/// The full version string looks like "a.b.c-beta.y". And we need to extract +/// the "y" part from the string. +pub fn extract_beta_rev(version: &str) -> Option { + let parts = version.splitn(2, "-beta.").collect::>(); + let count = parts.get(1).and_then(|s| s.find(' ').map(|p| (&s[..p]).to_string())); + + count +} diff --git a/src/bootstrap/src/utils/job.rs b/src/bootstrap/src/utils/job.rs new file mode 100644 index 000000000000..37235134a28c --- /dev/null +++ b/src/bootstrap/src/utils/job.rs @@ -0,0 +1,161 @@ +#[cfg(windows)] +pub use for_windows::*; + +#[cfg(any(target_os = "haiku", target_os = "hermit", not(any(unix, windows))))] +pub unsafe fn setup(_build: &mut crate::Build) {} + +#[cfg(all(unix, not(target_os = "haiku")))] +pub unsafe fn setup(build: &mut crate::Build) { + if build.config.low_priority { + libc::setpriority(libc::PRIO_PGRP as _, 0, 10); + } +} + +#[cfg(windows)] +mod for_windows { + //! Job management on Windows for bootstrapping + //! + //! Most of the time when you're running a build system (e.g., make) you expect + //! Ctrl-C or abnormal termination to actually terminate the entire tree of + //! process in play, not just the one at the top. This currently works "by + //! default" on Unix platforms because Ctrl-C actually sends a signal to the + //! *process group* rather than the parent process, so everything will get torn + //! down. On Windows, however, this does not happen and Ctrl-C just kills the + //! parent process. + //! + //! To achieve the same semantics on Windows we use Job Objects to ensure that + //! all processes die at the same time. Job objects have a mode of operation + //! where when all handles to the object are closed it causes all child + //! processes associated with the object to be terminated immediately. + //! Conveniently whenever a process in the job object spawns a new process the + //! child will be associated with the job object as well. This means if we add + //! ourselves to the job object we create then everything will get torn down! + //! + //! Unfortunately most of the time the build system is actually called from a + //! python wrapper (which manages things like building the build system) so this + //! all doesn't quite cut it so far. To go the last mile we duplicate the job + //! object handle into our parent process (a python process probably) and then + //! close our own handle. This means that the only handle to the job object + //! resides in the parent python process, so when python dies the whole build + //! system dies (as one would probably expect!). + //! + //! Note that this module has a #[cfg(windows)] above it as none of this logic + //! is required on Unix. + + use crate::Build; + use std::env; + use std::ffi::c_void; + use std::io; + use std::mem; + + use windows::{ + core::PCWSTR, + Win32::Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE}, + Win32::System::Diagnostics::Debug::{ + SetErrorMode, SEM_NOGPFAULTERRORBOX, THREAD_ERROR_MODE, + }, + Win32::System::JobObjects::{ + AssignProcessToJobObject, CreateJobObjectW, JobObjectExtendedLimitInformation, + SetInformationJobObject, JOBOBJECT_EXTENDED_LIMIT_INFORMATION, + JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS, + }, + Win32::System::Threading::{ + GetCurrentProcess, OpenProcess, BELOW_NORMAL_PRIORITY_CLASS, PROCESS_DUP_HANDLE, + }, + }; + + pub unsafe fn setup(build: &mut Build) { + // Enable the Windows Error Reporting dialog which msys disables, + // so we can JIT debug rustc + let mode = SetErrorMode(THREAD_ERROR_MODE::default()); + let mode = THREAD_ERROR_MODE(mode); + SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX); + + // Create a new job object for us to use + let job = CreateJobObjectW(None, PCWSTR::null()).unwrap(); + + // Indicate that when all handles to the job object are gone that all + // process in the object should be killed. Note that this includes our + // entire process tree by default because we've added ourselves and our + // children will reside in the job by default. + let mut info = JOBOBJECT_EXTENDED_LIMIT_INFORMATION::default(); + info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + if build.config.low_priority { + info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS; + info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS.0; + } + let r = SetInformationJobObject( + job, + JobObjectExtendedLimitInformation, + &info as *const _ as *const c_void, + mem::size_of_val(&info) as u32, + ) + .ok(); + assert!(r.is_ok(), "{}", io::Error::last_os_error()); + + // Assign our process to this job object. Note that if this fails, one very + // likely reason is that we are ourselves already in a job object! This can + // happen on the build bots that we've got for Windows, or if just anyone + // else is instrumenting the build. In this case we just bail out + // immediately and assume that they take care of it. + // + // Also note that nested jobs (why this might fail) are supported in recent + // versions of Windows, but the version of Windows that our bots are running + // at least don't support nested job objects. + let r = AssignProcessToJobObject(job, GetCurrentProcess()).ok(); + if r.is_err() { + CloseHandle(job); + return; + } + + // If we've got a parent process (e.g., the python script that called us) + // then move ownership of this job object up to them. That way if the python + // script is killed (e.g., via ctrl-c) then we'll all be torn down. + // + // If we don't have a parent (e.g., this was run directly) then we + // intentionally leak the job object handle. When our process exits + // (normally or abnormally) it will close the handle implicitly, causing all + // processes in the job to be cleaned up. + let pid = match env::var("BOOTSTRAP_PARENT_ID") { + Ok(s) => s, + Err(..) => return, + }; + + let parent = match OpenProcess(PROCESS_DUP_HANDLE, false, pid.parse().unwrap()).ok() { + Some(parent) => parent, + _ => { + // If we get a null parent pointer here, it is possible that either + // we have an invalid pid or the parent process has been closed. + // Since the first case rarely happens + // (only when wrongly setting the environmental variable), + // it might be better to improve the experience of the second case + // when users have interrupted the parent process and we haven't finish + // duplicating the handle yet. We just need close the job object if that occurs. + CloseHandle(job); + return; + } + }; + + let mut parent_handle = HANDLE::default(); + let r = DuplicateHandle( + GetCurrentProcess(), + job, + parent, + &mut parent_handle, + 0, + false, + DUPLICATE_SAME_ACCESS, + ) + .ok(); + + // If this failed, well at least we tried! An example of DuplicateHandle + // failing in the past has been when the wrong python2 package spawned this + // build system (e.g., the `python2` package in MSYS instead of + // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure + // mode" here is that we only clean everything up when the build system + // dies, not when the python parent does, so not too bad. + if r.is_err() { + CloseHandle(job); + } + } +} diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/src/utils/metrics.rs similarity index 99% rename from src/bootstrap/metrics.rs rename to src/bootstrap/src/utils/metrics.rs index cf8d33dfcb01..65794f05d2d9 100644 --- a/src/bootstrap/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -4,8 +4,8 @@ //! As this module requires additional dependencies not present during local builds, it's cfg'd //! away whenever the `build.metrics` config option is not set to `true`. -use crate::builder::{Builder, Step}; -use crate::util::t; +use crate::core::builder::{Builder, Step}; +use crate::utils::helpers::t; use crate::Build; use build_helper::metrics::{ JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test, diff --git a/src/bootstrap/src/utils/mod.rs b/src/bootstrap/src/utils/mod.rs new file mode 100644 index 000000000000..4f531f70cd62 --- /dev/null +++ b/src/bootstrap/src/utils/mod.rs @@ -0,0 +1,14 @@ +//! This module contains integral components of the build and configuration process, providing +//! support for a wide range of tasks and operations such as caching, tarballs, release +//! channels, job management, etc. + +pub(crate) mod cache; +pub(crate) mod cc_detect; +pub(crate) mod channel; +pub(crate) mod dylib_util; +pub(crate) mod helpers; +pub(crate) mod job; +#[cfg(feature = "build-metrics")] +pub(crate) mod metrics; +pub(crate) mod render_tests; +pub(crate) mod tarball; diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs similarity index 99% rename from src/bootstrap/render_tests.rs rename to src/bootstrap/src/utils/render_tests.rs index 6802bf4511bc..f97aa9585135 100644 --- a/src/bootstrap/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -6,7 +6,7 @@ //! and rustc) libtest doesn't include the rendered human-readable output as a JSON field. We had //! to reimplement all the rendering logic in this module because of that. -use crate::builder::Builder; +use crate::core::builder::Builder; use std::io::{BufRead, BufReader, Read, Write}; use std::process::{ChildStdout, Command, Stdio}; use std::time::Duration; diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/src/utils/tarball.rs similarity index 95% rename from src/bootstrap/tarball.rs rename to src/bootstrap/src/utils/tarball.rs index 95d909c5730f..b437456f8a10 100644 --- a/src/bootstrap/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -3,9 +3,10 @@ use std::{ process::Command, }; -use crate::builder::Builder; -use crate::channel; -use crate::util::t; +use crate::core::build_steps::dist::distdir; +use crate::core::builder::Builder; +use crate::utils::channel; +use crate::utils::helpers::t; #[derive(Copy, Clone)] pub(crate) enum OverlayKind { @@ -112,7 +113,7 @@ impl<'a> Tarball<'a> { } fn new_inner(builder: &'a Builder<'a>, component: &str, target: Option) -> Self { - let pkgname = crate::dist::pkgname(builder, component); + let pkgname = crate::core::build_steps::dist::pkgname(builder, component); let mut temp_dir = builder.out.join("tmp").join("tarball").join(component); if let Some(target) = &target { @@ -265,7 +266,7 @@ impl<'a> Tarball<'a> { t!(std::fs::rename(&self.image_dir, &dest)); self.run(|this, cmd| { - let distdir = crate::dist::distdir(this.builder); + let distdir = distdir(this.builder); t!(std::fs::create_dir_all(&distdir)); cmd.arg("tarball") .arg("--input") @@ -292,7 +293,7 @@ impl<'a> Tarball<'a> { .arg("--non-installed-overlay") .arg(&self.overlay_dir) .arg("--output-dir") - .arg(crate::dist::distdir(self.builder)); + .arg(distdir(self.builder)); } fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> GeneratedTarball { @@ -306,11 +307,11 @@ impl<'a> Tarball<'a> { self.builder.install(&self.builder.src.join(file), &self.overlay_dir, 0o644); } - let mut cmd = self.builder.tool_cmd(crate::tool::Tool::RustInstaller); + let mut cmd = self.builder.tool_cmd(crate::core::build_steps::tool::Tool::RustInstaller); let package_name = self.package_name(); self.builder.info(&format!("Dist {package_name}")); - let _time = crate::util::timeit(self.builder); + let _time = crate::utils::helpers::timeit(self.builder); build_cli(&self, &mut cmd); cmd.arg("--work-dir").arg(&self.temp_dir); @@ -344,7 +345,7 @@ impl<'a> Tarball<'a> { .unwrap_or("gz"); GeneratedTarball { - path: crate::dist::distdir(self.builder).join(format!("{package_name}.tar.{ext}")), + path: distdir(self.builder).join(format!("{package_name}.tar.{ext}")), decompressed_output, work: self.temp_dir, } From f1e3e75f6c046796541495da2e7d8a7c852b3e78 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 8 Oct 2023 00:07:59 +0300 Subject: [PATCH 51/94] rename bootstrap module utils/dylib_util->utils/dylib Signed-off-by: onur-ozkan --- src/bootstrap/src/bin/rustc.rs | 2 +- src/bootstrap/src/bin/rustdoc.rs | 2 +- src/bootstrap/src/utils/{dylib_util.rs => dylib.rs} | 0 src/bootstrap/src/utils/helpers.rs | 2 +- src/bootstrap/src/utils/mod.rs | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename src/bootstrap/src/utils/{dylib_util.rs => dylib.rs} (100%) diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index b050713265bf..241ae16e5953 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -25,7 +25,7 @@ use dylib_util::{dylib_path, dylib_path_var}; #[path = "../utils/bin_helpers.rs"] mod bin_helpers; -#[path = "../utils/dylib_util.rs"] +#[path = "../utils/dylib.rs"] mod dylib_util; fn main() { diff --git a/src/bootstrap/src/bin/rustdoc.rs b/src/bootstrap/src/bin/rustdoc.rs index 85d685475b40..f5f80ba2a0b8 100644 --- a/src/bootstrap/src/bin/rustdoc.rs +++ b/src/bootstrap/src/bin/rustdoc.rs @@ -12,7 +12,7 @@ use dylib_util::{dylib_path, dylib_path_var}; #[path = "../utils/bin_helpers.rs"] mod bin_helpers; -#[path = "../utils/dylib_util.rs"] +#[path = "../utils/dylib.rs"] mod dylib_util; fn main() { diff --git a/src/bootstrap/src/utils/dylib_util.rs b/src/bootstrap/src/utils/dylib.rs similarity index 100% rename from src/bootstrap/src/utils/dylib_util.rs rename to src/bootstrap/src/utils/dylib.rs diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 90db0a896548..bb84b70d987f 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -16,7 +16,7 @@ use crate::core::builder::Builder; use crate::core::config::{Config, TargetSelection}; use crate::OnceCell; -pub use crate::utils::dylib_util::{dylib_path, dylib_path_var}; +pub use crate::utils::dylib::{dylib_path, dylib_path_var}; /// A helper macro to `unwrap` a result except also print out details like: /// diff --git a/src/bootstrap/src/utils/mod.rs b/src/bootstrap/src/utils/mod.rs index 4f531f70cd62..7dcb6a828620 100644 --- a/src/bootstrap/src/utils/mod.rs +++ b/src/bootstrap/src/utils/mod.rs @@ -5,7 +5,7 @@ pub(crate) mod cache; pub(crate) mod cc_detect; pub(crate) mod channel; -pub(crate) mod dylib_util; +pub(crate) mod dylib; pub(crate) mod helpers; pub(crate) mod job; #[cfg(feature = "build-metrics")] From 3ecff1b760152191f41bb4872c02f818b80e7d10 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 12 Oct 2023 14:07:36 +0300 Subject: [PATCH 52/94] bootstrap: fix warnings Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/run.rs | 2 -- src/bootstrap/src/utils/bin_helpers.rs | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 29272bebf996..d1d6b7e869ec 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -1,8 +1,6 @@ use std::path::PathBuf; use std::process::Command; -use clap_complete::shells; - use crate::core::build_steps::dist::distdir; use crate::core::build_steps::test; use crate::core::build_steps::tool::{self, SourceType, Tool}; diff --git a/src/bootstrap/src/utils/bin_helpers.rs b/src/bootstrap/src/utils/bin_helpers.rs index ab41a6b96002..b9177c490ac2 100644 --- a/src/bootstrap/src/utils/bin_helpers.rs +++ b/src/bootstrap/src/utils/bin_helpers.rs @@ -18,6 +18,7 @@ pub(crate) fn parse_rustc_verbose() -> usize { /// Parses the value of the "RUSTC_STAGE" environment variable and returns it as a `String`. /// /// If "RUSTC_STAGE" was not set, the program will be terminated with 101. +#[allow(unused)] pub(crate) fn parse_rustc_stage() -> String { std::env::var("RUSTC_STAGE").unwrap_or_else(|_| { // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead. From ba13e37e3088b5c1114a4b258b55d9020c3f4c70 Mon Sep 17 00:00:00 2001 From: Nikolay Arhipov Date: Mon, 16 Oct 2023 00:05:11 +0300 Subject: [PATCH 53/94] Updated libc and doc for Vita target --- library/std/src/os/fd/owned.rs | 6 +- library/std/src/sys/unix/net.rs | 4 +- src/doc/rustc/src/platform-support.md | 2 +- .../armv7-sony-vita-newlibeabihf.md | 137 +++++------------- 4 files changed, 40 insertions(+), 109 deletions(-) diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 81106d6c62c3..24f2bdcf4217 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -97,14 +97,14 @@ impl BorrowedFd<'_> { // We want to atomically duplicate this file descriptor and set the // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This // is a POSIX flag that was added to Linux in 2.6.24. - #[cfg(not(target_os = "espidf"))] + #[cfg(not(any(target_os = "espidf", target_os = "vita")))] let cmd = libc::F_DUPFD_CLOEXEC; // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics // will never be supported, as this is a bare metal framework with // no capabilities for multi-process execution. While F_DUPFD is also // not supported yet, it might be (currently it returns ENOSYS). - #[cfg(target_os = "espidf")] + #[cfg(any(target_os = "espidf", target_os = "vita"))] let cmd = libc::F_DUPFD; // Avoid using file descriptors below 3 as they are used for stdio @@ -119,7 +119,7 @@ impl BorrowedFd<'_> { pub fn try_clone_to_owned(&self) -> crate::io::Result { Err(crate::io::const_io_error!( crate::io::ErrorKind::Unsupported, - "operation not supported on WASI yet", + "operation not supported on this platform", )) } } diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index f450d708dae6..7e2016c410eb 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -103,7 +103,7 @@ impl Socket { } } - #[cfg(not(any(target_os = "vxworks", target_os = "vita")))] + #[cfg(not(target_os = "vxworks"))] pub fn new_pair(fam: c_int, ty: c_int) -> io::Result<(Socket, Socket)> { unsafe { let mut fds = [0, 0]; @@ -135,7 +135,7 @@ impl Socket { } } - #[cfg(any(target_os = "vxworks", target_os = "vita"))] + #[cfg(target_os = "vxworks")] pub fn new_pair(_fam: c_int, _ty: c_int) -> io::Result<(Socket, Socket)> { unimplemented!() } diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 1fb5e56db5d7..db834600b9c1 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -244,7 +244,7 @@ target | std | host | notes `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD [`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv6 NetBSD w/hard-float [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) -[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? | | ARMv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) +[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ✓ | | ARMv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) [`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | ARMv7-A OpenHarmony | [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7-A Linux with uClibc, softfloat [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7-A Linux with uClibc, hardfloat diff --git a/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md b/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md index 49eed366dacf..e1473bd966c4 100644 --- a/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md +++ b/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md @@ -2,15 +2,16 @@ **Tier: 3** -This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. `armv7-vita-newlibeabihf` aims to have support for `std` crate using `newlib` as a bridge. +This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. Rust support for this target is not affiliated with Sony, and is not derived from nor used with any official Sony SDK. ## Target maintainers -* [@amg98](https://github.com/amg98) * [@nikarh](https://github.com/nikarh) +* [@pheki](https://github.com/pheki) +* [@ZetaNumbers](https://github.com/ZetaNumbers) ## Requirements @@ -20,18 +21,16 @@ This target is cross-compiled, and requires installing [VITASDK](https://vitasdk `alloc`, and `panic_abort`. `std` is partially supported, but mostly works. Some APIs are unimplemented -and will simply return an error, such as `std::process`. An allocator is provided -by default. +and will simply return an error, such as `std::process`. -In order to support some APIs, binaries must be linked against `libc` written -for the target, using a linker for the target. These are provided by the -VITASDK toolchain. +This target generates binaries in the ELF format with thumb ISA by default. + +Binaries are linked with `arm-vita-eabi-gcc` provided by VITASDK toolchain. -This target generates binaries in the ELF format with thumb ISA. ## Building the target -Rust does not ship pre-compiled artifacts for this target. You can use `build-std` flag to build binaries with `std`: +Rust does not ship pre-compiled artifacts for this target. You can use `build-std` flag to build ELF binaries with `std`: ```sh cargo build -Z build-std=std,panic_abort --target=armv7-sony-vita-newlibeabihf --release @@ -39,113 +38,45 @@ cargo build -Z build-std=std,panic_abort --target=armv7-sony-vita-newlibeabihf - ## Building Rust programs -To test your developed rust programs on PlayStation Vita, first you must correctly package your elf. These steps can be preformed using tools available in VITASDK, and can be automated using a tool like `cargo-make`. +The recommended way to build artifacts that can be installed and run on PlayStation Vita is by using the [cargo-vita](https://github.com/vita-rust/cargo-vita) tool. This tool uses `build-std` and VITASDK toolchain to build artifacts runnable on Vita. -First, set up environment variables for `VITASDK`, and it's binaries: +To install the tool run: + +```sh +cargo install cargo-vita +``` + +[VITASDK](https://vitasdk.org/) toolchain must be installed, and the `VITASDK` environment variable must be set to its location, e.g.: ```sh export VITASDK=/opt/vitasdk -export PATH=$PATH:$VITASDK/bin ``` -Use the example below as a template for your project: +Add the following section to your project's `Cargo.toml`: + ```toml -[env] -TITLE = "Rust Hello World" -TITLEID = "RUST00001" - -# At least a "sce_sys" folder should be place there for app metadata (title, icons, description...) -# You can find sample assets for that on $VITASDK/share/gcc-arm-vita-eabi/samples/hello_world/sce_sys/ -STATIC_DIR = "static" # Folder where static assets should be placed (sce_sys folder is at $STATIC_DIR/sce_sys) -CARGO_TARGET_DIR = { script = ["echo ${CARGO_TARGET_DIR:=target}"] } -CARGO_OUT_DIR = "${CARGO_TARGET_DIR}/${RUST_TARGET}/release" - -[tasks.build] -description = "Build the project using `cargo`." -command = "cargo" -args = ["build", "-Z", "build-std=std,panic_abort", "--target=armv7-sony-vita-newlibeabihf", "--release"] - -[tasks.strip] -description = "Strip the produced ELF executable." -dependencies = ["build"] -command = "arm-vita-eabi-strip" -args = ["-g", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_FS_NAME}.elf'] - -[tasks.velf] -description = "Build an VELF executable from the obtained ELF file." -dependencies = ["strip"] -command = "vita-elf-create" -args = ['${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.elf', '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf'] - -[tasks.eboot-bin] -description = "Build an `eboot.bin` file from the obtained VELF file." -dependencies = ["velf"] -command = "vita-make-fself" -args = ["-s", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf', '${CARGO_OUT_DIR}/eboot.bin'] - -[tasks.param-sfo] -description = "Build the `param.sfo` manifest using with given TITLE and TITLEID." -command = "vita-mksfoex" -args = ["-s", 'TITLE_ID=${TITLEID}', '${TITLE}', '${CARGO_OUT_DIR}/param.sfo'] - -[tasks.manifest] -description = "List all static resources into a manifest file." -script = [ - 'mkdir -p "${CARGO_OUT_DIR}"', - ''' - if [ -d "${STATIC_DIR}" ]; then - find "${STATIC_DIR}" -type f > "${CARGO_OUT_DIR}/MANIFEST" - else - touch "${CARGO_OUT_DIR}/MANIFEST" - fi - ''' -] - -[tasks.vpk] -description = "Build a VPK distribution of the project executable and resources." -dependencies = ["eboot-bin", "param-sfo", "manifest"] -script_runner = "@rust" -script = [ - ''' - use std::io::BufRead; - use std::fs::File; - - fn main() { - - let crate_name = env!("CARGO_MAKE_CRATE_NAME"); - let static_dir = env!("STATIC_DIR"); - let out_dir = std::path::PathBuf::from(env!("CARGO_OUT_DIR")); - - let mut cmd = ::std::process::Command::new("vita-pack-vpk"); - cmd.arg("-s").arg(out_dir.join("param.sfo")); - cmd.arg("-b").arg(out_dir.join("eboot.bin")); - - // Add files from MANIFEST - if let Ok(file) = File::open(out_dir.join("MANIFEST")) { - let mut reader = ::std::io::BufReader::new(file); - let mut lines = reader.lines(); - while let Some(Ok(line)) = lines.next() { - let p1 = ::std::path::PathBuf::from(line); // path on FS - let p2 = p1.strip_prefix(static_dir).unwrap(); // path in VPK - cmd.arg("--add").arg(format!("{}={}", p1.display(), p2.display())); - } - } - - cmd.arg(out_dir.join(format!("{}.vpk", crate_name))) - .output() - .expect("command failed."); - } - ''' -] +[package.metadata.vita] +# A unique 9 character alphanumeric identifier of the app. +title_id = "RUSTAPP01" +# A title that will be used for the app. Optional, name will be used if not defined +title_name = "My application" ``` -After running the above script, you should be able to get a *.vpk file in the same folder your *.elf executable resides. Now you can pick it and install it on your own PlayStation Vita using, or you can use an [Vita3K](https://vita3k.org/) emulator. +To build a VPK with ELF in the release profile, run: + +```sh +cargo vita build vpk --release +``` + +After building a *.vpk file it can be uploaded to a PlayStation Vita and installed, or used with a [Vita3K](https://vita3k.org/) emulator. ## Testing -Currently there is no support to run the rustc test suite for this target. +The default Rust test runner is supported, and tests can be compiled to an elf and packed to a *.vpk file using `cargo-vita` tool. Filtering tests is not currently supported since passing command-line arguments to the executable is not supported on Vita, so the runner will always execute all tests. + +The Rust test suite for `library/std` is not yet supported. ## Cross-compilation -This target can be cross-compiled from `x86_64` on either Windows, MacOS or Linux systems. Other hosts are not supported for cross-compilation. +This target can be cross-compiled from `x86_64` on Windows, MacOS or Linux systems. Other hosts are not supported for cross-compilation. From ab22470eb3592f41634e411ffe98343f70053e57 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 17 Oct 2023 10:44:45 +0200 Subject: [PATCH 54/94] Update to LLVM 17.0.3 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index d404cba4e39d..febc39711a7c 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit d404cba4e39df595710869988ded7cbe1104b52f +Subproject commit febc39711a7c91560eb0f0980916ae23c343b99d From 8f970c72a638e0fec70030f7c51e56d6b3564d90 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 17 Oct 2023 10:26:13 -0400 Subject: [PATCH 55/94] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 6fa6fdc7606c..8eb8acbb116e 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 6fa6fdc7606cfa664f9bee2fb33ee2ed904f4e88 +Subproject commit 8eb8acbb116e7923ea2ce33a50109933ed5ab375 From a8e7e791010a2ff1fca1b65dce48096419b99638 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Mon, 16 Oct 2023 11:05:04 -0700 Subject: [PATCH 56/94] disable missing_copy_implementations lint on non_exhaustive types use is_variant_list_non_exhaustive/is_field_list_non_exhaustive remove unused tcx inline non_exhaustive def/variant check --- compiler/rustc_lint/src/builtin.rs | 5 ++++ ...ing-copy-implementations-non-exhaustive.rs | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tests/ui/lint/missing-copy-implementations-non-exhaustive.rs diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 536f78a73edb..12e818b81cb3 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -677,6 +677,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { if type_implements_negative_copy_modulo_regions(cx.tcx, ty, param_env) { return; } + if def.is_variant_list_non_exhaustive() + || def.variants().iter().any(|variant| variant.is_field_list_non_exhaustive()) + { + return; + } // We shouldn't recommend implementing `Copy` on stateful things, // such as iterators. diff --git a/tests/ui/lint/missing-copy-implementations-non-exhaustive.rs b/tests/ui/lint/missing-copy-implementations-non-exhaustive.rs new file mode 100644 index 000000000000..2d5e90720ef2 --- /dev/null +++ b/tests/ui/lint/missing-copy-implementations-non-exhaustive.rs @@ -0,0 +1,25 @@ +// Test for issue #116766. +// Ensure that we don't suggest impl'ing `Copy` for a type if it or at least one +// of it's variants are marked as `non_exhaustive`. + +// check-pass + +#![deny(missing_copy_implementations)] + +#[non_exhaustive] +pub enum MyEnum { + A, +} + +#[non_exhaustive] +pub struct MyStruct { + foo: usize, +} + +pub enum MyEnum2 { + #[non_exhaustive] + A, + B, +} + +fn main() {} From 3895f0e9affaab800f5f2cdc06726aeee9a7ff10 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 16 Oct 2023 20:26:12 +0200 Subject: [PATCH 57/94] Remove "subprinter" types from `Printer` These are `Self` in almost all printers except one, which can just store the state as a field instead. This simplifies the printer and allows for further simplifications, for example using `&mut self` instead of passing around the printer. --- .../rustc_const_eval/src/util/type_name.rs | 30 +++--- .../src/infer/error_reporting/mod.rs | 49 +++++----- compiler/rustc_lint/src/context.rs | 62 ++++++------ compiler/rustc_middle/src/ty/print/mod.rs | 46 ++++----- compiler/rustc_middle/src/ty/print/pretty.rs | 98 +++++++------------ compiler/rustc_symbol_mangling/src/legacy.rs | 30 +++--- compiler/rustc_symbol_mangling/src/v0.rs | 34 +++---- 7 files changed, 149 insertions(+), 200 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index a924afda6f07..5a068feb2d2f 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -16,21 +16,15 @@ struct AbsolutePathPrinter<'tcx> { impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { type Error = std::fmt::Error; - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - type Const = Self; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { + fn print_region(self, _region: ty::Region<'_>) -> Result { Ok(self) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { match *ty.kind() { // Types without identity. ty::Bool @@ -68,18 +62,18 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } } - fn print_const(self, ct: ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { self.pretty_print_const(ct, false) } fn print_dyn_existential( self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { self.pretty_print_dyn_existential(predicates) } - fn path_crate(mut self, cnum: CrateNum) -> Result { + fn path_crate(mut self, cnum: CrateNum) -> Result { self.path.push_str(self.tcx.crate_name(cnum).as_str()); Ok(self) } @@ -88,17 +82,17 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.pretty_path_qualified(self_ty, trait_ref) } fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.pretty_path_append_impl( |mut cx| { cx = print_prefix(cx)?; @@ -114,9 +108,9 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; write!(self.path, "::{}", disambiguated_data.data).unwrap(); @@ -126,9 +120,9 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { self = print_prefix(self)?; let args = args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_))); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d35b318e258d..5a3188b02eeb 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -580,6 +580,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { struct AbsolutePathPrinter<'tcx> { tcx: TyCtxt<'tcx>, + segments: Vec, } struct NonTrivialPath; @@ -587,69 +588,64 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { type Error = NonTrivialPath; - type Path = Vec; - type Region = !; - type Type = !; - type DynExistential = !; - type Const = !; - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { + fn print_region(self, _region: ty::Region<'_>) -> Result { Err(NonTrivialPath) } - fn print_type(self, _ty: Ty<'tcx>) -> Result { + fn print_type(self, _ty: Ty<'tcx>) -> Result { Err(NonTrivialPath) } fn print_dyn_existential( self, _predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { Err(NonTrivialPath) } - fn print_const(self, _ct: ty::Const<'tcx>) -> Result { + fn print_const(self, _ct: ty::Const<'tcx>) -> Result { Err(NonTrivialPath) } - fn path_crate(self, cnum: CrateNum) -> Result { - Ok(vec![self.tcx.crate_name(cnum).to_string()]) + fn path_crate(mut self, cnum: CrateNum) -> Result { + self.segments = vec![self.tcx.crate_name(cnum).to_string()]; + Ok(self) } fn path_qualified( self, _self_ty: Ty<'tcx>, _trait_ref: Option>, - ) -> Result { + ) -> Result { Err(NonTrivialPath) } fn path_append_impl( self, - _print_prefix: impl FnOnce(Self) -> Result, + _print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, _self_ty: Ty<'tcx>, _trait_ref: Option>, - ) -> Result { + ) -> Result { Err(NonTrivialPath) } fn path_append( - self, - print_prefix: impl FnOnce(Self) -> Result, + mut self, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { - let mut path = print_prefix(self)?; - path.push(disambiguated_data.to_string()); - Ok(path) + ) -> Result { + self = print_prefix(self)?; + self.segments.push(disambiguated_data.to_string()); + Ok(self) } fn path_generic_args( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { print_prefix(self) } } @@ -659,8 +655,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // are from a local module we could have false positives, e.g. // let _ = [{struct Foo; Foo}, {struct Foo; Foo}]; if did1.krate != did2.krate { - let abs_path = - |def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]); + let abs_path = |def_id| { + AbsolutePathPrinter { tcx: self.tcx, segments: vec![] } + .print_def_path(def_id, &[]) + .map(|p| p.segments) + }; // We compare strings because DefPath can be different // for imported and non-imported crates diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index eb1c6be48e64..af7f2bcf6690 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -1200,51 +1200,47 @@ impl<'tcx> LateContext<'tcx> { /// } /// ``` pub fn get_def_path(&self, def_id: DefId) -> Vec { - pub struct AbsolutePathPrinter<'tcx> { - pub tcx: TyCtxt<'tcx>, + struct AbsolutePathPrinter<'tcx> { + tcx: TyCtxt<'tcx>, + path: Vec, } impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { type Error = !; - type Path = Vec; - type Region = (); - type Type = (); - type DynExistential = (); - type Const = (); - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { - Ok(()) + fn print_region(self, _region: ty::Region<'_>) -> Result { + Ok(self) } - fn print_type(self, _ty: Ty<'tcx>) -> Result { - Ok(()) + fn print_type(self, _ty: Ty<'tcx>) -> Result { + Ok(self) } fn print_dyn_existential( self, _predicates: &'tcx ty::List>, - ) -> Result { - Ok(()) + ) -> Result { + Ok(self) } - fn print_const(self, _ct: ty::Const<'tcx>) -> Result { - Ok(()) + fn print_const(self, _ct: ty::Const<'tcx>) -> Result { + Ok(self) } - fn path_crate(self, cnum: CrateNum) -> Result { - Ok(vec![self.tcx.crate_name(cnum)]) + fn path_crate(mut self, cnum: CrateNum) -> Result { + self.path = vec![self.tcx.crate_name(cnum)]; + Ok(self) } fn path_qualified( - self, + mut self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { if trait_ref.is_none() { if let ty::Adt(def, args) = self_ty.kind() { return self.print_def_path(def.did(), args); @@ -1253,24 +1249,25 @@ impl<'tcx> LateContext<'tcx> { // This shouldn't ever be needed, but just in case: with_no_trimmed_paths!({ - Ok(vec![match trait_ref { + self.path = vec![match trait_ref { Some(trait_ref) => Symbol::intern(&format!("{trait_ref:?}")), None => Symbol::intern(&format!("<{self_ty}>")), - }]) + }]; + Ok(self) }) } fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { let mut path = print_prefix(self)?; // This shouldn't ever be needed, but just in case: - path.push(match trait_ref { + path.path.push(match trait_ref { Some(trait_ref) => { with_no_trimmed_paths!(Symbol::intern(&format!( "", @@ -1288,9 +1285,9 @@ impl<'tcx> LateContext<'tcx> { fn path_append( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { let mut path = print_prefix(self)?; // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. @@ -1298,20 +1295,23 @@ impl<'tcx> LateContext<'tcx> { return Ok(path); } - path.push(Symbol::intern(&disambiguated_data.data.to_string())); + path.path.push(Symbol::intern(&disambiguated_data.data.to_string())); Ok(path) } fn path_generic_args( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { print_prefix(self) } } - AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]).unwrap() + AbsolutePathPrinter { tcx: self.tcx, path: vec![] } + .print_def_path(def_id, &[]) + .unwrap() + .path } /// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`. diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index aa8e2e30715e..263f192b280f 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -31,19 +31,13 @@ pub trait Print<'tcx, P> { pub trait Printer<'tcx>: Sized { type Error; - type Path; - type Region; - type Type; - type DynExistential; - type Const; - fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; fn print_def_path( self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { self.default_print_def_path(def_id, args) } @@ -53,48 +47,48 @@ pub trait Printer<'tcx>: Sized { args: &'tcx [GenericArg<'tcx>], self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.default_print_impl_path(impl_def_id, args, self_ty, trait_ref) } - fn print_region(self, region: ty::Region<'tcx>) -> Result; + fn print_region(self, region: ty::Region<'tcx>) -> Result; - fn print_type(self, ty: Ty<'tcx>) -> Result; + fn print_type(self, ty: Ty<'tcx>) -> Result; fn print_dyn_existential( self, predicates: &'tcx ty::List>, - ) -> Result; + ) -> Result; - fn print_const(self, ct: ty::Const<'tcx>) -> Result; + fn print_const(self, ct: ty::Const<'tcx>) -> Result; - fn path_crate(self, cnum: CrateNum) -> Result; + fn path_crate(self, cnum: CrateNum) -> Result; fn path_qualified( self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result; + ) -> Result; fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result; + ) -> Result; fn path_append( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result; + ) -> Result; fn path_generic_args( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result; + ) -> Result; // Defaults (should not be overridden): @@ -103,7 +97,7 @@ pub trait Printer<'tcx>: Sized { self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { let key = self.tcx().def_key(def_id); debug!(?key); @@ -194,7 +188,7 @@ pub trait Printer<'tcx>: Sized { _args: &'tcx [GenericArg<'tcx>], self_ty: Ty<'tcx>, impl_trait_ref: Option>, - ) -> Result { + ) -> Result { debug!( "default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}", impl_def_id, self_ty, impl_trait_ref @@ -295,7 +289,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> { - type Output = P::Region; + type Output = P; type Error = P::Error; fn print(&self, cx: P) -> Result { cx.print_region(*self) @@ -303,7 +297,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> { } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { - type Output = P::Type; + type Output = P; type Error = P::Error; fn print(&self, cx: P) -> Result { @@ -312,7 +306,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List> { - type Output = P::DynExistential; + type Output = P; type Error = P::Error; fn print(&self, cx: P) -> Result { cx.print_dyn_existential(self) @@ -320,7 +314,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List> Print<'tcx, P> for ty::Const<'tcx> { - type Output = P::Const; + type Output = P; type Error = P::Error; fn print(&self, cx: P) -> Result { cx.print_const(*self) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index e321f0a7b7f2..31d6b65111fe 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -205,23 +205,13 @@ impl<'tcx> RegionHighlightMode<'tcx> { } /// Trait for printers that pretty-print using `fmt::Write` to the printer. -pub trait PrettyPrinter<'tcx>: - Printer< - 'tcx, - Error = fmt::Error, - Path = Self, - Region = Self, - Type = Self, - DynExistential = Self, - Const = Self, - > + fmt::Write -{ +pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { /// Like `print_def_path` but for value paths. fn print_value_path( self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { self.print_def_path(def_id, args) } @@ -264,7 +254,7 @@ pub trait PrettyPrinter<'tcx>: f: impl FnOnce(Self) -> Result, t: impl FnOnce(Self) -> Result, conversion: &str, - ) -> Result { + ) -> Result { self.write_str("{")?; self = f(self)?; self.write_str(conversion)?; @@ -305,10 +295,7 @@ pub trait PrettyPrinter<'tcx>: // For enum variants, if they have an unique name, then we only print the name, otherwise we // print the enum name and the variant name. Otherwise, we do not print anything and let the // caller use the `print_def_path` fallback. - fn force_print_trimmed_def_path( - mut self, - def_id: DefId, - ) -> Result<(Self::Path, bool), Self::Error> { + fn force_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), Self::Error> { let key = self.tcx().def_key(def_id); let visible_parent_map = self.tcx().visible_parent_map(()); let kind = self.tcx().def_kind(def_id); @@ -378,10 +365,7 @@ pub trait PrettyPrinter<'tcx>: } /// Try to see if this path can be trimmed to a unique symbol name. - fn try_print_trimmed_def_path( - mut self, - def_id: DefId, - ) -> Result<(Self::Path, bool), Self::Error> { + fn try_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), Self::Error> { if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?; if trimmed { @@ -595,7 +579,7 @@ pub trait PrettyPrinter<'tcx>: self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { if trait_ref.is_none() { // Inherent impls. Try to print `Foo::bar` for an inherent // impl on `Foo`, but fallback to `::bar` if self-type is @@ -629,10 +613,10 @@ pub trait PrettyPrinter<'tcx>: fn pretty_path_append_impl( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self = print_prefix(self)?; self.generic_delimiters(|mut cx| { @@ -648,7 +632,7 @@ pub trait PrettyPrinter<'tcx>: }) } - fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result { + fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result { define_scoped_cx!(self); match *ty.kind() { @@ -919,7 +903,7 @@ pub trait PrettyPrinter<'tcx>: mut self, def_id: DefId, args: &'tcx ty::List>, - ) -> Result { + ) -> Result { let tcx = self.tcx(); // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, @@ -1189,7 +1173,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_print_inherent_projection( self, alias_ty: &ty::AliasTy<'tcx>, - ) -> Result { + ) -> Result { let def_key = self.tcx().def_key(alias_ty.def_id); self.path_generic_args( |cx| { @@ -1213,7 +1197,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { // Generate the main trait ref, including associated types. let mut first = true; @@ -1328,7 +1312,7 @@ pub trait PrettyPrinter<'tcx>: mut self, ct: ty::Const<'tcx>, print_ty: bool, - ) -> Result { + ) -> Result { define_scoped_cx!(self); if self.should_print_verbose() { @@ -1404,11 +1388,7 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } - fn pretty_print_const_scalar( - self, - scalar: Scalar, - ty: Ty<'tcx>, - ) -> Result { + fn pretty_print_const_scalar(self, scalar: Scalar, ty: Ty<'tcx>) -> Result { match scalar { Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty), Scalar::Int(int) => { @@ -1421,7 +1401,7 @@ pub trait PrettyPrinter<'tcx>: mut self, ptr: Pointer, ty: Ty<'tcx>, - ) -> Result { + ) -> Result { define_scoped_cx!(self); let (alloc_id, offset) = ptr.into_parts(); @@ -1483,7 +1463,7 @@ pub trait PrettyPrinter<'tcx>: int: ScalarInt, ty: Ty<'tcx>, print_ty: bool, - ) -> Result { + ) -> Result { define_scoped_cx!(self); match ty.kind() { @@ -1545,7 +1525,7 @@ pub trait PrettyPrinter<'tcx>: self, _: Pointer, ty: Ty<'tcx>, - ) -> Result { + ) -> Result { self.typed_value( |mut this| { this.write_str("&_")?; @@ -1556,7 +1536,7 @@ pub trait PrettyPrinter<'tcx>: ) } - fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result { + fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result { write!(self, "b\"{}\"", byte_str.escape_ascii())?; Ok(self) } @@ -1566,7 +1546,7 @@ pub trait PrettyPrinter<'tcx>: valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>, print_ty: bool, - ) -> Result { + ) -> Result { define_scoped_cx!(self); if self.should_print_verbose() { @@ -1689,7 +1669,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_closure_as_impl( mut self, closure: ty::ClosureArgs<'tcx>, - ) -> Result { + ) -> Result { let sig = closure.sig(); let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn); @@ -1864,12 +1844,6 @@ impl fmt::Write for FmtPrinter<'_, '_> { impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { type Error = fmt::Error; - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - type Const = Self; - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } @@ -1878,7 +1852,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { define_scoped_cx!(self); if args.is_empty() { @@ -1933,11 +1907,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { self.default_print_def_path(def_id, args) } - fn print_region(self, region: ty::Region<'tcx>) -> Result { + fn print_region(self, region: ty::Region<'tcx>) -> Result { self.pretty_print_region(region) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { if self.type_length_limit.value_within_limit(self.printed_type_count) { self.printed_type_count += 1; self.pretty_print_type(ty) @@ -1951,15 +1925,15 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn print_dyn_existential( self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { self.pretty_print_dyn_existential(predicates) } - fn print_const(self, ct: ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { self.pretty_print_const(ct, false) } - fn path_crate(mut self, cnum: CrateNum) -> Result { + fn path_crate(mut self, cnum: CrateNum) -> Result { self.empty_path = true; if cnum == LOCAL_CRATE { if self.tcx.sess.at_least_rust_2018() { @@ -1980,7 +1954,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { mut self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self = self.pretty_path_qualified(self_ty, trait_ref)?; self.empty_path = false; Ok(self) @@ -1988,11 +1962,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_append_impl( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self = self.pretty_path_append_impl( |mut cx| { cx = print_prefix(cx)?; @@ -2011,9 +1985,9 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. @@ -2042,9 +2016,9 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { self = print_prefix(self)?; let tcx = self.tcx; @@ -2101,7 +2075,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { let was_in_value = std::mem::replace(&mut self.in_value, true); self = self.print_def_path(def_id, args)?; self.in_value = was_in_value; @@ -2132,7 +2106,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { f: impl FnOnce(Self) -> Result, t: impl FnOnce(Self) -> Result, conversion: &str, - ) -> Result { + ) -> Result { self.write_str("{")?; self = f(self)?; self.write_str(conversion)?; @@ -2206,7 +2180,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self, p: Pointer, ty: Ty<'tcx>, - ) -> Result { + ) -> Result { let print = |mut this: Self| { define_scoped_cx!(this); if this.print_alloc_ids { diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 2fc102bda134..06b3f91ebef6 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -202,21 +202,15 @@ struct SymbolPrinter<'tcx> { impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { type Error = fmt::Error; - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - type Const = Self; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { + fn print_region(self, _region: ty::Region<'_>) -> Result { Ok(self) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { match *ty.kind() { // Print all nominal types as paths (unlike `pretty_print_type`). ty::FnDef(def_id, args) @@ -250,7 +244,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { fn print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { let mut first = true; for p in predicates { if !first { @@ -262,7 +256,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { Ok(self) } - fn print_const(self, ct: ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { // only print integers match (ct.kind(), ct.ty().kind()) { (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => { @@ -280,7 +274,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { Ok(self) } - fn path_crate(self, cnum: CrateNum) -> Result { + fn path_crate(self, cnum: CrateNum) -> Result { self.write_str(self.tcx.crate_name(cnum).as_str())?; Ok(self) } @@ -288,7 +282,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { // Similar to `pretty_path_qualified`, but for the other // types that are printed as paths (see `print_type` above). match self_ty.kind() { @@ -304,11 +298,11 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.pretty_path_append_impl( |mut cx| { cx = print_prefix(cx)?; @@ -328,9 +322,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { } fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. @@ -351,9 +345,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { } fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { self = print_prefix(self)?; let args = diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 82b1a772e3d7..249cdf7bdfab 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -232,12 +232,6 @@ impl<'tcx> SymbolMangler<'tcx> { impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { type Error = !; - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - type Const = Self; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -246,7 +240,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { if let Some(&i) = self.paths.get(&(def_id, args)) { return self.print_backref(i); } @@ -268,7 +262,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { args: &'tcx [GenericArg<'tcx>], mut self_ty: Ty<'tcx>, mut impl_trait_ref: Option>, - ) -> Result { + ) -> Result { let key = self.tcx.def_key(impl_def_id); let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; @@ -321,7 +315,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn print_region(self, region: ty::Region<'_>) -> Result { + fn print_region(self, region: ty::Region<'_>) -> Result { let i = match *region { // Erased lifetimes use the index 0, for a // shorter mangling of `L_`. @@ -343,7 +337,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { // Basic types, never cached (single-character). let basic_type = match ty.kind() { ty::Bool => "b", @@ -498,7 +492,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { // Okay, so this is a bit tricky. Imagine we have a trait object like // `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the // output looks really close to the syntax, where the `Bar = &'a ()` bit @@ -559,7 +553,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn print_const(mut self, ct: ty::Const<'tcx>) -> Result { + fn print_const(mut self, ct: ty::Const<'tcx>) -> Result { // We only mangle a typed value if the const can be evaluated. let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all()); match ct.kind() { @@ -731,7 +725,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn path_crate(self, cnum: CrateNum) -> Result { + fn path_crate(self, cnum: CrateNum) -> Result { self.push("C"); let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); self.push_disambiguator(stable_crate_id.as_u64()); @@ -744,7 +738,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { mut self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { assert!(trait_ref.is_some()); let trait_ref = trait_ref.unwrap(); @@ -755,20 +749,20 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn path_append_impl( self, - _: impl FnOnce(Self) -> Result, + _: impl FnOnce(Self) -> Result, _: &DisambiguatedDefPathData, _: Ty<'tcx>, _: Option>, - ) -> Result { + ) -> Result { // Inlined into `print_impl_path` unreachable!() } fn path_append( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { let ns = match disambiguated_data.data { // Extern block segments can be skipped, names from extern blocks // are effectively living in their parent modules. @@ -806,9 +800,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { // Don't print any regions if they're all erased. let print_regions = args.iter().any(|arg| match arg.unpack() { GenericArgKind::Lifetime(r) => !r.is_erased(), From 0b5a4c1adfc4cede0fa06243ef9e7447e286affb Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 16 Oct 2023 20:36:56 +0200 Subject: [PATCH 58/94] Remove `Print::Output` Now that `Printer` doesn't have subprinters anymore, the output of a printing operation is always the same. --- .../rustc_const_eval/src/util/type_name.rs | 2 +- .../nice_region_error/placeholder_error.rs | 4 +-- compiler/rustc_middle/src/ty/print/mod.rs | 15 +++------ compiler/rustc_middle/src/ty/print/pretty.rs | 31 +++++++++---------- compiler/rustc_symbol_mangling/src/legacy.rs | 2 +- .../error_reporting/type_err_ctxt_ext.rs | 16 +++------- 6 files changed, 27 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 5a068feb2d2f..fba8121ead03 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -140,7 +140,7 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { } fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error>, + T: Print<'tcx, Self, Error = Self::Error>, { if let Some(first) = elems.next() { self = first.print(self)?; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 4aec28b051f1..17a265fd4f47 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -28,7 +28,7 @@ pub struct Highlighted<'tcx, T> { impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T> where - T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error>, { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { rustc_errors::DiagnosticArgValue::Str(self.to_string().into()) @@ -43,7 +43,7 @@ impl<'tcx, T> Highlighted<'tcx, T> { impl<'tcx, T> fmt::Display for Highlighted<'tcx, T> where - T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS); diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 263f192b280f..e789374fdd63 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -13,10 +13,9 @@ pub use self::pretty::*; // FIXME(eddyb) false positive, the lifetime parameters are used with `P: Printer<...>`. #[allow(unused_lifetimes)] pub trait Print<'tcx, P> { - type Output; type Error; - fn print(&self, cx: P) -> Result; + fn print(&self, cx: P) -> Result; } /// Interface for outputting user-facing "type-system entities" @@ -289,34 +288,30 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> { - type Output = P; type Error = P::Error; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.print_region(*self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { - type Output = P; type Error = P::Error; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.print_type(*self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List> { - type Output = P; type Error = P::Error; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.print_dyn_existential(self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { - type Output = P; type Error = P::Error; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.print_const(*self) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 31d6b65111fe..ae3e6885b759 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -217,7 +217,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = Self::Error> + TypeFoldable>, { value.as_ref().skip_binder().print(self) } @@ -228,7 +228,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { f: F, ) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = Self::Error> + TypeFoldable>, { f(value.as_ref().skip_binder(), self) } @@ -236,7 +236,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { /// Prints comma-separated elements. fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error>, + T: Print<'tcx, Self, Error = Self::Error>, { if let Some(first) = elems.next() { self = first.print(self)?; @@ -2085,7 +2085,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = Self::Error> + TypeFoldable>, { self.pretty_in_binder(value) } @@ -2096,7 +2096,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { f: C, ) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = Self::Error> + TypeFoldable>, { self.pretty_wrap_binder(value, f) } @@ -2345,7 +2345,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { value: &ty::Binder<'tcx, T>, ) -> Result<(Self, T, BTreeMap>), fmt::Error> where - T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = fmt::Error> + TypeFoldable>, { fn name_by_region_index( index: usize, @@ -2515,7 +2515,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { pub fn pretty_in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = fmt::Error> + TypeFoldable>, { let old_region_index = self.region_index; let (new, new_value, _) = self.name_all_regions(value)?; @@ -2531,7 +2531,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { f: C, ) -> Result where - T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = fmt::Error> + TypeFoldable>, { let old_region_index = self.region_index; let (new, new_value, _) = self.name_all_regions(value)?; @@ -2596,24 +2596,22 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T> where - T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable>, + T: Print<'tcx, P, Error = P::Error> + TypeFoldable>, { - type Output = P; type Error = P::Error; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.in_binder(self) } } impl<'tcx, T, U, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate where - T: Print<'tcx, P, Output = P, Error = P::Error>, - U: Print<'tcx, P, Output = P, Error = P::Error>, + T: Print<'tcx, P, Error = P::Error>, + U: Print<'tcx, P, Error = P::Error>, { - type Output = P; type Error = P::Error; - fn print(&self, mut cx: P) -> Result { + fn print(&self, mut cx: P) -> Result { define_scoped_cx!(cx); p!(print(self.0), ": ", print(self.1)); Ok(cx) @@ -2640,9 +2638,8 @@ macro_rules! forward_display_to_print { macro_rules! define_print_and_forward_display { (($self:ident, $cx:ident): $($ty:ty $print:block)+) => { $(impl<'tcx, P: PrettyPrinter<'tcx>> Print<'tcx, P> for $ty { - type Output = P; type Error = fmt::Error; - fn print(&$self, $cx: P) -> Result { + fn print(&$self, $cx: P) -> Result { #[allow(unused_mut)] let mut $cx = $cx; define_scoped_cx!($cx); diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 06b3f91ebef6..9b8646a7751f 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -367,7 +367,7 @@ impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { } fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error>, + T: Print<'tcx, Self, Error = Self::Error>, { if let Some(first) = elems.next() { self = first.print(self)?; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 1020144a01b2..1133d4302fe4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -60,9 +60,7 @@ pub trait TypeErrCtxtExt<'tcx> { suggest_increasing_limit: bool, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, >>::Error: std::fmt::Debug; fn report_overflow_error( @@ -73,9 +71,7 @@ pub trait TypeErrCtxtExt<'tcx> { mutate: impl FnOnce(&mut Diagnostic), ) -> ! where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, >>::Error: std::fmt::Debug; fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed; @@ -227,9 +223,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { mutate: impl FnOnce(&mut Diagnostic), ) -> ! where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, >>::Error: std::fmt::Debug, { let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit); @@ -247,9 +241,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { suggest_increasing_limit: bool, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, >>::Error: std::fmt::Debug, { let predicate = self.resolve_vars_if_possible(predicate.clone()); From 6038888118d88ed4175ccb49e9e429865432f253 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 16 Oct 2023 20:46:24 +0200 Subject: [PATCH 59/94] Remove `Printer::Error` It's always a `fmt::Error` except in some cases where it was `!`, but we're not really winning anything in that case. --- .../rustc_const_eval/src/util/type_name.rs | 36 +++-- .../src/infer/error_reporting/mod.rs | 44 +++--- compiler/rustc_lint/src/context.rs | 28 ++-- compiler/rustc_middle/src/ty/print/mod.rs | 54 +++---- compiler/rustc_middle/src/ty/print/pretty.rs | 134 +++++++++--------- compiler/rustc_symbol_mangling/src/legacy.rs | 36 +++-- compiler/rustc_symbol_mangling/src/v0.rs | 42 +++--- 7 files changed, 180 insertions(+), 194 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index fba8121ead03..06944a93d3b7 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::CrateNum; use rustc_hir::definitions::DisambiguatedDefPathData; use rustc_middle::ty::{ self, - print::{PrettyPrinter, Print, Printer}, + print::{PrettyPrinter, Print, PrintError, Printer}, GenericArg, GenericArgKind, Ty, TyCtxt, }; use std::fmt::Write; @@ -14,17 +14,15 @@ struct AbsolutePathPrinter<'tcx> { } impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { - type Error = std::fmt::Error; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { + fn print_region(self, _region: ty::Region<'_>) -> Result { Ok(self) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { match *ty.kind() { // Types without identity. ty::Bool @@ -62,18 +60,18 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } } - fn print_const(self, ct: ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { self.pretty_print_const(ct, false) } fn print_dyn_existential( self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { self.pretty_print_dyn_existential(predicates) } - fn path_crate(mut self, cnum: CrateNum) -> Result { + fn path_crate(mut self, cnum: CrateNum) -> Result { self.path.push_str(self.tcx.crate_name(cnum).as_str()); Ok(self) } @@ -82,17 +80,17 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.pretty_path_qualified(self_ty, trait_ref) } fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.pretty_path_append_impl( |mut cx| { cx = print_prefix(cx)?; @@ -108,9 +106,9 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; write!(self.path, "::{}", disambiguated_data.data).unwrap(); @@ -120,9 +118,9 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { self = print_prefix(self)?; let args = args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_))); @@ -138,9 +136,9 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { fn should_print_region(&self, _region: ty::Region<'_>) -> bool { false } - fn comma_sep(mut self, mut elems: impl Iterator) -> Result + fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Error = Self::Error>, + T: Print<'tcx, Self, Error = PrintError>, { if let Some(first) = elems.next() { self = first.print(self)?; @@ -154,8 +152,8 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { fn generic_delimiters( mut self, - f: impl FnOnce(Self) -> Result, - ) -> Result { + f: impl FnOnce(Self) -> Result, + ) -> Result { write!(self, "<")?; self = f(self)?; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 5a3188b02eeb..496bb1766a71 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -67,7 +67,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_middle::dep_graph::DepContext; -use rustc_middle::ty::print::with_forced_trimmed_paths; +use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError}; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; use rustc_middle::ty::{ self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable, @@ -583,35 +583,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { segments: Vec, } - struct NonTrivialPath; - impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { - type Error = NonTrivialPath; - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { - Err(NonTrivialPath) + fn print_region(self, _region: ty::Region<'_>) -> Result { + Err(fmt::Error) } - fn print_type(self, _ty: Ty<'tcx>) -> Result { - Err(NonTrivialPath) + fn print_type(self, _ty: Ty<'tcx>) -> Result { + Err(fmt::Error) } fn print_dyn_existential( self, _predicates: &'tcx ty::List>, - ) -> Result { - Err(NonTrivialPath) + ) -> Result { + Err(fmt::Error) } - fn print_const(self, _ct: ty::Const<'tcx>) -> Result { - Err(NonTrivialPath) + fn print_const(self, _ct: ty::Const<'tcx>) -> Result { + Err(fmt::Error) } - fn path_crate(mut self, cnum: CrateNum) -> Result { + fn path_crate(mut self, cnum: CrateNum) -> Result { self.segments = vec![self.tcx.crate_name(cnum).to_string()]; Ok(self) } @@ -619,33 +615,33 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self, _self_ty: Ty<'tcx>, _trait_ref: Option>, - ) -> Result { - Err(NonTrivialPath) + ) -> Result { + Err(fmt::Error) } fn path_append_impl( self, - _print_prefix: impl FnOnce(Self) -> Result, + _print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, _self_ty: Ty<'tcx>, _trait_ref: Option>, - ) -> Result { - Err(NonTrivialPath) + ) -> Result { + Err(fmt::Error) } fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; self.segments.push(disambiguated_data.to_string()); Ok(self) } fn path_generic_args( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { print_prefix(self) } } @@ -663,7 +659,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // We compare strings because DefPath can be different // for imported and non-imported crates - let same_path = || -> Result<_, NonTrivialPath> { + let same_path = || -> Result<_, PrintError> { Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2) || abs_path(did1)? == abs_path(did2)?) }; diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index af7f2bcf6690..1f08db308607 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -31,7 +31,7 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::stability; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; -use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError}; use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, TyCtxt}; use rustc_session::config::ExpectedValues; use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId}; @@ -1206,32 +1206,30 @@ impl<'tcx> LateContext<'tcx> { } impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { - type Error = !; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { + fn print_region(self, _region: ty::Region<'_>) -> Result { Ok(self) } - fn print_type(self, _ty: Ty<'tcx>) -> Result { + fn print_type(self, _ty: Ty<'tcx>) -> Result { Ok(self) } fn print_dyn_existential( self, _predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { Ok(self) } - fn print_const(self, _ct: ty::Const<'tcx>) -> Result { + fn print_const(self, _ct: ty::Const<'tcx>) -> Result { Ok(self) } - fn path_crate(mut self, cnum: CrateNum) -> Result { + fn path_crate(mut self, cnum: CrateNum) -> Result { self.path = vec![self.tcx.crate_name(cnum)]; Ok(self) } @@ -1240,7 +1238,7 @@ impl<'tcx> LateContext<'tcx> { mut self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { if trait_ref.is_none() { if let ty::Adt(def, args) = self_ty.kind() { return self.print_def_path(def.did(), args); @@ -1259,11 +1257,11 @@ impl<'tcx> LateContext<'tcx> { fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { let mut path = print_prefix(self)?; // This shouldn't ever be needed, but just in case: @@ -1285,9 +1283,9 @@ impl<'tcx> LateContext<'tcx> { fn path_append( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { let mut path = print_prefix(self)?; // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. @@ -1301,9 +1299,9 @@ impl<'tcx> LateContext<'tcx> { fn path_generic_args( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { print_prefix(self) } } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index e789374fdd63..a1384c1616f5 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -10,12 +10,14 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; mod pretty; pub use self::pretty::*; +pub type PrintError = std::fmt::Error; + // FIXME(eddyb) false positive, the lifetime parameters are used with `P: Printer<...>`. #[allow(unused_lifetimes)] pub trait Print<'tcx, P> { type Error; - fn print(&self, cx: P) -> Result; + fn print(&self, cx: P) -> Result; } /// Interface for outputting user-facing "type-system entities" @@ -28,15 +30,13 @@ pub trait Print<'tcx, P> { // // FIXME(eddyb) find a better name; this is more general than "printing". pub trait Printer<'tcx>: Sized { - type Error; - fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; fn print_def_path( self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { self.default_print_def_path(def_id, args) } @@ -46,48 +46,48 @@ pub trait Printer<'tcx>: Sized { args: &'tcx [GenericArg<'tcx>], self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.default_print_impl_path(impl_def_id, args, self_ty, trait_ref) } - fn print_region(self, region: ty::Region<'tcx>) -> Result; + fn print_region(self, region: ty::Region<'tcx>) -> Result; - fn print_type(self, ty: Ty<'tcx>) -> Result; + fn print_type(self, ty: Ty<'tcx>) -> Result; fn print_dyn_existential( self, predicates: &'tcx ty::List>, - ) -> Result; + ) -> Result; - fn print_const(self, ct: ty::Const<'tcx>) -> Result; + fn print_const(self, ct: ty::Const<'tcx>) -> Result; - fn path_crate(self, cnum: CrateNum) -> Result; + fn path_crate(self, cnum: CrateNum) -> Result; fn path_qualified( self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result; + ) -> Result; fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result; + ) -> Result; fn path_append( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result; + ) -> Result; fn path_generic_args( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result; + ) -> Result; // Defaults (should not be overridden): @@ -96,7 +96,7 @@ pub trait Printer<'tcx>: Sized { self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { let key = self.tcx().def_key(def_id); debug!(?key); @@ -187,7 +187,7 @@ pub trait Printer<'tcx>: Sized { _args: &'tcx [GenericArg<'tcx>], self_ty: Ty<'tcx>, impl_trait_ref: Option>, - ) -> Result { + ) -> Result { debug!( "default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}", impl_def_id, self_ty, impl_trait_ref @@ -288,30 +288,30 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> { - type Error = P::Error; - fn print(&self, cx: P) -> Result { + type Error = PrintError; + fn print(&self, cx: P) -> Result { cx.print_region(*self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { - type Error = P::Error; + type Error = PrintError; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.print_type(*self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List> { - type Error = P::Error; - fn print(&self, cx: P) -> Result { + type Error = PrintError; + fn print(&self, cx: P) -> Result { cx.print_dyn_existential(self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { - type Error = P::Error; - fn print(&self, cx: P) -> Result { + type Error = PrintError; + fn print(&self, cx: P) -> Result { cx.print_const(*self) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ae3e6885b759..f1b17ddd2300 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -205,19 +205,19 @@ impl<'tcx> RegionHighlightMode<'tcx> { } /// Trait for printers that pretty-print using `fmt::Write` to the printer. -pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { +pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// Like `print_def_path` but for value paths. fn print_value_path( self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { self.print_def_path(def_id, args) } - fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = PrintError> + TypeFoldable>, { value.as_ref().skip_binder().print(self) } @@ -226,17 +226,17 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { self, value: &ty::Binder<'tcx, T>, f: F, - ) -> Result + ) -> Result where - T: Print<'tcx, Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = PrintError> + TypeFoldable>, { f(value.as_ref().skip_binder(), self) } /// Prints comma-separated elements. - fn comma_sep(mut self, mut elems: impl Iterator) -> Result + fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Error = Self::Error>, + T: Print<'tcx, Self, Error = PrintError>, { if let Some(first) = elems.next() { self = first.print(self)?; @@ -251,10 +251,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument fn typed_value( mut self, - f: impl FnOnce(Self) -> Result, - t: impl FnOnce(Self) -> Result, + f: impl FnOnce(Self) -> Result, + t: impl FnOnce(Self) -> Result, conversion: &str, - ) -> Result { + ) -> Result { self.write_str("{")?; self = f(self)?; self.write_str(conversion)?; @@ -266,8 +266,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { /// Prints `<...>` around what `f` prints. fn generic_delimiters( self, - f: impl FnOnce(Self) -> Result, - ) -> Result; + f: impl FnOnce(Self) -> Result, + ) -> Result; /// Returns `true` if the region should be printed in /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`. @@ -281,7 +281,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module, and returns `true`. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self::Error> { + fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), PrintError> { if NO_VISIBLE_PATH.with(|flag| flag.get()) { return Ok((self, false)); } @@ -295,7 +295,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { // For enum variants, if they have an unique name, then we only print the name, otherwise we // print the enum name and the variant name. Otherwise, we do not print anything and let the // caller use the `print_def_path` fallback. - fn force_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), Self::Error> { + fn force_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), PrintError> { let key = self.tcx().def_key(def_id); let visible_parent_map = self.tcx().visible_parent_map(()); let kind = self.tcx().def_kind(def_id); @@ -365,7 +365,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { } /// Try to see if this path can be trimmed to a unique symbol name. - fn try_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), Self::Error> { + fn try_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), PrintError> { if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?; if trimmed { @@ -407,7 +407,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { mut self, def_id: DefId, callers: &mut Vec, - ) -> Result<(Self, bool), Self::Error> { + ) -> Result<(Self, bool), PrintError> { define_scoped_cx!(self); debug!("try_print_visible_def_path: def_id={:?}", def_id); @@ -579,7 +579,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { if trait_ref.is_none() { // Inherent impls. Try to print `Foo::bar` for an inherent // impl on `Foo`, but fallback to `::bar` if self-type is @@ -613,10 +613,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { fn pretty_path_append_impl( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self = print_prefix(self)?; self.generic_delimiters(|mut cx| { @@ -632,7 +632,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { }) } - fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result { + fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result { define_scoped_cx!(self); match *ty.kind() { @@ -903,7 +903,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { mut self, def_id: DefId, args: &'tcx ty::List>, - ) -> Result { + ) -> Result { let tcx = self.tcx(); // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, @@ -1173,7 +1173,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { fn pretty_print_inherent_projection( self, alias_ty: &ty::AliasTy<'tcx>, - ) -> Result { + ) -> Result { let def_key = self.tcx().def_key(alias_ty.def_id); self.path_generic_args( |cx| { @@ -1197,7 +1197,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { fn pretty_print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { // Generate the main trait ref, including associated types. let mut first = true; @@ -1290,7 +1290,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { inputs: &[Ty<'tcx>], c_variadic: bool, output: Ty<'tcx>, - ) -> Result { + ) -> Result { define_scoped_cx!(self); p!("(", comma_sep(inputs.iter().copied())); @@ -1312,7 +1312,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { mut self, ct: ty::Const<'tcx>, print_ty: bool, - ) -> Result { + ) -> Result { define_scoped_cx!(self); if self.should_print_verbose() { @@ -1388,7 +1388,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { Ok(self) } - fn pretty_print_const_scalar(self, scalar: Scalar, ty: Ty<'tcx>) -> Result { + fn pretty_print_const_scalar(self, scalar: Scalar, ty: Ty<'tcx>) -> Result { match scalar { Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty), Scalar::Int(int) => { @@ -1401,7 +1401,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { mut self, ptr: Pointer, ty: Ty<'tcx>, - ) -> Result { + ) -> Result { define_scoped_cx!(self); let (alloc_id, offset) = ptr.into_parts(); @@ -1463,7 +1463,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { int: ScalarInt, ty: Ty<'tcx>, print_ty: bool, - ) -> Result { + ) -> Result { define_scoped_cx!(self); match ty.kind() { @@ -1525,7 +1525,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { self, _: Pointer, ty: Ty<'tcx>, - ) -> Result { + ) -> Result { self.typed_value( |mut this| { this.write_str("&_")?; @@ -1536,7 +1536,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { ) } - fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result { + fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result { write!(self, "b\"{}\"", byte_str.escape_ascii())?; Ok(self) } @@ -1546,7 +1546,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>, print_ty: bool, - ) -> Result { + ) -> Result { define_scoped_cx!(self); if self.should_print_verbose() { @@ -1669,7 +1669,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx, Error = fmt::Error> + fmt::Write { fn pretty_closure_as_impl( mut self, closure: ty::ClosureArgs<'tcx>, - ) -> Result { + ) -> Result { let sig = closure.sig(); let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn); @@ -1842,8 +1842,6 @@ impl fmt::Write for FmtPrinter<'_, '_> { } impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { - type Error = fmt::Error; - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } @@ -1852,7 +1850,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { define_scoped_cx!(self); if args.is_empty() { @@ -1907,11 +1905,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { self.default_print_def_path(def_id, args) } - fn print_region(self, region: ty::Region<'tcx>) -> Result { + fn print_region(self, region: ty::Region<'tcx>) -> Result { self.pretty_print_region(region) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { if self.type_length_limit.value_within_limit(self.printed_type_count) { self.printed_type_count += 1; self.pretty_print_type(ty) @@ -1925,15 +1923,15 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn print_dyn_existential( self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { self.pretty_print_dyn_existential(predicates) } - fn print_const(self, ct: ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { self.pretty_print_const(ct, false) } - fn path_crate(mut self, cnum: CrateNum) -> Result { + fn path_crate(mut self, cnum: CrateNum) -> Result { self.empty_path = true; if cnum == LOCAL_CRATE { if self.tcx.sess.at_least_rust_2018() { @@ -1954,7 +1952,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { mut self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self = self.pretty_path_qualified(self_ty, trait_ref)?; self.empty_path = false; Ok(self) @@ -1962,11 +1960,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_append_impl( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self = self.pretty_path_append_impl( |mut cx| { cx = print_prefix(cx)?; @@ -1985,9 +1983,9 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. @@ -2016,9 +2014,9 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { self = print_prefix(self)?; let tcx = self.tcx; @@ -2075,7 +2073,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { let was_in_value = std::mem::replace(&mut self.in_value, true); self = self.print_def_path(def_id, args)?; self.in_value = was_in_value; @@ -2083,30 +2081,30 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { Ok(self) } - fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = PrintError> + TypeFoldable>, { self.pretty_in_binder(value) } - fn wrap_binder Result>( + fn wrap_binder Result>( self, value: &ty::Binder<'tcx, T>, f: C, - ) -> Result + ) -> Result where - T: Print<'tcx, Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self, Error = PrintError> + TypeFoldable>, { self.pretty_wrap_binder(value, f) } fn typed_value( mut self, - f: impl FnOnce(Self) -> Result, - t: impl FnOnce(Self) -> Result, + f: impl FnOnce(Self) -> Result, + t: impl FnOnce(Self) -> Result, conversion: &str, - ) -> Result { + ) -> Result { self.write_str("{")?; self = f(self)?; self.write_str(conversion)?; @@ -2119,8 +2117,8 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { fn generic_delimiters( mut self, - f: impl FnOnce(Self) -> Result, - ) -> Result { + f: impl FnOnce(Self) -> Result, + ) -> Result { write!(self, "<")?; let was_in_value = std::mem::replace(&mut self.in_value, false); @@ -2180,7 +2178,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self, p: Pointer, ty: Ty<'tcx>, - ) -> Result { + ) -> Result { let print = |mut this: Self| { define_scoped_cx!(this); if this.print_alloc_ids { @@ -2596,22 +2594,22 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T> where - T: Print<'tcx, P, Error = P::Error> + TypeFoldable>, + T: Print<'tcx, P, Error = PrintError> + TypeFoldable>, { - type Error = P::Error; + type Error = PrintError; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.in_binder(self) } } impl<'tcx, T, U, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate where - T: Print<'tcx, P, Error = P::Error>, - U: Print<'tcx, P, Error = P::Error>, + T: Print<'tcx, P, Error = PrintError>, + U: Print<'tcx, P, Error = PrintError>, { - type Error = P::Error; - fn print(&self, mut cx: P) -> Result { + type Error = PrintError; + fn print(&self, mut cx: P) -> Result { define_scoped_cx!(cx); p!(print(self.0), ": ", print(self.1)); Ok(cx) @@ -2639,7 +2637,7 @@ macro_rules! define_print_and_forward_display { (($self:ident, $cx:ident): $($ty:ty $print:block)+) => { $(impl<'tcx, P: PrettyPrinter<'tcx>> Print<'tcx, P> for $ty { type Error = fmt::Error; - fn print(&$self, $cx: P) -> Result { + fn print(&$self, $cx: P) -> Result { #[allow(unused_mut)] let mut $cx = $cx; define_scoped_cx!($cx); diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 9b8646a7751f..5e7dba63ff71 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -1,7 +1,7 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_hir::def_id::CrateNum; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; -use rustc_middle::ty::print::{PrettyPrinter, Print, Printer}; +use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_middle::util::common::record_time; @@ -200,17 +200,15 @@ struct SymbolPrinter<'tcx> { // symbol names should have their own printing machinery. impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { - type Error = fmt::Error; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { + fn print_region(self, _region: ty::Region<'_>) -> Result { Ok(self) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { match *ty.kind() { // Print all nominal types as paths (unlike `pretty_print_type`). ty::FnDef(def_id, args) @@ -244,7 +242,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { fn print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { let mut first = true; for p in predicates { if !first { @@ -256,7 +254,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { Ok(self) } - fn print_const(self, ct: ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { // only print integers match (ct.kind(), ct.ty().kind()) { (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => { @@ -274,7 +272,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { Ok(self) } - fn path_crate(self, cnum: CrateNum) -> Result { + fn path_crate(self, cnum: CrateNum) -> Result { self.write_str(self.tcx.crate_name(cnum).as_str())?; Ok(self) } @@ -282,7 +280,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { // Similar to `pretty_path_qualified`, but for the other // types that are printed as paths (see `print_type` above). match self_ty.kind() { @@ -298,11 +296,11 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.pretty_path_append_impl( |mut cx| { cx = print_prefix(cx)?; @@ -322,9 +320,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { } fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. @@ -345,9 +343,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { } fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { self = print_prefix(self)?; let args = @@ -365,9 +363,9 @@ impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { fn should_print_region(&self, _region: ty::Region<'_>) -> bool { false } - fn comma_sep(mut self, mut elems: impl Iterator) -> Result + fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Error = Self::Error>, + T: Print<'tcx, Self, Error = PrintError>, { if let Some(first) = elems.next() { self = first.print(self)?; @@ -381,8 +379,8 @@ impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { fn generic_delimiters( mut self, - f: impl FnOnce(Self) -> Result, - ) -> Result { + f: impl FnOnce(Self) -> Result, + ) -> Result { write!(self, "<")?; let kept_within_component = mem::replace(&mut self.keep_within_component, true); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 249cdf7bdfab..99c5d0164399 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -6,7 +6,7 @@ use rustc_hir::def::CtorKind; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::print::{Print, Printer}; +use rustc_middle::ty::print::{Print, PrintError, Printer}; use rustc_middle::ty::{ self, EarlyBinder, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeVisitable, TypeVisitableExt, UintTy, @@ -181,11 +181,11 @@ impl<'tcx> SymbolMangler<'tcx> { fn path_append_ns<'a>( mut self: &'a mut Self, - print_prefix: impl FnOnce(&'a mut Self) -> Result<&'a mut Self, !>, + print_prefix: impl FnOnce(&'a mut Self) -> Result<&'a mut Self, PrintError>, ns: char, disambiguator: u64, name: &str, - ) -> Result<&'a mut Self, !> { + ) -> Result<&'a mut Self, PrintError> { self.push("N"); self.out.push(ns); self = print_prefix(self)?; @@ -194,7 +194,7 @@ impl<'tcx> SymbolMangler<'tcx> { Ok(self) } - fn print_backref(&mut self, i: usize) -> Result<&mut Self, !> { + fn print_backref(&mut self, i: usize) -> Result<&mut Self, PrintError> { self.push("B"); self.push_integer_62((i - self.start_offset) as u64); Ok(self) @@ -203,8 +203,8 @@ impl<'tcx> SymbolMangler<'tcx> { fn in_binder<'a, T>( mut self: &'a mut Self, value: &ty::Binder<'tcx, T>, - print_value: impl FnOnce(&'a mut Self, &T) -> Result<&'a mut Self, !>, - ) -> Result<&'a mut Self, !> + print_value: impl FnOnce(&'a mut Self, &T) -> Result<&'a mut Self, PrintError>, + ) -> Result<&'a mut Self, PrintError> where T: TypeVisitable>, { @@ -230,8 +230,6 @@ impl<'tcx> SymbolMangler<'tcx> { } impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { - type Error = !; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -240,7 +238,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { if let Some(&i) = self.paths.get(&(def_id, args)) { return self.print_backref(i); } @@ -262,7 +260,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { args: &'tcx [GenericArg<'tcx>], mut self_ty: Ty<'tcx>, mut impl_trait_ref: Option>, - ) -> Result { + ) -> Result { let key = self.tcx.def_key(impl_def_id); let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; @@ -315,7 +313,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn print_region(self, region: ty::Region<'_>) -> Result { + fn print_region(self, region: ty::Region<'_>) -> Result { let i = match *region { // Erased lifetimes use the index 0, for a // shorter mangling of `L_`. @@ -337,7 +335,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { // Basic types, never cached (single-character). let basic_type = match ty.kind() { ty::Bool => "b", @@ -492,7 +490,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { // Okay, so this is a bit tricky. Imagine we have a trait object like // `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the // output looks really close to the syntax, where the `Bar = &'a ()` bit @@ -553,7 +551,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn print_const(mut self, ct: ty::Const<'tcx>) -> Result { + fn print_const(mut self, ct: ty::Const<'tcx>) -> Result { // We only mangle a typed value if the const can be evaluated. let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all()); match ct.kind() { @@ -725,7 +723,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn path_crate(self, cnum: CrateNum) -> Result { + fn path_crate(self, cnum: CrateNum) -> Result { self.push("C"); let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); self.push_disambiguator(stable_crate_id.as_u64()); @@ -738,7 +736,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { mut self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { assert!(trait_ref.is_some()); let trait_ref = trait_ref.unwrap(); @@ -749,20 +747,20 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn path_append_impl( self, - _: impl FnOnce(Self) -> Result, + _: impl FnOnce(Self) -> Result, _: &DisambiguatedDefPathData, _: Ty<'tcx>, _: Option>, - ) -> Result { + ) -> Result { // Inlined into `print_impl_path` unreachable!() } fn path_append( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { let ns = match disambiguated_data.data { // Extern block segments can be skipped, names from extern blocks // are effectively living in their parent modules. @@ -800,9 +798,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { // Don't print any regions if they're all erased. let print_regions = args.iter().any(|arg| match arg.unpack() { GenericArgKind::Lifetime(r) => !r.is_erased(), From 6fc6a6d7831e6b7b23e9e7b7c15c6461ecbac16c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 16 Oct 2023 20:50:46 +0200 Subject: [PATCH 60/94] Remove `Print::Error` All printing goes through `fmt::Error` now. --- .../rustc_const_eval/src/util/type_name.rs | 2 +- .../nice_region_error/placeholder_error.rs | 4 +-- compiler/rustc_middle/src/ty/print/mod.rs | 7 ----- compiler/rustc_middle/src/ty/print/pretty.rs | 26 ++++++++----------- compiler/rustc_symbol_mangling/src/legacy.rs | 2 +- .../error_reporting/type_err_ctxt_ext.rs | 8 ++---- 6 files changed, 17 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 06944a93d3b7..54eb14ae8fc4 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -138,7 +138,7 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { } fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Error = PrintError>, + T: Print<'tcx, Self>, { if let Some(first) = elems.next() { self = first.print(self)?; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 17a265fd4f47..d6a3bc32cc93 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -28,7 +28,7 @@ pub struct Highlighted<'tcx, T> { impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T> where - T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error>, + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>, { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { rustc_errors::DiagnosticArgValue::Str(self.to_string().into()) @@ -43,7 +43,7 @@ impl<'tcx, T> Highlighted<'tcx, T> { impl<'tcx, T> fmt::Display for Highlighted<'tcx, T> where - T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error>, + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS); diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index a1384c1616f5..107b44285ac0 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -15,8 +15,6 @@ pub type PrintError = std::fmt::Error; // FIXME(eddyb) false positive, the lifetime parameters are used with `P: Printer<...>`. #[allow(unused_lifetimes)] pub trait Print<'tcx, P> { - type Error; - fn print(&self, cx: P) -> Result; } @@ -288,29 +286,24 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> { - type Error = PrintError; fn print(&self, cx: P) -> Result { cx.print_region(*self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { - type Error = PrintError; - fn print(&self, cx: P) -> Result { cx.print_type(*self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List> { - type Error = PrintError; fn print(&self, cx: P) -> Result { cx.print_dyn_existential(self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { - type Error = PrintError; fn print(&self, cx: P) -> Result { cx.print_const(*self) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f1b17ddd2300..d8010c714970 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -217,7 +217,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Error = PrintError> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { value.as_ref().skip_binder().print(self) } @@ -228,7 +228,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { f: F, ) -> Result where - T: Print<'tcx, Self, Error = PrintError> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { f(value.as_ref().skip_binder(), self) } @@ -236,7 +236,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// Prints comma-separated elements. fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Error = PrintError>, + T: Print<'tcx, Self>, { if let Some(first) = elems.next() { self = first.print(self)?; @@ -2083,7 +2083,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Error = PrintError> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { self.pretty_in_binder(value) } @@ -2094,7 +2094,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { f: C, ) -> Result where - T: Print<'tcx, Self, Error = PrintError> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { self.pretty_wrap_binder(value, f) } @@ -2343,7 +2343,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { value: &ty::Binder<'tcx, T>, ) -> Result<(Self, T, BTreeMap>), fmt::Error> where - T: Print<'tcx, Self, Error = fmt::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { fn name_by_region_index( index: usize, @@ -2513,7 +2513,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { pub fn pretty_in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Error = fmt::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { let old_region_index = self.region_index; let (new, new_value, _) = self.name_all_regions(value)?; @@ -2529,7 +2529,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { f: C, ) -> Result where - T: Print<'tcx, Self, Error = fmt::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { let old_region_index = self.region_index; let (new, new_value, _) = self.name_all_regions(value)?; @@ -2594,10 +2594,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T> where - T: Print<'tcx, P, Error = PrintError> + TypeFoldable>, + T: Print<'tcx, P> + TypeFoldable>, { - type Error = PrintError; - fn print(&self, cx: P) -> Result { cx.in_binder(self) } @@ -2605,10 +2603,9 @@ where impl<'tcx, T, U, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate where - T: Print<'tcx, P, Error = PrintError>, - U: Print<'tcx, P, Error = PrintError>, + T: Print<'tcx, P>, + U: Print<'tcx, P>, { - type Error = PrintError; fn print(&self, mut cx: P) -> Result { define_scoped_cx!(cx); p!(print(self.0), ": ", print(self.1)); @@ -2636,7 +2633,6 @@ macro_rules! forward_display_to_print { macro_rules! define_print_and_forward_display { (($self:ident, $cx:ident): $($ty:ty $print:block)+) => { $(impl<'tcx, P: PrettyPrinter<'tcx>> Print<'tcx, P> for $ty { - type Error = fmt::Error; fn print(&$self, $cx: P) -> Result { #[allow(unused_mut)] let mut $cx = $cx; diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 5e7dba63ff71..5290da9a25b9 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -365,7 +365,7 @@ impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { } fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Error = PrintError>, + T: Print<'tcx, Self>, { if let Some(first) = elems.next() { self = first.print(self)?; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 1133d4302fe4..640bd3fad7ca 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -60,8 +60,7 @@ pub trait TypeErrCtxtExt<'tcx> { suggest_increasing_limit: bool, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> where - T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug; + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; fn report_overflow_error( &self, @@ -71,8 +70,7 @@ pub trait TypeErrCtxtExt<'tcx> { mutate: impl FnOnce(&mut Diagnostic), ) -> ! where - T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug; + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed; @@ -224,7 +222,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> ! where T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug, { let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit); mutate(&mut err); @@ -242,7 +239,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> where T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug, { let predicate = self.resolve_vars_if_possible(predicate.clone()); let mut pred_str = predicate.to_string(); From e1aa5adc786d0579802785190ee561add3e53eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 16 Oct 2023 18:46:51 +0000 Subject: [PATCH 61/94] Use `YYYY-MM-DDTHH_MM_SS` as datetime format for ICE dump files Windows paths do not support `:`, so use a datetime format in ICE dump paths that Windows will accept. Fix #116809, fix #115180. --- compiler/rustc_driver_impl/Cargo.toml | 2 +- compiler/rustc_driver_impl/src/lib.rs | 9 +++++++-- tests/run-make/dump-ice-to-disk/check.sh | 6 ++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 4894312b0d21..d931a8dab9b8 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -52,7 +52,7 @@ rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" -time = { version = "0.3", default-features = false, features = ["formatting", ] } +time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] } tracing = { version = "0.1.35" } # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b0c95e1bd205..a0d0979005c2 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -62,7 +62,6 @@ use std::str; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::OnceLock; use std::time::{Instant, SystemTime}; -use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; #[allow(unused_macros)] @@ -1307,7 +1306,13 @@ fn ice_path() -> &'static Option { None => std::env::current_dir().unwrap_or_default(), }; let now: OffsetDateTime = SystemTime::now().into(); - let file_now = now.format(&Rfc3339).unwrap_or_default(); + let file_now = now + .format( + // Don't use a standard datetime format because Windows doesn't support `:` in paths + &time::format_description::parse("[year]-[month]-[day]T[hour]_[minute]_[second]") + .unwrap(), + ) + .unwrap_or_default(); let pid = std::process::id(); path.push(format!("rustc-ice-{file_now}-{pid}.txt")); Some(path) diff --git a/tests/run-make/dump-ice-to-disk/check.sh b/tests/run-make/dump-ice-to-disk/check.sh index ab6f9ab60188..ff6e4be35af9 100644 --- a/tests/run-make/dump-ice-to-disk/check.sh +++ b/tests/run-make/dump-ice-to-disk/check.sh @@ -11,6 +11,12 @@ export RUSTC_ICE=$TMPDIR $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-default-set.log 2>&1 default_set=$(cat $TMPDIR/rustc-ice-*.txt | wc -l) content=$(cat $TMPDIR/rustc-ice-*.txt) +# Ensure that the ICE dump path doesn't contain `:` because they cause problems on Windows +windows_safe=$(echo rustc-ice-*.txt | grep ':') +if [ ! -z "$windows_safe" ]; then + exit 1 +fi + rm $TMPDIR/rustc-ice-*.txt RUST_BACKTRACE=short $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-short.log 2>&1 short=$(cat $TMPDIR/rustc-ice-*.txt | wc -l) From 5cc9216ff3552ac1f6b545860bc25f25cf6551df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 13 Oct 2023 23:31:35 +0000 Subject: [PATCH 62/94] Properly account for self ty in method disambiguation suggestion Fix #116703. --- .../rustc_hir_typeck/src/method/suggest.rs | 9 ++++-- .../disambiguate-multiple-blanket-impl.rs | 27 ++++++++++++++++++ .../disambiguate-multiple-blanket-impl.stderr | 28 +++++++++++++++++++ .../ui/methods/disambiguate-multiple-impl.rs | 26 +++++++++++++++++ .../methods/disambiguate-multiple-impl.stderr | 28 +++++++++++++++++++ 5 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 tests/ui/methods/disambiguate-multiple-blanket-impl.rs create mode 100644 tests/ui/methods/disambiguate-multiple-blanket-impl.stderr create mode 100644 tests/ui/methods/disambiguate-multiple-impl.rs create mode 100644 tests/ui/methods/disambiguate-multiple-impl.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8ea0280c5e9b..56d7b94d493a 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1322,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id); let ty = match item.kind { - ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty, + ty::AssocKind::Const | ty::AssocKind::Type => impl_ty, ty::AssocKind::Fn => self .tcx .fn_sig(item.def_id) @@ -1340,6 +1340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, path, ty, + impl_ty, item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, @@ -1376,6 +1377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, path, rcvr_ty, + rcvr_ty, item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, @@ -3146,6 +3148,7 @@ fn print_disambiguation_help<'tcx>( err: &mut Diagnostic, trait_name: String, rcvr_ty: Ty<'_>, + self_ty: Ty<'_>, kind: ty::AssocKind, def_kind_descr: &'static str, span: Span, @@ -3172,13 +3175,13 @@ fn print_disambiguation_help<'tcx>( .join(", "), ); let trait_name = if !fn_has_self_parameter { - format!("<{rcvr_ty} as {trait_name}>") + format!("<{self_ty} as {trait_name}>") } else { trait_name }; (span, format!("{trait_name}::{item_name}{args}")) } else { - (span.with_hi(item_name.span.lo()), format!("<{rcvr_ty} as {trait_name}>::")) + (span.with_hi(item_name.span.lo()), format!("<{self_ty} as {trait_name}>::")) }; err.span_suggestion_verbose( span, diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs new file mode 100644 index 000000000000..39ac3389aab8 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs @@ -0,0 +1,27 @@ +trait A { + fn foo(&self); +} + +trait B { + fn foo(&self); +} + +#[derive(Debug)] +struct S; + +impl A for T { + fn foo(&self) {} //~ NOTE candidate #1 +} + +impl B for T { + fn foo(&self) {} //~ NOTE candidate #2 +} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate + //~| HELP disambiguate +} + diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr new file mode 100644 index 000000000000..dd0af051bb92 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-blanket-impl.rs:22:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:13:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:17:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | ::foo(&s); + | ~~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | ::foo(&s); + | ~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-impl.rs b/tests/ui/methods/disambiguate-multiple-impl.rs new file mode 100644 index 000000000000..fa9942c745ad --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-impl.rs @@ -0,0 +1,26 @@ +trait A { + fn foo(&self); +} + +trait B { + fn foo(&self); +} + +struct S; + +impl A for S { + fn foo(&self) {} //~ NOTE candidate #1 +} + +impl B for S { + fn foo(&self) {} //~ NOTE candidate #2 +} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate + //~| HELP disambiguate +} + diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr new file mode 100644 index 000000000000..b9fd10dba8d7 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-impl.rs:21:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:12:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:16:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | ::foo(&s); + | ~~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | ::foo(&s); + | ~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. From 6cf01fcf1ec24142919d92035b8531c4ff1deaca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 16 Oct 2023 01:22:25 +0000 Subject: [PATCH 63/94] review comments + more tests --- .../rustc_hir_typeck/src/method/suggest.rs | 17 ++- .../disambiguate-multiple-blanket-impl.rs | 15 +- .../disambiguate-multiple-blanket-impl.stderr | 49 ++++++- .../ui/methods/disambiguate-multiple-impl.rs | 15 +- .../methods/disambiguate-multiple-impl.stderr | 49 ++++++- .../methods/disambiguate-multiple-trait-2.rs | 57 ++++++++ .../disambiguate-multiple-trait-2.stderr | 138 ++++++++++++++++++ .../ui/methods/disambiguate-multiple-trait.rs | 34 +++++ .../disambiguate-multiple-trait.stderr | 67 +++++++++ 9 files changed, 421 insertions(+), 20 deletions(-) create mode 100644 tests/ui/methods/disambiguate-multiple-trait-2.rs create mode 100644 tests/ui/methods/disambiguate-multiple-trait-2.stderr create mode 100644 tests/ui/methods/disambiguate-multiple-trait.rs create mode 100644 tests/ui/methods/disambiguate-multiple-trait.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 56d7b94d493a..f3441b313cb5 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1340,7 +1340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, path, ty, - impl_ty, + Some(impl_ty), item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, @@ -1377,7 +1377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, path, rcvr_ty, - rcvr_ty, + None, item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, @@ -3148,7 +3148,7 @@ fn print_disambiguation_help<'tcx>( err: &mut Diagnostic, trait_name: String, rcvr_ty: Ty<'_>, - self_ty: Ty<'_>, + impl_self_ty: Option>, kind: ty::AssocKind, def_kind_descr: &'static str, span: Span, @@ -3174,20 +3174,21 @@ fn print_disambiguation_help<'tcx>( .collect::>() .join(", "), ); - let trait_name = if !fn_has_self_parameter { - format!("<{self_ty} as {trait_name}>") + let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty { + format!("<{impl_self_ty} as {trait_name}>") } else { trait_name }; (span, format!("{trait_name}::{item_name}{args}")) + } else if let Some(impl_self_ty) = impl_self_ty { + (span.with_hi(item_name.span.lo()), format!("<{impl_self_ty} as {trait_name}>::")) } else { - (span.with_hi(item_name.span.lo()), format!("<{self_ty} as {trait_name}>::")) + (span.with_hi(item_name.span.lo()), format!("{trait_name}::")) }; err.span_suggestion_verbose( span, format!( - "disambiguate the {} for {}", - def_kind_descr, + "disambiguate the {def_kind_descr} for {}", if let Some(candidate) = candidate { format!("candidate #{candidate}") } else { diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs index 39ac3389aab8..f8fb8439ddc5 100644 --- a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs @@ -1,8 +1,12 @@ trait A { + type Type; + const CONST: usize; fn foo(&self); } trait B { + type Type; + const CONST: usize; fn foo(&self); } @@ -10,10 +14,14 @@ trait B { struct S; impl A for T { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 fn foo(&self) {} //~ NOTE candidate #1 } impl B for T { + type Type = (); + const CONST: usize = 2; //~ NOTE candidate #2 fn foo(&self) {} //~ NOTE candidate #2 } @@ -23,5 +31,10 @@ fn main() { //~^ NOTE multiple `foo` found //~| HELP disambiguate //~| HELP disambiguate + S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate + let _: S::Type; //~ ERROR ambiguous associated type + //~^ HELP use the fully-qualified path } - diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr index dd0af051bb92..5138e7fa2cb0 100644 --- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr @@ -1,16 +1,29 @@ +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-blanket-impl.rs:38:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use the fully-qualified path + | +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ + error[E0034]: multiple applicable items in scope - --> $DIR/disambiguate-multiple-blanket-impl.rs:22:8 + --> $DIR/disambiguate-multiple-blanket-impl.rs:30:8 | LL | S::foo(&s); | ^^^ multiple `foo` found | note: candidate #1 is defined in an impl of the trait `A` for the type `T` - --> $DIR/disambiguate-multiple-blanket-impl.rs:13:5 + --> $DIR/disambiguate-multiple-blanket-impl.rs:19:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `B` for the type `T` - --> $DIR/disambiguate-multiple-blanket-impl.rs:17:5 + --> $DIR/disambiguate-multiple-blanket-impl.rs:25:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ @@ -23,6 +36,32 @@ help: disambiguate the method for candidate #2 LL | ::foo(&s); | ~~~~~~~~~~ -error: aborting due to previous error +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-blanket-impl.rs:34:8 + | +LL | S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:18:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:24:5 + | +LL | const CONST: usize = 2; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | ::CONST; + | ~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | ::CONST; + | ~~~~~~~~~~ -For more information about this error, try `rustc --explain E0034`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0034, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-impl.rs b/tests/ui/methods/disambiguate-multiple-impl.rs index fa9942c745ad..9562bb865da9 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.rs +++ b/tests/ui/methods/disambiguate-multiple-impl.rs @@ -1,18 +1,26 @@ trait A { + type Type; + const CONST: usize; fn foo(&self); } trait B { + type Type; + const CONST: usize; fn foo(&self); } struct S; impl A for S { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 fn foo(&self) {} //~ NOTE candidate #1 } impl B for S { + type Type = (); + const CONST: usize = 2; //~ NOTE candidate #2 fn foo(&self) {} //~ NOTE candidate #2 } @@ -22,5 +30,10 @@ fn main() { //~^ NOTE multiple `foo` found //~| HELP disambiguate //~| HELP disambiguate + let _: S::Type = (); //~ ERROR ambiguous associated type + //~| HELP use the fully-qualified path + let _ = S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate } - diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr index b9fd10dba8d7..60cb086a5734 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -1,16 +1,29 @@ +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-impl.rs:33:12 + | +LL | let _: S::Type = (); + | ^^^^^^^ + | +help: use the fully-qualified path + | +LL | let _: ::Type = (); + | ~~~~~~~~~~~~~~ +LL | let _: ::Type = (); + | ~~~~~~~~~~~~~~ + error[E0034]: multiple applicable items in scope - --> $DIR/disambiguate-multiple-impl.rs:21:8 + --> $DIR/disambiguate-multiple-impl.rs:29:8 | LL | S::foo(&s); | ^^^ multiple `foo` found | note: candidate #1 is defined in an impl of the trait `A` for the type `S` - --> $DIR/disambiguate-multiple-impl.rs:12:5 + --> $DIR/disambiguate-multiple-impl.rs:18:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `B` for the type `S` - --> $DIR/disambiguate-multiple-impl.rs:16:5 + --> $DIR/disambiguate-multiple-impl.rs:24:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ @@ -23,6 +36,32 @@ help: disambiguate the method for candidate #2 LL | ::foo(&s); | ~~~~~~~~~~ -error: aborting due to previous error +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-impl.rs:35:16 + | +LL | let _ = S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:17:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:23:5 + | +LL | const CONST: usize = 2; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ -For more information about this error, try `rustc --explain E0034`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0034, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.rs b/tests/ui/methods/disambiguate-multiple-trait-2.rs new file mode 100644 index 000000000000..72ed3413b4ad --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait-2.rs @@ -0,0 +1,57 @@ +trait A { + type Type; //~ NOTE ambiguous `Type` from `A` + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self); //~ NOTE candidate #1 +} + +trait B { + type Type; //~ NOTE ambiguous `Type` from `B` + const CONST: usize; //~ NOTE candidate #2 + fn foo(&self); //~ NOTE candidate #2 +} + +trait C: A + B {} + +fn a(t: T) { + t.foo(); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate the method + //~| HELP disambiguate the method + let _ = T::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate + let _: T::Type; //~ ERROR ambiguous associated type + //~^ NOTE ambiguous associated type `Type` + //~| HELP use fully qualified syntax + //~| HELP use fully qualified syntax +} + +#[derive(Debug)] +struct S; + +impl A for T { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self) {} //~ NOTE candidate #1 +} + +impl B for T { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #2 + fn foo(&self) {} //~ NOTE candidate #2 +} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate + //~| HELP disambiguate + let _ = S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate + let _: S::Type; //~ ERROR ambiguous associated type + //~^ HELP use the fully-qualified path +} diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr new file mode 100644 index 000000000000..76a240448e65 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr @@ -0,0 +1,138 @@ +error[E0221]: ambiguous associated type `Type` in bounds of `T` + --> $DIR/disambiguate-multiple-trait-2.rs:24:12 + | +LL | type Type; + | --------- ambiguous `Type` from `A` +... +LL | type Type; + | --------- ambiguous `Type` from `B` +... +LL | let _: T::Type; + | ^^^^^^^ ambiguous associated type `Type` + | +help: use fully qualified syntax to disambiguate + | +LL | let _: ::Type; + | ~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | let _: ::Type; + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:16:7 + | +LL | t.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/disambiguate-multiple-trait-2.rs:4:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/disambiguate-multiple-trait-2.rs:10:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | A::foo(t); + | ~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | B::foo(t); + | ~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:20:16 + | +LL | let _ = T::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/disambiguate-multiple-trait-2.rs:3:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/disambiguate-multiple-trait-2.rs:9:5 + | +LL | const CONST: usize; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | let _ = A::CONST; + | ~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | let _ = B::CONST; + | ~~~ + +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-trait-2.rs:55:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use the fully-qualified path + | +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:47:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:36:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:42:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | ::foo(&s); + | ~~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | ::foo(&s); + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:51:16 + | +LL | let _ = S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:35:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:41:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0034, E0221, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-trait.rs b/tests/ui/methods/disambiguate-multiple-trait.rs new file mode 100644 index 000000000000..73dfc43dd5b4 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait.rs @@ -0,0 +1,34 @@ +#![feature(associated_type_defaults)] + +trait A { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self) {} //~ NOTE candidate #1 +} + +trait B { + type Type = (); + const CONST: usize = 2; //~ NOTE candidate #2 + fn foo(&self) {} //~ NOTE candidate #2 +} + +#[derive(Debug)] +struct S; + +impl A for T {} + +impl B for T {} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate + //~| HELP disambiguate + let _ = S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate + let _: S::Type; //~ ERROR ambiguous associated type + //~^ HELP use the fully-qualified path +} diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr new file mode 100644 index 000000000000..f88c280dfa3b --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait.stderr @@ -0,0 +1,67 @@ +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-trait.rs:32:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use the fully-qualified path + | +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait.rs:24:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:6:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:12:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | ::foo(&s); + | ~~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | ::foo(&s); + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait.rs:28:16 + | +LL | let _ = S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:5:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:11:5 + | +LL | const CONST: usize = 2; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0034, E0223. +For more information about an error, try `rustc --explain E0034`. From 890e92feedcfe942cea8ffda2929d9d4ecf8ab5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 16 Oct 2023 18:25:11 +0000 Subject: [PATCH 64/94] Unify suggestion wording --- .../rustc_hir_analysis/src/astconv/mod.rs | 4 +- .../rustc_hir_typeck/src/method/suggest.rs | 96 ++++++++++--------- .../associated-const-ambiguity-report.stderr | 8 +- .../issue-109071.no_gate.stderr | 2 +- ...fers-shadowing-trait-item.uncovered.stderr | 2 +- ...guous-associated-type-with-generics.stderr | 2 +- .../associated-item-duplicate-names-3.stderr | 2 +- ...mbig-between-bound-and-where-clause.stderr | 24 ++--- ...rojection-from-multiple-supertraits.stderr | 8 +- ...sociated-types-in-ambiguous-context.stderr | 6 +- .../associated-types-path-1.stderr | 4 +- tests/ui/did_you_mean/bad-assoc-ty.stderr | 2 +- tests/ui/error-codes/E0034.stderr | 4 +- tests/ui/error-codes/E0221.stderr | 6 +- tests/ui/error-codes/E0223.stderr | 2 +- tests/ui/lint/bare-trait-objects-path.stderr | 2 +- .../disambiguate-multiple-blanket-impl.rs | 8 +- .../disambiguate-multiple-blanket-impl.stderr | 14 +-- .../ui/methods/disambiguate-multiple-impl.rs | 8 +- .../methods/disambiguate-multiple-impl.stderr | 14 +-- .../methods/disambiguate-multiple-trait-2.rs | 15 ++- .../disambiguate-multiple-trait-2.stderr | 34 +++---- .../ui/methods/disambiguate-multiple-trait.rs | 8 +- .../disambiguate-multiple-trait.stderr | 14 +-- ...method-ambig-two-traits-from-impls2.stderr | 4 +- tests/ui/self/self-impl.stderr | 4 +- .../struct-path-associated-type.stderr | 6 +- .../suggest-trait-in-ufcs-in-hrtb.stderr | 2 +- tests/ui/traits/item-privacy.stderr | 4 +- tests/ui/typeck/issue-107087.stderr | 2 +- tests/ui/typeck/issue-110052.stderr | 2 +- 31 files changed, 145 insertions(+), 168 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 960a1bfdd2d5..6b4980deae40 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1018,7 +1018,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } err.span_suggestions( span, - "use the fully-qualified path", + "use fully-qualified syntax", suggestions, Applicability::MachineApplicable, ); @@ -1190,7 +1190,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { err.span_suggestion_verbose( span.with_hi(assoc_name.span.lo()), - "use fully qualified syntax to disambiguate", + "use fully-qualified syntax to disambiguate", format!("<{ty_param_name} as {}>::", bound.print_only_trait_path()), Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index f3441b313cb5..29e5f39daf7e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1260,6 +1260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Dynamic limit to avoid hiding just one candidate, which is silly. let limit = if sources.len() == 5 { 5 } else { 4 }; + let mut suggs = vec![]; for (idx, source) in sources.iter().take(limit).enumerate() { match *source { CandidateSource::Impl(impl_did) => { @@ -1334,7 +1335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .copied() .unwrap_or(rcvr_ty), }; - print_disambiguation_help( + if let Some(sugg) = print_disambiguation_help( item_name, args, err, @@ -1347,7 +1348,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { idx, self.tcx.sess.source_map(), item.fn_has_self_parameter, - ); + ) { + suggs.push(sugg); + } } } CandidateSource::Trait(trait_did) => { @@ -1371,7 +1374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Some(sugg_span) = sugg_span { let path = self.tcx.def_path_str(trait_did); - print_disambiguation_help( + if let Some(sugg) = print_disambiguation_help( item_name, args, err, @@ -1384,11 +1387,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { idx, self.tcx.sess.source_map(), item.fn_has_self_parameter, - ); + ) { + suggs.push(sugg); + } } } } } + if !suggs.is_empty() && let Some(span) = sugg_span { + err.span_suggestions( + span.with_hi(item_name.span.lo()), + "use fully-qualified syntax to disambiguate", + suggs, + Applicability::MachineApplicable, + ); + } if sources.len() > limit { err.note(format!("and {} others", sources.len() - limit)); } @@ -3155,47 +3168,44 @@ fn print_disambiguation_help<'tcx>( candidate: Option, source_map: &source_map::SourceMap, fn_has_self_parameter: bool, -) { - let mut applicability = Applicability::MachineApplicable; - let (span, sugg) = if let ( - ty::AssocKind::Fn, - Some(MethodCallComponents { receiver, args, .. }), - ) = (kind, args) - { - let args = format!( - "({}{})", - rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()), - std::iter::once(receiver) - .chain(args.iter()) - .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| { - applicability = Applicability::HasPlaceholders; - "_".to_owned() - })) - .collect::>() - .join(", "), - ); - let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty { +) -> Option { + Some( + if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args) + { + let args = format!( + "({}{})", + rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()), + std::iter::once(receiver) + .chain(args.iter()) + .map(|arg| source_map + .span_to_snippet(arg.span) + .unwrap_or_else(|_| { "_".to_owned() })) + .collect::>() + .join(", "), + ); + let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty { format!("<{impl_self_ty} as {trait_name}>") } else { trait_name }; - (span, format!("{trait_name}::{item_name}{args}")) - } else if let Some(impl_self_ty) = impl_self_ty { - (span.with_hi(item_name.span.lo()), format!("<{impl_self_ty} as {trait_name}>::")) - } else { - (span.with_hi(item_name.span.lo()), format!("{trait_name}::")) - }; - err.span_suggestion_verbose( - span, - format!( - "disambiguate the {def_kind_descr} for {}", - if let Some(candidate) = candidate { - format!("candidate #{candidate}") - } else { - "the candidate".to_string() - }, - ), - sugg, - applicability, - ); + err.span_suggestion_verbose( + span, + format!( + "disambiguate the {def_kind_descr} for {}", + if let Some(candidate) = candidate { + format!("candidate #{candidate}") + } else { + "the candidate".to_string() + }, + ), + format!("{trait_name}::{item_name}{args}"), + Applicability::HasPlaceholders, + ); + return None; + } else if let Some(impl_self_ty) = impl_self_ty { + format!("<{impl_self_ty} as {trait_name}>::") + } else { + format!("{trait_name}::") + }, + ) } diff --git a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr index 5435f22321c9..e39224f2c164 100644 --- a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr +++ b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr @@ -14,14 +14,12 @@ note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32` | LL | const ID: i32 = 3; | ^^^^^^^^^^^^^ -help: disambiguate the associated constant for candidate #1 - | -LL | const X: i32 = ::ID; - | ~~~~~~~~~~~~~~ -help: disambiguate the associated constant for candidate #2 +help: use fully-qualified syntax to disambiguate | LL | const X: i32 = ::ID; | ~~~~~~~~~~~~~~ +LL | const X: i32 = ::ID; + | ~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr index 6f206f2b89c7..866a53f57fc2 100644 --- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr +++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr @@ -33,7 +33,7 @@ error[E0223]: ambiguous associated type --> $DIR/issue-109071.rs:15:22 | LL | fn T() -> Option {} - | ^^^^^^^^^^ help: use the fully-qualified path: ` as IntoIterator>::Item` + | ^^^^^^^^^^ help: use fully-qualified syntax: ` as IntoIterator>::Item` error: aborting due to 4 previous errors diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr index 88c72042ce2d..9206b4f6db7e 100644 --- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr +++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:12 | LL | let _: S::::Pr = (); - | ^^^^^^^^^^^^^ help: use the fully-qualified path: ` as Tr>::Pr` + | ^^^^^^^^^^^^^ help: use fully-qualified syntax: ` as Tr>::Pr` error: aborting due to previous error diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr index 97088b79fd67..f7a47be8dc39 100644 --- a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/ambiguous-associated-type-with-generics.rs:13:13 | LL | let _x: >::Ty; - | ^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: ` as Assoc>::Ty` + | ^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: ` as Assoc>::Ty` error: aborting due to previous error diff --git a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr index d0c170620766..a2346e292ac4 100644 --- a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr @@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type --> $DIR/associated-item-duplicate-names-3.rs:18:12 | LL | let x: Baz::Bar = 5; - | ^^^^^^^^ help: use the fully-qualified path: `::Bar` + | ^^^^^^^^ help: use fully-qualified syntax: `::Bar` error: aborting due to 2 previous errors diff --git a/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr index 236552baf928..df01e1e37686 100644 --- a/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr +++ b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr @@ -10,11 +10,11 @@ LL | type Color; LL | fn a(_: C::Color) { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn a(_: ::Color) { | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn a(_: ::Color) { | ~~~~~~~~~~~~~~~~ @@ -31,11 +31,11 @@ LL | type Color; LL | fn b(_: C::Color) where C : Vehicle+Box { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn b(_: ::Color) where C : Vehicle+Box { | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn b(_: ::Color) where C : Vehicle+Box { | ~~~~~~~~~~~~~~~~ @@ -52,11 +52,11 @@ LL | type Color; LL | fn c(_: C::Color) where C : Vehicle, C : Box { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn c(_: ::Color) where C : Vehicle, C : Box { | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn c(_: ::Color) where C : Vehicle, C : Box { | ~~~~~~~~~~~~~~~~ @@ -73,11 +73,11 @@ LL | type Color; LL | fn e(&self, _: X::Color) where X : Box; | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn e(&self, _: ::Color) where X : Box; | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn e(&self, _: ::Color) where X : Box; | ~~~~~~~~~~~~~~~~ @@ -94,11 +94,11 @@ LL | type Color; LL | fn f(&self, _: X::Color) where X : Box { } | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn f(&self, _: ::Color) where X : Box { } | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn f(&self, _: ::Color) where X : Box { } | ~~~~~~~~~~~~~~~~ @@ -115,11 +115,11 @@ LL | type Color; LL | fn d(&self, _: X::Color) where X : Box { } | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn d(&self, _: ::Color) where X : Box { } | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn d(&self, _: ::Color) where X : Box { } | ~~~~~~~~~~~~~~~~ diff --git a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr index e765f9323984..4f8954b80bc7 100644 --- a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr +++ b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr @@ -18,11 +18,11 @@ LL | type Color; LL | fn dent(c: C, color: C::Color) { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn dent(c: C, color: ::Color) { | ~~~~~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn dent(c: C, color: ::Color) { | ~~~~~~~~~~~~ @@ -71,11 +71,11 @@ LL | type Color; LL | fn paint(c: C, d: C::Color) { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn paint(c: C, d: ::Color) { | ~~~~~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn paint(c: C, d: ::Color) { | ~~~~~~~~~~~~ diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr index 1ff6fd4b821e..d361643f024d 100644 --- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr @@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:22:17 | LL | trait Foo where Foo::Assoc: Bar { - | ^^^^^^^^^^ help: use the fully-qualified path: `::Assoc` + | ^^^^^^^^^^ help: use fully-qualified syntax: `::Assoc` error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:27:10 @@ -21,7 +21,7 @@ error[E0223]: ambiguous associated type LL | type X = std::ops::Deref::Target; | ^^^^^^^^^^^^^^^^^^^^^^^ | -help: use the fully-qualified path +help: use fully-qualified syntax | LL | type X = ::Target; | ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -37,7 +37,7 @@ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:13:23 | LL | fn grab(&self) -> Grab::Value; - | ^^^^^^^^^^^ help: use the fully-qualified path: `::Value` + | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Value` error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:16:22 diff --git a/tests/ui/associated-types/associated-types-path-1.stderr b/tests/ui/associated-types/associated-types-path-1.stderr index a67f77e37c70..cab9dcec0b6b 100644 --- a/tests/ui/associated-types/associated-types-path-1.stderr +++ b/tests/ui/associated-types/associated-types-path-1.stderr @@ -16,11 +16,11 @@ LL | type A; LL | pub fn f2(a: T, x: T::A) {} | ^^^^ ambiguous associated type `A` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | pub fn f2(a: T, x: ::A) {} | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | pub fn f2(a: T, x: ::A) {} | ~~~~~~~~~~~~ diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index efa6bb668240..5c0c7a0b94ff 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -191,7 +191,7 @@ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:33:10 | LL | type H = Fn(u8) -> (u8)::Output; - | ^^^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output` + | ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output` error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:39:19 diff --git a/tests/ui/error-codes/E0034.stderr b/tests/ui/error-codes/E0034.stderr index e29621702657..da6f221881ce 100644 --- a/tests/ui/error-codes/E0034.stderr +++ b/tests/ui/error-codes/E0034.stderr @@ -14,12 +14,10 @@ note: candidate #2 is defined in an impl of the trait `Trait2` for the type `Tes | LL | fn foo() {} | ^^^^^^^^ -help: disambiguate the associated function for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | ::foo() | ~~~~~~~~~~~~~~~~~~ -help: disambiguate the associated function for candidate #2 - | LL | ::foo() | ~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/error-codes/E0221.stderr b/tests/ui/error-codes/E0221.stderr index 5414d77ad7c5..e600acf78344 100644 --- a/tests/ui/error-codes/E0221.stderr +++ b/tests/ui/error-codes/E0221.stderr @@ -10,11 +10,11 @@ LL | fn do_something() { LL | let _: Self::A; | ^^^^^^^ ambiguous associated type `A` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | let _: ::A; | ~~~~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | let _: ::A; | ~~~~~~~~~~~~~~~ @@ -29,7 +29,7 @@ LL | let _: Self::Err; | ^^^^^^^^^ ambiguous associated type `Err` | = note: associated type `Self` could derive from `FromStr` -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | let _: ::Err; | ~~~~~~~~~~~~~~ diff --git a/tests/ui/error-codes/E0223.stderr b/tests/ui/error-codes/E0223.stderr index 42945e42f6ea..1299ba5f50c1 100644 --- a/tests/ui/error-codes/E0223.stderr +++ b/tests/ui/error-codes/E0223.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/E0223.rs:8:14 | LL | let foo: MyTrait::X; - | ^^^^^^^^^^ help: use the fully-qualified path: `::X` + | ^^^^^^^^^^ help: use fully-qualified syntax: `::X` error: aborting due to previous error diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr index a19f4963c239..01ca08a6f19b 100644 --- a/tests/ui/lint/bare-trait-objects-path.stderr +++ b/tests/ui/lint/bare-trait-objects-path.stderr @@ -16,7 +16,7 @@ error[E0223]: ambiguous associated type --> $DIR/bare-trait-objects-path.rs:23:12 | LL | let _: Dyn::Ty; - | ^^^^^^^ help: use the fully-qualified path: `::Ty` + | ^^^^^^^ help: use fully-qualified syntax: `::Ty` warning: trait objects without an explicit `dyn` are deprecated --> $DIR/bare-trait-objects-path.rs:14:5 diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs index f8fb8439ddc5..6a17f6a2172a 100644 --- a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs @@ -29,12 +29,10 @@ fn main() { let s = S; S::foo(&s); //~ ERROR multiple applicable items in scope //~^ NOTE multiple `foo` found - //~| HELP disambiguate - //~| HELP disambiguate + //~| HELP use fully-qualified syntax to disambiguate S::CONST; //~ ERROR multiple applicable items in scope //~^ NOTE multiple `CONST` found - //~| HELP disambiguate - //~| HELP disambiguate + //~| HELP use fully-qualified syntax to disambiguate let _: S::Type; //~ ERROR ambiguous associated type - //~^ HELP use the fully-qualified path + //~^ HELP use fully-qualified syntax } diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr index 5138e7fa2cb0..a9e9c679fdb6 100644 --- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr @@ -1,10 +1,10 @@ error[E0223]: ambiguous associated type - --> $DIR/disambiguate-multiple-blanket-impl.rs:38:12 + --> $DIR/disambiguate-multiple-blanket-impl.rs:36:12 | LL | let _: S::Type; | ^^^^^^^ | -help: use the fully-qualified path +help: use fully-qualified syntax | LL | let _: ::Type; | ~~~~~~~~~~~~~~ @@ -27,17 +27,15 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `T` | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ -help: disambiguate the method for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | ::foo(&s); | ~~~~~~~~~~ -help: disambiguate the method for candidate #2 - | LL | ::foo(&s); | ~~~~~~~~~~ error[E0034]: multiple applicable items in scope - --> $DIR/disambiguate-multiple-blanket-impl.rs:34:8 + --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8 | LL | S::CONST; | ^^^^^ multiple `CONST` found @@ -52,12 +50,10 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `T` | LL | const CONST: usize = 2; | ^^^^^^^^^^^^^^^^^^ -help: disambiguate the associated constant for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | ::CONST; | ~~~~~~~~~~ -help: disambiguate the associated constant for candidate #2 - | LL | ::CONST; | ~~~~~~~~~~ diff --git a/tests/ui/methods/disambiguate-multiple-impl.rs b/tests/ui/methods/disambiguate-multiple-impl.rs index 9562bb865da9..9a82ff01574a 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.rs +++ b/tests/ui/methods/disambiguate-multiple-impl.rs @@ -28,12 +28,10 @@ fn main() { let s = S; S::foo(&s); //~ ERROR multiple applicable items in scope //~^ NOTE multiple `foo` found - //~| HELP disambiguate - //~| HELP disambiguate + //~| HELP use fully-qualified syntax let _: S::Type = (); //~ ERROR ambiguous associated type - //~| HELP use the fully-qualified path + //~| HELP use fully-qualified syntax let _ = S::CONST; //~ ERROR multiple applicable items in scope //~^ NOTE multiple `CONST` found - //~| HELP disambiguate - //~| HELP disambiguate + //~| HELP use fully-qualified syntax } diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr index 60cb086a5734..901bfc30a3f2 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -1,10 +1,10 @@ error[E0223]: ambiguous associated type - --> $DIR/disambiguate-multiple-impl.rs:33:12 + --> $DIR/disambiguate-multiple-impl.rs:32:12 | LL | let _: S::Type = (); | ^^^^^^^ | -help: use the fully-qualified path +help: use fully-qualified syntax | LL | let _: ::Type = (); | ~~~~~~~~~~~~~~ @@ -27,17 +27,15 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `S` | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ -help: disambiguate the method for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | ::foo(&s); | ~~~~~~~~~~ -help: disambiguate the method for candidate #2 - | LL | ::foo(&s); | ~~~~~~~~~~ error[E0034]: multiple applicable items in scope - --> $DIR/disambiguate-multiple-impl.rs:35:16 + --> $DIR/disambiguate-multiple-impl.rs:34:16 | LL | let _ = S::CONST; | ^^^^^ multiple `CONST` found @@ -52,12 +50,10 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `S` | LL | const CONST: usize = 2; | ^^^^^^^^^^^^^^^^^^ -help: disambiguate the associated constant for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | let _ = ::CONST; | ~~~~~~~~~~ -help: disambiguate the associated constant for candidate #2 - | LL | let _ = ::CONST; | ~~~~~~~~~~ diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.rs b/tests/ui/methods/disambiguate-multiple-trait-2.rs index 72ed3413b4ad..829491d824d7 100644 --- a/tests/ui/methods/disambiguate-multiple-trait-2.rs +++ b/tests/ui/methods/disambiguate-multiple-trait-2.rs @@ -19,12 +19,11 @@ fn a(t: T) { //~| HELP disambiguate the method let _ = T::CONST; //~ ERROR multiple applicable items in scope //~^ NOTE multiple `CONST` found - //~| HELP disambiguate - //~| HELP disambiguate + //~| HELP use fully-qualified syntax let _: T::Type; //~ ERROR ambiguous associated type //~^ NOTE ambiguous associated type `Type` - //~| HELP use fully qualified syntax - //~| HELP use fully qualified syntax + //~| HELP use fully-qualified syntax + //~| HELP use fully-qualified syntax } #[derive(Debug)] @@ -46,12 +45,10 @@ fn main() { let s = S; S::foo(&s); //~ ERROR multiple applicable items in scope //~^ NOTE multiple `foo` found - //~| HELP disambiguate - //~| HELP disambiguate + //~| HELP use fully-qualified syntax let _ = S::CONST; //~ ERROR multiple applicable items in scope //~^ NOTE multiple `CONST` found - //~| HELP disambiguate - //~| HELP disambiguate + //~| HELP use fully-qualified syntax let _: S::Type; //~ ERROR ambiguous associated type - //~^ HELP use the fully-qualified path + //~^ HELP use fully-qualified syntax } diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr index 76a240448e65..0f9c60ce243d 100644 --- a/tests/ui/methods/disambiguate-multiple-trait-2.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr @@ -1,5 +1,5 @@ error[E0221]: ambiguous associated type `Type` in bounds of `T` - --> $DIR/disambiguate-multiple-trait-2.rs:24:12 + --> $DIR/disambiguate-multiple-trait-2.rs:23:12 | LL | type Type; | --------- ambiguous `Type` from `A` @@ -10,11 +10,11 @@ LL | type Type; LL | let _: T::Type; | ^^^^^^^ ambiguous associated type `Type` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | let _: ::Type; | ~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | let _: ::Type; | ~~~~~~~~~~ @@ -60,22 +60,20 @@ note: candidate #2 is defined in the trait `B` | LL | const CONST: usize; | ^^^^^^^^^^^^^^^^^^ -help: disambiguate the associated constant for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | let _ = A::CONST; | ~~~ -help: disambiguate the associated constant for candidate #2 - | LL | let _ = B::CONST; | ~~~ error[E0223]: ambiguous associated type - --> $DIR/disambiguate-multiple-trait-2.rs:55:12 + --> $DIR/disambiguate-multiple-trait-2.rs:52:12 | LL | let _: S::Type; | ^^^^^^^ | -help: use the fully-qualified path +help: use fully-qualified syntax | LL | let _: ::Type; | ~~~~~~~~~~~~~~ @@ -83,52 +81,48 @@ LL | let _: ::Type; | ~~~~~~~~~~~~~~ error[E0034]: multiple applicable items in scope - --> $DIR/disambiguate-multiple-trait-2.rs:47:8 + --> $DIR/disambiguate-multiple-trait-2.rs:46:8 | LL | S::foo(&s); | ^^^ multiple `foo` found | note: candidate #1 is defined in an impl of the trait `A` for the type `T` - --> $DIR/disambiguate-multiple-trait-2.rs:36:5 + --> $DIR/disambiguate-multiple-trait-2.rs:35:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `B` for the type `T` - --> $DIR/disambiguate-multiple-trait-2.rs:42:5 + --> $DIR/disambiguate-multiple-trait-2.rs:41:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ -help: disambiguate the method for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | ::foo(&s); | ~~~~~~~~~~ -help: disambiguate the method for candidate #2 - | LL | ::foo(&s); | ~~~~~~~~~~ error[E0034]: multiple applicable items in scope - --> $DIR/disambiguate-multiple-trait-2.rs:51:16 + --> $DIR/disambiguate-multiple-trait-2.rs:49:16 | LL | let _ = S::CONST; | ^^^^^ multiple `CONST` found | note: candidate #1 is defined in an impl of the trait `A` for the type `T` - --> $DIR/disambiguate-multiple-trait-2.rs:35:5 + --> $DIR/disambiguate-multiple-trait-2.rs:34:5 | LL | const CONST: usize = 1; | ^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `B` for the type `T` - --> $DIR/disambiguate-multiple-trait-2.rs:41:5 + --> $DIR/disambiguate-multiple-trait-2.rs:40:5 | LL | const CONST: usize = 1; | ^^^^^^^^^^^^^^^^^^ -help: disambiguate the associated constant for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | let _ = ::CONST; | ~~~~~~~~~~ -help: disambiguate the associated constant for candidate #2 - | LL | let _ = ::CONST; | ~~~~~~~~~~ diff --git a/tests/ui/methods/disambiguate-multiple-trait.rs b/tests/ui/methods/disambiguate-multiple-trait.rs index 73dfc43dd5b4..c990d047576b 100644 --- a/tests/ui/methods/disambiguate-multiple-trait.rs +++ b/tests/ui/methods/disambiguate-multiple-trait.rs @@ -23,12 +23,10 @@ fn main() { let s = S; S::foo(&s); //~ ERROR multiple applicable items in scope //~^ NOTE multiple `foo` found - //~| HELP disambiguate - //~| HELP disambiguate + //~| HELP use fully-qualified syntax let _ = S::CONST; //~ ERROR multiple applicable items in scope //~^ NOTE multiple `CONST` found - //~| HELP disambiguate - //~| HELP disambiguate + //~| HELP use fully-qualified syntax let _: S::Type; //~ ERROR ambiguous associated type - //~^ HELP use the fully-qualified path + //~^ HELP use fully-qualified syntax } diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr index f88c280dfa3b..9a50d51245ba 100644 --- a/tests/ui/methods/disambiguate-multiple-trait.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait.stderr @@ -1,10 +1,10 @@ error[E0223]: ambiguous associated type - --> $DIR/disambiguate-multiple-trait.rs:32:12 + --> $DIR/disambiguate-multiple-trait.rs:30:12 | LL | let _: S::Type; | ^^^^^^^ | -help: use the fully-qualified path +help: use fully-qualified syntax | LL | let _: ::Type; | ~~~~~~~~~~~~~~ @@ -27,17 +27,15 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `T` | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ -help: disambiguate the method for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | ::foo(&s); | ~~~~~~~~~~ -help: disambiguate the method for candidate #2 - | LL | ::foo(&s); | ~~~~~~~~~~ error[E0034]: multiple applicable items in scope - --> $DIR/disambiguate-multiple-trait.rs:28:16 + --> $DIR/disambiguate-multiple-trait.rs:27:16 | LL | let _ = S::CONST; | ^^^^^ multiple `CONST` found @@ -52,12 +50,10 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `T` | LL | const CONST: usize = 2; | ^^^^^^^^^^^^^^^^^^ -help: disambiguate the associated constant for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | let _ = ::CONST; | ~~~~~~~~~~ -help: disambiguate the associated constant for candidate #2 - | LL | let _ = ::CONST; | ~~~~~~~~~~ diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr index 4ba778e0ef72..5bb887b4503a 100644 --- a/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr +++ b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr @@ -14,12 +14,10 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `AB` | LL | fn foo() {} | ^^^^^^^^ -help: disambiguate the associated function for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | ::foo(); | ~~~~~~~~~~~ -help: disambiguate the associated function for candidate #2 - | LL | ::foo(); | ~~~~~~~~~~~ diff --git a/tests/ui/self/self-impl.stderr b/tests/ui/self/self-impl.stderr index 36372b644d6e..18ffd15427f8 100644 --- a/tests/ui/self/self-impl.stderr +++ b/tests/ui/self/self-impl.stderr @@ -2,13 +2,13 @@ error[E0223]: ambiguous associated type --> $DIR/self-impl.rs:23:16 | LL | let _: ::Baz = true; - | ^^^^^^^^^^^ help: use the fully-qualified path: `::Baz` + | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Baz` error[E0223]: ambiguous associated type --> $DIR/self-impl.rs:25:16 | LL | let _: Self::Baz = true; - | ^^^^^^^^^ help: use the fully-qualified path: `::Baz` + | ^^^^^^^^^ help: use fully-qualified syntax: `::Baz` error: aborting due to 2 previous errors diff --git a/tests/ui/structs/struct-path-associated-type.stderr b/tests/ui/structs/struct-path-associated-type.stderr index acfddaf37607..0c9d2aad5d82 100644 --- a/tests/ui/structs/struct-path-associated-type.stderr +++ b/tests/ui/structs/struct-path-associated-type.stderr @@ -48,19 +48,19 @@ error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:32:13 | LL | let s = S::A {}; - | ^^^^ help: use the fully-qualified path: `::A` + | ^^^^ help: use fully-qualified syntax: `::A` error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:33:13 | LL | let z = S::A:: {}; - | ^^^^ help: use the fully-qualified path: `::A` + | ^^^^ help: use fully-qualified syntax: `::A` error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:35:9 | LL | S::A {} => {} - | ^^^^ help: use the fully-qualified path: `::A` + | ^^^^ help: use fully-qualified syntax: `::A` error: aborting due to 8 previous errors diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr index 0ca5b9b92079..0d1eed67c55e 100644 --- a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr +++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/suggest-trait-in-ufcs-in-hrtb.rs:5:38 | LL | impl Foo for Bar where for<'a> <&'a S>::Item: Foo {} - | ^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'a S as IntoIterator>::Item` + | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'a S as IntoIterator>::Item` error: aborting due to previous error diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index f53813189254..af2e07632121 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -159,13 +159,13 @@ error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:116:12 | LL | let _: S::B; - | ^^^^ help: use the fully-qualified path: `::B` + | ^^^^ help: use fully-qualified syntax: `::B` error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:117:12 | LL | let _: S::C; - | ^^^^ help: use the fully-qualified path: `::C` + | ^^^^ help: use fully-qualified syntax: `::C` error[E0624]: associated type `A` is private --> $DIR/item-privacy.rs:119:12 diff --git a/tests/ui/typeck/issue-107087.stderr b/tests/ui/typeck/issue-107087.stderr index 70f19320802b..8921e3f7694d 100644 --- a/tests/ui/typeck/issue-107087.stderr +++ b/tests/ui/typeck/issue-107087.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/issue-107087.rs:16:5 | LL | A::B::<>::C - | ^^^^^^^^ help: use the fully-qualified path: ` as Foo>::B` + | ^^^^^^^^ help: use fully-qualified syntax: ` as Foo>::B` error: aborting due to previous error diff --git a/tests/ui/typeck/issue-110052.stderr b/tests/ui/typeck/issue-110052.stderr index 0c15c03a7408..75374fa6121e 100644 --- a/tests/ui/typeck/issue-110052.stderr +++ b/tests/ui/typeck/issue-110052.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/issue-110052.rs:6:30 | LL | for<'iter> dyn Validator<<&'iter I>::Item>:, - | ^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'iter I as IntoIterator>::Item` + | ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'iter I as IntoIterator>::Item` error: aborting due to previous error From bcdd3d77397295f1e20cd257c306d25c3a32dde2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 17 Oct 2023 17:52:11 +0000 Subject: [PATCH 65/94] Disable effects in libcore again --- library/core/src/lib.rs | 1 - tests/ui/consts/effect_param.rs | 11 +++++++++++ tests/ui/consts/effect_param.stderr | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/ui/consts/effect_param.rs create mode 100644 tests/ui/consts/effect_param.stderr diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 963545a2eb2d..03243e31348e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -219,7 +219,6 @@ #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] -#![feature(effects)] #![feature(exhaustive_patterns)] #![feature(extern_types)] #![feature(fundamental)] diff --git a/tests/ui/consts/effect_param.rs b/tests/ui/consts/effect_param.rs new file mode 100644 index 000000000000..f11ec739fce5 --- /dev/null +++ b/tests/ui/consts/effect_param.rs @@ -0,0 +1,11 @@ +//! Ensure we don't allow accessing const effect parameters from stable Rust. + +fn main() { + i8::checked_sub::(42, 43); + //~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied +} + +const FOO: () = { + i8::checked_sub::(42, 43); + //~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied +}; diff --git a/tests/ui/consts/effect_param.stderr b/tests/ui/consts/effect_param.stderr new file mode 100644 index 000000000000..f8c4bfc02e54 --- /dev/null +++ b/tests/ui/consts/effect_param.stderr @@ -0,0 +1,19 @@ +error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/effect_param.rs:9:9 + | +LL | i8::checked_sub::(42, 43); + | ^^^^^^^^^^^--------- help: remove these generics + | | + | expected 0 generic arguments + +error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/effect_param.rs:4:9 + | +LL | i8::checked_sub::(42, 43); + | ^^^^^^^^^^^-------- help: remove these generics + | | + | expected 0 generic arguments + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. From dee86bff4049692ba50122717131d58582e0f281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 17 Oct 2023 23:08:07 +0000 Subject: [PATCH 66/94] Suggest constraining assoc types in more cases Fix #46969. --- .../infer/error_reporting/note_and_explain.rs | 100 ++++++++++-------- ...ng-assoc-type-because-of-assoc-const.fixed | 14 +++ ...ining-assoc-type-because-of-assoc-const.rs | 14 +++ ...g-assoc-type-because-of-assoc-const.stderr | 16 +++ 4 files changed, 101 insertions(+), 43 deletions(-) create mode 100644 tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed create mode 100644 tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs create mode 100644 tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 24767b0bda6e..8ecf63ec6656 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -341,39 +341,48 @@ impl Trait for X { let tcx = self.tcx; let assoc = tcx.associated_item(proj_ty.def_id); let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx); - if let Some(item) = tcx.hir().get_if_local(body_owner_def_id) { - if let Some(hir_generics) = item.generics() { - // Get the `DefId` for the type parameter corresponding to `A` in `::Foo`. - // This will also work for `impl Trait`. - let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() { - let generics = tcx.generics_of(body_owner_def_id); - generics.type_param(param_ty, tcx).def_id - } else { - return false; - }; - let Some(def_id) = def_id.as_local() else { - return false; - }; + let Some(item) = tcx.hir().get_if_local(body_owner_def_id) else { + return false; + }; + let Some(hir_generics) = item.generics() else { + return false; + }; + // Get the `DefId` for the type parameter corresponding to `A` in `::Foo`. + // This will also work for `impl Trait`. + let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() { + let generics = tcx.generics_of(body_owner_def_id); + generics.type_param(param_ty, tcx).def_id + } else { + return false; + }; + let Some(def_id) = def_id.as_local() else { + return false; + }; - // First look in the `where` clause, as this might be - // `fn foo(x: T) where T: Trait`. - for pred in hir_generics.bounds_for_param(def_id) { - if self.constrain_generic_bound_associated_type_structured_suggestion( - diag, - &trait_ref, - pred.bounds, - assoc, - assoc_args, - ty, - &msg, - false, - ) { - return true; - } - } + // First look in the `where` clause, as this might be + // `fn foo(x: T) where T: Trait`. + for pred in hir_generics.bounds_for_param(def_id) { + if self.constrain_generic_bound_associated_type_structured_suggestion( + diag, + &trait_ref, + pred.bounds, + assoc, + assoc_args, + ty, + &msg, + false, + ) { + return true; } } - false + // If associated item, look to constrain the params of the trait/impl. + let hir_id = match item { + hir::Node::ImplItem(item) => item.hir_id(), + hir::Node::TraitItem(item) => item.hir_id(), + _ => return false, + }; + let parent = tcx.hir().get_parent_item(hir_id).def_id; + self.suggest_constraint(diag, msg, parent.into(), proj_ty, ty) } /// An associated type was expected and a different type was found. @@ -426,21 +435,26 @@ impl Trait for X { let impl_comparison = matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. }); let assoc = tcx.associated_item(proj_ty.def_id); - if !callable_scope || impl_comparison { + if impl_comparison { // We do not want to suggest calling functions when the reason of the - // type error is a comparison of an `impl` with its `trait` or when the - // scope is outside of a `Body`. + // type error is a comparison of an `impl` with its `trait`. } else { - // If we find a suitable associated function that returns the expected type, we don't - // want the more general suggestion later in this method about "consider constraining - // the associated type or calling a method that returns the associated type". - let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type( - diag, - assoc.container_id(tcx), - current_method_ident, - proj_ty.def_id, - values.expected, - ); + let point_at_assoc_fn = if callable_scope + && self.point_at_methods_that_satisfy_associated_type( + diag, + assoc.container_id(tcx), + current_method_ident, + proj_ty.def_id, + values.expected, + ) { + // If we find a suitable associated function that returns the expected type, we + // don't want the more general suggestion later in this method about "consider + // constraining the associated type or calling a method that returns the associated + // type". + true + } else { + false + }; // Possibly suggest constraining the associated type to conform to the // found type. if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found) diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed new file mode 100644 index 000000000000..b9f26a40219b --- /dev/null +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed @@ -0,0 +1,14 @@ +// run-rustfix +trait O { + type M; +} +trait U { + const N: A::M; +} +impl O for D { + type M = u8; +} +impl> U for u16 { + const N: C::M = 4u8; //~ ERROR mismatched types +} +fn main() {} diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs new file mode 100644 index 000000000000..abff6af73e24 --- /dev/null +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs @@ -0,0 +1,14 @@ +// run-rustfix +trait O { + type M; +} +trait U { + const N: A::M; +} +impl O for D { + type M = u8; +} +impl U for u16 { + const N: C::M = 4u8; //~ ERROR mismatched types +} +fn main() {} diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr new file mode 100644 index 000000000000..b104f38ce908 --- /dev/null +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21 + | +LL | const N: C::M = 4u8; + | ^^^ expected associated type, found `u8` + | + = note: expected associated type `::M` + found type `u8` +help: consider constraining the associated type `::M` to `u8` + | +LL | impl> U for u16 { + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 33b0e4be060c8a3f5cc86b6a3e89d8e980a9a51b Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 6 Oct 2023 20:29:42 -0400 Subject: [PATCH 67/94] Automatically enable cross-crate inlining for small functions --- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_metadata/src/rmeta/decoder.rs | 4 + .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +- compiler/rustc_metadata/src/rmeta/mod.rs | 1 + compiler/rustc_metadata/src/rmeta/table.rs | 24 ++++ .../src/middle/codegen_fn_attrs.rs | 8 -- compiler/rustc_middle/src/query/mod.rs | 5 + compiler/rustc_middle/src/ty/instance.rs | 9 +- .../src/cross_crate_inline.rs | 119 +++++++++++++++++ compiler/rustc_mir_transform/src/inline.rs | 14 +- compiler/rustc_mir_transform/src/lib.rs | 2 + compiler/rustc_passes/src/reachable.rs | 58 ++------ compiler/rustc_session/src/options.rs | 2 + library/alloc/src/raw_vec.rs | 1 + library/std/src/rt.rs | 1 + tests/assembly/asm/arm-types.rs | 1 + .../closure-inherit-target-feature.rs | 1 + tests/assembly/dwarf5.rs | 2 +- .../codegen-units/item-collection/asm-sym.rs | 3 + .../auxiliary/cgu_export_trait_method.rs | 2 + .../cross-crate-trait-method.rs | 2 +- .../items-within-generic-items.rs | 2 +- .../item-collection/unreferenced-const-fn.rs | 1 + tests/codegen/asm-sanitize-llvm.rs | 2 +- tests/codegen/async-fn-debug-awaitee-field.rs | 2 +- tests/codegen/debug-linkage-name.rs | 4 +- tests/codegen/default-requires-uwtable.rs | 2 +- tests/codegen/drop.rs | 2 + tests/codegen/force-frame-pointers.rs | 2 +- tests/codegen/force-unwind-tables.rs | 2 +- .../inline-function-args-debug-info.rs | 5 +- tests/codegen/instrument-mcount.rs | 2 +- tests/codegen/instrument-xray/basic.rs | 2 +- .../instrument-xray/options-combine.rs | 6 +- .../instrument-xray/options-override.rs | 4 +- tests/codegen/panic-unwind-default-uwtable.rs | 2 +- tests/codegen/personality_lifetimes.rs | 2 + ...fi-emit-type-metadata-attr-cfi-encoding.rs | 2 +- ...i-emit-type-metadata-id-itanium-cxx-abi.rs | 2 +- .../sanitizer/cfi-generalize-pointers.rs | 2 +- .../sanitizer/cfi-normalize-integers.rs | 2 +- .../sanitizer/kasan-emits-instrumentation.rs | 2 +- tests/codegen/sanitizer/memtag-attr-check.rs | 2 +- tests/codegen/sanitizer/no-sanitize.rs | 2 +- .../codegen/sanitizer/safestack-attr-check.rs | 2 +- .../src-hash-algorithm-md5.rs | 2 +- .../src-hash-algorithm-sha1.rs | 2 +- .../src-hash-algorithm-sha256.rs | 2 +- tests/codegen/target-cpu-on-functions.rs | 3 +- tests/codegen/tied-features-strength.rs | 8 +- tests/codegen/tune-cpu-on-functions.rs | 2 +- ...in.DestinationPropagation.panic-abort.diff | 19 +-- ...n.DestinationPropagation.panic-unwind.diff | 19 +-- ...onential_common.ConstProp.panic-abort.diff | 124 +++++++++--------- ...nential_common.ConstProp.panic-unwind.diff | 124 +++++++++--------- tests/mir-opt/inline/issue_106141.rs | 1 + .../issue_78442.bar.Inline.panic-abort.diff | 22 ++-- .../issue_78442.bar.Inline.panic-unwind.diff | 31 +++-- ...ans.outer.PreCodegen.after.panic-abort.mir | 11 +- ...ns.outer.PreCodegen.after.panic-unwind.mir | 11 +- ...hile_loop.PreCodegen.after.panic-abort.mir | 34 ++--- ...ile_loop.PreCodegen.after.panic-unwind.mir | 34 ++--- tests/run-make/emit-stack-sizes/foo.rs | 1 + .../intrinsic-unreachable/exit-ret.rs | 1 + .../intrinsic-unreachable/exit-unreachable.rs | 1 + tests/ui/hygiene/panic-location.run.stderr | 2 +- 67 files changed, 434 insertions(+), 344 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/cross_crate_inline.rs diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 7799af370089..ec4fd78994e9 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -770,6 +770,7 @@ fn test_unstable_options_tracking_hash() { ); tracked!(codegen_backend, Some("abc".to_string())); tracked!(crate_attr, vec!["abc".to_string()]); + tracked!(cross_crate_inline_threshold, Some(200)); tracked!(debug_info_for_profiling, true); tracked!(debug_macros, true); tracked!(dep_info_omit_d_target, true); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 846f8d25025a..d6ceaa8a0914 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1273,6 +1273,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.optimized_mir.get(self, id).is_some() } + fn cross_crate_inlinable(self, id: DefIndex) -> bool { + self.root.tables.cross_crate_inlinable.get(self, id).unwrap_or(false) + } + fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool { self.root .tables diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f27eee0d79a5..6b6c0d527425 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -287,6 +287,7 @@ provide! { tcx, def_id, other, cdata, item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } + cross_crate_inlinable => { cdata.cross_crate_inlinable(def_id.index) } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } is_private_dep => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index dee2326ae327..7c406f9bddac 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1046,7 +1046,7 @@ fn should_encode_mir( || (tcx.sess.opts.output_types.should_codegen() && reachable_set.contains(&def_id) && (generics.requires_monomorphization(tcx) - || tcx.codegen_fn_attrs(def_id).requests_inline())); + || tcx.cross_crate_inlinable(def_id))); // The function has a `const` modifier or is in a `#[const_trait]`. let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()) || tcx.is_const_default_method(def_id.to_def_id()); @@ -1615,6 +1615,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("EntryBuilder::encode_mir({:?})", def_id); if encode_opt { record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id)); + self.tables + .cross_crate_inlinable + .set(def_id.to_def_id().index, Some(self.tcx.cross_crate_inlinable(def_id))); record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()] <- tcx.closure_saved_names_of_captured_variables(def_id)); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 42764af52c43..2609767a85c5 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -427,6 +427,7 @@ define_tables! { object_lifetime_default: Table>, optimized_mir: Table>>, mir_for_ctfe: Table>>, + cross_crate_inlinable: Table, closure_saved_names_of_captured_variables: Table>>, mir_generator_witnesses: Table>>, promoted_mir: Table>>>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index bb1320942b07..34118e9e8a33 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -299,6 +299,30 @@ impl FixedSizeEncoding for bool { } } +impl FixedSizeEncoding for Option { + type ByteArray = [u8; 1]; + + #[inline] + fn from_bytes(b: &[u8; 1]) -> Self { + match b[0] { + 0 => Some(false), + 1 => Some(true), + 2 => None, + _ => unreachable!(), + } + } + + #[inline] + fn write_to_bytes(self, b: &mut [u8; 1]) { + debug_assert!(!self.is_default()); + b[0] = match self { + Some(false) => 0, + Some(true) => 1, + None => 2, + }; + } +} + impl FixedSizeEncoding for UnusedGenericParams { type ByteArray = [u8; 4]; diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 4e5725876c45..f758c1d5e6f5 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -126,14 +126,6 @@ impl CodegenFnAttrs { } } - /// Returns `true` if `#[inline]` or `#[inline(always)]` is present. - pub fn requests_inline(&self) -> bool { - match self.inline { - InlineAttr::Hint | InlineAttr::Always => true, - InlineAttr::None | InlineAttr::Never => false, - } - } - /// Returns `true` if it looks like this symbol needs to be exported, for example: /// /// * `#[no_mangle]` is present diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 340c5a769dbc..940ab190ffc0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2202,6 +2202,11 @@ rustc_queries! { query generics_require_sized_self(def_id: DefId) -> bool { desc { "check whether the item has a `where Self: Sized` bound" } } + + query cross_crate_inlinable(def_id: DefId) -> bool { + desc { "whether the item should be made inlinable across crates" } + separate_provide_extern + } } rustc_query_append! { define_callbacks! } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 0a425be52ffb..0b308d5dec14 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -245,16 +245,15 @@ impl<'tcx> InstanceDef<'tcx> { // drops of `Option::None` before LTO. We also respect the intent of // `#[inline]` on `Drop::drop` implementations. return ty.ty_adt_def().map_or(true, |adt_def| { - adt_def.destructor(tcx).map_or_else( - || adt_def.is_enum(), - |dtor| tcx.codegen_fn_attrs(dtor.did).requests_inline(), - ) + adt_def + .destructor(tcx) + .map_or_else(|| adt_def.is_enum(), |dtor| tcx.cross_crate_inlinable(dtor.did)) }); } if let ty::InstanceDef::ThreadLocalShim(..) = *self { return false; } - tcx.codegen_fn_attrs(self.def_id()).requests_inline() + tcx.cross_crate_inlinable(self.def_id()) } pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool { diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs new file mode 100644 index 000000000000..24d081f2ac9a --- /dev/null +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -0,0 +1,119 @@ +use rustc_attr::InlineAttr; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::LocalDefId; +use rustc_middle::mir::visit::Visitor; +use rustc_middle::mir::*; +use rustc_middle::query::Providers; +use rustc_middle::ty::TyCtxt; +use rustc_session::config::OptLevel; + +pub fn provide(providers: &mut Providers) { + providers.cross_crate_inlinable = cross_crate_inlinable; +} + +fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id); + // If this has an extern indicator, then this function is globally shared and thus will not + // generate cgu-internal copies which would make it cross-crate inlinable. + if codegen_fn_attrs.contains_extern_indicator() { + return false; + } + + // Obey source annotations first; this is important because it means we can use + // #[inline(never)] to force code generation. + match codegen_fn_attrs.inline { + InlineAttr::Never => return false, + InlineAttr::Hint | InlineAttr::Always => return true, + _ => {} + } + + // This just reproduces the logic from Instance::requires_inline. + match tcx.def_kind(def_id) { + DefKind::Ctor(..) | DefKind::Closure => return true, + DefKind::Fn | DefKind::AssocFn => {} + _ => return false, + } + + // Don't do any inference when incremental compilation is enabled; the additional inlining that + // inference permits also creates more work for small edits. + if tcx.sess.opts.incremental.is_some() { + return false; + } + + // Don't do any inference unless optimizations are enabled. + if matches!(tcx.sess.opts.optimize, OptLevel::No) { + return false; + } + + if !tcx.is_mir_available(def_id) { + return false; + } + + let mir = tcx.optimized_mir(def_id); + let mut checker = + CostChecker { tcx, callee_body: mir, calls: 0, statements: 0, landing_pads: 0, resumes: 0 }; + checker.visit_body(mir); + checker.calls == 0 + && checker.resumes == 0 + && checker.landing_pads == 0 + && checker.statements + <= tcx.sess.opts.unstable_opts.cross_crate_inline_threshold.unwrap_or(100) +} + +struct CostChecker<'b, 'tcx> { + tcx: TyCtxt<'tcx>, + callee_body: &'b Body<'tcx>, + calls: usize, + statements: usize, + landing_pads: usize, + resumes: usize, +} + +impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { + fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { + // Don't count StorageLive/StorageDead in the inlining cost. + match statement.kind { + StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) + | StatementKind::Deinit(_) + | StatementKind::Nop => {} + _ => self.statements += 1, + } + } + + fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, _: Location) { + let tcx = self.tcx; + match terminator.kind { + TerminatorKind::Drop { ref place, unwind, .. } => { + let ty = place.ty(self.callee_body, tcx).ty; + if !ty.is_trivially_pure_clone_copy() { + self.calls += 1; + if let UnwindAction::Cleanup(_) = unwind { + self.landing_pads += 1; + } + } + } + TerminatorKind::Call { unwind, .. } => { + self.calls += 1; + if let UnwindAction::Cleanup(_) = unwind { + self.landing_pads += 1; + } + } + TerminatorKind::Assert { unwind, .. } => { + self.calls += 1; + if let UnwindAction::Cleanup(_) = unwind { + self.landing_pads += 1; + } + } + TerminatorKind::UnwindResume => self.resumes += 1, + TerminatorKind::InlineAsm { unwind, .. } => { + self.statements += 1; + if let UnwindAction::Cleanup(_) = unwind { + self.landing_pads += 1; + } + } + TerminatorKind::Return => {} + _ => self.statements += 1, + } + } +} diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 06ae070c9083..a70371172f73 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -169,8 +169,11 @@ impl<'tcx> Inliner<'tcx> { caller_body: &mut Body<'tcx>, callsite: &CallSite<'tcx>, ) -> Result, &'static str> { + self.check_mir_is_available(caller_body, &callsite.callee)?; + let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id()); - self.check_codegen_attributes(callsite, callee_attrs)?; + let cross_crate_inlinable = self.tcx.cross_crate_inlinable(callsite.callee.def_id()); + self.check_codegen_attributes(callsite, callee_attrs, cross_crate_inlinable)?; let terminator = caller_body[callsite.block].terminator.as_ref().unwrap(); let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; @@ -183,9 +186,8 @@ impl<'tcx> Inliner<'tcx> { } } - self.check_mir_is_available(caller_body, &callsite.callee)?; let callee_body = try_instance_mir(self.tcx, callsite.callee.def)?; - self.check_mir_body(callsite, callee_body, callee_attrs)?; + self.check_mir_body(callsite, callee_body, callee_attrs, cross_crate_inlinable)?; if !self.tcx.consider_optimizing(|| { format!("Inline {:?} into {:?}", callsite.callee, caller_body.source) @@ -401,6 +403,7 @@ impl<'tcx> Inliner<'tcx> { &self, callsite: &CallSite<'tcx>, callee_attrs: &CodegenFnAttrs, + cross_crate_inlinable: bool, ) -> Result<(), &'static str> { if let InlineAttr::Never = callee_attrs.inline { return Err("never inline hint"); @@ -414,7 +417,7 @@ impl<'tcx> Inliner<'tcx> { .non_erasable_generics(self.tcx, callsite.callee.def_id()) .next() .is_some(); - if !is_generic && !callee_attrs.requests_inline() { + if !is_generic && !cross_crate_inlinable { return Err("not exported"); } @@ -456,10 +459,11 @@ impl<'tcx> Inliner<'tcx> { callsite: &CallSite<'tcx>, callee_body: &Body<'tcx>, callee_attrs: &CodegenFnAttrs, + cross_crate_inlinable: bool, ) -> Result<(), &'static str> { let tcx = self.tcx; - let mut threshold = if callee_attrs.requests_inline() { + let mut threshold = if cross_crate_inlinable { self.tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100) } else { self.tcx.sess.opts.unstable_opts.inline_mir_threshold.unwrap_or(50) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 78f76f1e5136..011369747300 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -62,6 +62,7 @@ mod const_prop; mod const_prop_lint; mod copy_prop; mod coverage; +mod cross_crate_inline; mod ctfe_limit; mod dataflow_const_prop; mod dead_store_elimination; @@ -123,6 +124,7 @@ pub fn provide(providers: &mut Providers) { coverage::query::provide(providers); ffi_unwind_calls::provide(providers); shim::provide(providers); + cross_crate_inline::provide(providers); *providers = Providers { mir_keys, mir_const, diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index e93368a84bad..650bb97c4d16 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -18,43 +18,10 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::CrateType; use rustc_target::spec::abi::Abi; -// Returns true if the given item must be inlined because it may be -// monomorphized or it was marked with `#[inline]`. This will only return -// true for functions. -fn item_might_be_inlined(tcx: TyCtxt<'_>, item: &hir::Item<'_>, attrs: &CodegenFnAttrs) -> bool { - if attrs.requests_inline() { - return true; - } - - match item.kind { - hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true, - hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => { - let generics = tcx.generics_of(item.owner_id); - generics.requires_monomorphization(tcx) - } - _ => false, - } -} - -fn method_might_be_inlined( - tcx: TyCtxt<'_>, - impl_item: &hir::ImplItem<'_>, - impl_src: LocalDefId, -) -> bool { - let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id().owner.to_def_id()); - let generics = tcx.generics_of(impl_item.owner_id); - if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { - return true; - } - if let hir::ImplItemKind::Fn(method_sig, _) = &impl_item.kind { - if method_sig.header.is_const() { - return true; - } - } - match tcx.hir().find_by_def_id(impl_src) { - Some(Node::Item(item)) => item_might_be_inlined(tcx, &item, codegen_fn_attrs), - Some(..) | None => span_bug!(impl_item.span, "impl did is not an item"), - } +fn item_might_be_inlined(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + tcx.generics_of(def_id).requires_monomorphization(tcx) + || tcx.cross_crate_inlinable(def_id) + || tcx.is_const_fn(def_id) } // Information needed while computing reachability. @@ -150,9 +117,7 @@ impl<'tcx> ReachableContext<'tcx> { match self.tcx.hir().find_by_def_id(def_id) { Some(Node::Item(item)) => match item.kind { - hir::ItemKind::Fn(..) => { - item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id)) - } + hir::ItemKind::Fn(..) => item_might_be_inlined(self.tcx, def_id.into()), _ => false, }, Some(Node::TraitItem(trait_method)) => match trait_method.kind { @@ -164,9 +129,7 @@ impl<'tcx> ReachableContext<'tcx> { Some(Node::ImplItem(impl_item)) => match impl_item.kind { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Fn(..) => { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - let impl_did = self.tcx.hir().get_parent_item(hir_id); - method_might_be_inlined(self.tcx, impl_item, impl_did.def_id) + item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) } hir::ImplItemKind::Type(_) => false, }, @@ -226,11 +189,7 @@ impl<'tcx> ReachableContext<'tcx> { Node::Item(item) => { match item.kind { hir::ItemKind::Fn(.., body) => { - if item_might_be_inlined( - self.tcx, - &item, - self.tcx.codegen_fn_attrs(item.owner_id), - ) { + if item_might_be_inlined(self.tcx, item.owner_id.into()) { self.visit_nested_body(body); } } @@ -279,8 +238,7 @@ impl<'tcx> ReachableContext<'tcx> { self.visit_nested_body(body); } hir::ImplItemKind::Fn(_, body) => { - let impl_def_id = self.tcx.local_parent(search_item); - if method_might_be_inlined(self.tcx, impl_item, impl_def_id) { + if item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) { self.visit_nested_body(body) } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f33139c5c4b9..11fbd9f8f86a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1452,6 +1452,8 @@ options! { "combine CGUs into a single one"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), + cross_crate_inline_threshold: Option = (None, parse_opt_number, [TRACKED], + "threshold to allow cross crate inlining of functions"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), debug_macros: bool = (false, parse_bool, [TRACKED], diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 01b03de6acb5..625b67a79ad0 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -530,6 +530,7 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { // ensure that the code generation related to these panics is minimal as there's // only one location which panics rather than a bunch throughout the module. #[cfg(not(no_global_oom_handling))] +#[inline(never)] fn capacity_overflow() -> ! { panic!("capacity overflow"); } diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index f1eeb75be7c4..5c83f72f3c1a 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -155,6 +155,7 @@ fn lang_start_internal( } #[cfg(not(test))] +#[inline(never)] #[lang = "start"] fn lang_start( main: fn() -> T, diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs index b22a26ce36f1..9520f9327797 100644 --- a/tests/assembly/asm/arm-types.rs +++ b/tests/assembly/asm/arm-types.rs @@ -1,6 +1,7 @@ // assembly-output: emit-asm // compile-flags: --target armv7-unknown-linux-gnueabihf // compile-flags: -C target-feature=+neon +// compile-flags: -C opt-level=0 // needs-llvm-components: arm #![feature(no_core, lang_items, rustc_attrs, repr_simd)] diff --git a/tests/assembly/closure-inherit-target-feature.rs b/tests/assembly/closure-inherit-target-feature.rs index 65728a155166..248026034526 100644 --- a/tests/assembly/closure-inherit-target-feature.rs +++ b/tests/assembly/closure-inherit-target-feature.rs @@ -22,6 +22,7 @@ pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128) -> __m128 { f(x, y) } +#[no_mangle] #[target_feature(enable = "sse4.1")] pub fn sse41_blend_noinline(x: __m128, y: __m128) -> __m128 { let f = { diff --git a/tests/assembly/dwarf5.rs b/tests/assembly/dwarf5.rs index f41e6bd55be7..253baafb8873 100644 --- a/tests/assembly/dwarf5.rs +++ b/tests/assembly/dwarf5.rs @@ -1,6 +1,6 @@ // Makes sure that `-Z dwarf-version=5` causes `rustc` to emit DWARF version 5. // assembly-output: emit-asm -// compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5 +// compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5 -Copt-level=0 // needs-llvm-components: x86 #![feature(no_core, lang_items)] diff --git a/tests/codegen-units/item-collection/asm-sym.rs b/tests/codegen-units/item-collection/asm-sym.rs index 8bafb95bc16d..4b05b771a9b2 100644 --- a/tests/codegen-units/item-collection/asm-sym.rs +++ b/tests/codegen-units/item-collection/asm-sym.rs @@ -6,15 +6,18 @@ pub unsafe fn f() { //~ MONO_ITEM static f::S @@ asm_sym-cgu.0[External] static S: usize = 1; //~ MONO_ITEM fn f::fun @@ asm_sym-cgu.0[External] + #[inline(never)] fn fun() {} core::arch::asm!("/* {0} {1} */", sym S, sym fun); } //~ MONO_ITEM fn g @@ asm_sym-cgu.0[External] +#[inline(never)] pub unsafe fn g() { //~ MONO_ITEM static g::S @@ asm_sym-cgu.0[Internal] static S: usize = 2; //~ MONO_ITEM fn g::fun @@ asm_sym-cgu.0[Internal] + #[inline(never)] fn fun() {} core::arch::asm!("/* {0} {1} */", sym S, sym fun); } diff --git a/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs b/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs index ecea26dc4be4..e94dded55cff 100644 --- a/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs +++ b/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs @@ -1,3 +1,5 @@ +// compile-flags: -Copt-level=0 + #![crate_type = "lib"] pub trait Trait : Sized { diff --git a/tests/codegen-units/item-collection/cross-crate-trait-method.rs b/tests/codegen-units/item-collection/cross-crate-trait-method.rs index b7216a143180..778b3820f18e 100644 --- a/tests/codegen-units/item-collection/cross-crate-trait-method.rs +++ b/tests/codegen-units/item-collection/cross-crate-trait-method.rs @@ -1,4 +1,4 @@ -// compile-flags:-Zprint-mono-items=eager -Zinline-mir=no +// compile-flags:-Zprint-mono-items=eager -Zinline-mir=no -Copt-level=0 #![deny(dead_code)] #![feature(start)] diff --git a/tests/codegen-units/item-collection/items-within-generic-items.rs b/tests/codegen-units/item-collection/items-within-generic-items.rs index d37d7f7d9b2b..bb1a3be36c5c 100644 --- a/tests/codegen-units/item-collection/items-within-generic-items.rs +++ b/tests/codegen-units/item-collection/items-within-generic-items.rs @@ -1,4 +1,4 @@ -// compile-flags:-Zprint-mono-items=eager +// compile-flags:-Zprint-mono-items=eager -Copt-level=0 #![deny(dead_code)] #![feature(start)] diff --git a/tests/codegen-units/item-collection/unreferenced-const-fn.rs b/tests/codegen-units/item-collection/unreferenced-const-fn.rs index 17b92eae00d0..5f59d801504e 100644 --- a/tests/codegen-units/item-collection/unreferenced-const-fn.rs +++ b/tests/codegen-units/item-collection/unreferenced-const-fn.rs @@ -4,6 +4,7 @@ #![crate_type = "rlib"] //~ MONO_ITEM fn foo @@ unreferenced_const_fn-cgu.0[External] +#[inline(never)] pub const fn foo(x: u32) -> u32 { x + 0xf00 } diff --git a/tests/codegen/asm-sanitize-llvm.rs b/tests/codegen/asm-sanitize-llvm.rs index 6dcacd08cacd..41bed98038ec 100644 --- a/tests/codegen/asm-sanitize-llvm.rs +++ b/tests/codegen/asm-sanitize-llvm.rs @@ -1,5 +1,5 @@ // FIXME(nagisa): remove the flags below once all targets support `asm!`. -// compile-flags: --target x86_64-unknown-linux-gnu +// compile-flags: --target x86_64-unknown-linux-gnu -Copt-level=0 // needs-llvm-components: x86 // Verify we sanitize the special tokens for the LLVM inline-assembly, ensuring people won't diff --git a/tests/codegen/async-fn-debug-awaitee-field.rs b/tests/codegen/async-fn-debug-awaitee-field.rs index 690505fd72bd..29defe68f8b8 100644 --- a/tests/codegen/async-fn-debug-awaitee-field.rs +++ b/tests/codegen/async-fn-debug-awaitee-field.rs @@ -3,7 +3,7 @@ // extensions rely on the field having this name. // ignore-tidy-linelength -// compile-flags: -C debuginfo=2 --edition=2018 +// compile-flags: -C debuginfo=2 --edition=2018 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/debug-linkage-name.rs b/tests/codegen/debug-linkage-name.rs index 9011a7da51db..9bf4d521fc01 100644 --- a/tests/codegen/debug-linkage-name.rs +++ b/tests/codegen/debug-linkage-name.rs @@ -1,8 +1,8 @@ // Verifies that linkage name is omitted when it is // the same as variable / function name. // -// compile-flags: -C no-prepopulate-passes -// compile-flags: -C debuginfo=2 +// compile-flags: -C no-prepopulate-passes -Copt-level=0 +// compile-flags: -C debuginfo=2 -Copt-level=0 #![crate_type = "lib"] pub mod xyz { diff --git a/tests/codegen/default-requires-uwtable.rs b/tests/codegen/default-requires-uwtable.rs index 5d77d3f14bb1..26424f03568b 100644 --- a/tests/codegen/default-requires-uwtable.rs +++ b/tests/codegen/default-requires-uwtable.rs @@ -1,5 +1,5 @@ // revisions: WINDOWS ANDROID -// compile-flags: -C panic=abort +// compile-flags: -C panic=abort -Copt-level=0 // [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc // [WINDOWS] needs-llvm-components: x86 // [ANDROID] compile-flags: --target=armv7-linux-androideabi diff --git a/tests/codegen/drop.rs b/tests/codegen/drop.rs index 3615ef47b531..14b5840e2fe2 100644 --- a/tests/codegen/drop.rs +++ b/tests/codegen/drop.rs @@ -7,10 +7,12 @@ struct SomeUniqueName; impl Drop for SomeUniqueName { + #[inline(never)] fn drop(&mut self) { } } +#[inline(never)] pub fn possibly_unwinding() { } diff --git a/tests/codegen/force-frame-pointers.rs b/tests/codegen/force-frame-pointers.rs index 637c4234654b..5791ae47937b 100644 --- a/tests/codegen/force-frame-pointers.rs +++ b/tests/codegen/force-frame-pointers.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y +// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y -Copt-level=0 #![crate_type="lib"] diff --git a/tests/codegen/force-unwind-tables.rs b/tests/codegen/force-unwind-tables.rs index 4c0a5602c6da..c904978c9ff2 100644 --- a/tests/codegen/force-unwind-tables.rs +++ b/tests/codegen/force-unwind-tables.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y +// compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y -Copt-level=0 #![crate_type="lib"] diff --git a/tests/codegen/inline-function-args-debug-info.rs b/tests/codegen/inline-function-args-debug-info.rs index e3d8caa49d45..ffae99e0f24e 100644 --- a/tests/codegen/inline-function-args-debug-info.rs +++ b/tests/codegen/inline-function-args-debug-info.rs @@ -6,6 +6,7 @@ #![crate_type = "lib"] +#[inline(never)] pub fn outer_function(x: usize, y: usize) -> usize { inner_function(x, y) + 1 } @@ -13,8 +14,8 @@ pub fn outer_function(x: usize, y: usize) -> usize { #[inline] fn inner_function(aaaa: usize, bbbb: usize) -> usize { // CHECK: !DILocalVariable(name: "aaaa", arg: 1 - // CHECK-SAME: line: 14 + // CHECK-SAME: line: 15 // CHECK: !DILocalVariable(name: "bbbb", arg: 2 - // CHECK-SAME: line: 14 + // CHECK-SAME: line: 15 aaaa + bbbb } diff --git a/tests/codegen/instrument-mcount.rs b/tests/codegen/instrument-mcount.rs index b26076e7a7bf..50823775a41a 100644 --- a/tests/codegen/instrument-mcount.rs +++ b/tests/codegen/instrument-mcount.rs @@ -1,5 +1,5 @@ // -// compile-flags: -Z instrument-mcount +// compile-flags: -Z instrument-mcount -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/instrument-xray/basic.rs b/tests/codegen/instrument-xray/basic.rs index d3e49d531744..5da878474f2e 100644 --- a/tests/codegen/instrument-xray/basic.rs +++ b/tests/codegen/instrument-xray/basic.rs @@ -1,7 +1,7 @@ // Checks that `-Z instrument-xray` produces expected instrumentation. // // needs-xray -// compile-flags: -Z instrument-xray=always +// compile-flags: -Z instrument-xray=always -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/instrument-xray/options-combine.rs b/tests/codegen/instrument-xray/options-combine.rs index f7e500b65f62..d1e56586279a 100644 --- a/tests/codegen/instrument-xray/options-combine.rs +++ b/tests/codegen/instrument-xray/options-combine.rs @@ -1,9 +1,9 @@ // Checks that `-Z instrument-xray` options can be specified multiple times. // // needs-xray -// compile-flags: -Z instrument-xray=skip-exit -// compile-flags: -Z instrument-xray=instruction-threshold=123 -// compile-flags: -Z instrument-xray=instruction-threshold=456 +// compile-flags: -Z instrument-xray=skip-exit -Copt-level=0 +// compile-flags: -Z instrument-xray=instruction-threshold=123 -Copt-level=0 +// compile-flags: -Z instrument-xray=instruction-threshold=456 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/instrument-xray/options-override.rs b/tests/codegen/instrument-xray/options-override.rs index 00f81837902d..b1fc4c966dcb 100644 --- a/tests/codegen/instrument-xray/options-override.rs +++ b/tests/codegen/instrument-xray/options-override.rs @@ -1,8 +1,8 @@ // Checks that the last `-Z instrument-xray` option wins. // // needs-xray -// compile-flags: -Z instrument-xray=always -// compile-flags: -Z instrument-xray=never +// compile-flags: -Z instrument-xray=always -Copt-level=0 +// compile-flags: -Z instrument-xray=never -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/panic-unwind-default-uwtable.rs b/tests/codegen/panic-unwind-default-uwtable.rs index 4c85008cf359..b78b159d20d5 100644 --- a/tests/codegen/panic-unwind-default-uwtable.rs +++ b/tests/codegen/panic-unwind-default-uwtable.rs @@ -1,4 +1,4 @@ -// compile-flags: -C panic=unwind -C no-prepopulate-passes +// compile-flags: -C panic=unwind -C no-prepopulate-passes -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/personality_lifetimes.rs b/tests/codegen/personality_lifetimes.rs index 47243bece98f..b39718a8d08c 100644 --- a/tests/codegen/personality_lifetimes.rs +++ b/tests/codegen/personality_lifetimes.rs @@ -9,10 +9,12 @@ struct S; impl Drop for S { + #[inline(never)] fn drop(&mut self) { } } +#[inline(never)] fn might_unwind() { } diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs index 084d8bf803c8..f16890afad08 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs @@ -1,7 +1,7 @@ // Verifies that user-defined CFI encoding for types are emitted. // // needs-sanitizer-cfi -// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi +// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 #![crate_type="lib"] #![feature(cfi_encoding, extern_types)] diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs index 2d8b13e2080e..4ed7c27fc4e8 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -1,7 +1,7 @@ // Verifies that type metadata identifiers for functions are emitted correctly. // // needs-sanitizer-cfi -// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi +// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 #![crate_type="lib"] #![allow(dead_code)] diff --git a/tests/codegen/sanitizer/cfi-generalize-pointers.rs b/tests/codegen/sanitizer/cfi-generalize-pointers.rs index 677ebdb27ec5..17cb42d3e74f 100644 --- a/tests/codegen/sanitizer/cfi-generalize-pointers.rs +++ b/tests/codegen/sanitizer/cfi-generalize-pointers.rs @@ -1,7 +1,7 @@ // Verifies that pointer types are generalized. // // needs-sanitizer-cfi -// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers +// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers -Copt-level=0 #![crate_type="lib"] diff --git a/tests/codegen/sanitizer/cfi-normalize-integers.rs b/tests/codegen/sanitizer/cfi-normalize-integers.rs index aa3913cb8e7d..9663aa54c28d 100644 --- a/tests/codegen/sanitizer/cfi-normalize-integers.rs +++ b/tests/codegen/sanitizer/cfi-normalize-integers.rs @@ -1,7 +1,7 @@ // Verifies that integer types are normalized. // // needs-sanitizer-cfi -// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers +// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -Copt-level=0 #![crate_type="lib"] diff --git a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs index 783bc47b9d05..29d50d8df24a 100644 --- a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs +++ b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs @@ -1,6 +1,6 @@ // Verifies that `-Zsanitizer=kernel-address` emits sanitizer instrumentation. -// compile-flags: -Zsanitizer=kernel-address +// compile-flags: -Zsanitizer=kernel-address -Copt-level=0 // revisions: aarch64 riscv64imac riscv64gc x86_64 //[aarch64] compile-flags: --target aarch64-unknown-none //[aarch64] needs-llvm-components: aarch64 diff --git a/tests/codegen/sanitizer/memtag-attr-check.rs b/tests/codegen/sanitizer/memtag-attr-check.rs index 2fd362656d4b..3e5e14e84297 100644 --- a/tests/codegen/sanitizer/memtag-attr-check.rs +++ b/tests/codegen/sanitizer/memtag-attr-check.rs @@ -2,7 +2,7 @@ // applied when enabling the memtag sanitizer. // // needs-sanitizer-memtag -// compile-flags: -Zsanitizer=memtag -Ctarget-feature=+mte +// compile-flags: -Zsanitizer=memtag -Ctarget-feature=+mte -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/no-sanitize.rs b/tests/codegen/sanitizer/no-sanitize.rs index d0b692434537..029cf8e7f5c9 100644 --- a/tests/codegen/sanitizer/no-sanitize.rs +++ b/tests/codegen/sanitizer/no-sanitize.rs @@ -2,7 +2,7 @@ // selectively disable sanitizer instrumentation. // // needs-sanitizer-address -// compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static +// compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static -Copt-level=0 #![crate_type="lib"] #![feature(no_sanitize)] diff --git a/tests/codegen/sanitizer/safestack-attr-check.rs b/tests/codegen/sanitizer/safestack-attr-check.rs index b73ed00e7308..b19e2d131334 100644 --- a/tests/codegen/sanitizer/safestack-attr-check.rs +++ b/tests/codegen/sanitizer/safestack-attr-check.rs @@ -1,7 +1,7 @@ // This tests that the safestack attribute is applied when enabling the safe-stack sanitizer. // // needs-sanitizer-safestack -// compile-flags: -Zsanitizer=safestack +// compile-flags: -Zsanitizer=safestack -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs b/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs index 64be1127786f..6ef0f0406d20 100644 --- a/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs +++ b/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs @@ -1,4 +1,4 @@ -// compile-flags: -g -Z src-hash-algorithm=md5 +// compile-flags: -g -Z src-hash-algorithm=md5 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs index 54e07152142e..ebfa3040acaf 100644 --- a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs +++ b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs @@ -1,4 +1,4 @@ -// compile-flags: -g -Z src-hash-algorithm=sha1 +// compile-flags: -g -Z src-hash-algorithm=sha1 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs index dc7db8e23728..5ec678d55f34 100644 --- a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs +++ b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs @@ -1,4 +1,4 @@ -// compile-flags: -g -Z src-hash-algorithm=sha256 +// compile-flags: -g -Z src-hash-algorithm=sha256 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/target-cpu-on-functions.rs b/tests/codegen/target-cpu-on-functions.rs index c043eceb5cd1..d5250f22cca9 100644 --- a/tests/codegen/target-cpu-on-functions.rs +++ b/tests/codegen/target-cpu-on-functions.rs @@ -15,7 +15,8 @@ pub extern "C" fn exported() { // CHECK-LABEL: ; target_cpu_on_functions::not_exported // CHECK-NEXT: ; Function Attrs: -// CHECK-NEXT: define {{.*}}() {{.*}} #0 +// CHECK-NEXT: define {{.*}}() {{.*}} #1 +#[inline(never)] fn not_exported() {} // CHECK: attributes #0 = {{.*}} "target-cpu"="{{.*}}" diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 51334c121582..71cea48c4da5 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -7,16 +7,16 @@ // are targeting older LLVM versions. Once the min supported version // is LLVM-14 we can remove the optional regex matching for this feature. -// [ENABLE_SVE] compile-flags: -C target-feature=+sve +// [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0 // ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?))*}}" } -// [DISABLE_SVE] compile-flags: -C target-feature=-sve +// [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 // DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" } -// [DISABLE_NEON] compile-flags: -C target-feature=-neon +// [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 // DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" } -// [ENABLE_NEON] compile-flags: -C target-feature=+neon +// [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 // ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } diff --git a/tests/codegen/tune-cpu-on-functions.rs b/tests/codegen/tune-cpu-on-functions.rs index ed8dc0e93837..116f0772d255 100644 --- a/tests/codegen/tune-cpu-on-functions.rs +++ b/tests/codegen/tune-cpu-on-functions.rs @@ -3,7 +3,7 @@ // no-prefer-dynamic // -// compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals -Z tune-cpu=generic +// compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals -Z tune-cpu=generic -Copt-level=0 #![crate_type = "staticlib"] diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index d5e58265dcc8..142e08f4d6c3 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -4,29 +4,20 @@ fn main() -> () { let mut _0: (); let _1: main::Un; - let mut _2: u32; - let mut _3: u32; scope 1 { debug un => _1; scope 2 { } - scope 3 (inlined std::mem::drop::) { - debug _x => _3; + scope 4 (inlined std::mem::drop::) { + debug _x => const 1_u32; } } + scope 3 (inlined val) { + } bb0: { StorageLive(_1); - StorageLive(_2); - _2 = val() -> [return: bb1, unwind unreachable]; - } - - bb1: { - _1 = Un { us: move _2 }; - StorageDead(_2); - StorageLive(_3); - _3 = (_1.0: u32); - StorageDead(_3); + _1 = Un { us: const 1_u32 }; StorageDead(_1); return; } diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index 5eaaeba135bd..142e08f4d6c3 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -4,29 +4,20 @@ fn main() -> () { let mut _0: (); let _1: main::Un; - let mut _2: u32; - let mut _3: u32; scope 1 { debug un => _1; scope 2 { } - scope 3 (inlined std::mem::drop::) { - debug _x => _3; + scope 4 (inlined std::mem::drop::) { + debug _x => const 1_u32; } } + scope 3 (inlined val) { + } bb0: { StorageLive(_1); - StorageLive(_2); - _2 = val() -> [return: bb1, unwind continue]; - } - - bb1: { - _1 = Un { us: move _2 }; - StorageDead(_2); - StorageLive(_3); - _3 = (_1.0: u32); - StorageDead(_3); + _1 = Un { us: const 1_u32 }; StorageDead(_1); return; } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff index a538756ba2d0..298a60848993 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff @@ -7,104 +7,104 @@ debug upper => _3; let mut _0: std::result::Result<(), std::fmt::Error>; let _4: bool; - let mut _5: &std::fmt::Formatter<'_>; - let mut _7: std::option::Option; - let mut _8: &std::fmt::Formatter<'_>; - let mut _9: isize; - let mut _11: &mut std::fmt::Formatter<'_>; - let mut _12: &T; - let mut _13: core::num::flt2dec::Sign; - let mut _14: u32; - let mut _15: u32; - let mut _16: usize; - let mut _17: bool; - let mut _18: &mut std::fmt::Formatter<'_>; - let mut _19: &T; - let mut _20: core::num::flt2dec::Sign; - let mut _21: bool; + let mut _6: std::option::Option; + let mut _7: isize; + let mut _9: &mut std::fmt::Formatter<'_>; + let mut _10: &T; + let mut _11: core::num::flt2dec::Sign; + let mut _12: u32; + let mut _13: u32; + let mut _14: usize; + let mut _15: bool; + let mut _16: &mut std::fmt::Formatter<'_>; + let mut _17: &T; + let mut _18: core::num::flt2dec::Sign; + let mut _19: bool; scope 1 { debug force_sign => _4; - let _6: core::num::flt2dec::Sign; + let _5: core::num::flt2dec::Sign; scope 2 { - debug sign => _6; + debug sign => _5; scope 3 { - debug precision => _10; - let _10: usize; + debug precision => _8; + let _8: usize; + scope 5 (inlined Formatter::<'_>::precision) { + debug self => _1; + } } } } + scope 4 (inlined Formatter::<'_>::sign_plus) { + debug self => _1; + let mut _20: u32; + let mut _21: u32; + } bb0: { StorageLive(_4); + StorageLive(_20); + StorageLive(_21); + _21 = ((*_1).0: u32); + _20 = BitAnd(move _21, const 1_u32); + StorageDead(_21); + _4 = Ne(move _20, const 0_u32); + StorageDead(_20); StorageLive(_5); - _5 = &(*_1); - _4 = Formatter::<'_>::sign_plus(move _5) -> [return: bb1, unwind unreachable]; + switchInt(_4) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageDead(_5); - StorageLive(_6); - switchInt(_4) -> [0: bb3, otherwise: bb2]; +- _5 = MinusPlus; ++ _5 = const MinusPlus; + goto -> bb3; } bb2: { -- _6 = MinusPlus; -+ _6 = const MinusPlus; - goto -> bb4; +- _5 = Minus; ++ _5 = const Minus; + goto -> bb3; } bb3: { -- _6 = Minus; -+ _6 = const Minus; - goto -> bb4; + StorageLive(_6); + _6 = ((*_1).4: std::option::Option); + _7 = discriminant(_6); + switchInt(move _7) -> [1: bb4, otherwise: bb6]; } bb4: { - StorageLive(_7); - StorageLive(_8); - _8 = &(*_1); - _7 = Formatter::<'_>::precision(move _8) -> [return: bb5, unwind unreachable]; + _8 = ((_6 as Some).0: usize); + StorageLive(_11); + _11 = _5; + StorageLive(_12); + StorageLive(_13); + _13 = _8 as u32 (IntToInt); + _12 = Add(move _13, const 1_u32); + StorageDead(_13); + _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_8); - _9 = discriminant(_7); - switchInt(move _9) -> [1: bb6, otherwise: bb8]; + StorageDead(_12); + StorageDead(_11); + goto -> bb8; } bb6: { - _10 = ((_7 as Some).0: usize); - StorageLive(_13); - _13 = _6; - StorageLive(_14); - StorageLive(_15); - _15 = _10 as u32 (IntToInt); - _14 = Add(move _15, const 1_u32); - StorageDead(_15); - _0 = float_to_exponential_common_exact::(_1, _2, move _13, move _14, _3) -> [return: bb7, unwind unreachable]; + StorageLive(_18); + _18 = _5; + _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_14); - StorageDead(_13); - goto -> bb10; + StorageDead(_18); + goto -> bb8; } bb8: { - StorageLive(_20); - _20 = _6; - _0 = float_to_exponential_common_shortest::(_1, _2, move _20, _3) -> [return: bb9, unwind unreachable]; - } - - bb9: { - StorageDead(_20); - goto -> bb10; - } - - bb10: { - StorageDead(_6); + StorageDead(_5); StorageDead(_4); - StorageDead(_7); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff index 8a3dcfab44bd..037f4f7cfac2 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff @@ -7,104 +7,104 @@ debug upper => _3; let mut _0: std::result::Result<(), std::fmt::Error>; let _4: bool; - let mut _5: &std::fmt::Formatter<'_>; - let mut _7: std::option::Option; - let mut _8: &std::fmt::Formatter<'_>; - let mut _9: isize; - let mut _11: &mut std::fmt::Formatter<'_>; - let mut _12: &T; - let mut _13: core::num::flt2dec::Sign; - let mut _14: u32; - let mut _15: u32; - let mut _16: usize; - let mut _17: bool; - let mut _18: &mut std::fmt::Formatter<'_>; - let mut _19: &T; - let mut _20: core::num::flt2dec::Sign; - let mut _21: bool; + let mut _6: std::option::Option; + let mut _7: isize; + let mut _9: &mut std::fmt::Formatter<'_>; + let mut _10: &T; + let mut _11: core::num::flt2dec::Sign; + let mut _12: u32; + let mut _13: u32; + let mut _14: usize; + let mut _15: bool; + let mut _16: &mut std::fmt::Formatter<'_>; + let mut _17: &T; + let mut _18: core::num::flt2dec::Sign; + let mut _19: bool; scope 1 { debug force_sign => _4; - let _6: core::num::flt2dec::Sign; + let _5: core::num::flt2dec::Sign; scope 2 { - debug sign => _6; + debug sign => _5; scope 3 { - debug precision => _10; - let _10: usize; + debug precision => _8; + let _8: usize; + scope 5 (inlined Formatter::<'_>::precision) { + debug self => _1; + } } } } + scope 4 (inlined Formatter::<'_>::sign_plus) { + debug self => _1; + let mut _20: u32; + let mut _21: u32; + } bb0: { StorageLive(_4); + StorageLive(_20); + StorageLive(_21); + _21 = ((*_1).0: u32); + _20 = BitAnd(move _21, const 1_u32); + StorageDead(_21); + _4 = Ne(move _20, const 0_u32); + StorageDead(_20); StorageLive(_5); - _5 = &(*_1); - _4 = Formatter::<'_>::sign_plus(move _5) -> [return: bb1, unwind continue]; + switchInt(_4) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageDead(_5); - StorageLive(_6); - switchInt(_4) -> [0: bb3, otherwise: bb2]; +- _5 = MinusPlus; ++ _5 = const MinusPlus; + goto -> bb3; } bb2: { -- _6 = MinusPlus; -+ _6 = const MinusPlus; - goto -> bb4; +- _5 = Minus; ++ _5 = const Minus; + goto -> bb3; } bb3: { -- _6 = Minus; -+ _6 = const Minus; - goto -> bb4; + StorageLive(_6); + _6 = ((*_1).4: std::option::Option); + _7 = discriminant(_6); + switchInt(move _7) -> [1: bb4, otherwise: bb6]; } bb4: { - StorageLive(_7); - StorageLive(_8); - _8 = &(*_1); - _7 = Formatter::<'_>::precision(move _8) -> [return: bb5, unwind continue]; + _8 = ((_6 as Some).0: usize); + StorageLive(_11); + _11 = _5; + StorageLive(_12); + StorageLive(_13); + _13 = _8 as u32 (IntToInt); + _12 = Add(move _13, const 1_u32); + StorageDead(_13); + _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind continue]; } bb5: { - StorageDead(_8); - _9 = discriminant(_7); - switchInt(move _9) -> [1: bb6, otherwise: bb8]; + StorageDead(_12); + StorageDead(_11); + goto -> bb8; } bb6: { - _10 = ((_7 as Some).0: usize); - StorageLive(_13); - _13 = _6; - StorageLive(_14); - StorageLive(_15); - _15 = _10 as u32 (IntToInt); - _14 = Add(move _15, const 1_u32); - StorageDead(_15); - _0 = float_to_exponential_common_exact::(_1, _2, move _13, move _14, _3) -> [return: bb7, unwind continue]; + StorageLive(_18); + _18 = _5; + _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind continue]; } bb7: { - StorageDead(_14); - StorageDead(_13); - goto -> bb10; + StorageDead(_18); + goto -> bb8; } bb8: { - StorageLive(_20); - _20 = _6; - _0 = float_to_exponential_common_shortest::(_1, _2, move _20, _3) -> [return: bb9, unwind continue]; - } - - bb9: { - StorageDead(_20); - goto -> bb10; - } - - bb10: { - StorageDead(_6); + StorageDead(_5); StorageDead(_4); - StorageDead(_7); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/inline/issue_106141.rs b/tests/mir-opt/inline/issue_106141.rs index eed1d89172ce..e442f8a7522f 100644 --- a/tests/mir-opt/inline/issue_106141.rs +++ b/tests/mir-opt/inline/issue_106141.rs @@ -3,6 +3,7 @@ pub fn outer() -> usize { inner() } +#[inline(never)] fn index() -> usize { loop {} } diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff index bee01a5f97b9..b9f268df3515 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff @@ -8,31 +8,37 @@ let mut _3: &fn() {foo}; let _4: fn() {foo}; let mut _5: (); ++ scope 1 (inlined hide_foo) { ++ } bb0: { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind unreachable]; - } - - bb1: { +- _4 = hide_foo() -> [return: bb1, unwind unreachable]; +- } +- +- bb1: { _3 = &_4; StorageLive(_5); _5 = (); - _2 = >::call(move _3, move _5) -> [return: bb2, unwind unreachable]; +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind unreachable]; ++ _2 = >::call(move _3, move _5) -> [return: bb1, unwind unreachable]; } - bb2: { +- bb2: { ++ bb1: { StorageDead(_5); StorageDead(_3); StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind unreachable]; +- drop(_1) -> [return: bb3, unwind unreachable]; ++ drop(_1) -> [return: bb2, unwind unreachable]; } - bb3: { +- bb3: { ++ bb2: { return; } } diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff index 5a946712ea43..8495164df9c6 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff @@ -8,39 +8,48 @@ let mut _3: &fn() {foo}; let _4: fn() {foo}; let mut _5: (); ++ scope 1 (inlined hide_foo) { ++ } bb0: { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind: bb4]; - } - - bb1: { +- _4 = hide_foo() -> [return: bb1, unwind: bb4]; +- } +- +- bb1: { _3 = &_4; StorageLive(_5); _5 = (); - _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; ++ _2 = >::call(move _3, move _5) -> [return: bb1, unwind: bb3]; } - bb2: { +- bb2: { ++ bb1: { StorageDead(_5); StorageDead(_3); StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind: bb5]; +- drop(_1) -> [return: bb3, unwind: bb5]; ++ drop(_1) -> [return: bb2, unwind: bb4]; } - bb3: { +- bb3: { ++ bb2: { return; } - bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate(cleanup)]; +- bb4 (cleanup): { +- drop(_1) -> [return: bb5, unwind terminate(cleanup)]; ++ bb3 (cleanup): { ++ drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } - bb5 (cleanup): { +- bb5 (cleanup): { ++ bb4 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir index 1d3317efd41d..7af69e08ca1b 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir @@ -4,17 +4,14 @@ fn outer(_1: u8) -> u8 { debug v => _1; // in scope 0 at $DIR/spans.rs:9:14: 9:15 let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:9:24: 9:26 let mut _2: &u8; // in scope 0 at $DIR/spans.rs:10:11: 10:13 + scope 1 (inlined inner) { // at $DIR/spans.rs:10:5: 10:14 + debug x => _2; // in scope 1 at $DIR/spans.rs:13:14: 13:15 + } bb0: { StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13 _2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13 - _0 = inner(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/spans.rs:10:5: 10:14 - // mir::ConstOperand - // + span: $DIR/spans.rs:10:5: 10:10 - // + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) } - } - - bb1: { + _0 = _1; // scope 1 at $DIR/spans.rs:14:5: 14:7 StorageDead(_2); // scope 0 at $DIR/spans.rs:10:13: 10:14 return; // scope 0 at $DIR/spans.rs:11:2: 11:2 } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir index aba66861f7d2..7af69e08ca1b 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir @@ -4,17 +4,14 @@ fn outer(_1: u8) -> u8 { debug v => _1; // in scope 0 at $DIR/spans.rs:9:14: 9:15 let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:9:24: 9:26 let mut _2: &u8; // in scope 0 at $DIR/spans.rs:10:11: 10:13 + scope 1 (inlined inner) { // at $DIR/spans.rs:10:5: 10:14 + debug x => _2; // in scope 1 at $DIR/spans.rs:13:14: 13:15 + } bb0: { StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13 _2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13 - _0 = inner(move _2) -> [return: bb1, unwind continue]; // scope 0 at $DIR/spans.rs:10:5: 10:14 - // mir::ConstOperand - // + span: $DIR/spans.rs:10:5: 10:10 - // + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) } - } - - bb1: { + _0 = _1; // scope 1 at $DIR/spans.rs:14:5: 14:7 StorageDead(_2); // scope 0 at $DIR/spans.rs:10:13: 10:14 return; // scope 0 at $DIR/spans.rs:11:2: 11:2 } diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir index c04fdeb637d8..e6ce33ed682f 100644 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir @@ -3,44 +3,26 @@ fn while_loop(_1: bool) -> () { debug c => _1; let mut _0: (); - let mut _2: bool; - let mut _3: bool; + scope 1 (inlined get_bool) { + debug c => _1; + } + scope 2 (inlined get_bool) { + debug c => _1; + } bb0: { goto -> bb1; } bb1: { - StorageLive(_2); - _2 = get_bool(_1) -> [return: bb2, unwind unreachable]; + switchInt(_1) -> [0: bb3, otherwise: bb2]; } bb2: { - switchInt(move _2) -> [0: bb7, otherwise: bb3]; + switchInt(_1) -> [0: bb1, otherwise: bb3]; } bb3: { - StorageLive(_3); - _3 = get_bool(_1) -> [return: bb4, unwind unreachable]; - } - - bb4: { - switchInt(move _3) -> [0: bb5, otherwise: bb6]; - } - - bb5: { - StorageDead(_3); - StorageDead(_2); - goto -> bb1; - } - - bb6: { - StorageDead(_3); - goto -> bb7; - } - - bb7: { - StorageDead(_2); return; } } diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir index 7dc4f7ab1a87..e6ce33ed682f 100644 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir @@ -3,44 +3,26 @@ fn while_loop(_1: bool) -> () { debug c => _1; let mut _0: (); - let mut _2: bool; - let mut _3: bool; + scope 1 (inlined get_bool) { + debug c => _1; + } + scope 2 (inlined get_bool) { + debug c => _1; + } bb0: { goto -> bb1; } bb1: { - StorageLive(_2); - _2 = get_bool(_1) -> [return: bb2, unwind continue]; + switchInt(_1) -> [0: bb3, otherwise: bb2]; } bb2: { - switchInt(move _2) -> [0: bb7, otherwise: bb3]; + switchInt(_1) -> [0: bb1, otherwise: bb3]; } bb3: { - StorageLive(_3); - _3 = get_bool(_1) -> [return: bb4, unwind continue]; - } - - bb4: { - switchInt(move _3) -> [0: bb5, otherwise: bb6]; - } - - bb5: { - StorageDead(_3); - StorageDead(_2); - goto -> bb1; - } - - bb6: { - StorageDead(_3); - goto -> bb7; - } - - bb7: { - StorageDead(_2); return; } } diff --git a/tests/run-make/emit-stack-sizes/foo.rs b/tests/run-make/emit-stack-sizes/foo.rs index ee51ae32886e..fd0b51205789 100644 --- a/tests/run-make/emit-stack-sizes/foo.rs +++ b/tests/run-make/emit-stack-sizes/foo.rs @@ -1,3 +1,4 @@ #![crate_type = "lib"] +#[inline(never)] pub fn foo() {} diff --git a/tests/run-make/intrinsic-unreachable/exit-ret.rs b/tests/run-make/intrinsic-unreachable/exit-ret.rs index e7b9694d9f2a..c8ba5b4599f2 100644 --- a/tests/run-make/intrinsic-unreachable/exit-ret.rs +++ b/tests/run-make/intrinsic-unreachable/exit-ret.rs @@ -2,6 +2,7 @@ use std::arch::asm; #[deny(unreachable_code)] +#[inline(never)] pub fn exit(n: usize) -> i32 { unsafe { // Pretend this asm is an exit() syscall. diff --git a/tests/run-make/intrinsic-unreachable/exit-unreachable.rs b/tests/run-make/intrinsic-unreachable/exit-unreachable.rs index ec85db733df0..75f893eb2df1 100644 --- a/tests/run-make/intrinsic-unreachable/exit-unreachable.rs +++ b/tests/run-make/intrinsic-unreachable/exit-unreachable.rs @@ -5,6 +5,7 @@ use std::arch::asm; use std::intrinsics; #[allow(unreachable_code)] +#[inline(never)] pub fn exit(n: usize) -> i32 { unsafe { // Pretend this asm is an exit() syscall. diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5ed0d9fcf1ef..1fd61084130a 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:534:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:535:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From a76cae02345a861285334446cd24c6eb9616866a Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 12 Oct 2023 16:50:55 -0400 Subject: [PATCH 68/94] Bless coverage-map tests --- .../status-quo/try_error_result.cov-map | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/tests/coverage-map/status-quo/try_error_result.cov-map b/tests/coverage-map/status-quo/try_error_result.cov-map index 8367103a21a4..d254ba7b3b68 100644 --- a/tests/coverage-map/status-quo/try_error_result.cov-map +++ b/tests/coverage-map/status-quo/try_error_result.cov-map @@ -1,45 +1,62 @@ Function name: ::get_thing_2 -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 1a, 07, 02, 05, 00, 06] +Raw bytes (63): 0x[01, 01, 02, 01, 05, 05, 02, 0b, 01, 28, 05, 01, 18, 05, 02, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 02, 02, 0d, 00, 1a, 00, 00, 0d, 00, 1a, 00, 00, 0d, 00, 1a, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 4 +Number of file 0 mappings: 11 - Code(Counter(0)) at (prev + 40, 5) to (start + 1, 24) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) +- Code(Zero) at (prev + 0, 13) to (start + 0, 20) +- Code(Zero) at (prev + 0, 13) to (start + 0, 20) +- Code(Zero) at (prev + 0, 13) to (start + 0, 20) +- Code(Zero) at (prev + 0, 13) to (start + 0, 20) +- Code(Zero) at (prev + 0, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 26) = (c0 - c1) +- Code(Zero) at (prev + 0, 13) to (start + 0, 26) +- Code(Zero) at (prev + 0, 13) to (start + 0, 26) - Code(Expression(1, Add)) at (prev + 2, 5) to (start + 0, 6) = (c1 + (c0 - c1)) Function name: ::call -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 33, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 07, 02, 05, 00, 06] +Raw bytes (63): 0x[01, 01, 02, 01, 05, 05, 02, 0b, 01, 33, 05, 01, 18, 05, 02, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 02, 02, 0d, 00, 13, 00, 00, 0d, 00, 13, 00, 00, 0d, 00, 13, 00, 00, 0d, 00, 13, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 4 +Number of file 0 mappings: 11 - Code(Counter(0)) at (prev + 51, 5) to (start + 1, 24) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) +- Code(Zero) at (prev + 0, 13) to (start + 0, 20) +- Code(Zero) at (prev + 0, 13) to (start + 0, 20) +- Code(Zero) at (prev + 0, 13) to (start + 0, 20) +- Code(Zero) at (prev + 0, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) +- Code(Zero) at (prev + 0, 13) to (start + 0, 19) +- Code(Zero) at (prev + 0, 13) to (start + 0, 19) +- Code(Zero) at (prev + 0, 13) to (start + 0, 19) - Code(Expression(1, Add)) at (prev + 2, 5) to (start + 0, 6) = (c1 + (c0 - c1)) Function name: try_error_result::call -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 07, 02, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 04, 01, 01, 14, 05, 02, 09, 00, 10, 00, 00, 09, 00, 10, 00, 00, 09, 00, 10, 02, 02, 09, 00, 0f, 00, 00, 09, 00, 0f, 07, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 4 +Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) +- Code(Zero) at (prev + 0, 9) to (start + 0, 16) +- Code(Zero) at (prev + 0, 9) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) +- Code(Zero) at (prev + 0, 9) to (start + 0, 15) - Code(Expression(1, Add)) at (prev + 2, 1) to (start + 0, 2) = (c1 + (c0 - c1)) From 9917ef9a6674619a72c16efaf1ca3777730d0012 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 18 Oct 2023 02:27:03 +0000 Subject: [PATCH 69/94] Don't compare host param by name --- compiler/rustc_hir_analysis/src/bounds.rs | 9 +++++---- compiler/rustc_hir_typeck/src/callee.rs | 7 +++++-- compiler/rustc_middle/src/ty/generic_args.rs | 5 ----- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index af1a4e5d99e9..b6688e0ce29e 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -46,10 +46,11 @@ impl<'tcx> Bounds<'tcx> { ) { self.push_trait_bound_inner(tcx, trait_ref, span, polarity); - // if we have a host param, we push an unconst trait bound in addition - // to the const one. - // FIXME(effects) we should find a better way than name matching - if tcx.features().effects && trait_ref.skip_binder().args.host_effect_param().is_some() { + // push a non-const (`host = true`) version of the bound if it is `~const`. + if tcx.features().effects + && let Some(host_effect_idx) = tcx.generics_of(trait_ref.def_id()).host_effect_index + && trait_ref.skip_binder().args.const_at(host_effect_idx) != tcx.consts.true_ + { let generics = tcx.generics_of(trait_ref.def_id()); let Some(host_index) = generics.host_effect_index else { return }; let trait_ref = trait_ref.map_bound(|mut trait_ref| { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 1c23ccd15794..78d30f3aa12e 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -786,8 +786,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.consts.false_ } Some(hir::ConstContext::ConstFn) => { - let args = ty::GenericArgs::identity_for_item(tcx, context); - args.host_effect_param().expect("ConstContext::Maybe must have host effect param") + let host_idx = tcx + .generics_of(context) + .host_effect_index + .expect("ConstContext::Maybe must have host effect param"); + ty::GenericArgs::identity_for_item(tcx, context).const_at(host_idx) } None => tcx.consts.true_, }; diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 72390e4bbb03..a861af478594 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -11,7 +11,6 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; -use rustc_span::sym; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; @@ -452,10 +451,6 @@ impl<'tcx> GenericArgs<'tcx> { tcx.mk_args_from_iter(self.iter().take(generics.count())) } - pub fn host_effect_param(&'tcx self) -> Option> { - self.consts().rfind(|x| matches!(x.kind(), ty::ConstKind::Param(p) if p.name == sym::host)) - } - pub fn print_as_list(&self) -> String { let v = self.iter().map(|arg| arg.to_string()).collect::>(); format!("[{}]", v.join(", ")) From a1e274f1721f6be4a36afe10e57a6825eeeaf848 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Wed, 18 Oct 2023 06:19:04 +0000 Subject: [PATCH 70/94] revert rust-lang/rust#114586 --- .../src/region_infer/opaque_types.rs | 33 ++++++++----------- .../rustc_infer/src/infer/opaque_types.rs | 20 +---------- .../src/traits/fulfill.rs | 23 ++----------- .../src/traits/select/mod.rs | 23 ++----------- .../equality-in-canonical-query.clone.stderr | 29 ++++++++++++++++ .../impl-trait/equality-in-canonical-query.rs | 23 +++++++++++++ ...equality_in_canonical_query.current.stderr | 13 ++++++-- .../rpit_tait_equality_in_canonical_query.rs | 2 +- ...rpit_tait_equality_in_canonical_query_2.rs | 18 ++++++++++ 9 files changed, 100 insertions(+), 84 deletions(-) create mode 100644 tests/ui/impl-trait/equality-in-canonical-query.clone.stderr create mode 100644 tests/ui/impl-trait/equality-in-canonical-query.rs create mode 100644 tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index ee5543703052..fb0e5811c267 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -328,26 +328,19 @@ fn check_opaque_type_well_formed<'tcx>( // Require that the hidden type actually fulfills all the bounds of the opaque type, even without // the bounds that the function supplies. - let mut obligations = vec![]; - infcx - .insert_hidden_type( - OpaqueTypeKey { def_id, args: identity_args }, - &ObligationCause::misc(definition_span, def_id), - param_env, - definition_ty, - true, - &mut obligations, - ) - .unwrap(); - infcx.add_item_bounds_for_hidden_type( - def_id.to_def_id(), - identity_args, - ObligationCause::misc(definition_span, def_id), - param_env, - definition_ty, - &mut obligations, - ); - ocx.register_obligations(obligations); + let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args); + ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty) + .map_err(|err| { + infcx + .err_ctxt() + .report_mismatched_types( + &ObligationCause::misc(definition_span, def_id), + opaque_ty, + definition_ty, + err, + ) + .emit() + })?; // Require the hidden type to be well-formed with only the generics of the opaque type. // Defining use functions may have more bounds than the opaque type, which is ok, as long as the diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 09df93fcc2fd..1c3a5c360765 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -145,25 +145,7 @@ impl<'tcx> InferCtxt<'tcx> { return None; } } - DefiningAnchor::Bubble => { - if let ty::Alias(ty::Opaque, _) = b.kind() { - // In bubble mode we don't know which of the two opaque types is supposed to have the other - // as a hidden type (both, none or either one of them could be in its defining scope). - let predicate = ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ); - let obligation = traits::Obligation::new( - self.tcx, - cause.clone(), - param_env, - predicate, - ); - let obligations = vec![obligation]; - return Some(Ok(InferOk { value: (), obligations })); - } - } + DefiningAnchor::Bubble => {} DefiningAnchor::Error => return None, }; if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index da357dac415f..55b5604b16b5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -6,7 +6,6 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine}; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::GenericArgsRef; @@ -626,27 +625,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, - ty::PredicateKind::AliasRelate(..) - if matches!(self.selcx.infcx.defining_use_anchor, DefiningAnchor::Bubble) => - { - ProcessResult::Unchanged + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } - ty::PredicateKind::AliasRelate(a, b, relate) => match relate { - ty::AliasRelationDirection::Equate => match self - .selcx - .infcx - .at(&obligation.cause, obligation.param_env) - .eq(DefineOpaqueTypes::Yes, a, b) - { - Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), - Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError( - SelectionError::Unimplemented, - )), - }, - ty::AliasRelationDirection::Subtype => { - bug!("AliasRelate with subtyping is only used for new solver") - } - }, ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( DefineOpaqueTypes::No, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 97366a93e311..940ceca50d2d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -38,7 +38,6 @@ use rustc_infer::traits::TraitObligation; use rustc_middle::dep_graph::dep_kinds; use rustc_middle::dep_graph::DepNodeIndex; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::_match::MatchAgainstFreshVars; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fold::BottomUpFolder; @@ -1005,27 +1004,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } } - ty::PredicateKind::AliasRelate(..) - if matches!(self.infcx.defining_use_anchor, DefiningAnchor::Bubble) => - { - Ok(EvaluatedToAmbig) + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } - ty::PredicateKind::AliasRelate(a, b, relate) => match relate { - ty::AliasRelationDirection::Equate => match self - .infcx - .at(&obligation.cause, obligation.param_env) - .eq(DefineOpaqueTypes::Yes, a, b) - { - Ok(inf_ok) => self.evaluate_predicates_recursively( - previous_stack, - inf_ok.into_obligations(), - ), - Err(_) => Ok(EvaluatedToErr), - }, - ty::AliasRelationDirection::Subtype => { - bug!("AliasRelate subtyping is only used for new solver") - } - }, ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { match self.infcx.at(&obligation.cause, obligation.param_env).eq( diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr new file mode 100644 index 000000000000..83791f0d3afd --- /dev/null +++ b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr @@ -0,0 +1,29 @@ +error: internal compiler error: no errors encountered even though `delay_span_bug` issued + +error: internal compiler error: {OpaqueTypeKey { def_id: DefId(rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }) } }} + | + = + + +error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }))), bound_vars: [] } } } + --> $DIR/equality-in-canonical-query.rs:19:5 + | +LL | same_output(foo, rpit); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + + --> $DIR/equality-in-canonical-query.rs:19:5 + | +LL | same_output(foo, rpit); + | ^^^^^^^^^^^^^^^^^^^^^^ + + + + + + + +query stack during panic: +end of query stack +error: aborting due to 3 previous errors + diff --git a/tests/ui/impl-trait/equality-in-canonical-query.rs b/tests/ui/impl-trait/equality-in-canonical-query.rs new file mode 100644 index 000000000000..672b1eeeab69 --- /dev/null +++ b/tests/ui/impl-trait/equality-in-canonical-query.rs @@ -0,0 +1,23 @@ +// issue: #116877 +// revisions: sized clone +//[sized] check-pass + +//[clone] known-bug: #108498 +//[clone] failure-status: 101 +//[clone] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" +//[clone] normalize-stderr-test: "(?m)note: .*$" -> "" +//[clone] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" +//[clone] normalize-stderr-test: "(?m)^ *at .*\n" -> "" + +#[cfg(sized)] fn rpit() -> impl Sized {} +#[cfg(clone)] fn rpit() -> impl Clone {} + +fn same_output(_: impl Fn() -> Out, _: impl Fn() -> Out) {} + +pub fn foo() -> impl Sized { + same_output(rpit, foo); + same_output(foo, rpit); + rpit() +} + +fn main () {} diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr index 4b09a9e743b4..844103d77a8c 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr @@ -1,11 +1,17 @@ error: internal compiler error: no errors encountered even though `delay_span_bug` issued -error: internal compiler error: ambiguity performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } } +error: internal compiler error: {OpaqueTypeKey { def_id: DefId(get_rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }) } }} + | + = + + +error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } } --> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5 | LL | query(get_rpit); | ^^^^^^^^^^^^^^^ | + --> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5 | LL | query(get_rpit); @@ -14,7 +20,10 @@ LL | query(get_rpit); + + + query stack during panic: end of query stack -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs index 8dccd2ed46f8..0f0002f7797e 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs @@ -12,7 +12,7 @@ //[current] known-bug: #108498 //[current] failure-status: 101 //[current] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" -//[current] normalize-stderr-test: "(?m)^note: .*\n" -> "" +//[current] normalize-stderr-test: "(?m)note: .*$" -> "" //[current] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" //[current] normalize-stderr-test: "(?m)^ *at .*\n" -> "" diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs new file mode 100644 index 000000000000..9d7e647dd943 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs @@ -0,0 +1,18 @@ +// The canonical query `Projection(::Output = Opaque)` +// is the *only* site that defines `Opaque` in MIR typeck. +// +// check-pass + +#![feature(type_alias_impl_trait)] + +type Opaque = impl Sized; + +fn get_rpit() -> impl Sized {} + +fn query(_: impl FnOnce() -> Opaque) {} + +fn test(_: Opaque) { + query(get_rpit); +} + +fn main() {} From c479bc7f3b8bb0441bef0634b0a60cfdd1ac0914 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 10 Sep 2023 16:35:37 +1000 Subject: [PATCH 71/94] coverage: Attach an optional `FunctionCoverageInfo` to `mir::Body` This allows coverage information to be attached to the function as a whole when appropriate, instead of being smuggled through coverage statements in the function's basic blocks. As an example, this patch moves the `function_source_hash` value out of individual `CoverageKind::Counter` statements and into the per-function info. When synthesizing unused functions for coverage purposes, the absence of this info is taken to indicate that a function was not eligible for coverage and should not be synthesized. --- .../src/coverageinfo/map_data.rs | 52 +++++++++---------- .../src/coverageinfo/mapgen.rs | 17 +++--- .../src/coverageinfo/mod.rs | 28 +++++----- compiler/rustc_middle/src/mir/coverage.rs | 12 ++++- compiler/rustc_middle/src/mir/mod.rs | 10 ++++ .../rustc_mir_build/src/build/custom/mod.rs | 1 + .../rustc_mir_transform/src/coverage/mod.rs | 8 +-- 7 files changed, 74 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 55f43aa53417..f9d761083027 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -2,7 +2,9 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_data_structures::fx::FxIndexSet; use rustc_index::IndexVec; -use rustc_middle::mir::coverage::{CodeRegion, CounterId, ExpressionId, Op, Operand}; +use rustc_middle::mir::coverage::{ + CodeRegion, CounterId, ExpressionId, FunctionCoverageInfo, Op, Operand, +}; use rustc_middle::ty::Instance; use rustc_middle::ty::TyCtxt; @@ -27,8 +29,8 @@ pub struct Expression { /// line." #[derive(Debug)] pub struct FunctionCoverage<'tcx> { - instance: Instance<'tcx>, - source_hash: u64, + /// Coverage info that was attached to this function by the instrumentor. + function_coverage_info: &'tcx FunctionCoverageInfo, is_used: bool, counters: IndexVec>>, expressions: IndexVec>, @@ -37,24 +39,36 @@ pub struct FunctionCoverage<'tcx> { impl<'tcx> FunctionCoverage<'tcx> { /// Creates a new set of coverage data for a used (called) function. - pub fn new(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { - Self::create(tcx, instance, true) + pub fn new( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + function_coverage_info: &'tcx FunctionCoverageInfo, + ) -> Self { + Self::create(tcx, instance, function_coverage_info, true) } /// Creates a new set of coverage data for an unused (never called) function. - pub fn unused(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { - Self::create(tcx, instance, false) + pub fn unused( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + function_coverage_info: &'tcx FunctionCoverageInfo, + ) -> Self { + Self::create(tcx, instance, function_coverage_info, false) } - fn create(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, is_used: bool) -> Self { + fn create( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + function_coverage_info: &'tcx FunctionCoverageInfo, + is_used: bool, + ) -> Self { let coverageinfo = tcx.coverageinfo(instance.def); debug!( "FunctionCoverage::create(instance={:?}) has coverageinfo={:?}. is_used={}", instance, coverageinfo, is_used ); Self { - instance, - source_hash: 0, // will be set with the first `add_counter()` + function_coverage_info, is_used, counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize), expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize), @@ -67,16 +81,6 @@ impl<'tcx> FunctionCoverage<'tcx> { self.is_used } - /// Sets the function source hash value. If called multiple times for the same function, all - /// calls should have the same hash value. - pub fn set_function_source_hash(&mut self, source_hash: u64) { - if self.source_hash == 0 { - self.source_hash = source_hash; - } else { - debug_assert_eq!(source_hash, self.source_hash); - } - } - /// Adds code regions to be counted by an injected counter intrinsic. #[instrument(level = "debug", skip(self))] pub(crate) fn add_counter(&mut self, id: CounterId, code_regions: &[CodeRegion]) { @@ -195,7 +199,7 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Return the source hash, generated from the HIR node structure, and used to indicate whether /// or not the source code structure changed between different compilations. pub fn source_hash(&self) -> u64 { - self.source_hash + if self.is_used { self.function_coverage_info.function_source_hash } else { 0 } } /// Generate an array of CounterExpressions, and an iterator over all `Counter`s and their @@ -204,12 +208,6 @@ impl<'tcx> FunctionCoverage<'tcx> { pub fn get_expressions_and_counter_regions( &self, ) -> (Vec, impl Iterator) { - assert!( - self.source_hash != 0 || !self.is_used, - "No counters provided the source_hash for used function: {:?}", - self.instance - ); - let counter_expressions = self.counter_expressions(); // Expression IDs are indices into `self.expressions`, and on the LLVM // side they will be treated as indices into `counter_expressions`, so diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index d4e775256985..a2bf53e605d7 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -10,9 +10,8 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_index::IndexVec; use rustc_middle::bug; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::CodeRegion; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Symbol; /// Generates and exports the Coverage Map. @@ -331,16 +330,14 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) { for non_codegenned_def_id in eligible_def_ids.into_iter().filter(|id| !codegenned_def_ids.contains(id)) { - let codegen_fn_attrs = tcx.codegen_fn_attrs(non_codegenned_def_id); - - // If a function is marked `#[coverage(off)]`, then skip generating a - // dead code stub for it. - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { - debug!("skipping unused fn marked #[coverage(off)]: {:?}", non_codegenned_def_id); + // Skip any function that didn't have coverage data added to it by the + // coverage instrumentor. + let body = tcx.instance_mir(ty::InstanceDef::Item(non_codegenned_def_id)); + let Some(function_coverage_info) = body.function_coverage_info.as_deref() else { continue; - } + }; debug!("generating unused fn: {:?}", non_codegenned_def_id); - cx.define_unused_fn(non_codegenned_def_id); + cx.define_unused_fn(non_codegenned_def_id, function_coverage_info); } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index dd2ce9b525b7..0d9d3c7ad417 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -16,7 +16,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_llvm::RustString; use rustc_middle::bug; -use rustc_middle::mir::coverage::{CounterId, CoverageKind}; +use rustc_middle::mir::coverage::{CounterId, CoverageKind, FunctionCoverageInfo}; use rustc_middle::mir::Coverage; use rustc_middle::ty; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; @@ -91,31 +91,34 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// codegenned, collect the coverage `CodeRegion`s from the MIR and add /// them. Since the function is never called, all of its `CodeRegion`s can be /// added as `unreachable_region`s. - fn define_unused_fn(&self, def_id: DefId) { + fn define_unused_fn(&self, def_id: DefId, function_coverage_info: &'tcx FunctionCoverageInfo) { let instance = declare_unused_fn(self, def_id); codegen_unused_fn_and_counter(self, instance); - add_unused_function_coverage(self, instance, def_id); + add_unused_function_coverage(self, instance, def_id, function_coverage_info); } } impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { + #[instrument(level = "debug", skip(self))] fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) { let bx = self; + let Some(function_coverage_info) = + bx.tcx.instance_mir(instance.def).function_coverage_info.as_deref() + else { + debug!("function has a coverage statement but no coverage info"); + return; + }; + let Some(coverage_context) = bx.coverage_context() else { return }; let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); let func_coverage = coverage_map .entry(instance) - .or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance)); + .or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance, function_coverage_info)); let Coverage { kind, code_regions } = coverage; match *kind { - CoverageKind::Counter { function_source_hash, id } => { - debug!( - "ensuring function source hash is set for instance={:?}; function_source_hash={}", - instance, function_source_hash, - ); - func_coverage.set_function_source_hash(function_source_hash); + CoverageKind::Counter { id } => { func_coverage.add_counter(id, code_regions); // We need to explicitly drop the `RefMut` before calling into `instrprof_increment`, // as that needs an exclusive borrow. @@ -124,7 +127,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let coverageinfo = bx.tcx().coverageinfo(instance.def); let fn_name = bx.get_pgo_func_name_var(instance); - let hash = bx.const_u64(function_source_hash); + let hash = bx.const_u64(function_coverage_info.function_source_hash); let num_counters = bx.const_u32(coverageinfo.num_counters); let index = bx.const_u32(id.as_u32()); debug!( @@ -201,10 +204,11 @@ fn add_unused_function_coverage<'tcx>( cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>, def_id: DefId, + function_coverage_info: &'tcx FunctionCoverageInfo, ) { let tcx = cx.tcx; - let mut function_coverage = FunctionCoverage::unused(tcx, instance); + let mut function_coverage = FunctionCoverage::unused(tcx, instance, function_coverage_info); for &code_region in tcx.covered_code_regions(def_id) { let code_region = std::slice::from_ref(code_region); function_coverage.add_unreachable_regions(code_region); diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index a6d6f6f5df4b..e1434e71a47e 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -60,7 +60,6 @@ impl Debug for Operand { #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum CoverageKind { Counter { - function_source_hash: u64, /// ID of this counter within its enclosing function. /// Expressions in the same function can refer to it as an operand. id: CounterId, @@ -80,7 +79,7 @@ impl Debug for CoverageKind { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { use CoverageKind::*; match self { - Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()), + Counter { id } => write!(fmt, "Counter({:?})", id.index()), Expression { id, lhs, op, rhs } => write!( fmt, "Expression({:?}) = {:?} {} {:?}", @@ -133,3 +132,12 @@ impl Op { matches!(self, Self::Subtract) } } + +/// Stores per-function coverage information attached to a `mir::Body`, +/// to be used in conjunction with the individual coverage statements injected +/// into the function's basic blocks. +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct FunctionCoverageInfo { + pub function_source_hash: u64, +} diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index f979f736b157..3a5ff4dc91fd 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -345,6 +345,14 @@ pub struct Body<'tcx> { pub injection_phase: Option, pub tainted_by_errors: Option, + + /// Per-function coverage information added by the `InstrumentCoverage` + /// pass, to be used in conjunction with the coverage statements injected + /// into this body's blocks. + /// + /// If `-Cinstrument-coverage` is not active, or if an individual function + /// is not eligible for coverage, then this should always be `None`. + pub function_coverage_info: Option>, } impl<'tcx> Body<'tcx> { @@ -392,6 +400,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, injection_phase: None, tainted_by_errors, + function_coverage_info: None, }; body.is_polymorphic = body.has_non_region_param(); body @@ -420,6 +429,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, injection_phase: None, tainted_by_errors: None, + function_coverage_info: None, }; body.is_polymorphic = body.has_non_region_param(); body diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index e5c2cc6c7bbc..a81f70e3346a 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -60,6 +60,7 @@ pub(super) fn build_custom_mir<'tcx>( tainted_by_errors: None, injection_phase: None, pass_count: 0, + function_coverage_info: None, }; body.local_decls.push(LocalDecl::new(return_ty, return_ty_span)); diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index abf13519e9ee..1ce6ecc3bb57 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -211,6 +211,10 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { self.make_mir_coverage_kind(intermediate_expression), ); } + + self.mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { + function_source_hash: self.function_source_hash, + })); } /// Injects a single [`StatementKind::Coverage`] for each BCB that has one @@ -323,9 +327,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind { match *counter_kind { - BcbCounter::Counter { id } => { - CoverageKind::Counter { function_source_hash: self.function_source_hash, id } - } + BcbCounter::Counter { id } => CoverageKind::Counter { id }, BcbCounter::Expression { id, lhs, op, rhs } => { CoverageKind::Expression { id, lhs, op, rhs } } From a18c5f3b751dbfa6c192dc48a6c6f28250e9bc97 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 13 Sep 2023 12:15:40 +1000 Subject: [PATCH 72/94] coverage: Store the number of counters/expressions in function coverage info Coverage codegen can now allocate arrays based on the number of counters/expressions originally used by the instrumentor. The existing query that inspects coverage statements is still used for determining the number of counters passed to `llvm.instrprof.increment`. If some high-numbered counters were removed by MIR optimizations, the instrumented binary can potentially use less memory and disk space at runtime. --- .../src/coverageinfo/map_data.rs | 19 ++-- .../src/coverageinfo/mod.rs | 18 +++- compiler/rustc_middle/src/mir/coverage.rs | 2 + compiler/rustc_middle/src/mir/query.rs | 24 +++-- compiler/rustc_middle/src/query/mod.rs | 9 +- .../src/coverage/counters.rs | 8 ++ .../rustc_mir_transform/src/coverage/mod.rs | 2 + .../rustc_mir_transform/src/coverage/query.rs | 89 ++++--------------- 8 files changed, 69 insertions(+), 102 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index f9d761083027..4dbc0e403fd5 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -6,7 +6,6 @@ use rustc_middle::mir::coverage::{ CodeRegion, CounterId, ExpressionId, FunctionCoverageInfo, Op, Operand, }; use rustc_middle::ty::Instance; -use rustc_middle::ty::TyCtxt; #[derive(Clone, Debug, PartialEq)] pub struct Expression { @@ -40,38 +39,36 @@ pub struct FunctionCoverage<'tcx> { impl<'tcx> FunctionCoverage<'tcx> { /// Creates a new set of coverage data for a used (called) function. pub fn new( - tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, ) -> Self { - Self::create(tcx, instance, function_coverage_info, true) + Self::create(instance, function_coverage_info, true) } /// Creates a new set of coverage data for an unused (never called) function. pub fn unused( - tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, ) -> Self { - Self::create(tcx, instance, function_coverage_info, false) + Self::create(instance, function_coverage_info, false) } fn create( - tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, is_used: bool, ) -> Self { - let coverageinfo = tcx.coverageinfo(instance.def); + let num_counters = function_coverage_info.num_counters; + let num_expressions = function_coverage_info.num_expressions; debug!( - "FunctionCoverage::create(instance={:?}) has coverageinfo={:?}. is_used={}", - instance, coverageinfo, is_used + "FunctionCoverage::create(instance={instance:?}) has \ + num_counters={num_counters}, num_expressions={num_expressions}, is_used={is_used}" ); Self { function_coverage_info, is_used, - counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize), - expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize), + counters: IndexVec::from_elem_n(None, num_counters), + expressions: IndexVec::from_elem_n(None, num_expressions), unreachable_regions: Vec::new(), } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 0d9d3c7ad417..c975d3432b92 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -114,7 +114,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); let func_coverage = coverage_map .entry(instance) - .or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance, function_coverage_info)); + .or_insert_with(|| FunctionCoverage::new(instance, function_coverage_info)); let Coverage { kind, code_regions } = coverage; match *kind { @@ -124,11 +124,21 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { // as that needs an exclusive borrow. drop(coverage_map); - let coverageinfo = bx.tcx().coverageinfo(instance.def); + // The number of counters passed to `llvm.instrprof.increment` might + // be smaller than the number originally inserted by the instrumentor, + // if some high-numbered counters were removed by MIR optimizations. + // If so, LLVM's profiler runtime will use fewer physical counters. + let num_counters = + bx.tcx().coverage_ids_info(instance.def).max_counter_id.as_u32() + 1; + assert!( + num_counters as usize <= function_coverage_info.num_counters, + "num_counters disagreement: query says {num_counters} but function info only has {}", + function_coverage_info.num_counters + ); let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_coverage_info.function_source_hash); - let num_counters = bx.const_u32(coverageinfo.num_counters); + let num_counters = bx.const_u32(num_counters); let index = bx.const_u32(id.as_u32()); debug!( "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", @@ -208,7 +218,7 @@ fn add_unused_function_coverage<'tcx>( ) { let tcx = cx.tcx; - let mut function_coverage = FunctionCoverage::unused(tcx, instance, function_coverage_info); + let mut function_coverage = FunctionCoverage::unused(instance, function_coverage_info); for &code_region in tcx.covered_code_regions(def_id) { let code_region = std::slice::from_ref(code_region); function_coverage.add_unreachable_regions(code_region); diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index e1434e71a47e..837331a2de81 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -140,4 +140,6 @@ impl Op { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct FunctionCoverageInfo { pub function_source_hash: u64, + pub num_counters: usize, + pub num_expressions: usize, } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index c74a9536b633..f407dc4d7ae3 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,5 +1,6 @@ //! Values computed by queries that use MIR. +use crate::mir; use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordSet; @@ -445,14 +446,19 @@ pub struct DestructuredConstant<'tcx> { pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)], } -/// Coverage information summarized from a MIR if instrumented for source code coverage (see -/// compiler option `-Cinstrument-coverage`). This information is generated by the -/// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query. +/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass +/// (for compiler option `-Cinstrument-coverage`), after MIR optimizations +/// have had a chance to potentially remove some of them. +/// +/// Used by the `coverage_ids_info` query. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)] -pub struct CoverageInfo { - /// The total number of coverage region counters added to the MIR `Body`. - pub num_counters: u32, - - /// The total number of coverage region counter expressions added to the MIR `Body`. - pub num_expressions: u32, +pub struct CoverageIdsInfo { + /// Coverage codegen needs to know the highest counter ID that is ever + /// incremented within a function, so that it can set the `num-counters` + /// argument of the `llvm.instrprof.increment` intrinsic. + /// + /// This may be less than the highest counter ID emitted by the + /// InstrumentCoverage MIR pass, if the highest-numbered counter increments + /// were removed by MIR optimizations. + pub max_counter_id: mir::coverage::CounterId, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 940ab190ffc0..ed0f73fcf2fa 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -573,10 +573,11 @@ rustc_queries! { separate_provide_extern } - /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` - /// MIR pass (assuming the -Cinstrument-coverage option is enabled). - query coverageinfo(key: ty::InstanceDef<'tcx>) -> &'tcx mir::CoverageInfo { - desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.def_id()) } + /// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass + /// (for compiler option `-Cinstrument-coverage`), after MIR optimizations + /// have had a chance to potentially remove some of them. + query coverage_ids_info(key: ty::InstanceDef<'tcx>) -> &'tcx mir::CoverageIdsInfo { + desc { |tcx| "retrieving coverage IDs info from MIR for `{}`", tcx.def_path_str(key.def_id()) } arena_cache } diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 77e3dee1fefa..938c4b2bd3f0 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -126,6 +126,14 @@ impl CoverageCounters { next } + pub(super) fn num_counters(&self) -> usize { + self.next_counter_id.as_usize() + } + + pub(super) fn num_expressions(&self) -> usize { + self.next_expression_id.as_usize() + } + fn set_bcb_counter( &mut self, bcb: BasicCoverageBlock, diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 1ce6ecc3bb57..e1b656bd9819 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -214,6 +214,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { self.mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { function_source_hash: self.function_source_hash, + num_counters: self.coverage_counters.num_counters(), + num_expressions: self.coverage_counters.num_expressions(), })); } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 2c0164e765c7..b1f46c8e05c6 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -2,92 +2,33 @@ use super::*; use rustc_data_structures::captures::Captures; use rustc_middle::mir::coverage::*; -use rustc_middle::mir::{self, Body, Coverage, CoverageInfo}; +use rustc_middle::mir::{self, Body, Coverage, CoverageIdsInfo}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; /// A `query` provider for retrieving coverage information injected into MIR. pub(crate) fn provide(providers: &mut Providers) { - providers.coverageinfo = |tcx, def_id| coverageinfo(tcx, def_id); + providers.coverage_ids_info = |tcx, def_id| coverage_ids_info(tcx, def_id); providers.covered_code_regions = |tcx, def_id| covered_code_regions(tcx, def_id); } -/// Coverage codegen needs to know the total number of counter IDs and expression IDs that have -/// been used by a function's coverage mappings. These totals are used to create vectors to hold -/// the relevant counter and expression data, and the maximum counter ID (+ 1) is also needed by -/// the `llvm.instrprof.increment` intrinsic. -/// -/// MIR optimization may split and duplicate some BasicBlock sequences, or optimize out some code -/// including injected counters. (It is OK if some counters are optimized out, but those counters -/// are still included in the total `num_counters` or `num_expressions`.) Simply counting the -/// calls may not work; but computing the number of counters or expressions by adding `1` to the -/// highest ID (for a given instrumented function) is valid. -/// -/// It's possible for a coverage expression to remain in MIR while one or both of its operands -/// have been optimized away. To avoid problems in codegen, we include those operands' IDs when -/// determining the maximum counter/expression ID, even if the underlying counter/expression is -/// no longer present. -struct CoverageVisitor { - max_counter_id: CounterId, - max_expression_id: ExpressionId, -} - -impl CoverageVisitor { - /// Updates `max_counter_id` to the maximum encountered counter ID. - #[inline(always)] - fn update_max_counter_id(&mut self, counter_id: CounterId) { - self.max_counter_id = self.max_counter_id.max(counter_id); - } - - /// Updates `max_expression_id` to the maximum encountered expression ID. - #[inline(always)] - fn update_max_expression_id(&mut self, expression_id: ExpressionId) { - self.max_expression_id = self.max_expression_id.max(expression_id); - } - - fn update_from_expression_operand(&mut self, operand: Operand) { - match operand { - Operand::Counter(id) => self.update_max_counter_id(id), - Operand::Expression(id) => self.update_max_expression_id(id), - Operand::Zero => {} - } - } - - fn visit_body(&mut self, body: &Body<'_>) { - for coverage in all_coverage_in_mir_body(body) { - self.visit_coverage(coverage); - } - } - - fn visit_coverage(&mut self, coverage: &Coverage) { - match coverage.kind { - CoverageKind::Counter { id, .. } => self.update_max_counter_id(id), - CoverageKind::Expression { id, lhs, rhs, .. } => { - self.update_max_expression_id(id); - self.update_from_expression_operand(lhs); - self.update_from_expression_operand(rhs); - } - CoverageKind::Unreachable => {} - } - } -} - -fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> CoverageInfo { +/// Query implementation for `coverage_ids_info`. +fn coverage_ids_info<'tcx>( + tcx: TyCtxt<'tcx>, + instance_def: ty::InstanceDef<'tcx>, +) -> CoverageIdsInfo { let mir_body = tcx.instance_mir(instance_def); - let mut coverage_visitor = CoverageVisitor { - max_counter_id: CounterId::START, - max_expression_id: ExpressionId::START, - }; + let max_counter_id = all_coverage_in_mir_body(mir_body) + .filter_map(|coverage| match coverage.kind { + CoverageKind::Counter { id } => Some(id), + _ => None, + }) + .max() + .unwrap_or(CounterId::START); - coverage_visitor.visit_body(mir_body); - - // Add 1 to the highest IDs to get the total number of IDs. - CoverageInfo { - num_counters: (coverage_visitor.max_counter_id + 1).as_u32(), - num_expressions: (coverage_visitor.max_expression_id + 1).as_u32(), - } + CoverageIdsInfo { max_counter_id } } fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> { From 79f935b96c2447c979124628187125a9e381e9dc Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 31 Aug 2023 16:03:12 +1000 Subject: [PATCH 73/94] coverage: Rename `Operand` to `CovTerm` Later patches in this PR will use `CovTerm` to represent things that are not expression operands. --- .../src/coverageinfo/ffi.rs | 12 +++--- .../src/coverageinfo/map_data.rs | 32 +++++++-------- compiler/rustc_middle/src/mir/coverage.rs | 16 ++++---- .../src/coverage/counters.rs | 40 +++++++++---------- 4 files changed, 51 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 763186a58bf9..194ed7d661da 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir::coverage::{CounterId, ExpressionId, Operand}; +use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId}; /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] @@ -43,11 +43,11 @@ impl Counter { Self { kind: CounterKind::Expression, id: expression_id.as_u32() } } - pub(crate) fn from_operand(operand: Operand) -> Self { - match operand { - Operand::Zero => Self::ZERO, - Operand::Counter(id) => Self::counter_value_reference(id), - Operand::Expression(id) => Self::expression(id), + pub(crate) fn from_term(term: CovTerm) -> Self { + match term { + CovTerm::Zero => Self::ZERO, + CovTerm::Counter(id) => Self::counter_value_reference(id), + CovTerm::Expression(id) => Self::expression(id), } } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 4dbc0e403fd5..9798c18f21b0 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -3,15 +3,15 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_data_structures::fx::FxIndexSet; use rustc_index::IndexVec; use rustc_middle::mir::coverage::{ - CodeRegion, CounterId, ExpressionId, FunctionCoverageInfo, Op, Operand, + CodeRegion, CounterId, CovTerm, ExpressionId, FunctionCoverageInfo, Op, }; use rustc_middle::ty::Instance; #[derive(Clone, Debug, PartialEq)] pub struct Expression { - lhs: Operand, + lhs: CovTerm, op: Op, - rhs: Operand, + rhs: CovTerm, code_regions: Vec, } @@ -101,15 +101,15 @@ impl<'tcx> FunctionCoverage<'tcx> { /// code regions mapped to that expression. /// /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other - /// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity + /// expressions. These are tracked as separate variants of `CovTerm`, so there is no ambiguity /// between operands that are counter IDs and operands that are expression IDs. #[instrument(level = "debug", skip(self))] pub(crate) fn add_counter_expression( &mut self, expression_id: ExpressionId, - lhs: Operand, + lhs: CovTerm, op: Op, - rhs: Operand, + rhs: CovTerm, code_regions: &[CodeRegion], ) { debug_assert!( @@ -151,7 +151,7 @@ impl<'tcx> FunctionCoverage<'tcx> { // The set of expressions that either were optimized out entirely, or // have zero as both of their operands, and will therefore always have // a value of zero. Other expressions that refer to these as operands - // can have those operands replaced with `Operand::Zero`. + // can have those operands replaced with `CovTerm::Zero`. let mut zero_expressions = FxIndexSet::default(); // For each expression, perform simplifications based on lower-numbered @@ -168,10 +168,10 @@ impl<'tcx> FunctionCoverage<'tcx> { }; // If an operand refers to an expression that is always zero, then - // that operand can be replaced with `Operand::Zero`. - let maybe_set_operand_to_zero = |operand: &mut Operand| match &*operand { - Operand::Expression(id) if zero_expressions.contains(id) => { - *operand = Operand::Zero; + // that operand can be replaced with `CovTerm::Zero`. + let maybe_set_operand_to_zero = |operand: &mut CovTerm| match &*operand { + CovTerm::Expression(id) if zero_expressions.contains(id) => { + *operand = CovTerm::Zero; } _ => (), }; @@ -181,13 +181,13 @@ impl<'tcx> FunctionCoverage<'tcx> { // Coverage counter values cannot be negative, so if an expression // involves subtraction from zero, assume that its RHS must also be zero. // (Do this after simplifications that could set the LHS to zero.) - if let Expression { lhs: Operand::Zero, op: Op::Subtract, .. } = expression { - expression.rhs = Operand::Zero; + if let Expression { lhs: CovTerm::Zero, op: Op::Subtract, .. } = expression { + expression.rhs = CovTerm::Zero; } // After the above simplifications, if both operands are zero, then // we know that this expression is always zero too. - if let Expression { lhs: Operand::Zero, rhs: Operand::Zero, .. } = expression { + if let Expression { lhs: CovTerm::Zero, rhs: CovTerm::Zero, .. } = expression { zero_expressions.insert(id); } } @@ -254,12 +254,12 @@ impl<'tcx> FunctionCoverage<'tcx> { &Some(Expression { lhs, op, rhs, .. }) => { // Convert the operands and operator as normal. CounterExpression::new( - Counter::from_operand(lhs), + Counter::from_term(lhs), match op { Op::Add => ExprKind::Add, Op::Subtract => ExprKind::Subtract, }, - Counter::from_operand(rhs), + Counter::from_term(rhs), ) } }) diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 837331a2de81..fbb7f33a983a 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -35,19 +35,21 @@ impl ExpressionId { pub const START: Self = Self::from_u32(0); } -/// Operand of a coverage-counter expression. +/// Enum that can hold a constant zero value, the ID of an physical coverage +/// counter, or the ID of a coverage-counter expression. /// -/// Operands can be a constant zero value, an actual coverage counter, or another -/// expression. Counter/expression operands are referred to by ID. +/// This was originally only used for expression operands (and named `Operand`), +/// but the zero/counter/expression distinction is also useful for representing +/// the value of code/gap mappings, and the true/false arms of branch mappings. #[derive(Copy, Clone, PartialEq, Eq)] #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub enum Operand { +pub enum CovTerm { Zero, Counter(CounterId), Expression(ExpressionId), } -impl Debug for Operand { +impl Debug for CovTerm { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Self::Zero => write!(f, "Zero"), @@ -68,9 +70,9 @@ pub enum CoverageKind { /// ID of this coverage-counter expression within its enclosing function. /// Other expressions in the same function can refer to it as an operand. id: ExpressionId, - lhs: Operand, + lhs: CovTerm, op: Op, - rhs: Operand, + rhs: CovTerm, }, Unreachable, } diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 938c4b2bd3f0..4140d402c753 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -19,7 +19,7 @@ const NESTED_INDENT: &str = " "; #[derive(Clone)] pub(super) enum BcbCounter { Counter { id: CounterId }, - Expression { id: ExpressionId, lhs: Operand, op: Op, rhs: Operand }, + Expression { id: ExpressionId, lhs: CovTerm, op: Op, rhs: CovTerm }, } impl BcbCounter { @@ -27,10 +27,10 @@ impl BcbCounter { matches!(self, Self::Expression { .. }) } - pub(super) fn as_operand(&self) -> Operand { + pub(super) fn as_term(&self) -> CovTerm { match *self { - BcbCounter::Counter { id, .. } => Operand::Counter(id), - BcbCounter::Expression { id, .. } => Operand::Expression(id), + BcbCounter::Counter { id, .. } => CovTerm::Counter(id), + BcbCounter::Expression { id, .. } => CovTerm::Expression(id), } } } @@ -106,7 +106,7 @@ impl CoverageCounters { BcbCounter::Counter { id } } - fn make_expression(&mut self, lhs: Operand, op: Op, rhs: Operand) -> BcbCounter { + fn make_expression(&mut self, lhs: CovTerm, op: Op, rhs: CovTerm) -> BcbCounter { let id = self.next_expression(); BcbCounter::Expression { id, lhs, op, rhs } } @@ -138,7 +138,7 @@ impl CoverageCounters { &mut self, bcb: BasicCoverageBlock, counter_kind: BcbCounter, - ) -> Result { + ) -> Result { debug_assert!( // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also // have an expression (to be injected into an existing `BasicBlock` represented by this @@ -146,14 +146,14 @@ impl CoverageCounters { counter_kind.is_expression() || !self.bcb_has_incoming_edge_counters.contains(bcb), "attempt to add a `Counter` to a BCB target with existing incoming edge counters" ); - let operand = counter_kind.as_operand(); + let term = counter_kind.as_term(); if let Some(replaced) = self.bcb_counters[bcb].replace(counter_kind) { Error::from_string(format!( "attempt to set a BasicCoverageBlock coverage counter more than once; \ {bcb:?} already had counter {replaced:?}", )) } else { - Ok(operand) + Ok(term) } } @@ -162,7 +162,7 @@ impl CoverageCounters { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, counter_kind: BcbCounter, - ) -> Result { + ) -> Result { if level_enabled!(tracing::Level::DEBUG) { // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also // have an expression (to be injected into an existing `BasicBlock` represented by this @@ -175,14 +175,14 @@ impl CoverageCounters { } } self.bcb_has_incoming_edge_counters.insert(to_bcb); - let operand = counter_kind.as_operand(); + let term = counter_kind.as_term(); if let Some(replaced) = self.bcb_edge_counters.insert((from_bcb, to_bcb), counter_kind) { Error::from_string(format!( "attempt to set an edge counter more than once; from_bcb: \ {from_bcb:?} already had counter {replaced:?}", )) } else { - Ok(operand) + Ok(term) } } @@ -284,7 +284,7 @@ impl<'a> MakeBcbCounters<'a> { &mut self, traversal: &TraverseCoverageGraphWithLoops<'_>, branching_bcb: BasicCoverageBlock, - branching_counter_operand: Operand, + branching_counter_operand: CovTerm, ) -> Result<(), Error> { let branches = self.bcb_branches(branching_bcb); debug!( @@ -332,7 +332,7 @@ impl<'a> MakeBcbCounters<'a> { sumup_counter_operand, ); debug!(" [new intermediate expression: {:?}]", intermediate_expression); - let intermediate_expression_operand = intermediate_expression.as_operand(); + let intermediate_expression_operand = intermediate_expression.as_term(); self.coverage_counters.intermediate_expressions.push(intermediate_expression); some_sumup_counter_operand.replace(intermediate_expression_operand); } @@ -364,7 +364,7 @@ impl<'a> MakeBcbCounters<'a> { Ok(()) } - fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> Result { + fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> Result { self.recursive_get_or_make_counter_operand(bcb, 1) } @@ -372,7 +372,7 @@ impl<'a> MakeBcbCounters<'a> { &mut self, bcb: BasicCoverageBlock, debug_indent_level: usize, - ) -> Result { + ) -> Result { // If the BCB already has a counter, return it. if let Some(counter_kind) = &self.coverage_counters.bcb_counters[bcb] { debug!( @@ -381,7 +381,7 @@ impl<'a> MakeBcbCounters<'a> { bcb, counter_kind, ); - return Ok(counter_kind.as_operand()); + return Ok(counter_kind.as_term()); } // A BCB with only one incoming edge gets a simple `Counter` (via `make_counter()`). @@ -445,7 +445,7 @@ impl<'a> MakeBcbCounters<'a> { NESTED_INDENT.repeat(debug_indent_level), intermediate_expression ); - let intermediate_expression_operand = intermediate_expression.as_operand(); + let intermediate_expression_operand = intermediate_expression.as_term(); self.coverage_counters.intermediate_expressions.push(intermediate_expression); some_sumup_edge_counter_operand.replace(intermediate_expression_operand); } @@ -468,7 +468,7 @@ impl<'a> MakeBcbCounters<'a> { &mut self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, - ) -> Result { + ) -> Result { self.recursive_get_or_make_edge_counter_operand(from_bcb, to_bcb, 1) } @@ -477,7 +477,7 @@ impl<'a> MakeBcbCounters<'a> { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, debug_indent_level: usize, - ) -> Result { + ) -> Result { // If the source BCB has only one successor (assumed to be the given target), an edge // counter is unnecessary. Just get or make a counter for the source BCB. let successors = self.bcb_successors(from_bcb).iter(); @@ -496,7 +496,7 @@ impl<'a> MakeBcbCounters<'a> { to_bcb, counter_kind ); - return Ok(counter_kind.as_operand()); + return Ok(counter_kind.as_term()); } // Make a new counter to count this edge. From 8efdd4cca61df9adf7f90c40fcc176a2842a9c28 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 4 Sep 2023 12:50:51 +1000 Subject: [PATCH 74/94] coverage: Collect a function's coverage mappings into a single list This is an intermediate step towards being able to store all of a function's mappings in function coverage info. --- .../src/coverageinfo/map_data.rs | 115 +++++++----------- .../src/coverageinfo/mapgen.rs | 11 +- compiler/rustc_middle/src/mir/coverage.rs | 14 +++ 3 files changed, 65 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 9798c18f21b0..407ac5662d30 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,9 +1,10 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_data_structures::fx::FxIndexSet; +use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; use rustc_middle::mir::coverage::{ - CodeRegion, CounterId, CovTerm, ExpressionId, FunctionCoverageInfo, Op, + CodeRegion, CounterId, CovTerm, ExpressionId, FunctionCoverageInfo, Mapping, Op, }; use rustc_middle::ty::Instance; @@ -12,28 +13,21 @@ pub struct Expression { lhs: CovTerm, op: Op, rhs: CovTerm, - code_regions: Vec, } -/// Collects all of the coverage regions associated with (a) injected counters, (b) counter -/// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero), -/// for a given Function. This struct also stores the `function_source_hash`, -/// computed during instrumentation, and forwarded with counters. -/// -/// Note, it may be important to understand LLVM's definitions of `unreachable` regions versus "gap -/// regions" (or "gap areas"). A gap region is a code region within a counted region (either counter -/// or expression), but the line or lines in the gap region are not executable (such as lines with -/// only whitespace or comments). According to LLVM Code Coverage Mapping documentation, "A count -/// for a gap area is only used as the line execution count if there are no other regions on a -/// line." +/// Holds all of the coverage mapping data associated with a function instance, +/// collected during traversal of `Coverage` statements in the function's MIR. #[derive(Debug)] pub struct FunctionCoverage<'tcx> { /// Coverage info that was attached to this function by the instrumentor. function_coverage_info: &'tcx FunctionCoverageInfo, is_used: bool, - counters: IndexVec>>, + + /// Tracks which counters have been seen, to avoid duplicate mappings + /// that might be introduced by MIR inlining. + counters_seen: BitSet, expressions: IndexVec>, - unreachable_regions: Vec, + mappings: Vec, } impl<'tcx> FunctionCoverage<'tcx> { @@ -67,9 +61,9 @@ impl<'tcx> FunctionCoverage<'tcx> { Self { function_coverage_info, is_used, - counters: IndexVec::from_elem_n(None, num_counters), + counters_seen: BitSet::new_empty(num_counters), expressions: IndexVec::from_elem_n(None, num_expressions), - unreachable_regions: Vec::new(), + mappings: Vec::new(), } } @@ -81,19 +75,8 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Adds code regions to be counted by an injected counter intrinsic. #[instrument(level = "debug", skip(self))] pub(crate) fn add_counter(&mut self, id: CounterId, code_regions: &[CodeRegion]) { - if code_regions.is_empty() { - return; - } - - let slot = &mut self.counters[id]; - match slot { - None => *slot = Some(code_regions.to_owned()), - // If this counter ID slot has already been filled, it should - // contain identical information. - Some(ref previous_regions) => assert_eq!( - previous_regions, code_regions, - "add_counter: code regions for id changed" - ), + if self.counters_seen.insert(id) { + self.add_mappings(CovTerm::Counter(id), code_regions); } } @@ -121,10 +104,13 @@ impl<'tcx> FunctionCoverage<'tcx> { self, ); - let expression = Expression { lhs, op, rhs, code_regions: code_regions.to_owned() }; + let expression = Expression { lhs, op, rhs }; let slot = &mut self.expressions[expression_id]; match slot { - None => *slot = Some(expression), + None => { + *slot = Some(expression); + self.add_mappings(CovTerm::Expression(expression_id), code_regions); + } // If this expression ID slot has already been filled, it should // contain identical information. Some(ref previous_expression) => assert_eq!( @@ -138,7 +124,25 @@ impl<'tcx> FunctionCoverage<'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn add_unreachable_regions(&mut self, code_regions: &[CodeRegion]) { assert!(!code_regions.is_empty(), "unreachable regions always have code regions"); - self.unreachable_regions.extend_from_slice(code_regions); + self.add_mappings(CovTerm::Zero, code_regions); + } + + #[instrument(level = "debug", skip(self))] + fn add_mappings(&mut self, term: CovTerm, code_regions: &[CodeRegion]) { + self.mappings + .extend(code_regions.iter().cloned().map(|code_region| Mapping { term, code_region })); + } + + pub(crate) fn finalize(&mut self) { + self.simplify_expressions(); + + // Reorder the collected mappings so that counter mappings are first and + // zero mappings are last, matching the historical order. + self.mappings.sort_by_key(|mapping| match mapping.term { + CovTerm::Counter(_) => 0, + CovTerm::Expression(_) => 1, + CovTerm::Zero => u8::MAX, + }); } /// Perform some simplifications to make the final coverage mappings @@ -147,7 +151,7 @@ impl<'tcx> FunctionCoverage<'tcx> { /// This method mainly exists to preserve the simplifications that were /// already being performed by the Rust-side expression renumbering, so that /// the resulting coverage mappings don't get worse. - pub(crate) fn simplify_expressions(&mut self) { + fn simplify_expressions(&mut self) { // The set of expressions that either were optimized out entirely, or // have zero as both of their operands, and will therefore always have // a value of zero. Other expressions that refer to these as operands @@ -212,27 +216,10 @@ impl<'tcx> FunctionCoverage<'tcx> { assert_eq!(self.expressions.len(), counter_expressions.len()); let counter_regions = self.counter_regions(); - let expression_regions = self.expression_regions(); - let unreachable_regions = self.unreachable_regions(); - let counter_regions = - counter_regions.chain(expression_regions.into_iter().chain(unreachable_regions)); (counter_expressions, counter_regions) } - fn counter_regions(&self) -> impl Iterator { - self.counters - .iter_enumerated() - // Filter out counter IDs that we never saw during MIR traversal. - // This can happen if a counter was optimized out by MIR transforms - // (and replaced with `CoverageKind::Unreachable` instead). - .filter_map(|(id, maybe_code_regions)| Some((id, maybe_code_regions.as_ref()?))) - .flat_map(|(id, code_regions)| { - let counter = Counter::counter_value_reference(id); - code_regions.iter().map(move |region| (counter, region)) - }) - } - /// Convert this function's coverage expression data into a form that can be /// passed through FFI to LLVM. fn counter_expressions(&self) -> Vec { @@ -266,24 +253,12 @@ impl<'tcx> FunctionCoverage<'tcx> { .collect::>() } - fn expression_regions(&self) -> Vec<(Counter, &CodeRegion)> { - // Find all of the expression IDs that weren't optimized out AND have - // one or more attached code regions, and return the corresponding - // mappings as counter/region pairs. - self.expressions - .iter_enumerated() - .filter_map(|(id, maybe_expression)| { - let code_regions = &maybe_expression.as_ref()?.code_regions; - Some((id, code_regions)) - }) - .flat_map(|(id, code_regions)| { - let counter = Counter::expression(id); - code_regions.iter().map(move |code_region| (counter, code_region)) - }) - .collect::>() - } - - fn unreachable_regions(&self) -> impl Iterator { - self.unreachable_regions.iter().map(|region| (Counter::ZERO, region)) + /// Converts this function's coverage mappings into an intermediate form + /// that will be used by `mapgen` when preparing for FFI. + fn counter_regions(&self) -> impl Iterator { + self.mappings.iter().map(|&Mapping { term, ref code_region }| { + let counter = Counter::from_term(term); + (counter, code_region) + }) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index a2bf53e605d7..cde12b133074 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -61,7 +61,7 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { let mut function_data = Vec::new(); for (instance, mut function_coverage) in function_coverage_map { debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance); - function_coverage.simplify_expressions(); + function_coverage.finalize(); let function_coverage = function_coverage; let mangled_function_name = tcx.symbol_name(instance).name; @@ -169,10 +169,11 @@ fn encode_mappings_for_function( let mut virtual_file_mapping = IndexVec::::new(); let mut mapping_regions = Vec::with_capacity(counter_regions.len()); - // Sort the list of (counter, region) mapping pairs by region, so that they - // can be grouped by filename. Prepare file IDs for each filename, and - // prepare the mapping data so that we can pass it through FFI to LLVM. - counter_regions.sort_by_key(|(_counter, region)| *region); + // Sort and group the list of (counter, region) mapping pairs by filename. + // (Preserve any further ordering imposed by `FunctionCoverage`.) + // Prepare file IDs for each filename, and prepare the mapping data so that + // we can pass it through FFI to LLVM. + counter_regions.sort_by_key(|(_counter, region)| region.file_name); for counter_regions_for_file in counter_regions.group_by(|(_, a), (_, b)| a.file_name == b.file_name) { diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index fbb7f33a983a..164a17ff77a9 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -135,6 +135,20 @@ impl Op { } } +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct Mapping { + pub code_region: CodeRegion, + + /// Indicates whether this mapping uses a counter value, expression value, + /// or zero value. + /// + /// FIXME: When we add support for mapping kinds other than `Code` + /// (e.g. branch regions, expansion regions), replace this with a dedicated + /// mapping-kind enum. + pub term: CovTerm, +} + /// Stores per-function coverage information attached to a `mir::Body`, /// to be used in conjunction with the individual coverage statements injected /// into the function's basic blocks. From 54eef1601de6ace9d0e49bee1b567292f0918a1f Mon Sep 17 00:00:00 2001 From: blyxyas Date: Wed, 18 Oct 2023 12:34:16 +0200 Subject: [PATCH 75/94] Change my name in mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 26d6be9f0c60..37b1e350108e 100644 --- a/.mailmap +++ b/.mailmap @@ -74,6 +74,7 @@ Benoît Cortier Bheesham Persaud Bheesham Persaud Björn Steinbrink blake2-ppc +blyxyas Alejandra González boolean_coercion Boris Egorov bors bors[bot] <26634292+bors[bot]@users.noreply.github.com> From 4099ab19979e2f22b7a949f83241f4f0adc00ca9 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 13 Sep 2023 19:22:17 +1000 Subject: [PATCH 76/94] coverage: Make expression simplification non-destructive Instead of modifying the accumulated expressions in-place, we now build a set of expressions that are known to be zero, and then consult that set on the fly when converting the expression data for FFI. This will be necessary when moving mappings and expression data into function coverage info, which can't be mutated during codegen. --- .../src/coverageinfo/map_data.rs | 80 ++++++++++++++----- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 407ac5662d30..02831c92a08c 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -134,8 +134,6 @@ impl<'tcx> FunctionCoverage<'tcx> { } pub(crate) fn finalize(&mut self) { - self.simplify_expressions(); - // Reorder the collected mappings so that counter mappings are first and // zero mappings are last, matching the historical order. self.mappings.sort_by_key(|mapping| match mapping.term { @@ -145,25 +143,25 @@ impl<'tcx> FunctionCoverage<'tcx> { }); } - /// Perform some simplifications to make the final coverage mappings - /// slightly smaller. + /// Identify expressions that will always have a value of zero, and note + /// their IDs in [`ZeroExpressions`]. Mappings that refer to a zero expression + /// can instead become mappings to a constant zero value. /// /// This method mainly exists to preserve the simplifications that were /// already being performed by the Rust-side expression renumbering, so that /// the resulting coverage mappings don't get worse. - fn simplify_expressions(&mut self) { + fn identify_zero_expressions(&self) -> ZeroExpressions { // The set of expressions that either were optimized out entirely, or // have zero as both of their operands, and will therefore always have // a value of zero. Other expressions that refer to these as operands // can have those operands replaced with `CovTerm::Zero`. let mut zero_expressions = FxIndexSet::default(); - // For each expression, perform simplifications based on lower-numbered - // expressions, and then update the set of always-zero expressions if - // necessary. + // Simplify a copy of each expression based on lower-numbered expressions, + // and then update the set of always-zero expressions if necessary. // (By construction, expressions can only refer to other expressions - // that have lower IDs, so one simplification pass is sufficient.) - for (id, maybe_expression) in self.expressions.iter_enumerated_mut() { + // that have lower IDs, so one pass is sufficient.) + for (id, maybe_expression) in self.expressions.iter_enumerated() { let Some(expression) = maybe_expression else { // If an expression is missing, it must have been optimized away, // so any operand that refers to it can be replaced with zero. @@ -171,30 +169,50 @@ impl<'tcx> FunctionCoverage<'tcx> { continue; }; + // We don't need to simplify the actual expression data in the + // expressions list; we can just simplify a temporary copy and then + // use that to update the set of always-zero expressions. + let Expression { mut lhs, op, mut rhs } = *expression; + + // If an expression has an operand that is also an expression, the + // operand's ID must be strictly lower. This is what lets us find + // all zero expressions in one pass. + let assert_operand_expression_is_lower = |operand_id: ExpressionId| { + assert!( + operand_id < id, + "Operand {operand_id:?} should be less than {id:?} in {expression:?}", + ) + }; + // If an operand refers to an expression that is always zero, then // that operand can be replaced with `CovTerm::Zero`. - let maybe_set_operand_to_zero = |operand: &mut CovTerm| match &*operand { - CovTerm::Expression(id) if zero_expressions.contains(id) => { - *operand = CovTerm::Zero; + let maybe_set_operand_to_zero = |operand: &mut CovTerm| match *operand { + CovTerm::Expression(id) => { + assert_operand_expression_is_lower(id); + if zero_expressions.contains(&id) { + *operand = CovTerm::Zero; + } } _ => (), }; - maybe_set_operand_to_zero(&mut expression.lhs); - maybe_set_operand_to_zero(&mut expression.rhs); + maybe_set_operand_to_zero(&mut lhs); + maybe_set_operand_to_zero(&mut rhs); // Coverage counter values cannot be negative, so if an expression // involves subtraction from zero, assume that its RHS must also be zero. // (Do this after simplifications that could set the LHS to zero.) - if let Expression { lhs: CovTerm::Zero, op: Op::Subtract, .. } = expression { - expression.rhs = CovTerm::Zero; + if lhs == CovTerm::Zero && op == Op::Subtract { + rhs = CovTerm::Zero; } // After the above simplifications, if both operands are zero, then // we know that this expression is always zero too. - if let Expression { lhs: CovTerm::Zero, rhs: CovTerm::Zero, .. } = expression { + if lhs == CovTerm::Zero && rhs == CovTerm::Zero { zero_expressions.insert(id); } } + + ZeroExpressions(zero_expressions) } /// Return the source hash, generated from the HIR node structure, and used to indicate whether @@ -209,7 +227,9 @@ impl<'tcx> FunctionCoverage<'tcx> { pub fn get_expressions_and_counter_regions( &self, ) -> (Vec, impl Iterator) { - let counter_expressions = self.counter_expressions(); + let zero_expressions = self.identify_zero_expressions(); + + let counter_expressions = self.counter_expressions(&zero_expressions); // Expression IDs are indices into `self.expressions`, and on the LLVM // side they will be treated as indices into `counter_expressions`, so // the two vectors should correspond 1:1. @@ -222,12 +242,17 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Convert this function's coverage expression data into a form that can be /// passed through FFI to LLVM. - fn counter_expressions(&self) -> Vec { + fn counter_expressions(&self, zero_expressions: &ZeroExpressions) -> Vec { // We know that LLVM will optimize out any unused expressions before // producing the final coverage map, so there's no need to do the same // thing on the Rust side unless we're confident we can do much better. // (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.) + let counter_from_operand = |operand: CovTerm| match operand { + CovTerm::Expression(id) if zero_expressions.contains(id) => Counter::ZERO, + _ => Counter::from_term(operand), + }; + self.expressions .iter() .map(|expression| match expression { @@ -241,12 +266,12 @@ impl<'tcx> FunctionCoverage<'tcx> { &Some(Expression { lhs, op, rhs, .. }) => { // Convert the operands and operator as normal. CounterExpression::new( - Counter::from_term(lhs), + counter_from_operand(lhs), match op { Op::Add => ExprKind::Add, Op::Subtract => ExprKind::Subtract, }, - Counter::from_term(rhs), + counter_from_operand(rhs), ) } }) @@ -262,3 +287,14 @@ impl<'tcx> FunctionCoverage<'tcx> { }) } } + +/// Set of expression IDs that are known to always evaluate to zero. +/// Any mapping or expression operand that refers to these expressions can have +/// that reference replaced with a constant zero value. +struct ZeroExpressions(FxIndexSet); + +impl ZeroExpressions { + fn contains(&self, id: ExpressionId) -> bool { + self.0.contains(&id) + } +} From 306a7ea8b40acadbb630dbf8322b59e855c73fdc Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 18 Oct 2023 13:57:19 +0200 Subject: [PATCH 77/94] AliasTy::new instead of tcx method --- .../rustc_hir_analysis/src/astconv/bounds.rs | 2 +- .../rustc_hir_analysis/src/astconv/errors.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 4 +-- .../src/check/compare_impl_item.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 10 ------- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/relate.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 26 ++++++++++++++----- .../src/solve/normalize.rs | 2 +- .../src/solve/project_goals/mod.rs | 17 +++++++----- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/project.rs | 8 +++--- .../src/traits/select/candidate_assembly.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 2 +- 15 files changed, 46 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 059dfc604500..711da6db5acc 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -448,7 +448,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { debug!(?args_trait_ref_and_assoc_item); - tcx.mk_alias_ty(assoc_item.def_id, args_trait_ref_and_assoc_item) + ty::AliasTy::new(tcx, assoc_item.def_id, args_trait_ref_and_assoc_item) }) }; diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 9e18767a7c3e..889bc2ea4329 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -437,7 +437,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); let quiet_projection_ty = - tcx.mk_alias_ty(projection_ty.def_id, args_with_infer_self); + ty::AliasTy::new(tcx, projection_ty.def_id, args_with_infer_self); let term = pred.skip_binder().term; diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6b4980deae40..2fcb45ef8aa1 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -916,7 +916,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Type aliases defined in crates that have the // feature `lazy_type_alias` enabled get encoded as a type alias that normalization will // then actually instantiate the where bounds of. - let alias_ty = tcx.mk_alias_ty(did, args); + let alias_ty = ty::AliasTy::new(tcx, did, args); Ty::new_alias(tcx, ty::Weak, alias_ty) } else { tcx.at(span).type_of(did).instantiate(tcx, args) @@ -1718,7 +1718,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .chain(args.into_iter().skip(parent_args.len())), ); - let ty = Ty::new_alias(tcx, ty::Inherent, tcx.mk_alias_ty(assoc_item, args)); + let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args)); return Ok(Some((ty, assoc_item))); } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2eb9b773b2ef..a1470cc69c30 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2286,7 +2286,7 @@ pub(super) fn check_type_bounds<'tcx>( _ => predicates.push( ty::Binder::bind_with_vars( ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args), + projection_ty: ty::AliasTy::new(tcx, trait_ty.def_id, rebased_args), term: normalize_impl_ty.into(), }, bound_vars, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 29e5f39daf7e..6b0dc73d49c6 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -674,7 +674,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let quiet_projection_ty = - tcx.mk_alias_ty(projection_ty.def_id, args_with_infer_self); + ty::AliasTy::new(tcx, projection_ty.def_id, args_with_infer_self); let term = pred.skip_binder().term; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f7bce93fee55..05706e331f3a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1687,7 +1687,6 @@ impl<'tcx> TyCtxt<'tcx> { && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(_def_id)) { // If this is an inherent projection. - generics.params.len() + 1 } else { generics.count() @@ -1897,15 +1896,6 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_args_from_iter(iter::once(self_ty.into()).chain(rest)) } - pub fn mk_alias_ty( - self, - def_id: DefId, - args: impl IntoIterator>>, - ) -> ty::AliasTy<'tcx> { - let args = self.check_and_mk_args(def_id, args); - ty::AliasTy { def_id, args, _use_mk_alias_ty_instead: () } - } - pub fn mk_bound_variable_kinds_from_iter(self, iter: I) -> T::Output where I: Iterator, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b7d2e3d9493f..e6cd3dd4d82d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1023,7 +1023,7 @@ impl<'tcx> Term<'tcx> { _ => None, }, TermKind::Const(ct) => match ct.kind() { - ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.args)), + ConstKind::Unevaluated(uv) => Some(AliasTy::new(tcx, uv.def, uv.args)), _ => None, }, } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 96268006353c..fdfdd6cc8d6d 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -288,7 +288,7 @@ impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> { } def => bug!("unknown alias DefKind: {def:?}"), }; - Ok(relation.tcx().mk_alias_ty(a.def_id, args)) + Ok(ty::AliasTy::new(relation.tcx(), a.def_id, args)) } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 30318e585cb9..fc207a2c350d 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1213,11 +1213,20 @@ pub struct AliasTy<'tcx> { pub def_id: DefId, /// This field exists to prevent the creation of `AliasTy` without using - /// [TyCtxt::mk_alias_ty]. - pub(super) _use_mk_alias_ty_instead: (), + /// [AliasTy::new]. + _use_alias_ty_new_instead: (), } impl<'tcx> AliasTy<'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + def_id: DefId, + args: impl IntoIterator>>, + ) -> ty::AliasTy<'tcx> { + let args = tcx.check_and_mk_args(def_id, args); + ty::AliasTy { def_id, args, _use_alias_ty_new_instead: () } + } + pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind { match tcx.def_kind(self.def_id) { DefKind::AssocTy @@ -1245,7 +1254,7 @@ impl<'tcx> AliasTy<'tcx> { } pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1))) + AliasTy::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1))) } } @@ -1667,8 +1676,11 @@ impl<'tcx> ExistentialProjection<'tcx> { debug_assert!(!self_ty.has_escaping_bound_vars()); ty::ProjectionPredicate { - projection_ty: tcx - .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.args)), + projection_ty: AliasTy::new( + tcx, + self.def_id, + [self_ty.into()].into_iter().chain(self.args), + ), term: self.term, } } @@ -1971,7 +1983,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { - Ty::new_alias(tcx, ty::Opaque, tcx.mk_alias_ty(def_id, args)) + Ty::new_alias(tcx, ty::Opaque, AliasTy::new(tcx, def_id, args)) } /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` @@ -2135,7 +2147,7 @@ impl<'tcx> Ty<'tcx> { item_def_id: DefId, args: impl IntoIterator>>, ) -> Ty<'tcx> { - Ty::new_alias(tcx, ty::Projection, tcx.mk_alias_ty(item_def_id, args)) + Ty::new_alias(tcx, ty::Projection, AliasTy::new(tcx, item_def_id, args)) } #[inline] diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 872f0c879160..b0a348985708 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -129,7 +129,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { self.at.cause.clone(), self.at.param_env, ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(uv.def, uv.args), + projection_ty: AliasTy::new(tcx, uv.def, uv.args), term: new_infer_ct.into(), }, ); diff --git a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs index 2c000293f268..73c8d0c85dda 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs @@ -352,8 +352,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { let pred = tupled_inputs_and_output .map_bound(|(inputs, output)| ty::ProjectionPredicate { - projection_ty: tcx - .mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]), + projection_ty: ty::AliasTy::new( + tcx, + goal.predicate.def_id(), + [goal.predicate.self_ty(), inputs], + ), term: output.into(), }) .to_predicate(tcx); @@ -472,7 +475,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ecx, goal, ty::ProjectionPredicate { - projection_ty: ecx.tcx().mk_alias_ty(goal.predicate.def_id(), [self_ty]), + projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), term, } .to_predicate(tcx), @@ -512,9 +515,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ecx, goal, ty::ProjectionPredicate { - projection_ty: ecx - .tcx() - .mk_alias_ty(goal.predicate.def_id(), [self_ty, generator.resume_ty()]), + projection_ty: ty::AliasTy::new( + ecx.tcx(), + goal.predicate.def_id(), + [self_ty, generator.resume_ty()], + ), term, } .to_predicate(tcx), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 4329460b1b72..66529b67c17b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3937,7 +3937,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // This corresponds to `::Item = _`. let projection = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_ty: self.tcx.mk_alias_ty(proj.def_id, args), + projection_ty: ty::AliasTy::new(self.tcx, proj.def_id, args), term: ty_var.into(), }), )); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 175cc2b116b7..b923926d28df 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2072,7 +2072,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( }; ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.args), + projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args), term: ty.into(), } }); @@ -2116,7 +2116,7 @@ fn confirm_future_candidate<'cx, 'tcx>( debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output); ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.args), + projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args), term: return_ty.into(), } }); @@ -2172,7 +2172,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( }; let predicate = - ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, args), term }; + ty::ProjectionPredicate { projection_ty: ty::AliasTy::new(tcx, item_def_id, args), term }; confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) .with_addl_obligations(obligations) @@ -2245,7 +2245,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( flag, ) .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.args), + projection_ty: ty::AliasTy::new(tcx, fn_once_output_def_id, trait_ref.args), term: ret_type.into(), }); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index f08cf6cef5b3..a8001577bcd5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -704,7 +704,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let ty = traits::normalize_projection_type( self, param_env, - tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.args), + ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args), cause.clone(), 0, // We're *intentionally* throwing these away, diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 2d305a63eca1..673b259523e1 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -1133,7 +1133,7 @@ pub fn make_projection<'tcx>( #[cfg(debug_assertions)] assert_generic_args_match(tcx, assoc_item.def_id, args); - Some(tcx.mk_alias_ty(assoc_item.def_id, args)) + Some(ty::AliasTy::new(tcx, assoc_item.def_id, args)) } helper( tcx, From 6da319f63583215d593919bcd994785141f7265d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 13 Sep 2023 12:51:43 +1000 Subject: [PATCH 78/94] coverage: Store all of a function's mappings in function coverage info Previously, mappings were attached to individual coverage statements in MIR. That necessitated special handling in MIR optimizations to avoid deleting those statements, since otherwise codegen would be unable to reassemble the original list of mappings. With this change, a function's list of mappings is now attached to its MIR body, and survives intact even if individual statements are deleted by optimizations. --- .../src/coverageinfo/map_data.rs | 75 +++++-------- .../src/coverageinfo/mapgen.rs | 4 +- .../src/coverageinfo/mod.rs | 29 ++--- compiler/rustc_middle/src/mir/coverage.rs | 18 +-- compiler/rustc_middle/src/mir/pretty.rs | 26 +++-- compiler/rustc_middle/src/mir/syntax.rs | 3 +- compiler/rustc_middle/src/query/mod.rs | 11 -- .../rustc_mir_transform/src/coverage/mod.rs | 34 +++--- .../rustc_mir_transform/src/coverage/query.rs | 22 +--- compiler/rustc_mir_transform/src/simplify.rs | 103 +----------------- .../status-quo/issue-84561.cov-map | 5 +- .../status-quo/try_error_result.cov-map | 29 +---- ...ument_coverage.bar.InstrumentCoverage.diff | 4 +- ...ment_coverage.main.InstrumentCoverage.diff | 14 ++- 14 files changed, 107 insertions(+), 270 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 02831c92a08c..e6b39c714536 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -23,11 +23,10 @@ pub struct FunctionCoverage<'tcx> { function_coverage_info: &'tcx FunctionCoverageInfo, is_used: bool, - /// Tracks which counters have been seen, to avoid duplicate mappings - /// that might be introduced by MIR inlining. + /// Tracks which counters have been seen, so that we can identify mappings + /// to counters that were optimized out, and set them to zero. counters_seen: BitSet, expressions: IndexVec>, - mappings: Vec, } impl<'tcx> FunctionCoverage<'tcx> { @@ -63,7 +62,6 @@ impl<'tcx> FunctionCoverage<'tcx> { is_used, counters_seen: BitSet::new_empty(num_counters), expressions: IndexVec::from_elem_n(None, num_expressions), - mappings: Vec::new(), } } @@ -72,20 +70,13 @@ impl<'tcx> FunctionCoverage<'tcx> { self.is_used } - /// Adds code regions to be counted by an injected counter intrinsic. + /// Marks a counter ID as having been seen in a counter-increment statement. #[instrument(level = "debug", skip(self))] - pub(crate) fn add_counter(&mut self, id: CounterId, code_regions: &[CodeRegion]) { - if self.counters_seen.insert(id) { - self.add_mappings(CovTerm::Counter(id), code_regions); - } + pub(crate) fn mark_counter_id_seen(&mut self, id: CounterId) { + self.counters_seen.insert(id); } - /// Adds information about a coverage expression, along with zero or more - /// code regions mapped to that expression. - /// - /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other - /// expressions. These are tracked as separate variants of `CovTerm`, so there is no ambiguity - /// between operands that are counter IDs and operands that are expression IDs. + /// Adds information about a coverage expression. #[instrument(level = "debug", skip(self))] pub(crate) fn add_counter_expression( &mut self, @@ -93,7 +84,6 @@ impl<'tcx> FunctionCoverage<'tcx> { lhs: CovTerm, op: Op, rhs: CovTerm, - code_regions: &[CodeRegion], ) { debug_assert!( expression_id.as_usize() < self.expressions.len(), @@ -107,10 +97,7 @@ impl<'tcx> FunctionCoverage<'tcx> { let expression = Expression { lhs, op, rhs }; let slot = &mut self.expressions[expression_id]; match slot { - None => { - *slot = Some(expression); - self.add_mappings(CovTerm::Expression(expression_id), code_regions); - } + None => *slot = Some(expression), // If this expression ID slot has already been filled, it should // contain identical information. Some(ref previous_expression) => assert_eq!( @@ -120,29 +107,6 @@ impl<'tcx> FunctionCoverage<'tcx> { } } - /// Adds regions that will be marked as "unreachable", with a constant "zero counter". - #[instrument(level = "debug", skip(self))] - pub(crate) fn add_unreachable_regions(&mut self, code_regions: &[CodeRegion]) { - assert!(!code_regions.is_empty(), "unreachable regions always have code regions"); - self.add_mappings(CovTerm::Zero, code_regions); - } - - #[instrument(level = "debug", skip(self))] - fn add_mappings(&mut self, term: CovTerm, code_regions: &[CodeRegion]) { - self.mappings - .extend(code_regions.iter().cloned().map(|code_region| Mapping { term, code_region })); - } - - pub(crate) fn finalize(&mut self) { - // Reorder the collected mappings so that counter mappings are first and - // zero mappings are last, matching the historical order. - self.mappings.sort_by_key(|mapping| match mapping.term { - CovTerm::Counter(_) => 0, - CovTerm::Expression(_) => 1, - CovTerm::Zero => u8::MAX, - }); - } - /// Identify expressions that will always have a value of zero, and note /// their IDs in [`ZeroExpressions`]. Mappings that refer to a zero expression /// can instead become mappings to a constant zero value. @@ -235,7 +199,7 @@ impl<'tcx> FunctionCoverage<'tcx> { // the two vectors should correspond 1:1. assert_eq!(self.expressions.len(), counter_expressions.len()); - let counter_regions = self.counter_regions(); + let counter_regions = self.counter_regions(zero_expressions); (counter_expressions, counter_regions) } @@ -280,9 +244,26 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Converts this function's coverage mappings into an intermediate form /// that will be used by `mapgen` when preparing for FFI. - fn counter_regions(&self) -> impl Iterator { - self.mappings.iter().map(|&Mapping { term, ref code_region }| { - let counter = Counter::from_term(term); + fn counter_regions( + &self, + zero_expressions: ZeroExpressions, + ) -> impl Iterator { + // Historically, mappings were stored directly in counter/expression + // statements in MIR, and MIR optimizations would sometimes remove them. + // That's mostly no longer true, so now we detect cases where that would + // have happened, and zero out the corresponding mappings here instead. + let counter_for_term = move |term: CovTerm| { + let force_to_zero = match term { + CovTerm::Counter(id) => !self.counters_seen.contains(id), + CovTerm::Expression(id) => zero_expressions.contains(id), + CovTerm::Zero => false, + }; + if force_to_zero { Counter::ZERO } else { Counter::from_term(term) } + }; + + self.function_coverage_info.mappings.iter().map(move |mapping| { + let &Mapping { term, ref code_region } = mapping; + let counter = counter_for_term(term); (counter, code_region) }) } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index cde12b133074..ef3647efd881 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -59,10 +59,8 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { // Encode coverage mappings and generate function records let mut function_data = Vec::new(); - for (instance, mut function_coverage) in function_coverage_map { + for (instance, function_coverage) in function_coverage_map { debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance); - function_coverage.finalize(); - let function_coverage = function_coverage; let mangled_function_name = tcx.symbol_name(instance).name; let source_hash = function_coverage.source_hash(); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index c975d3432b92..14332927c8db 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -88,13 +88,12 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// For used/called functions, the coverageinfo was already added to the /// `function_coverage_map` (keyed by function `Instance`) during codegen. /// But in this case, since the unused function was _not_ previously - /// codegenned, collect the coverage `CodeRegion`s from the MIR and add - /// them. Since the function is never called, all of its `CodeRegion`s can be - /// added as `unreachable_region`s. + /// codegenned, collect the function coverage info from MIR and add an + /// "unused" entry to the function coverage map. fn define_unused_fn(&self, def_id: DefId, function_coverage_info: &'tcx FunctionCoverageInfo) { let instance = declare_unused_fn(self, def_id); codegen_unused_fn_and_counter(self, instance); - add_unused_function_coverage(self, instance, def_id, function_coverage_info); + add_unused_function_coverage(self, instance, function_coverage_info); } } @@ -116,10 +115,10 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { .entry(instance) .or_insert_with(|| FunctionCoverage::new(instance, function_coverage_info)); - let Coverage { kind, code_regions } = coverage; + let Coverage { kind } = coverage; match *kind { - CoverageKind::Counter { id } => { - func_coverage.add_counter(id, code_regions); + CoverageKind::CounterIncrement { id } => { + func_coverage.mark_counter_id_seen(id); // We need to explicitly drop the `RefMut` before calling into `instrprof_increment`, // as that needs an exclusive borrow. drop(coverage_map); @@ -147,10 +146,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { bx.instrprof_increment(fn_name, hash, num_counters, index); } CoverageKind::Expression { id, lhs, op, rhs } => { - func_coverage.add_counter_expression(id, lhs, op, rhs, code_regions); - } - CoverageKind::Unreachable => { - func_coverage.add_unreachable_regions(code_regions); + func_coverage.add_counter_expression(id, lhs, op, rhs); } } } @@ -213,16 +209,11 @@ fn codegen_unused_fn_and_counter<'tcx>(cx: &CodegenCx<'_, 'tcx>, instance: Insta fn add_unused_function_coverage<'tcx>( cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>, - def_id: DefId, function_coverage_info: &'tcx FunctionCoverageInfo, ) { - let tcx = cx.tcx; - - let mut function_coverage = FunctionCoverage::unused(instance, function_coverage_info); - for &code_region in tcx.covered_code_regions(def_id) { - let code_region = std::slice::from_ref(code_region); - function_coverage.add_unreachable_regions(code_region); - } + // An unused function's mappings will automatically be rewritten to map to + // zero, because none of its counters/expressions are marked as seen. + let function_coverage = FunctionCoverage::unused(instance, function_coverage_info); if let Some(coverage_context) = cx.coverage_context() { coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage); diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 164a17ff77a9..2587a6eae1aa 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -61,11 +61,13 @@ impl Debug for CovTerm { #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum CoverageKind { - Counter { - /// ID of this counter within its enclosing function. - /// Expressions in the same function can refer to it as an operand. - id: CounterId, - }, + /// Marks the point in MIR control flow represented by a coverage counter. + /// + /// This is eventually lowered to `llvm.instrprof.increment` in LLVM IR. + /// + /// If this statement does not survive MIR optimizations, any mappings that + /// refer to this counter can have those references simplified to zero. + CounterIncrement { id: CounterId }, Expression { /// ID of this coverage-counter expression within its enclosing function. /// Other expressions in the same function can refer to it as an operand. @@ -74,14 +76,13 @@ pub enum CoverageKind { op: Op, rhs: CovTerm, }, - Unreachable, } impl Debug for CoverageKind { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { use CoverageKind::*; match self { - Counter { id } => write!(fmt, "Counter({:?})", id.index()), + CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()), Expression { id, lhs, op, rhs } => write!( fmt, "Expression({:?}) = {:?} {} {:?}", @@ -93,7 +94,6 @@ impl Debug for CoverageKind { }, rhs, ), - Unreachable => write!(fmt, "Unreachable"), } } } @@ -158,4 +158,6 @@ pub struct FunctionCoverageInfo { pub function_source_hash: u64, pub num_counters: usize, pub num_expressions: usize, + + pub mappings: Vec, } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index c5e3ee575e1a..11269e749f86 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -493,6 +493,24 @@ pub fn write_mir_intro<'tcx>( // Add an empty line before the first block is printed. writeln!(w)?; + if let Some(function_coverage_info) = &body.function_coverage_info { + write_function_coverage_info(function_coverage_info, w)?; + } + + Ok(()) +} + +fn write_function_coverage_info( + function_coverage_info: &coverage::FunctionCoverageInfo, + w: &mut dyn io::Write, +) -> io::Result<()> { + let coverage::FunctionCoverageInfo { mappings, .. } = function_coverage_info; + + for coverage::Mapping { term, code_region } in mappings { + writeln!(w, "{INDENT}coverage {term:?} => {code_region:?};")?; + } + writeln!(w)?; + Ok(()) } @@ -685,13 +703,7 @@ impl Debug for Statement<'_> { AscribeUserType(box (ref place, ref c_ty), ref variance) => { write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})") } - Coverage(box mir::Coverage { ref kind, ref code_regions }) => { - if code_regions.is_empty() { - write!(fmt, "Coverage::{kind:?}") - } else { - write!(fmt, "Coverage::{kind:?} for {code_regions:?}") - } - } + Coverage(box mir::Coverage { ref kind }) => write!(fmt, "Coverage::{kind:?}"), Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), ConstEvalCounter => write!(fmt, "ConstEvalCounter"), Nop => write!(fmt, "nop"), diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index c7d99648f1e2..77b26e0a4cde 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -5,7 +5,7 @@ use super::{BasicBlock, Const, Local, UserTypeProjection}; -use crate::mir::coverage::{CodeRegion, CoverageKind}; +use crate::mir::coverage::CoverageKind; use crate::traits::Reveal; use crate::ty::adjustment::PointerCoercion; use crate::ty::GenericArgsRef; @@ -514,7 +514,6 @@ pub enum FakeReadCause { #[derive(TypeFoldable, TypeVisitable)] pub struct Coverage { pub kind: CoverageKind, - pub code_regions: Vec, } #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ed0f73fcf2fa..afe94d107521 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -581,17 +581,6 @@ rustc_queries! { arena_cache } - /// Returns the `CodeRegions` for a function that has instrumented coverage, in case the - /// function was optimized out before codegen, and before being added to the Coverage Map. - query covered_code_regions(key: DefId) -> &'tcx Vec<&'tcx mir::coverage::CodeRegion> { - desc { - |tcx| "retrieving the covered `CodeRegion`s, if instrumented, for `{}`", - tcx.def_path_str(key) - } - arena_cache - cache_on_disk_if { key.is_local() } - } - /// The `DefId` is the `DefId` of the containing MIR body. Promoteds do not have their own /// `DefId`. This function returns all promoteds in the specified body. The body references /// promoteds by the `DefId` and the `mir::Promoted` index. This is necessary, because diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index e1b656bd9819..078123a7b7fb 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -104,6 +104,7 @@ struct Instrumentor<'a, 'tcx> { function_source_hash: u64, basic_coverage_blocks: CoverageGraph, coverage_counters: CoverageCounters, + mappings: Vec, } impl<'a, 'tcx> Instrumentor<'a, 'tcx> { @@ -144,6 +145,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { function_source_hash, basic_coverage_blocks, coverage_counters, + mappings: Vec::new(), } } @@ -216,6 +218,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { function_source_hash: self.function_source_hash, num_counters: self.coverage_counters.num_counters(), num_expressions: self.coverage_counters.num_expressions(), + mappings: std::mem::take(&mut self.mappings), })); } @@ -232,18 +235,16 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { bug!("Every BasicCoverageBlock should have a Counter or Expression"); }); - // Convert the coverage spans into a vector of code regions to be - // associated with this BCB's coverage statement. - let code_regions = spans - .iter() - .map(|&span| make_code_region(source_map, file_name, span, body_span)) - .collect::>(); + let term = counter_kind.as_term(); + self.mappings.extend(spans.iter().map(|&span| { + let code_region = make_code_region(source_map, file_name, span, body_span); + Mapping { code_region, term } + })); inject_statement( self.mir_body, self.make_mir_coverage_kind(&counter_kind), self.bcb_leader_bb(bcb), - code_regions, ); } } @@ -301,7 +302,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { self.mir_body, self.make_mir_coverage_kind(&counter_kind), inject_to_bb, - Vec::new(), ); } BcbCounter::Expression { .. } => inject_intermediate_expression( @@ -329,7 +329,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind { match *counter_kind { - BcbCounter::Counter { id } => CoverageKind::Counter { id }, + BcbCounter::Counter { id } => CoverageKind::CounterIncrement { id }, BcbCounter::Expression { id, lhs, op, rhs } => { CoverageKind::Expression { id, lhs, op, rhs } } @@ -360,18 +360,13 @@ fn inject_edge_counter_basic_block( new_bb } -fn inject_statement( - mir_body: &mut mir::Body<'_>, - counter_kind: CoverageKind, - bb: BasicBlock, - code_regions: Vec, -) { - debug!(" injecting statement {counter_kind:?} for {bb:?} at code regions: {code_regions:?}"); +fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb: BasicBlock) { + debug!(" injecting statement {counter_kind:?} for {bb:?}"); let data = &mut mir_body[bb]; let source_info = data.terminator().source_info; let statement = Statement { source_info, - kind: StatementKind::Coverage(Box::new(Coverage { kind: counter_kind, code_regions })), + kind: StatementKind::Coverage(Box::new(Coverage { kind: counter_kind })), }; data.statements.insert(0, statement); } @@ -385,10 +380,7 @@ fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: Cove let source_info = data.terminator().source_info; let statement = Statement { source_info, - kind: StatementKind::Coverage(Box::new(Coverage { - kind: expression, - code_regions: Vec::new(), - })), + kind: StatementKind::Coverage(Box::new(Coverage { kind: expression })), }; data.statements.push(statement); } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index b1f46c8e05c6..809407f897db 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -2,15 +2,13 @@ use super::*; use rustc_data_structures::captures::Captures; use rustc_middle::mir::coverage::*; -use rustc_middle::mir::{self, Body, Coverage, CoverageIdsInfo}; +use rustc_middle::mir::{Body, Coverage, CoverageIdsInfo}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::def_id::DefId; /// A `query` provider for retrieving coverage information injected into MIR. pub(crate) fn provide(providers: &mut Providers) { providers.coverage_ids_info = |tcx, def_id| coverage_ids_info(tcx, def_id); - providers.covered_code_regions = |tcx, def_id| covered_code_regions(tcx, def_id); } /// Query implementation for `coverage_ids_info`. @@ -22,7 +20,7 @@ fn coverage_ids_info<'tcx>( let max_counter_id = all_coverage_in_mir_body(mir_body) .filter_map(|coverage| match coverage.kind { - CoverageKind::Counter { id } => Some(id), + CoverageKind::CounterIncrement { id } => Some(id), _ => None, }) .max() @@ -31,14 +29,6 @@ fn coverage_ids_info<'tcx>( CoverageIdsInfo { max_counter_id } } -fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> { - let body = mir_body(tcx, def_id); - all_coverage_in_mir_body(body) - // Coverage statements have a list of code regions (possibly empty). - .flat_map(|coverage| coverage.code_regions.as_slice()) - .collect() -} - fn all_coverage_in_mir_body<'a, 'tcx>( body: &'a Body<'tcx>, ) -> impl Iterator + Captures<'tcx> { @@ -56,11 +46,3 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool { let scope_data = &body.source_scopes[statement.source_info.scope]; scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some() } - -/// This function ensures we obtain the correct MIR for the given item irrespective of -/// whether that means const mir or runtime mir. For `const fn` this opts for runtime -/// mir. -fn mir_body(tcx: TyCtxt<'_>, def_id: DefId) -> &mir::Body<'_> { - let def = ty::InstanceDef::Item(def_id); - tcx.instance_mir(def) -} diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 73dae0443553..3ecb7403387b 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -28,10 +28,8 @@ //! return. use crate::MirPass; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_index::{Idx, IndexSlice, IndexVec}; -use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -337,7 +335,7 @@ pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut B } } -pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +pub fn remove_dead_blocks<'tcx>(_tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let reachable = traversal::reachable_as_bitset(body); let num_blocks = body.basic_blocks.len(); if num_blocks == reachable.count() { @@ -345,10 +343,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } let basic_blocks = body.basic_blocks.as_mut(); - let source_scopes = &body.source_scopes; - if tcx.sess.instrument_coverage() { - save_unreachable_coverage(basic_blocks, source_scopes, &reachable); - } let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); let mut orig_index = 0; @@ -370,99 +364,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } } -/// Some MIR transforms can determine at compile time that a sequences of -/// statements will never be executed, so they can be dropped from the MIR. -/// For example, an `if` or `else` block that is guaranteed to never be executed -/// because its condition can be evaluated at compile time, such as by const -/// evaluation: `if false { ... }`. -/// -/// Those statements are bypassed by redirecting paths in the CFG around the -/// `dead blocks`; but with `-C instrument-coverage`, the dead blocks usually -/// include `Coverage` statements representing the Rust source code regions to -/// be counted at runtime. Without these `Coverage` statements, the regions are -/// lost, and the Rust source code will show no coverage information. -/// -/// What we want to show in a coverage report is the dead code with coverage -/// counts of `0`. To do this, we need to save the code regions, by injecting -/// `Unreachable` coverage statements. These are non-executable statements whose -/// code regions are still recorded in the coverage map, representing regions -/// with `0` executions. -/// -/// If there are no live `Counter` `Coverage` statements remaining, we remove -/// `Coverage` statements along with the dead blocks. Since at least one -/// counter per function is required by LLVM (and necessary, to add the -/// `function_hash` to the counter's call to the LLVM intrinsic -/// `instrprof.increment()`). -/// -/// The `generator::StateTransform` MIR pass and MIR inlining can create -/// atypical conditions, where all live `Counter`s are dropped from the MIR. -/// -/// With MIR inlining we can have coverage counters belonging to different -/// instances in a single body, so the strategy described above is applied to -/// coverage counters from each instance individually. -fn save_unreachable_coverage( - basic_blocks: &mut IndexSlice>, - source_scopes: &IndexSlice>, - reachable: &BitSet, -) { - // Identify instances that still have some live coverage counters left. - let mut live = FxHashSet::default(); - for bb in reachable.iter() { - let basic_block = &basic_blocks[bb]; - for statement in &basic_block.statements { - let StatementKind::Coverage(coverage) = &statement.kind else { continue }; - let CoverageKind::Counter { .. } = coverage.kind else { continue }; - let instance = statement.source_info.scope.inlined_instance(source_scopes); - live.insert(instance); - } - } - - for bb in reachable.iter() { - let block = &mut basic_blocks[bb]; - for statement in &mut block.statements { - let StatementKind::Coverage(_) = &statement.kind else { continue }; - let instance = statement.source_info.scope.inlined_instance(source_scopes); - if !live.contains(&instance) { - statement.make_nop(); - } - } - } - - if live.is_empty() { - return; - } - - // Retain coverage for instances that still have some live counters left. - let mut retained_coverage = Vec::new(); - for dead_block in basic_blocks.indices() { - if reachable.contains(dead_block) { - continue; - } - let dead_block = &basic_blocks[dead_block]; - for statement in &dead_block.statements { - let StatementKind::Coverage(coverage) = &statement.kind else { continue }; - if coverage.code_regions.is_empty() { - continue; - }; - let instance = statement.source_info.scope.inlined_instance(source_scopes); - if live.contains(&instance) { - retained_coverage.push((statement.source_info, coverage.code_regions.clone())); - } - } - } - - let start_block = &mut basic_blocks[START_BLOCK]; - start_block.statements.extend(retained_coverage.into_iter().map( - |(source_info, code_regions)| Statement { - source_info, - kind: StatementKind::Coverage(Box::new(Coverage { - kind: CoverageKind::Unreachable, - code_regions, - })), - }, - )); -} - pub enum SimplifyLocals { BeforeConstProp, Final, diff --git a/tests/coverage-map/status-quo/issue-84561.cov-map b/tests/coverage-map/status-quo/issue-84561.cov-map index fe098fd396c2..01fa7ec573c5 100644 --- a/tests/coverage-map/status-quo/issue-84561.cov-map +++ b/tests/coverage-map/status-quo/issue-84561.cov-map @@ -1,11 +1,10 @@ Function name: ::eq -Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 0a, 00, 13, 00, 00, 0a, 00, 13] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 0a, 00, 13] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 2 +Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 4, 10) to (start + 0, 19) -- Code(Zero) at (prev + 0, 10) to (start + 0, 19) Function name: ::fmt Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 89, 01, 09, 00, 25, 05, 00, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06] diff --git a/tests/coverage-map/status-quo/try_error_result.cov-map b/tests/coverage-map/status-quo/try_error_result.cov-map index d254ba7b3b68..8367103a21a4 100644 --- a/tests/coverage-map/status-quo/try_error_result.cov-map +++ b/tests/coverage-map/status-quo/try_error_result.cov-map @@ -1,62 +1,45 @@ Function name: ::get_thing_2 -Raw bytes (63): 0x[01, 01, 02, 01, 05, 05, 02, 0b, 01, 28, 05, 01, 18, 05, 02, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 02, 02, 0d, 00, 1a, 00, 00, 0d, 00, 1a, 00, 00, 0d, 00, 1a, 07, 02, 05, 00, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 1a, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 11 +Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 40, 5) to (start + 1, 24) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) -- Code(Zero) at (prev + 0, 13) to (start + 0, 20) -- Code(Zero) at (prev + 0, 13) to (start + 0, 20) -- Code(Zero) at (prev + 0, 13) to (start + 0, 20) -- Code(Zero) at (prev + 0, 13) to (start + 0, 20) -- Code(Zero) at (prev + 0, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 26) = (c0 - c1) -- Code(Zero) at (prev + 0, 13) to (start + 0, 26) -- Code(Zero) at (prev + 0, 13) to (start + 0, 26) - Code(Expression(1, Add)) at (prev + 2, 5) to (start + 0, 6) = (c1 + (c0 - c1)) Function name: ::call -Raw bytes (63): 0x[01, 01, 02, 01, 05, 05, 02, 0b, 01, 33, 05, 01, 18, 05, 02, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 02, 02, 0d, 00, 13, 00, 00, 0d, 00, 13, 00, 00, 0d, 00, 13, 00, 00, 0d, 00, 13, 07, 02, 05, 00, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 33, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 11 +Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 51, 5) to (start + 1, 24) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) -- Code(Zero) at (prev + 0, 13) to (start + 0, 20) -- Code(Zero) at (prev + 0, 13) to (start + 0, 20) -- Code(Zero) at (prev + 0, 13) to (start + 0, 20) -- Code(Zero) at (prev + 0, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) -- Code(Zero) at (prev + 0, 13) to (start + 0, 19) -- Code(Zero) at (prev + 0, 13) to (start + 0, 19) -- Code(Zero) at (prev + 0, 13) to (start + 0, 19) - Code(Expression(1, Add)) at (prev + 2, 5) to (start + 0, 6) = (c1 + (c0 - c1)) Function name: try_error_result::call -Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 04, 01, 01, 14, 05, 02, 09, 00, 10, 00, 00, 09, 00, 10, 00, 00, 09, 00, 10, 02, 02, 09, 00, 0f, 00, 00, 09, 00, 0f, 07, 02, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 07, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 7 +Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) -- Code(Zero) at (prev + 0, 9) to (start + 0, 16) -- Code(Zero) at (prev + 0, 9) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) -- Code(Zero) at (prev + 0, 9) to (start + 0, 15) - Code(Expression(1, Add)) at (prev + 2, 1) to (start + 0, 2) = (c1 + (c0 - c1)) diff --git a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff index 28a7ffda3717..13ff1e284d9a 100644 --- a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff @@ -4,8 +4,10 @@ fn bar() -> bool { let mut _0: bool; ++ coverage Counter(0) => /the/src/instrument_coverage.rs:20:1 - 22:2; ++ bb0: { -+ Coverage::Counter(0) for [/the/src/instrument_coverage.rs:20:1 - 22:2]; ++ Coverage::CounterIncrement(0); _0 = const true; return; } diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index 9a8caa26307a..5459ecd98c5f 100644 --- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -7,13 +7,19 @@ let mut _2: bool; let mut _3: !; ++ coverage Counter(0) => /the/src/instrument_coverage.rs:11:1 - 11:11; ++ coverage Expression(0) => /the/src/instrument_coverage.rs:12:5 - 13:17; ++ coverage Expression(1) => /the/src/instrument_coverage.rs:14:13 - 14:18; ++ coverage Expression(1) => /the/src/instrument_coverage.rs:17:1 - 17:2; ++ coverage Counter(1) => /the/src/instrument_coverage.rs:15:10 - 15:11; ++ bb0: { -+ Coverage::Counter(0) for [/the/src/instrument_coverage.rs:11:1 - 11:11]; ++ Coverage::CounterIncrement(0); goto -> bb1; } bb1: { -+ Coverage::Expression(0) = Counter(0) + Counter(1) for [/the/src/instrument_coverage.rs:12:5 - 13:17]; ++ Coverage::Expression(0) = Counter(0) + Counter(1); falseUnwind -> [real: bb2, unwind: bb6]; } @@ -27,14 +33,14 @@ } bb4: { -+ Coverage::Expression(1) = Expression(0) - Counter(1) for [/the/src/instrument_coverage.rs:14:13 - 14:18, /the/src/instrument_coverage.rs:17:1 - 17:2]; ++ Coverage::Expression(1) = Expression(0) - Counter(1); _0 = const (); StorageDead(_2); return; } bb5: { -+ Coverage::Counter(1) for [/the/src/instrument_coverage.rs:15:10 - 15:11]; ++ Coverage::CounterIncrement(1); _1 = const (); StorageDead(_2); goto -> bb1; From 7d38f4a6114b461ce77e9cd1d7fd65ec79c05a64 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 7 Sep 2023 21:57:24 +1000 Subject: [PATCH 79/94] Remove unused `TyCtxt` from `remove_dead_blocks` This context was only needed by code for processing coverage statements, which has been removed. --- compiler/rustc_mir_transform/src/abort_unwinding_calls.rs | 2 +- compiler/rustc_mir_transform/src/dest_prop.rs | 2 +- compiler/rustc_mir_transform/src/generator.rs | 4 ++-- compiler/rustc_mir_transform/src/inline.rs | 2 +- .../rustc_mir_transform/src/multiple_return_terminators.rs | 2 +- compiler/rustc_mir_transform/src/simplify.rs | 4 ++-- compiler/rustc_mir_transform/src/unreachable_prop.rs | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 4500bb7ff0f0..74243f1f8f27 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -113,6 +113,6 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { } // We may have invalidated some `cleanup` blocks so clean those up now. - super::simplify::remove_dead_blocks(tcx, body); + super::simplify::remove_dead_blocks(body); } } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index d9a132e5cf17..99b070c018e3 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -244,7 +244,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { if round_count != 0 { // Merging can introduce overlap between moved arguments and/or call destination in an // unreachable code, which validator considers to be ill-formed. - remove_dead_blocks(tcx, body); + remove_dead_blocks(body); } trace!(round_count); diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index c16f07a453c3..a6693519e54b 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1088,7 +1088,7 @@ fn create_generator_drop_shim<'tcx>( // Make sure we remove dead blocks to remove // unrelated code from the resume part of the function - simplify::remove_dead_blocks(tcx, &mut body); + simplify::remove_dead_blocks(&mut body); // Update the body's def to become the drop glue. // This needs to be updated before the AbortUnwindingCalls pass. @@ -1276,7 +1276,7 @@ fn create_generator_resume_function<'tcx>( // Make sure we remove dead blocks to remove // unrelated code from the drop part of the function - simplify::remove_dead_blocks(tcx, body); + simplify::remove_dead_blocks(body); pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index a70371172f73..8f578b696944 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -63,7 +63,7 @@ impl<'tcx> MirPass<'tcx> for Inline { if inline(tcx, body) { debug!("running simplify cfg on {:?}", body.source); CfgSimplifier::new(body).simplify(); - remove_dead_blocks(tcx, body); + remove_dead_blocks(body); deref_finder(tcx, body); } } diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index c97d034544a8..c9b42e75cb25 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -38,6 +38,6 @@ impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { } } - simplify::remove_dead_blocks(tcx, body) + simplify::remove_dead_blocks(body) } } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 3ecb7403387b..88c89e106fd5 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -66,7 +66,7 @@ impl SimplifyCfg { pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { CfgSimplifier::new(body).simplify(); remove_duplicate_unreachable_blocks(tcx, body); - remove_dead_blocks(tcx, body); + remove_dead_blocks(body); // FIXME: Should probably be moved into some kind of pass manager body.basic_blocks_mut().raw.shrink_to_fit(); @@ -335,7 +335,7 @@ pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut B } } -pub fn remove_dead_blocks<'tcx>(_tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +pub fn remove_dead_blocks(body: &mut Body<'_>) { let reachable = traversal::reachable_as_bitset(body); let num_blocks = body.basic_blocks.len(); if num_blocks == reachable.count() { diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index 0b9311a20efa..ea7aafd866b1 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -65,7 +65,7 @@ impl MirPass<'_> for UnreachablePropagation { } if replaced { - simplify::remove_dead_blocks(tcx, body); + simplify::remove_dead_blocks(body); } } } From 13b2d604ec31f76b8e913b6d2b28e1d2dad2249f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 13 Sep 2023 13:20:13 +1000 Subject: [PATCH 80/94] coverage: Store expression data in function coverage info Even though expression details are now stored in the info structure, we still need to inject `ExpressionUsed` statements into MIR, because if one is missing during codegen then we know that it was optimized out and we can remap all of its associated code regions to zero. --- .../src/coverageinfo/ffi.rs | 11 -- .../src/coverageinfo/map_data.rs | 105 +++++++----------- .../src/coverageinfo/mod.rs | 4 +- compiler/rustc_middle/src/mir/coverage.rs | 41 +++---- compiler/rustc_middle/src/mir/pretty.rs | 5 +- .../src/coverage/counters.rs | 47 +++----- .../rustc_mir_transform/src/coverage/mod.rs | 42 +------ .../rustc_mir_transform/src/coverage/tests.rs | 2 +- ...ment_coverage.main.InstrumentCoverage.diff | 6 +- 9 files changed, 90 insertions(+), 173 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 194ed7d661da..7ad2d03a5edd 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -73,17 +73,6 @@ pub struct CounterExpression { pub rhs: Counter, } -impl CounterExpression { - /// The dummy expression `(0 - 0)` has a representation of all zeroes, - /// making it marginally more efficient to initialize than `(0 + 0)`. - pub(crate) const DUMMY: Self = - Self { lhs: Counter::ZERO, kind: ExprKind::Subtract, rhs: Counter::ZERO }; - - pub fn new(lhs: Counter, kind: ExprKind, rhs: Counter) -> Self { - Self { kind, lhs, rhs } - } -} - /// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`. /// /// Must match the layout of `LLVMRustCounterMappingRegionKind`. diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index e6b39c714536..84319b4ba2d3 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -2,19 +2,11 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::BitSet; -use rustc_index::IndexVec; use rustc_middle::mir::coverage::{ - CodeRegion, CounterId, CovTerm, ExpressionId, FunctionCoverageInfo, Mapping, Op, + CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, Op, }; use rustc_middle::ty::Instance; -#[derive(Clone, Debug, PartialEq)] -pub struct Expression { - lhs: CovTerm, - op: Op, - rhs: CovTerm, -} - /// Holds all of the coverage mapping data associated with a function instance, /// collected during traversal of `Coverage` statements in the function's MIR. #[derive(Debug)] @@ -26,7 +18,12 @@ pub struct FunctionCoverage<'tcx> { /// Tracks which counters have been seen, so that we can identify mappings /// to counters that were optimized out, and set them to zero. counters_seen: BitSet, - expressions: IndexVec>, + /// Contains all expression IDs that have been seen in an `ExpressionUsed` + /// coverage statement, plus all expression IDs that aren't directly used + /// by any mappings (and therefore do not have expression-used statements). + /// After MIR traversal is finished, we can conclude that any IDs missing + /// from this set must have had their statements deleted by MIR opts. + expressions_seen: BitSet, } impl<'tcx> FunctionCoverage<'tcx> { @@ -52,16 +49,30 @@ impl<'tcx> FunctionCoverage<'tcx> { is_used: bool, ) -> Self { let num_counters = function_coverage_info.num_counters; - let num_expressions = function_coverage_info.num_expressions; + let num_expressions = function_coverage_info.expressions.len(); debug!( "FunctionCoverage::create(instance={instance:?}) has \ num_counters={num_counters}, num_expressions={num_expressions}, is_used={is_used}" ); + + // Create a filled set of expression IDs, so that expressions not + // directly used by mappings will be treated as "seen". + // (If they end up being unused, LLVM will delete them for us.) + let mut expressions_seen = BitSet::new_filled(num_expressions); + // For each expression ID that is directly used by one or more mappings, + // mark it as not-yet-seen. This indicates that we expect to see a + // corresponding `ExpressionUsed` statement during MIR traversal. + for Mapping { term, .. } in &function_coverage_info.mappings { + if let &CovTerm::Expression(id) = term { + expressions_seen.remove(id); + } + } + Self { function_coverage_info, is_used, counters_seen: BitSet::new_empty(num_counters), - expressions: IndexVec::from_elem_n(None, num_expressions), + expressions_seen, } } @@ -76,35 +87,10 @@ impl<'tcx> FunctionCoverage<'tcx> { self.counters_seen.insert(id); } - /// Adds information about a coverage expression. + /// Marks an expression ID as having been seen in an expression-used statement. #[instrument(level = "debug", skip(self))] - pub(crate) fn add_counter_expression( - &mut self, - expression_id: ExpressionId, - lhs: CovTerm, - op: Op, - rhs: CovTerm, - ) { - debug_assert!( - expression_id.as_usize() < self.expressions.len(), - "expression_id {} is out of range for expressions.len() = {} - for {:?}", - expression_id.as_usize(), - self.expressions.len(), - self, - ); - - let expression = Expression { lhs, op, rhs }; - let slot = &mut self.expressions[expression_id]; - match slot { - None => *slot = Some(expression), - // If this expression ID slot has already been filled, it should - // contain identical information. - Some(ref previous_expression) => assert_eq!( - previous_expression, &expression, - "add_counter_expression: expression for id changed" - ), - } + pub(crate) fn mark_expression_id_seen(&mut self, id: ExpressionId) { + self.expressions_seen.insert(id); } /// Identify expressions that will always have a value of zero, and note @@ -125,13 +111,13 @@ impl<'tcx> FunctionCoverage<'tcx> { // and then update the set of always-zero expressions if necessary. // (By construction, expressions can only refer to other expressions // that have lower IDs, so one pass is sufficient.) - for (id, maybe_expression) in self.expressions.iter_enumerated() { - let Some(expression) = maybe_expression else { - // If an expression is missing, it must have been optimized away, + for (id, expression) in self.function_coverage_info.expressions.iter_enumerated() { + if !self.expressions_seen.contains(id) { + // If an expression was not seen, it must have been optimized away, // so any operand that refers to it can be replaced with zero. zero_expressions.insert(id); continue; - }; + } // We don't need to simplify the actual expression data in the // expressions list; we can just simplify a temporary copy and then @@ -197,7 +183,7 @@ impl<'tcx> FunctionCoverage<'tcx> { // Expression IDs are indices into `self.expressions`, and on the LLVM // side they will be treated as indices into `counter_expressions`, so // the two vectors should correspond 1:1. - assert_eq!(self.expressions.len(), counter_expressions.len()); + assert_eq!(self.function_coverage_info.expressions.len(), counter_expressions.len()); let counter_regions = self.counter_regions(zero_expressions); @@ -217,27 +203,16 @@ impl<'tcx> FunctionCoverage<'tcx> { _ => Counter::from_term(operand), }; - self.expressions + self.function_coverage_info + .expressions .iter() - .map(|expression| match expression { - None => { - // This expression ID was allocated, but we never saw the - // actual expression, so it must have been optimized out. - // Replace it with a dummy expression, and let LLVM take - // care of omitting it from the expression list. - CounterExpression::DUMMY - } - &Some(Expression { lhs, op, rhs, .. }) => { - // Convert the operands and operator as normal. - CounterExpression::new( - counter_from_operand(lhs), - match op { - Op::Add => ExprKind::Add, - Op::Subtract => ExprKind::Subtract, - }, - counter_from_operand(rhs), - ) - } + .map(|&Expression { lhs, op, rhs }| CounterExpression { + lhs: counter_from_operand(lhs), + kind: match op { + Op::Add => ExprKind::Add, + Op::Subtract => ExprKind::Subtract, + }, + rhs: counter_from_operand(rhs), }) .collect::>() } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 14332927c8db..f6bc4783564a 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -145,8 +145,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { ); bx.instrprof_increment(fn_name, hash, num_counters, index); } - CoverageKind::Expression { id, lhs, op, rhs } => { - func_coverage.add_counter_expression(id, lhs, op, rhs); + CoverageKind::ExpressionUsed { id } => { + func_coverage.mark_expression_id_seen(id); } } } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 2587a6eae1aa..db578854fdcf 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -1,5 +1,6 @@ //! Metadata from source code coverage analysis and instrumentation. +use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_span::Symbol; @@ -68,14 +69,16 @@ pub enum CoverageKind { /// If this statement does not survive MIR optimizations, any mappings that /// refer to this counter can have those references simplified to zero. CounterIncrement { id: CounterId }, - Expression { - /// ID of this coverage-counter expression within its enclosing function. - /// Other expressions in the same function can refer to it as an operand. - id: ExpressionId, - lhs: CovTerm, - op: Op, - rhs: CovTerm, - }, + + /// Marks the point in MIR control-flow represented by a coverage expression. + /// + /// If this statement does not survive MIR optimizations, any mappings that + /// refer to this expression can have those references simplified to zero. + /// + /// (This is only inserted for expression IDs that are directly used by + /// mappings. Intermediate expressions with no direct mappings are + /// retained/zeroed based on whether they are transitively used.) + ExpressionUsed { id: ExpressionId }, } impl Debug for CoverageKind { @@ -83,17 +86,7 @@ impl Debug for CoverageKind { use CoverageKind::*; match self { CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()), - Expression { id, lhs, op, rhs } => write!( - fmt, - "Expression({:?}) = {:?} {} {:?}", - id.index(), - lhs, - match op { - Op::Add => "+", - Op::Subtract => "-", - }, - rhs, - ), + ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()), } } } @@ -135,6 +128,14 @@ impl Op { } } +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct Expression { + pub lhs: CovTerm, + pub op: Op, + pub rhs: CovTerm, +} + #[derive(Clone, Debug)] #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Mapping { @@ -157,7 +158,7 @@ pub struct Mapping { pub struct FunctionCoverageInfo { pub function_source_hash: u64, pub num_counters: usize, - pub num_expressions: usize, + pub expressions: IndexVec, pub mappings: Vec, } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 11269e749f86..3b3b61e4e21d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -504,8 +504,11 @@ fn write_function_coverage_info( function_coverage_info: &coverage::FunctionCoverageInfo, w: &mut dyn io::Write, ) -> io::Result<()> { - let coverage::FunctionCoverageInfo { mappings, .. } = function_coverage_info; + let coverage::FunctionCoverageInfo { expressions, mappings, .. } = function_coverage_info; + for (id, expression) in expressions.iter_enumerated() { + writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; + } for coverage::Mapping { term, code_region } in mappings { writeln!(w, "{INDENT}coverage {term:?} => {code_region:?};")?; } diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 4140d402c753..a83ccf8fc3c2 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -19,7 +19,7 @@ const NESTED_INDENT: &str = " "; #[derive(Clone)] pub(super) enum BcbCounter { Counter { id: CounterId }, - Expression { id: ExpressionId, lhs: CovTerm, op: Op, rhs: CovTerm }, + Expression { id: ExpressionId }, } impl BcbCounter { @@ -39,17 +39,7 @@ impl Debug for BcbCounter { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()), - Self::Expression { id, lhs, op, rhs } => write!( - fmt, - "Expression({:?}) = {:?} {} {:?}", - id.index(), - lhs, - match op { - Op::Add => "+", - Op::Subtract => "-", - }, - rhs, - ), + Self::Expression { id } => write!(fmt, "Expression({:?})", id.index()), } } } @@ -58,7 +48,6 @@ impl Debug for BcbCounter { /// associated with nodes/edges in the BCB graph. pub(super) struct CoverageCounters { next_counter_id: CounterId, - next_expression_id: ExpressionId, /// Coverage counters/expressions that are associated with individual BCBs. bcb_counters: IndexVec>, @@ -69,10 +58,9 @@ pub(super) struct CoverageCounters { /// Only used by debug assertions, to verify that BCBs with incoming edge /// counters do not have their own physical counters (expressions are allowed). bcb_has_incoming_edge_counters: BitSet, - /// Expression nodes that are not directly associated with any particular - /// BCB/edge, but are needed as operands to more complex expressions. - /// These are always [`BcbCounter::Expression`]. - pub(super) intermediate_expressions: Vec, + /// Table of expression data, associating each expression ID with its + /// corresponding operator (+ or -) and its LHS/RHS operands. + expressions: IndexVec, } impl CoverageCounters { @@ -81,12 +69,10 @@ impl CoverageCounters { Self { next_counter_id: CounterId::START, - next_expression_id: ExpressionId::START, - bcb_counters: IndexVec::from_elem_n(None, num_bcbs), bcb_edge_counters: FxHashMap::default(), bcb_has_incoming_edge_counters: BitSet::new_empty(num_bcbs), - intermediate_expressions: Vec::new(), + expressions: IndexVec::new(), } } @@ -107,8 +93,8 @@ impl CoverageCounters { } fn make_expression(&mut self, lhs: CovTerm, op: Op, rhs: CovTerm) -> BcbCounter { - let id = self.next_expression(); - BcbCounter::Expression { id, lhs, op, rhs } + let id = self.expressions.push(Expression { lhs, op, rhs }); + BcbCounter::Expression { id } } /// Counter IDs start from one and go up. @@ -118,20 +104,13 @@ impl CoverageCounters { next } - /// Expression IDs start from 0 and go up. - /// (Counter IDs and Expression IDs are distinguished by the `Operand` enum.) - fn next_expression(&mut self) -> ExpressionId { - let next = self.next_expression_id; - self.next_expression_id = self.next_expression_id + 1; - next - } - pub(super) fn num_counters(&self) -> usize { self.next_counter_id.as_usize() } + #[cfg(test)] pub(super) fn num_expressions(&self) -> usize { - self.next_expression_id.as_usize() + self.expressions.len() } fn set_bcb_counter( @@ -207,6 +186,10 @@ impl CoverageCounters { ) -> impl Iterator + '_ { self.bcb_edge_counters.drain() } + + pub(super) fn take_expressions(&mut self) -> IndexVec { + std::mem::take(&mut self.expressions) + } } /// Traverse the `CoverageGraph` and add either a `Counter` or `Expression` to every BCB, to be @@ -333,7 +316,6 @@ impl<'a> MakeBcbCounters<'a> { ); debug!(" [new intermediate expression: {:?}]", intermediate_expression); let intermediate_expression_operand = intermediate_expression.as_term(); - self.coverage_counters.intermediate_expressions.push(intermediate_expression); some_sumup_counter_operand.replace(intermediate_expression_operand); } } @@ -446,7 +428,6 @@ impl<'a> MakeBcbCounters<'a> { intermediate_expression ); let intermediate_expression_operand = intermediate_expression.as_term(); - self.coverage_counters.intermediate_expressions.push(intermediate_expression); some_sumup_edge_counter_operand.replace(intermediate_expression_operand); } } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 078123a7b7fb..df4dccf0f0b3 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -167,9 +167,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { // every coverage span has a `Counter` or `Expression` assigned to its `BasicCoverageBlock` // and all `Expression` dependencies (operands) are also generated, for any other // `BasicCoverageBlock`s not already associated with a coverage span. - // - // Intermediate expressions (used to compute other `Expression` values), which have no - // direct association with any `BasicCoverageBlock`, are accumulated inside `coverage_counters`. let bcb_has_coverage_spans = |bcb| coverage_spans.bcb_has_coverage_spans(bcb); let result = self .coverage_counters @@ -195,29 +192,16 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { // are in fact counted, even though they don't directly contribute to counting // their own independent code region's coverage. self.inject_indirect_counters(); - - // Intermediate expressions will be injected as the final step, after generating - // debug output, if any. - //////////////////////////////////////////////////// }; if let Err(e) = result { bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e.message) }; - //////////////////////////////////////////////////// - // Finally, inject the intermediate expressions collected along the way. - for intermediate_expression in &self.coverage_counters.intermediate_expressions { - inject_intermediate_expression( - self.mir_body, - self.make_mir_coverage_kind(intermediate_expression), - ); - } - self.mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { function_source_hash: self.function_source_hash, num_counters: self.coverage_counters.num_counters(), - num_expressions: self.coverage_counters.num_expressions(), + expressions: self.coverage_counters.take_expressions(), mappings: std::mem::take(&mut self.mappings), })); } @@ -304,10 +288,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { inject_to_bb, ); } - BcbCounter::Expression { .. } => inject_intermediate_expression( - self.mir_body, - self.make_mir_coverage_kind(&counter_kind), - ), + // Experessions with no associated spans don't need to inject a statement. + BcbCounter::Expression { .. } => {} } } } @@ -330,9 +312,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind { match *counter_kind { BcbCounter::Counter { id } => CoverageKind::CounterIncrement { id }, - BcbCounter::Expression { id, lhs, op, rhs } => { - CoverageKind::Expression { id, lhs, op, rhs } - } + BcbCounter::Expression { id } => CoverageKind::ExpressionUsed { id }, } } } @@ -371,20 +351,6 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb data.statements.insert(0, statement); } -// Non-code expressions are injected into the coverage map, without generating executable code. -fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: CoverageKind) { - debug_assert!(matches!(expression, CoverageKind::Expression { .. })); - debug!(" injecting non-code expression {:?}", expression); - let inject_in_bb = mir::START_BLOCK; - let data = &mut mir_body[inject_in_bb]; - let source_info = data.terminator().source_info; - let statement = Statement { - source_info, - kind: StatementKind::Coverage(Box::new(Coverage { kind: expression })), - }; - data.statements.push(statement); -} - /// Convert the Span into its file name, start line and column, and end line and column fn make_code_region( source_map: &SourceMap, diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 487d22823644..795cbce963d1 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -656,7 +656,7 @@ fn test_make_bcb_counters() { coverage_counters .make_bcb_counters(&mut basic_coverage_blocks, bcb_has_coverage_spans) .expect("should be Ok"); - assert_eq!(coverage_counters.intermediate_expressions.len(), 0); + assert_eq!(coverage_counters.num_expressions(), 0); let_bcb!(1); assert_eq!( diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index 5459ecd98c5f..f5c59c84693f 100644 --- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -7,6 +7,8 @@ let mut _2: bool; let mut _3: !; ++ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) }; ++ coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Subtract, rhs: Counter(1) }; + coverage Counter(0) => /the/src/instrument_coverage.rs:11:1 - 11:11; + coverage Expression(0) => /the/src/instrument_coverage.rs:12:5 - 13:17; + coverage Expression(1) => /the/src/instrument_coverage.rs:14:13 - 14:18; @@ -19,7 +21,7 @@ } bb1: { -+ Coverage::Expression(0) = Counter(0) + Counter(1); ++ Coverage::ExpressionUsed(0); falseUnwind -> [real: bb2, unwind: bb6]; } @@ -33,7 +35,7 @@ } bb4: { -+ Coverage::Expression(1) = Expression(0) - Counter(1); ++ Coverage::ExpressionUsed(1); _0 = const (); StorageDead(_2); return; From 753caf292c10a172b45e749047221c31d35d76eb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 23 Sep 2023 13:17:05 +1000 Subject: [PATCH 81/94] coverage: Update docs for `StatementKind::Coverage` This new description reflects the changes made in this PR, and should hopefully be more useful to non-coverage developers who need to care about coverage statements. --- compiler/rustc_middle/src/mir/syntax.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 77b26e0a4cde..7a645fb5d62b 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -361,11 +361,16 @@ pub enum StatementKind<'tcx> { /// Disallowed after drop elaboration. AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance), - /// Marks the start of a "coverage region", injected with '-Cinstrument-coverage'. A - /// `Coverage` statement carries metadata about the coverage region, used to inject a coverage - /// map into the binary. If `Coverage::kind` is a `Counter`, the statement also generates - /// executable code, to increment a counter variable at runtime, each time the code region is - /// executed. + /// Carries control-flow-sensitive information injected by `-Cinstrument-coverage`, + /// such as where to generate physical coverage-counter-increments during codegen. + /// + /// Coverage statements are used in conjunction with the coverage mappings and other + /// information stored in the function's + /// [`mir::Body::function_coverage_info`](crate::mir::Body::function_coverage_info). + /// (For inlined MIR, take care to look up the *original function's* coverage info.) + /// + /// Interpreters and codegen backends that don't support coverage instrumentation + /// can usually treat this as a no-op. Coverage(Box), /// Denotes a call to an intrinsic that does not require an unwind path and always returns. From 33da0978ac2674d046d3b01a9db33dc7f19339c6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 18 Oct 2023 12:44:47 +1100 Subject: [PATCH 82/94] coverage: Explicitly note that counter/expression IDs are function-local --- compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs | 7 +++++++ compiler/rustc_middle/src/mir/coverage.rs | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index f6bc4783564a..204a73b788a6 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -100,6 +100,13 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { #[instrument(level = "debug", skip(self))] fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) { + // Our caller should have already taken care of inlining subtleties, + // so we can assume that counter/expression IDs in this coverage + // statement are meaningful for the given instance. + // + // (Either the statement was not inlined and directly belongs to this + // instance, or it was inlined *from* this instance.) + let bx = self; let Some(function_coverage_info) = diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index db578854fdcf..08d377a8695f 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -9,6 +9,11 @@ use std::fmt::{self, Debug, Formatter}; rustc_index::newtype_index! { /// ID of a coverage counter. Values ascend from 0. /// + /// Before MIR inlining, counter IDs are local to their enclosing function. + /// After MIR inlining, coverage statements may have been inlined into + /// another function, so use the statement's source-scope to find which + /// function/instance its IDs are meaningful for. + /// /// Note that LLVM handles counter IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. #[derive(HashStable)] @@ -24,6 +29,11 @@ impl CounterId { rustc_index::newtype_index! { /// ID of a coverage-counter expression. Values ascend from 0. /// + /// Before MIR inlining, expression IDs are local to their enclosing function. + /// After MIR inlining, coverage statements may have been inlined into + /// another function, so use the statement's source-scope to find which + /// function/instance its IDs are meaningful for. + /// /// Note that LLVM handles expression IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. #[derive(HashStable)] From d0b99e3efe62b5acc107da9c84331eae6cbe5a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 17 Oct 2023 03:06:52 +0200 Subject: [PATCH 83/94] Make `#[repr(Rust)]` and `#[repr(C)]` incompatible with one another --- compiler/rustc_passes/src/check_attr.rs | 13 +++++-- compiler/rustc_passes/src/errors.rs | 9 ++++- tests/ui/repr/explicit-rust-repr-conflicts.rs | 23 +++++++++++ .../repr/explicit-rust-repr-conflicts.stderr | 39 +++++++++++++++++++ 4 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 tests/ui/repr/explicit-rust-repr-conflicts.rs create mode 100644 tests/ui/repr/explicit-rust-repr-conflicts.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9a7564cb213d..d92923e78ffe 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1767,6 +1767,7 @@ impl CheckAttrVisitor<'_> { .collect(); let mut int_reprs = 0; + let mut is_explicit_rust = false; let mut is_c = false; let mut is_simd = false; let mut is_transparent = false; @@ -1778,7 +1779,9 @@ impl CheckAttrVisitor<'_> { } match hint.name_or_empty() { - sym::Rust => {} + sym::Rust => { + is_explicit_rust = true; + } sym::C => { is_c = true; match target { @@ -1888,12 +1891,16 @@ impl CheckAttrVisitor<'_> { // Error on repr(transparent, ). if is_transparent && hints.len() > 1 { - let hint_spans: Vec<_> = hint_spans.clone().collect(); + let hint_spans = hint_spans.clone().collect(); self.tcx.sess.emit_err(errors::TransparentIncompatible { hint_spans, target: target.to_string(), }); } + if is_explicit_rust && (int_reprs > 0 || is_c || is_simd) { + let hint_spans = hint_spans.clone().collect(); + self.tcx.sess.emit_err(errors::ReprConflicting { hint_spans }); + } // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8) if (int_reprs > 1) || (is_simd && is_c) @@ -1910,7 +1917,7 @@ impl CheckAttrVisitor<'_> { CONFLICTING_REPR_HINTS, hir_id, hint_spans.collect::>(), - errors::ReprConflicting, + errors::ReprConflictingLint, ); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index bcf5abbfe7d9..f4a6bf017d65 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -558,9 +558,16 @@ pub struct ReprIdent { pub span: Span, } +#[derive(Diagnostic)] +#[diag(passes_repr_conflicting, code = "E0566")] +pub struct ReprConflicting { + #[primary_span] + pub hint_spans: Vec, +} + #[derive(LintDiagnostic)] #[diag(passes_repr_conflicting, code = "E0566")] -pub struct ReprConflicting; +pub struct ReprConflictingLint; #[derive(Diagnostic)] #[diag(passes_used_static)] diff --git a/tests/ui/repr/explicit-rust-repr-conflicts.rs b/tests/ui/repr/explicit-rust-repr-conflicts.rs new file mode 100644 index 000000000000..22dd12d316ac --- /dev/null +++ b/tests/ui/repr/explicit-rust-repr-conflicts.rs @@ -0,0 +1,23 @@ +#[repr(C, Rust)] //~ ERROR conflicting representation hints +struct S { + a: i32, +} + + +#[repr(Rust)] //~ ERROR conflicting representation hints +#[repr(C)] +struct T { + a: i32, +} + +#[repr(Rust, u64)] //~ ERROR conflicting representation hints +enum U { + V, +} + +#[repr(Rust, simd)] +//~^ ERROR conflicting representation hints +//~| ERROR SIMD types are experimental and possibly buggy +struct F32x4(f32, f32, f32, f32); + +fn main() {} diff --git a/tests/ui/repr/explicit-rust-repr-conflicts.stderr b/tests/ui/repr/explicit-rust-repr-conflicts.stderr new file mode 100644 index 000000000000..7126da574b63 --- /dev/null +++ b/tests/ui/repr/explicit-rust-repr-conflicts.stderr @@ -0,0 +1,39 @@ +error[E0658]: SIMD types are experimental and possibly buggy + --> $DIR/explicit-rust-repr-conflicts.rs:18:1 + | +LL | #[repr(Rust, simd)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(repr_simd)]` to the crate attributes to enable + +error[E0566]: conflicting representation hints + --> $DIR/explicit-rust-repr-conflicts.rs:1:8 + | +LL | #[repr(C, Rust)] + | ^ ^^^^ + +error[E0566]: conflicting representation hints + --> $DIR/explicit-rust-repr-conflicts.rs:7:8 + | +LL | #[repr(Rust)] + | ^^^^ +LL | #[repr(C)] + | ^ + +error[E0566]: conflicting representation hints + --> $DIR/explicit-rust-repr-conflicts.rs:13:8 + | +LL | #[repr(Rust, u64)] + | ^^^^ ^^^ + +error[E0566]: conflicting representation hints + --> $DIR/explicit-rust-repr-conflicts.rs:18:8 + | +LL | #[repr(Rust, simd)] + | ^^^^ ^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0566, E0658. +For more information about an error, try `rustc --explain E0566`. From c1c5a1d69ace8bdfd34f449bdb00797f1fc723cc Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 18 Oct 2023 16:34:04 +0000 Subject: [PATCH 84/94] Only check in a single place if a pass is enabled. --- compiler/rustc_mir_transform/src/lib.rs | 2 +- .../rustc_mir_transform/src/pass_manager.rs | 33 ++++++++++++------- tests/mir-opt/inline/unit_test.rs | 19 +++++++++++ 3 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 tests/mir-opt/inline/unit_test.rs diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 011369747300..d579420ecb83 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -383,7 +383,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & let is_fn_like = tcx.def_kind(def).is_fn_like(); if is_fn_like { // Do not compute the mir call graph without said call graph actually being used. - if inline::Inline.is_enabled(&tcx.sess) { + if pm::should_run_pass(tcx, &inline::Inline) { tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def.to_def_id())); } } diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 5abb2f3d0412..a8aba29adcd1 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -83,6 +83,25 @@ pub fn run_passes<'tcx>( run_passes_inner(tcx, body, passes, phase_change, true); } +pub fn should_run_pass<'tcx, P>(tcx: TyCtxt<'tcx>, pass: &P) -> bool +where + P: MirPass<'tcx> + ?Sized, +{ + let name = pass.name(); + + let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; + let overridden = + overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| { + trace!( + pass = %name, + "{} as requested by flag", + if *polarity { "Running" } else { "Not running" }, + ); + *polarity + }); + overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) +} + fn run_passes_inner<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, @@ -100,19 +119,9 @@ fn run_passes_inner<'tcx>( for pass in passes { let name = pass.name(); - let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map( - |(_name, polarity)| { - trace!( - pass = %name, - "{} as requested by flag", - if *polarity { "Running" } else { "Not running" }, - ); - *polarity - }, - ); - if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) { + if !should_run_pass(tcx, *pass) { continue; - } + }; let dump_enabled = pass.is_mir_dump_enabled(); diff --git a/tests/mir-opt/inline/unit_test.rs b/tests/mir-opt/inline/unit_test.rs new file mode 100644 index 000000000000..0d877bb10b42 --- /dev/null +++ b/tests/mir-opt/inline/unit_test.rs @@ -0,0 +1,19 @@ +// Check that `-Zmir-enable-passes=+Inline` does not ICE because of stolen MIR. +// unit-test: Inline +// skip-filecheck +#![crate_type = "lib"] + +// Randomize `def_path_hash` by defining them under a module with different names +macro_rules! emit { + ($($m:ident)*) => {$( + pub mod $m { + pub fn main() { + let func = || 123u8; + func(); + } + } + )*}; +} + +// Increase the chance of triggering the bug +emit!(m00 m01 m02 m03 m04 m05 m06 m07 m08 m09 m10 m11 m12 m13 m14 m15 m16 m17 m18 m19); From 973d5895829e424e9a8df9cf4de08682760752c8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 6 Oct 2023 19:40:16 +0000 Subject: [PATCH 85/94] Bump COINDUCTIVE_OVERLAP_IN_COHERENCE --- compiler/rustc_lint_defs/src/builtin.rs | 4 +-- ...rn-when-cycle-is-error-in-coherence.stderr | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 96a98393fb28..c8d42937f7bd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4449,11 +4449,11 @@ declare_lint! { /// on itself), the blanket impl is not considered to hold for `u8`. This will /// change in a future release. pub COINDUCTIVE_OVERLAP_IN_COHERENCE, - Warn, + Deny, "impls that are not considered to overlap may be considered to \ overlap in the future", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #114040 ", }; } diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr index ecc73d994f9a..4f32639a6310 100644 --- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr @@ -24,3 +24,28 @@ LL | #![deny(coinductive_overlap_in_coherence)] error: aborting due to previous error +Future incompatibility report: Future breakage diagnostic: +error: implementations of `PartialEq>` for `Interval<_>` will conflict in the future + --> $DIR/warn-when-cycle-is-error-in-coherence.rs:13:1 + | +LL | #[derive(PartialEq, Default)] + | --------- the second impl is here +... +LL | / impl PartialEq for Interval +LL | | +LL | | +LL | | where +LL | | T: Borrow, +LL | | Q: ?Sized + PartialOrd, + | |___________________________^ the first impl is here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #114040 + = note: impls that are not considered to overlap may be considered to overlap in the future + = note: `Interval<_>: PartialOrd` may be considered to hold in future releases, causing the impls to overlap +note: the lint level is defined here + --> $DIR/warn-when-cycle-is-error-in-coherence.rs:1:9 + | +LL | #![deny(coinductive_overlap_in_coherence)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + From ea73f10867e104ec5bb0ef2e83c2e330adc16758 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 12 Oct 2023 14:00:00 +0000 Subject: [PATCH 86/94] Don't ICE when encountering unresolved regions in fully_resolve --- compiler/rustc_infer/src/infer/mod.rs | 27 ++++++++++++++----- compiler/rustc_lint/src/async_fn_in_trait.rs | 1 - .../in-trait/unconstrained-impl-region.rs | 19 +++++++++++++ .../in-trait/unconstrained-impl-region.stderr | 9 +++++++ 4 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 tests/ui/async-await/in-trait/unconstrained-impl-region.rs create mode 100644 tests/ui/async-await/in-trait/unconstrained-impl-region.stderr diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index aeb3177af027..8ffcf1fce9cf 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -36,7 +36,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtx use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid}; use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef}; use rustc_span::symbol::Symbol; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::cell::{Cell, RefCell}; use std::fmt; @@ -1422,12 +1422,25 @@ impl<'tcx> InferCtxt<'tcx> { /// This method is idempotent, but it not typically not invoked /// except during the writeback phase. pub fn fully_resolve>>(&self, value: T) -> FixupResult<'tcx, T> { - let value = resolve::fully_resolve(self, value); - assert!( - value.as_ref().map_or(true, |value| !value.has_infer()), - "`{value:?}` is not fully resolved" - ); - value + match resolve::fully_resolve(self, value) { + Ok(value) => { + if value.has_non_region_infer() { + bug!("`{value:?}` is not fully resolved"); + } + if value.has_infer_regions() { + let guar = self + .tcx + .sess + .delay_span_bug(DUMMY_SP, format!("`{value:?}` is not fully resolved")); + Ok(self.tcx.fold_regions(value, |re, _| { + if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re } + })) + } else { + Ok(value) + } + } + Err(e) => Err(e), + } } // Instantiates the bound variables in a given binder with fresh inference diff --git a/compiler/rustc_lint/src/async_fn_in_trait.rs b/compiler/rustc_lint/src/async_fn_in_trait.rs index 2a49a003da11..512136473617 100644 --- a/compiler/rustc_lint/src/async_fn_in_trait.rs +++ b/compiler/rustc_lint/src/async_fn_in_trait.rs @@ -58,7 +58,6 @@ declare_lint! { /// /// /// ```rust - /// # #![feature(return_position_impl_trait_in_trait)] /// use core::future::Future; /// pub trait Trait { /// fn method(&self) -> impl Future + Send { async {} } diff --git a/tests/ui/async-await/in-trait/unconstrained-impl-region.rs b/tests/ui/async-await/in-trait/unconstrained-impl-region.rs new file mode 100644 index 000000000000..c06f9f005f19 --- /dev/null +++ b/tests/ui/async-await/in-trait/unconstrained-impl-region.rs @@ -0,0 +1,19 @@ +// edition: 2021 + +pub(crate) trait Inbox { + async fn next(self) -> M; +} + +pub(crate) trait Actor: Sized { + type Message; + + async fn on_mount(self, _: impl Inbox); +} + +impl<'a> Actor for () { +//~^ ERROR the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + type Message = &'a (); + async fn on_mount(self, _: impl Inbox<&'a ()>) {} +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr new file mode 100644 index 000000000000..2cb0da2e8bc0 --- /dev/null +++ b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/unconstrained-impl-region.rs:13:6 + | +LL | impl<'a> Actor for () { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. From 60c95448c378fd25ecd358454b9c5f763c294c19 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 18 Oct 2023 21:55:15 +0000 Subject: [PATCH 87/94] Use v0.0.0 in compiler crates --- Cargo.lock | 10 +++++----- compiler/rustc_fluent_macro/Cargo.toml | 2 +- compiler/rustc_hir_typeck/Cargo.toml | 2 +- compiler/rustc_lexer/Cargo.toml | 2 +- compiler/rustc_macros/Cargo.toml | 2 +- compiler/rustc_transmute/Cargo.toml | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c8e7665337fb..aa2f9c4147e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3839,7 +3839,7 @@ dependencies = [ [[package]] name = "rustc_fluent_macro" -version = "0.1.0" +version = "0.0.0" dependencies = [ "annotate-snippets", "fluent-bundle", @@ -3915,7 +3915,7 @@ dependencies = [ [[package]] name = "rustc_hir_typeck" -version = "0.1.0" +version = "0.0.0" dependencies = [ "rustc_ast", "rustc_attr", @@ -4043,7 +4043,7 @@ dependencies = [ [[package]] name = "rustc_lexer" -version = "0.1.0" +version = "0.0.0" dependencies = [ "expect-test", "unicode-properties", @@ -4112,7 +4112,7 @@ dependencies = [ [[package]] name = "rustc_macros" -version = "0.1.0" +version = "0.0.0" dependencies = [ "proc-macro2", "quote", @@ -4595,7 +4595,7 @@ dependencies = [ [[package]] name = "rustc_transmute" -version = "0.1.0" +version = "0.0.0" dependencies = [ "itertools", "rustc_data_structures", diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml index f5a6585b5c68..60b8e1e3786d 100644 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ b/compiler/rustc_fluent_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_fluent_macro" -version = "0.1.0" +version = "0.0.0" edition = "2021" [lib] diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index ce91d023a0ae..0666eeee4d38 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_hir_typeck" -version = "0.1.0" +version = "0.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index 2211ac1c8a75..373a8970de83 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_lexer" -version = "0.1.0" +version = "0.0.0" license = "MIT OR Apache-2.0" edition = "2021" diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index 17651ce95987..6e7e19a24024 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_macros" -version = "0.1.0" +version = "0.0.0" edition = "2021" [lib] diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index aa6fe7d24196..c2b2730c328f 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_transmute" -version = "0.1.0" +version = "0.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 8d20182999a2baf711e37da276c1a4b2831dcc12 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 18 Oct 2023 23:09:17 +0000 Subject: [PATCH 88/94] Remove unused variant BinderListTy --- compiler/rustc_middle/src/ty/context.rs | 1 - compiler/rustc_type_ir/src/lib.rs | 1 - compiler/rustc_type_ir/src/sty.rs | 3 --- 3 files changed, 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 05706e331f3a..5030474d96b2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -94,7 +94,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Movability = hir::Movability; type PolyFnSig = PolyFnSig<'tcx>; type ListBinderExistentialPredicate = &'tcx List>; - type BinderListTy = Binder<'tcx, &'tcx List>>; type ListTy = &'tcx List>; type AliasTy = ty::AliasTy<'tcx>; type ParamTy = ParamTy; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 9f8d9f02ec24..51b3007723b2 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -60,7 +60,6 @@ pub trait Interner: Sized { type Movability: Clone + Debug + Hash + Ord; type PolyFnSig: Clone + DebugWithInfcx + Hash + Ord; type ListBinderExistentialPredicate: Clone + DebugWithInfcx + Hash + Ord; - type BinderListTy: Clone + DebugWithInfcx + Hash + Ord; type ListTy: Clone + Debug + Hash + Ord + IntoIterator; type AliasTy: Clone + DebugWithInfcx + Hash + Ord; type ParamTy: Clone + Debug + Hash + Ord; diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index 091b51440a6e..5ff17a48e756 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -577,7 +577,6 @@ where I::Movability: Encodable, I::PolyFnSig: Encodable, I::ListBinderExistentialPredicate: Encodable, - I::BinderListTy: Encodable, I::ListTy: Encodable, I::AliasTy: Encodable, I::ParamTy: Encodable, @@ -692,7 +691,6 @@ where I::Movability: Decodable, I::PolyFnSig: Decodable, I::ListBinderExistentialPredicate: Decodable, - I::BinderListTy: Decodable, I::ListTy: Decodable, I::AliasTy: Decodable, I::ParamTy: Decodable, @@ -757,7 +755,6 @@ where I::Region: HashStable, I::Movability: HashStable, I::Mutability: HashStable, - I::BinderListTy: HashStable, I::ListTy: HashStable, I::AliasTy: HashStable, I::BoundTy: HashStable, From 189e6a833eaa370ce2c66bd451f536e8ee7e7f14 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 18 Oct 2023 23:29:28 +0000 Subject: [PATCH 89/94] Some renaming nits for rustc_type_ir --- compiler/rustc_middle/src/ty/context.rs | 28 +++++------ compiler/rustc_type_ir/src/lib.rs | 33 ++++++++---- .../rustc_type_ir/src/structural_impls.rs | 4 +- compiler/rustc_type_ir/src/sty.rs | 50 +++++++++---------- 4 files changed, 62 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5030474d96b2..82c7f8ab4867 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -80,42 +80,40 @@ use std::ops::{Bound, Deref}; #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Interner for TyCtxt<'tcx> { - type AdtDef = ty::AdtDef<'tcx>; - type GenericArgsRef = ty::GenericArgsRef<'tcx>; - type GenericArg = ty::GenericArg<'tcx>; type DefId = DefId; + type AdtDef = ty::AdtDef<'tcx>; + type GenericArgs = ty::GenericArgsRef<'tcx>; + type GenericArg = ty::GenericArg<'tcx>; type Binder = Binder<'tcx, T>; - type Ty = Ty<'tcx>; - type Const = ty::Const<'tcx>; - type Region = Region<'tcx>; type Predicate = Predicate<'tcx>; + type PredicateKind = ty::PredicateKind<'tcx>; type TypeAndMut = TypeAndMut<'tcx>; type Mutability = hir::Mutability; type Movability = hir::Movability; - type PolyFnSig = PolyFnSig<'tcx>; - type ListBinderExistentialPredicate = &'tcx List>; - type ListTy = &'tcx List>; + type Ty = Ty<'tcx>; + type Tys = &'tcx List>; type AliasTy = ty::AliasTy<'tcx>; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; - type PlaceholderType = ty::PlaceholderType; + type PlaceholderTy = ty::PlaceholderType; type InferTy = InferTy; type ErrorGuaranteed = ErrorGuaranteed; - type PredicateKind = ty::PredicateKind<'tcx>; + type BoundExistentialPredicates = &'tcx List>; + type PolyFnSig = PolyFnSig<'tcx>; type AllocId = crate::mir::interpret::AllocId; - + type Const = ty::Const<'tcx>; type InferConst = ty::InferConst<'tcx>; type AliasConst = ty::UnevaluatedConst<'tcx>; + type PlaceholderConst = ty::PlaceholderConst<'tcx>; type ParamConst = ty::ParamConst; type BoundConst = ty::BoundVar; - type PlaceholderConst = ty::PlaceholderConst<'tcx>; type ValueConst = ty::ValTree<'tcx>; type ExprConst = ty::Expr<'tcx>; - + type Region = Region<'tcx>; type EarlyBoundRegion = ty::EarlyBoundRegion; type BoundRegion = ty::BoundRegion; type FreeRegion = ty::FreeRegion; - type RegionVid = ty::RegionVid; + type InferRegion = ty::RegionVid; type PlaceholderRegion = ty::PlaceholderRegion; fn ty_and_mut_to_parts( diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 51b3007723b2..6b1f0bae91ad 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -42,34 +42,43 @@ pub use ty_info::*; pub trait HashStableContext {} pub trait Interner: Sized { + type DefId: Clone + Debug + Hash + Ord; type AdtDef: Clone + Debug + Hash + Ord; - type GenericArgsRef: Clone + + type GenericArgs: Clone + DebugWithInfcx + Hash + Ord + IntoIterator; type GenericArg: Clone + DebugWithInfcx + Hash + Ord; - type DefId: Clone + Debug + Hash + Ord; + type Binder; - type Ty: Clone + DebugWithInfcx + Hash + Ord; - type Const: Clone + DebugWithInfcx + Hash + Ord; - type Region: Clone + DebugWithInfcx + Hash + Ord; + + // Predicates type Predicate; + type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; + type TypeAndMut: Clone + Debug + Hash + Ord; type Mutability: Clone + Debug + Hash + Ord; type Movability: Clone + Debug + Hash + Ord; - type PolyFnSig: Clone + DebugWithInfcx + Hash + Ord; - type ListBinderExistentialPredicate: Clone + DebugWithInfcx + Hash + Ord; - type ListTy: Clone + Debug + Hash + Ord + IntoIterator; + + // Kinds of tys + type Ty: Clone + DebugWithInfcx + Hash + Ord; + type Tys: Clone + Debug + Hash + Ord + IntoIterator; type AliasTy: Clone + DebugWithInfcx + Hash + Ord; type ParamTy: Clone + Debug + Hash + Ord; type BoundTy: Clone + Debug + Hash + Ord; - type PlaceholderType: Clone + Debug + Hash + Ord; + type PlaceholderTy: Clone + Debug + Hash + Ord; type InferTy: Clone + DebugWithInfcx + Hash + Ord; + + // Things stored inside of tys type ErrorGuaranteed: Clone + Debug + Hash + Ord; - type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; + type BoundExistentialPredicates: Clone + DebugWithInfcx + Hash + Ord; + type PolyFnSig: Clone + DebugWithInfcx + Hash + Ord; type AllocId: Clone + Debug + Hash + Ord; + // Kinds of consts + type Const: Clone + DebugWithInfcx + Hash + Ord; type InferConst: Clone + DebugWithInfcx + Hash + Ord; type AliasConst: Clone + DebugWithInfcx + Hash + Ord; type PlaceholderConst: Clone + Debug + Hash + Ord; @@ -78,10 +87,12 @@ pub trait Interner: Sized { type ValueConst: Clone + Debug + Hash + Ord; type ExprConst: Clone + DebugWithInfcx + Hash + Ord; + // Kinds of regions + type Region: Clone + DebugWithInfcx + Hash + Ord; type EarlyBoundRegion: Clone + Debug + Hash + Ord; type BoundRegion: Clone + Debug + Hash + Ord; type FreeRegion: Clone + Debug + Hash + Ord; - type RegionVid: Clone + DebugWithInfcx + Hash + Ord; + type InferRegion: Clone + DebugWithInfcx + Hash + Ord; type PlaceholderRegion: Clone + Debug + Hash + Ord; fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability); diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 08af96ea15f0..93b3674b51a5 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -208,7 +208,7 @@ impl, Ix: Idx> TypeVisitable for IndexVec { fn universe_of_ty(&self, ty: I::InferTy) -> Option; - fn universe_of_lt(&self, lt: I::RegionVid) -> Option; + fn universe_of_lt(&self, lt: I::InferRegion) -> Option; fn universe_of_ct(&self, ct: I::InferConst) -> Option; } @@ -219,7 +219,7 @@ impl InferCtxtLike for core::convert::Infallible { fn universe_of_ct(&self, _ct: ::InferConst) -> Option { match *self {} } - fn universe_of_lt(&self, _lt: ::RegionVid) -> Option { + fn universe_of_lt(&self, _lt: ::InferRegion) -> Option { match *self {} } } diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index 5ff17a48e756..991b8e1589bc 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -79,7 +79,7 @@ pub enum TyKind { /// /// Note that generic parameters in fields only get lazily substituted /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, args))`. - Adt(I::AdtDef, I::GenericArgsRef), + Adt(I::AdtDef, I::GenericArgs), /// An unsized FFI type that is opaque to Rust. Written as `extern type T`. Foreign(I::DefId), @@ -111,7 +111,7 @@ pub enum TyKind { /// fn foo() -> i32 { 1 } /// let bar = foo; // bar: fn() -> i32 {foo} /// ``` - FnDef(I::DefId, I::GenericArgsRef), + FnDef(I::DefId, I::GenericArgs), /// A pointer to a function. Written as `fn() -> i32`. /// @@ -127,21 +127,21 @@ pub enum TyKind { FnPtr(I::PolyFnSig), /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. - Dynamic(I::ListBinderExistentialPredicate, I::Region, DynKind), + Dynamic(I::BoundExistentialPredicates, I::Region, DynKind), /// The anonymous type of a closure. Used to represent the type of `|a| a`. /// /// Closure args contain both the - potentially substituted - generic parameters /// of its parent and some synthetic parameters. See the documentation for /// `ClosureArgs` for more details. - Closure(I::DefId, I::GenericArgsRef), + Closure(I::DefId, I::GenericArgs), /// The anonymous type of a generator. Used to represent the type of /// `|a| yield a`. /// /// For more info about generator args, visit the documentation for /// `GeneratorArgs`. - Generator(I::DefId, I::GenericArgsRef, I::Movability), + Generator(I::DefId, I::GenericArgs, I::Movability), /// A type representing the types stored inside a generator. /// This should only appear as part of the `GeneratorArgs`. @@ -167,13 +167,13 @@ pub enum TyKind { /// } /// # ; /// ``` - GeneratorWitness(I::DefId, I::GenericArgsRef), + GeneratorWitness(I::DefId, I::GenericArgs), /// The never type `!`. Never, /// A tuple type. For example, `(i32, bool)`. - Tuple(I::ListTy), + Tuple(I::Tys), /// A projection, opaque type, weak type alias, or inherent associated type. /// All of these types are represented as pairs of def-id and args, and can @@ -209,7 +209,7 @@ pub enum TyKind { /// to the bound variable's index from the binder from which it was instantiated), /// and `U` is the universe index in which it is instantiated, or totally omitted /// if the universe index is zero. - Placeholder(I::PlaceholderType), + Placeholder(I::PlaceholderTy), /// A type variable used during type checking. /// @@ -567,7 +567,7 @@ impl Encodable for TyKind where I::ErrorGuaranteed: Encodable, I::AdtDef: Encodable, - I::GenericArgsRef: Encodable, + I::GenericArgs: Encodable, I::DefId: Encodable, I::Ty: Encodable, I::Const: Encodable, @@ -576,12 +576,12 @@ where I::Mutability: Encodable, I::Movability: Encodable, I::PolyFnSig: Encodable, - I::ListBinderExistentialPredicate: Encodable, - I::ListTy: Encodable, + I::BoundExistentialPredicates: Encodable, + I::Tys: Encodable, I::AliasTy: Encodable, I::ParamTy: Encodable, I::BoundTy: Encodable, - I::PlaceholderType: Encodable, + I::PlaceholderTy: Encodable, I::InferTy: Encodable, I::PredicateKind: Encodable, I::AllocId: Encodable, @@ -681,7 +681,7 @@ impl> Decodable for TyKind where I::ErrorGuaranteed: Decodable, I::AdtDef: Decodable, - I::GenericArgsRef: Decodable, + I::GenericArgs: Decodable, I::DefId: Decodable, I::Ty: Decodable, I::Const: Decodable, @@ -690,13 +690,13 @@ where I::Mutability: Decodable, I::Movability: Decodable, I::PolyFnSig: Decodable, - I::ListBinderExistentialPredicate: Decodable, - I::ListTy: Decodable, + I::BoundExistentialPredicates: Decodable, + I::Tys: Decodable, I::AliasTy: Decodable, I::ParamTy: Decodable, I::AliasTy: Decodable, I::BoundTy: Decodable, - I::PlaceholderType: Decodable, + I::PlaceholderTy: Decodable, I::InferTy: Decodable, I::PredicateKind: Decodable, I::AllocId: Decodable, @@ -746,20 +746,20 @@ impl HashStable for TyKind where I::AdtDef: HashStable, I::DefId: HashStable, - I::GenericArgsRef: HashStable, + I::GenericArgs: HashStable, I::Ty: HashStable, I::Const: HashStable, I::TypeAndMut: HashStable, I::PolyFnSig: HashStable, - I::ListBinderExistentialPredicate: HashStable, + I::BoundExistentialPredicates: HashStable, I::Region: HashStable, I::Movability: HashStable, I::Mutability: HashStable, - I::ListTy: HashStable, + I::Tys: HashStable, I::AliasTy: HashStable, I::BoundTy: HashStable, I::ParamTy: HashStable, - I::PlaceholderType: HashStable, + I::PlaceholderTy: HashStable, I::InferTy: HashStable, I::ErrorGuaranteed: HashStable, { @@ -1201,7 +1201,7 @@ pub enum RegionKind { ReStatic, /// A region variable. Should not exist outside of type inference. - ReVar(I::RegionVid), + ReVar(I::InferRegion), /// A placeholder region -- basically, the higher-ranked version of `ReFree`. /// Should not exist outside of type inference. @@ -1236,7 +1236,7 @@ where I::EarlyBoundRegion: Copy, I::BoundRegion: Copy, I::FreeRegion: Copy, - I::RegionVid: Copy, + I::InferRegion: Copy, I::PlaceholderRegion: Copy, I::ErrorGuaranteed: Copy, { @@ -1376,7 +1376,7 @@ where I::EarlyBoundRegion: Encodable, I::BoundRegion: Encodable, I::FreeRegion: Encodable, - I::RegionVid: Encodable, + I::InferRegion: Encodable, I::PlaceholderRegion: Encodable, { fn encode(&self, e: &mut E) { @@ -1411,7 +1411,7 @@ where I::EarlyBoundRegion: Decodable, I::BoundRegion: Decodable, I::FreeRegion: Decodable, - I::RegionVid: Decodable, + I::InferRegion: Decodable, I::PlaceholderRegion: Decodable, I::ErrorGuaranteed: Decodable, { @@ -1442,7 +1442,7 @@ where I::EarlyBoundRegion: HashStable, I::BoundRegion: HashStable, I::FreeRegion: HashStable, - I::RegionVid: HashStable, + I::InferRegion: HashStable, I::PlaceholderRegion: HashStable, { #[inline] From bd8b46800d152ce14029be5df784c1abaa8febd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 18 Oct 2023 22:10:48 +0000 Subject: [PATCH 90/94] Tweak wording of type errors involving type params Fix #78206. --- .../infer/error_reporting/note_and_explain.rs | 23 +++++++++++++++---- .../tests/ui/builtin_type_shadow.stderr | 2 +- .../ui/associated-type-bounds/elision.stderr | 2 +- .../associated-types-issue-20346.stderr | 2 +- .../hr-associated-type-projection-1.stderr | 4 +++- .../issues/issue-67945-1.full.stderr | 2 +- .../issue-68648-2.stderr | 2 +- .../issue-68656-unsized-values.stderr | 2 +- .../issue-88360.stderr | 2 +- .../missing-bounds.stderr | 6 ++--- .../arg-position-impl-trait-too-long.stderr | 2 +- .../method-signature-matches.lt.stderr | 2 +- .../in-trait/specialization-broken.stderr | 2 +- .../universal-mismatched-type.stderr | 2 +- tests/ui/inference/issue-107090.stderr | 2 +- tests/ui/issues/issue-20225.stderr | 6 ++--- tests/ui/issues/issue-51154.stderr | 2 +- tests/ui/issues/issue-69306.stderr | 12 +++++----- .../start_lang_item_args.main_ret.stderr | 2 +- tests/ui/mismatched_types/issue-35030.stderr | 2 +- tests/ui/return/return-impl-trait-bad.stderr | 8 +++---- tests/ui/return/return-impl-trait.stderr | 4 ++-- ...n-unconstrained-borrowed-type-param.stderr | 2 +- .../expected-boxed-future-isnt-pinned.stderr | 4 ++-- .../restrict-existing-type-bounds.stderr | 4 ++-- ...missing-associated-type-restriction.stderr | 2 +- tests/ui/traits/issue-52893.stderr | 2 +- .../traits/new-solver/object-unsafety.stderr | 2 +- .../enum-variant-generic-args.stderr | 12 +++++----- .../ui/typeck/bad-index-due-to-nested.stderr | 4 ++-- tests/ui/typeck/issue-13853.stderr | 2 +- 31 files changed, 72 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 8ecf63ec6656..3da6d8a89e10 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -85,8 +85,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { { let p_def_id = tcx.generics_of(body_owner_def_id).type_param(p, tcx).def_id; let p_span = tcx.def_span(p_def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; if !sp.contains(p_span) { - diag.span_label(p_span, "this type parameter"); + diag.span_label(p_span, format!("{expected}this type parameter")); } let hir = tcx.hir(); let mut note = true; @@ -168,8 +173,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => { let generics = tcx.generics_of(body_owner_def_id); let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; if !sp.contains(p_span) { - diag.span_label(p_span, "this type parameter"); + diag.span_label(p_span, format!("{expected}this type parameter")); } diag.help("type parameters must be constrained to match other types"); if tcx.sess.teach(&diag.get_code().unwrap()) { @@ -209,7 +219,7 @@ impl Trait for X { let generics = tcx.generics_of(body_owner_def_id); let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); if !sp.contains(p_span) { - diag.span_label(p_span, "this type parameter"); + diag.span_label(p_span, "expected this type parameter"); } diag.help(format!( "every closure has a distinct type and so could not always match the \ @@ -219,8 +229,13 @@ impl Trait for X { (ty::Param(p), _) | (_, ty::Param(p)) => { let generics = tcx.generics_of(body_owner_def_id); let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; if !sp.contains(p_span) { - diag.span_label(p_span, "this type parameter"); + diag.span_label(p_span, format!("{expected}this type parameter")); } } (ty::Alias(ty::Projection | ty::Inherent, proj_ty), _) diff --git a/src/tools/clippy/tests/ui/builtin_type_shadow.stderr b/src/tools/clippy/tests/ui/builtin_type_shadow.stderr index cb8462182b89..e051c00eb8d2 100644 --- a/src/tools/clippy/tests/ui/builtin_type_shadow.stderr +++ b/src/tools/clippy/tests/ui/builtin_type_shadow.stderr @@ -13,7 +13,7 @@ error[E0308]: mismatched types LL | fn foo(a: u32) -> u32 { | --- --- expected `u32` because of return type | | - | this type parameter + | expected this type parameter LL | 42 | ^^ expected type parameter `u32`, found integer | diff --git a/tests/ui/associated-type-bounds/elision.stderr b/tests/ui/associated-type-bounds/elision.stderr index cc10bbcc0b50..a29e32a784fe 100644 --- a/tests/ui/associated-type-bounds/elision.stderr +++ b/tests/ui/associated-type-bounds/elision.stderr @@ -17,7 +17,7 @@ LL | fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> | ----------------------------- -------------- ^^^^^^^^ expected `Option<&()>`, found `Option>` | | | | | expected `Option<&()>` because of return type - | this type parameter + | found this type parameter | = note: expected enum `Option<&()>` found enum `Option>` diff --git a/tests/ui/associated-types/associated-types-issue-20346.stderr b/tests/ui/associated-types/associated-types-issue-20346.stderr index b1708b96e525..f384079862fb 100644 --- a/tests/ui/associated-types/associated-types-issue-20346.stderr +++ b/tests/ui/associated-types/associated-types-issue-20346.stderr @@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving ` as Iterator>::Item == Option< --> $DIR/associated-types-issue-20346.rs:34:36 | LL | fn test_adapter>>(it: I) { - | - this type parameter + | - found this type parameter ... LL | is_iterator_of::, _>(&adapter); | ------------------------------ ^^^^^^^^ type mismatch resolving ` as Iterator>::Item == Option` diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr index dd0389c34e69..425cfdca01d1 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -2,7 +2,9 @@ error[E0271]: type mismatch resolving `::Target == T` --> $DIR/hr-associated-type-projection-1.rs:13:33 | LL | impl UnsafeCopy<'_, T> for T { - | - this type parameter ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type + | - ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type + | | + | expected this type parameter | = note: expected type parameter `T` found associated type `::Target` diff --git a/tests/ui/const-generics/issues/issue-67945-1.full.stderr b/tests/ui/const-generics/issues/issue-67945-1.full.stderr index 8879aec35e59..ee17ec3c698b 100644 --- a/tests/ui/const-generics/issues/issue-67945-1.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-1.full.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-67945-1.rs:10:20 | LL | struct Bug { - | - this type parameter + | - expected this type parameter ... LL | let x: S = MaybeUninit::uninit(); | - ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found `MaybeUninit<_>` diff --git a/tests/ui/generic-associated-types/issue-68648-2.stderr b/tests/ui/generic-associated-types/issue-68648-2.stderr index b2bef19eb5e9..0514e7bd6f69 100644 --- a/tests/ui/generic-associated-types/issue-68648-2.stderr +++ b/tests/ui/generic-associated-types/issue-68648-2.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-68648-2.rs:12:17 | LL | fn bug<'a, T: Fun = T>>(t: T) -> T::F<'a> { - | - this type parameter + | - expected this type parameter LL | T::identity(()) | ----------- ^^ expected type parameter `T`, found `()` | | diff --git a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr index f0212e985a92..20c07db4c04f 100644 --- a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr +++ b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `::Target == T` --> $DIR/issue-68656-unsized-values.rs:13:21 | LL | impl UnsafeCopy for T { - | - this type parameter + | - expected this type parameter LL | type Item<'a> = T; | ^ expected type parameter `T`, found associated type | diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr index 520aeff18948..ad40ee180019 100644 --- a/tests/ui/generic-associated-types/issue-88360.stderr +++ b/tests/ui/generic-associated-types/issue-88360.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-88360.rs:15:9 | LL | trait SuperTrait - | - this type parameter + | - found this type parameter ... LL | fn copy(&self) -> Self::Gat<'_> where T: Copy { | ------------- expected `&T` because of return type diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index 535edec575a7..1d7d80d1b076 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/missing-bounds.rs:11:11 | LL | impl Add for A where B: Add { - | - this type parameter + | - expected this type parameter ... LL | A(self.0 + rhs.0) | - ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type @@ -44,7 +44,7 @@ error[E0308]: mismatched types --> $DIR/missing-bounds.rs:21:14 | LL | impl Add for C { - | - this type parameter + | - expected this type parameter ... LL | Self(self.0 + rhs.0) | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type @@ -80,7 +80,7 @@ error[E0308]: mismatched types --> $DIR/missing-bounds.rs:42:14 | LL | impl Add for E where ::Output = B { - | - this type parameter + | - expected this type parameter ... LL | Self(self.0 + rhs.0) | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type diff --git a/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr index 40446a3d339a..d5086c7bc515 100644 --- a/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr +++ b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr @@ -7,7 +7,7 @@ LL | | &mut Header, LL | | &mut [EntryMetadata], LL | | &mut [Entry] LL | | ) -> R, - | |__________- this type parameter + | |__________- expected this type parameter LL | ) { LL | let () = y; | ^^ - this expression has type `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry]) -> R` diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr index 59139e4d5ae6..874a1b95a431 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr @@ -6,7 +6,7 @@ LL | fn early<'late, T>(_: &'late ()) {} | | | | | expected type parameter `T`, found `()` | | help: change the parameter type to match the trait: `&T` - | this type parameter + | expected this type parameter | note: type in trait --> $DIR/method-signature-matches.rs:52:28 diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.stderr index 1d169b5d690c..25c0adeddbd7 100644 --- a/tests/ui/impl-trait/in-trait/specialization-broken.stderr +++ b/tests/ui/impl-trait/in-trait/specialization-broken.stderr @@ -2,7 +2,7 @@ error[E0053]: method `bar` has an incompatible type for trait --> $DIR/specialization-broken.rs:15:22 | LL | default impl Foo for U - | - this type parameter + | - found this type parameter ... LL | fn bar(&self) -> U { | ^ diff --git a/tests/ui/impl-trait/universal-mismatched-type.stderr b/tests/ui/impl-trait/universal-mismatched-type.stderr index a56e542d8345..82e0f23964f7 100644 --- a/tests/ui/impl-trait/universal-mismatched-type.stderr +++ b/tests/ui/impl-trait/universal-mismatched-type.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo(x: impl Debug) -> String { | ---------- ------ expected `String` because of return type | | - | this type parameter + | found this type parameter LL | x | ^ expected `String`, found type parameter `impl Debug` | diff --git a/tests/ui/inference/issue-107090.stderr b/tests/ui/inference/issue-107090.stderr index 6233b629ad6c..55825f7765bb 100644 --- a/tests/ui/inference/issue-107090.stderr +++ b/tests/ui/inference/issue-107090.stderr @@ -70,7 +70,7 @@ error[E0308]: mismatched types --> $DIR/issue-107090.rs:22:5 | LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T { - | - this type parameter ------- expected `&'out T` because of return type + | - expected this type parameter ------- expected `&'out T` because of return type LL | LL | sadness.cast() | ^^^^^^^^^^^^^^ expected `&T`, found `&Foo<'_, '_, T>` diff --git a/tests/ui/issues/issue-20225.stderr b/tests/ui/issues/issue-20225.stderr index b1c15672051d..b34aa8e1ff5a 100644 --- a/tests/ui/issues/issue-20225.stderr +++ b/tests/ui/issues/issue-20225.stderr @@ -2,7 +2,7 @@ error[E0053]: method `call` has an incompatible type for trait --> $DIR/issue-20225.rs:6:43 | LL | impl<'a, T> Fn<(&'a T,)> for Foo { - | - this type parameter + | - found this type parameter LL | extern "rust-call" fn call(&self, (_,): (T,)) {} | ^^^^ | | @@ -16,7 +16,7 @@ error[E0053]: method `call_mut` has an incompatible type for trait --> $DIR/issue-20225.rs:11:51 | LL | impl<'a, T> FnMut<(&'a T,)> for Foo { - | - this type parameter + | - found this type parameter LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} | ^^^^ | | @@ -30,7 +30,7 @@ error[E0053]: method `call_once` has an incompatible type for trait --> $DIR/issue-20225.rs:18:47 | LL | impl<'a, T> FnOnce<(&'a T,)> for Foo { - | - this type parameter + | - found this type parameter ... LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} | ^^^^ diff --git a/tests/ui/issues/issue-51154.stderr b/tests/ui/issues/issue-51154.stderr index 002d5ccdc67a..5ae8e067807f 100644 --- a/tests/ui/issues/issue-51154.stderr +++ b/tests/ui/issues/issue-51154.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-51154.rs:2:30 | LL | fn foo() { - | - this type parameter + | - expected this type parameter LL | let _: Box = Box::new(|| ()); | -------- ^^^^^ expected type parameter `F`, found closure | | diff --git a/tests/ui/issues/issue-69306.stderr b/tests/ui/issues/issue-69306.stderr index 570677298ffa..6fc5c33af6ac 100644 --- a/tests/ui/issues/issue-69306.stderr +++ b/tests/ui/issues/issue-69306.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:5:28 | LL | impl S0 { - | - this type parameter + | - expected this type parameter LL | const C: S0 = Self(0); | ---- ^ expected type parameter `T`, found integer | | @@ -20,7 +20,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:5:23 | LL | impl S0 { - | - this type parameter + | - found this type parameter LL | const C: S0 = Self(0); | ^^^^^^^ expected `S0`, found `S0` | @@ -31,7 +31,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:10:14 | LL | impl S0 { - | - this type parameter + | - expected this type parameter ... LL | Self(0); | ---- ^ expected type parameter `T`, found integer @@ -50,7 +50,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:27:14 | LL | impl Foo for as Fun>::Out { - | - this type parameter + | - expected this type parameter LL | fn foo() { LL | Self(0); | ---- ^ expected type parameter `T`, found integer @@ -69,7 +69,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:33:32 | LL | impl S1 { - | - this type parameter + | - expected this type parameter LL | const C: S1 = Self(0, 1); | ---- ^ expected type parameter `T`, found integer | | @@ -87,7 +87,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:33:27 | LL | impl S1 { - | - this type parameter + | - found this type parameter LL | const C: S1 = Self(0, 1); | ^^^^^^^^^^ expected `S1`, found `S1` | diff --git a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr index 4582b69850cf..25570f960537 100644 --- a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr +++ b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr @@ -4,7 +4,7 @@ error[E0308]: lang item `start` function has wrong type LL | fn start(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { | - ^^^^^^^^^^^ expected type parameter `T`, found `u16` | | - | this type parameter + | expected this type parameter | = note: expected signature `fn(fn() -> T, _, _, _) -> _` found signature `fn(fn() -> u16, _, _, _) -> _` diff --git a/tests/ui/mismatched_types/issue-35030.stderr b/tests/ui/mismatched_types/issue-35030.stderr index de4e067fead4..881ff909722f 100644 --- a/tests/ui/mismatched_types/issue-35030.stderr +++ b/tests/ui/mismatched_types/issue-35030.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-35030.rs:9:14 | LL | impl Parser for bool { - | ---- this type parameter + | ---- expected this type parameter LL | fn parse(text: &str) -> Option { LL | Some(true) | ---- ^^^^ expected type parameter `bool`, found `bool` diff --git a/tests/ui/return/return-impl-trait-bad.stderr b/tests/ui/return/return-impl-trait-bad.stderr index 237b85ee66a1..a015b9f53aff 100644 --- a/tests/ui/return/return-impl-trait-bad.stderr +++ b/tests/ui/return/return-impl-trait-bad.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn bad_echo(_t: T) -> T { | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter LL | "this should not suggest impl Trait" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` | @@ -17,7 +17,7 @@ error[E0308]: mismatched types LL | fn bad_echo_2(_t: T) -> T { | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter LL | "this will not suggest it, because that would probably be wrong" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` | @@ -30,7 +30,7 @@ error[E0308]: mismatched types LL | fn other_bounds_bad() -> T | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter ... LL | "don't suggest this, because Option places additional constraints" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` @@ -46,7 +46,7 @@ LL | fn used_in_trait() -> T | | | | | expected `T` because of return type | | help: consider using an impl return type: `impl Send` - | this type parameter + | expected this type parameter ... LL | "don't suggest this, because the generic param is used in the bound." | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` diff --git a/tests/ui/return/return-impl-trait.stderr b/tests/ui/return/return-impl-trait.stderr index 43d40972fcac..707f014a16f9 100644 --- a/tests/ui/return/return-impl-trait.stderr +++ b/tests/ui/return/return-impl-trait.stderr @@ -5,7 +5,7 @@ LL | fn bar() -> T | - - | | | | | expected `T` because of return type - | this type parameter help: consider using an impl return type: `impl Trait + std::marker::Sync + Send` + | expected this type parameter help: consider using an impl return type: `impl Trait + std::marker::Sync + Send` ... LL | () | ^^ expected type parameter `T`, found `()` @@ -21,7 +21,7 @@ LL | fn other_bounds() -> T | | | | | expected `T` because of return type | | help: consider using an impl return type: `impl Trait` - | this type parameter + | expected this type parameter ... LL | () | ^^ expected type parameter `T`, found `()` diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr index 0716005c679a..8c973995c34b 100644 --- a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr +++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn wat(t: &T) -> T { | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter LL | t.clone() | ^^^^^^^^^ expected type parameter `T`, found `&T` | diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 5093448d2ca4..7c81825e5764 100644 --- a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/expected-boxed-future-isnt-pinned.rs:11:5 | LL | fn foo + Send + 'static>(x: F) -> BoxFuture<'static, i32> { - | - this type parameter ----------------------- expected `Pin + Send + 'static)>>` because of return type + | - found this type parameter ----------------------- expected `Pin + Send + 'static)>>` because of return type LL | // We could instead use an `async` block, but this way we have no std spans. LL | x | ^ expected `Pin>`, found type parameter `F` @@ -30,7 +30,7 @@ error[E0308]: mismatched types --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14 | LL | fn baz + Send + 'static>(x: F) -> BoxFuture<'static, i32> { - | - this type parameter + | - found this type parameter LL | Pin::new(x) | -------- ^ expected `Box + Send>`, found type parameter `F` | | diff --git a/tests/ui/suggestions/restrict-existing-type-bounds.stderr b/tests/ui/suggestions/restrict-existing-type-bounds.stderr index 14a244b790a6..fe8338c18c2b 100644 --- a/tests/ui/suggestions/restrict-existing-type-bounds.stderr +++ b/tests/ui/suggestions/restrict-existing-type-bounds.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/restrict-existing-type-bounds.rs:13:12 | LL | impl TryAdd for Option { - | - this type parameter + | - found this type parameter ... LL | Ok(self) | -- ^^^^ expected `Option<::Output>`, found `Option` @@ -29,7 +29,7 @@ error[E0308]: mismatched types --> $DIR/restrict-existing-type-bounds.rs:26:12 | LL | impl> TryAdd for Other { - | - this type parameter + | - found this type parameter ... LL | Ok(self) | -- ^^^^ expected `Other<::Output>`, found `Other` diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr index 7deb9a4342d9..980c2455c8e4 100644 --- a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -124,7 +124,7 @@ error[E0308]: mismatched types --> $DIR/trait-with-missing-associated-type-restriction.rs:31:9 | LL | fn baz>(x: T) { - | - this type parameter + | - found this type parameter LL | qux(x.func()) | --- ^^^^^^^^ expected `usize`, found type parameter `D` | | diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr index db807a38830a..c57921a08aab 100644 --- a/tests/ui/traits/issue-52893.stderr +++ b/tests/ui/traits/issue-52893.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-52893.rs:53:22 | LL | impl AddClass for Class