From ac59bdc20cf07422557b5dc512ee6749a73c9414 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 22 Apr 2024 23:47:48 +0200 Subject: [PATCH 001/104] Add `--print=check-cfg` to get the expected configs --- compiler/rustc_driver_impl/src/lib.rs | 33 ++++++ compiler/rustc_session/src/config.rs | 14 ++- .../src/compiler-flags/print-check-cfg.md | 25 +++++ tests/run-make/print-check-cfg/lib.rs | 1 + tests/run-make/print-check-cfg/rmake.rs | 106 ++++++++++++++++++ .../feature-gate-print-check-cfg.rs | 3 + .../feature-gate-print-check-cfg.stderr | 2 + tests/ui/invalid-compile-flags/print.stderr | 2 +- 8 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/print-check-cfg.md create mode 100644 tests/run-make/print-check-cfg/lib.rs create mode 100644 tests/run-make/print-check-cfg/rmake.rs create mode 100644 tests/ui/feature-gates/feature-gate-print-check-cfg.rs create mode 100644 tests/ui/feature-gates/feature-gate-print-check-cfg.stderr diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b3cba4dbfc20..cf9d0fe794f8 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -804,6 +804,39 @@ fn print_crate_info( println_info!("{cfg}"); } } + CheckCfg => { + let mut check_cfgs: Vec = Vec::with_capacity(410); + + // INSTABILITY: We are sorting the output below. + #[allow(rustc::potential_query_instability)] + for (name, expected_values) in &sess.psess.check_config.expecteds { + use crate::config::ExpectedValues; + match expected_values { + ExpectedValues::Any => check_cfgs.push(format!("{name}=any()")), + ExpectedValues::Some(values) => { + check_cfgs.extend(values.iter().map(|value| { + if let Some(value) = value { + format!("{name}=\"{value}\"") + } else { + name.to_string() + } + })) + } + } + } + + check_cfgs.sort_unstable(); + if !sess.psess.check_config.exhaustive_names { + if !sess.psess.check_config.exhaustive_values { + println_info!("any()=any()"); + } else { + println_info!("any()"); + } + } + for check_cfg in check_cfgs { + println_info!("{check_cfg}"); + } + } CallingConventions => { let mut calling_conventions = rustc_target::spec::abi::all_names(); calling_conventions.sort_unstable(); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 4f259960ac3a..5c56191c21bd 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -745,6 +745,7 @@ pub enum PrintKind { TargetLibdir, CrateName, Cfg, + CheckCfg, CallingConventions, TargetList, TargetCPUs, @@ -1424,7 +1425,7 @@ pub fn rustc_short_optgroups() -> Vec { "", "print", "Compiler information to print on stdout", - "[crate-name|file-names|sysroot|target-libdir|cfg|calling-conventions|\ + "[crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|\ target-list|target-cpus|target-features|relocation-models|code-models|\ tls-models|target-spec-json|all-target-specs-json|native-static-libs|\ stack-protector-strategies|link-args|deployment-target]", @@ -1834,6 +1835,7 @@ fn collect_print_requests( ("all-target-specs-json", PrintKind::AllTargetSpecs), ("calling-conventions", PrintKind::CallingConventions), ("cfg", PrintKind::Cfg), + ("check-cfg", PrintKind::CheckCfg), ("code-models", PrintKind::CodeModels), ("crate-name", PrintKind::CrateName), ("deployment-target", PrintKind::DeploymentTarget), @@ -1883,6 +1885,16 @@ fn collect_print_requests( ); } } + Some((_, PrintKind::CheckCfg)) => { + if unstable_opts.unstable_options { + PrintKind::CheckCfg + } else { + early_dcx.early_fatal( + "the `-Z unstable-options` flag must also be passed to \ + enable the check-cfg print option", + ); + } + } Some(&(_, print_kind)) => print_kind, None => { let prints = diff --git a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md new file mode 100644 index 000000000000..e55165b53740 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md @@ -0,0 +1,25 @@ +# `print=check-cfg` + +The tracking issue for this feature is: [#XXXXXX](https://github.com/rust-lang/rust/issues/XXXXXX). + +------------------------ + +This option of the `--print` flag print the list of expected cfgs. + +This is related to the `--check-cfg` flag which allows specifying arbitrary expected +names and values. + +This print option works similarly to `--print=cfg` (modulo check-cfg specifics): + - *check_cfg syntax*: *output of --print=check-cfg* + - `cfg(windows)`: `windows` + - `cfg(feature, values("foo", "bar"))`: `feature="foo"` and `feature="bar"` + - `cfg(feature, values(none(), ""))`: `feature` and `feature=""` + - `cfg(feature, values(any()))`: `feature=any()` + - `cfg(any())`: `any()` + - *nothing*: `any()=any()` + +To be used like this: + +```bash +rustc --print=check-cfg -Zunstable-options lib.rs +``` diff --git a/tests/run-make/print-check-cfg/lib.rs b/tests/run-make/print-check-cfg/lib.rs new file mode 100644 index 000000000000..c09e4c98dffd --- /dev/null +++ b/tests/run-make/print-check-cfg/lib.rs @@ -0,0 +1 @@ +// empty crate diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs new file mode 100644 index 000000000000..554884b7d579 --- /dev/null +++ b/tests/run-make/print-check-cfg/rmake.rs @@ -0,0 +1,106 @@ +//! This checks the output of `--print=check-cfg` + +extern crate run_make_support; + +use std::collections::HashSet; +use std::iter::FromIterator; +use std::ops::Deref; + +use run_make_support::rustc; + +fn main() { + check( + /*args*/ &[], + /*has_any*/ false, + /*has_any_any*/ true, + /*contains*/ &[], + ); + check( + /*args*/ &["--check-cfg=cfg()"], + /*has_any*/ false, + /*has_any_any*/ false, + /*contains*/ &["unix", "miri"], + ); + check( + /*args*/ &["--check-cfg=cfg(any())"], + /*has_any*/ true, + /*has_any_any*/ false, + /*contains*/ &["windows", "test"], + ); + check( + /*args*/ &["--check-cfg=cfg(feature)"], + /*has_any*/ false, + /*has_any_any*/ false, + /*contains*/ &["unix", "miri", "feature"], + ); + check( + /*args*/ &[r#"--check-cfg=cfg(feature, values(none(), "", "test", "lol"))"#], + /*has_any*/ false, + /*has_any_any*/ false, + /*contains*/ &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""], + ); + check( + /*args*/ &[ + r#"--check-cfg=cfg(feature, values(any()))"#, + r#"--check-cfg=cfg(feature, values("tmp"))"# + ], + /*has_any*/ false, + /*has_any_any*/ false, + /*contains*/ &["unix", "miri", "feature=any()"], + ); + check( + /*args*/ &[ + r#"--check-cfg=cfg(has_foo, has_bar)"#, + r#"--check-cfg=cfg(feature, values("tmp"))"#, + r#"--check-cfg=cfg(feature, values("tmp"))"# + ], + /*has_any*/ false, + /*has_any_any*/ false, + /*contains*/ &["has_foo", "has_bar", "feature=\"tmp\""], + ); +} + +fn check(args: &[&str], has_any: bool, has_any_any: bool, contains: &[&str]) { + let output = rustc() + .input("lib.rs") + .arg("-Zunstable-options") + .arg("--print=check-cfg") + .args(&*args) + .run(); + + let stdout = String::from_utf8(output.stdout).unwrap(); + + let mut found_any = false; + let mut found_any_any = false; + let mut found = HashSet::::new(); + let mut recorded = HashSet::::new(); + + for l in stdout.lines() { + assert!(l == l.trim()); + if l == "any()" { + found_any = true; + } else if l == "any()=any()" { + found_any_any = true; + } else if let Some((left, right)) = l.split_once('=') { + if right != "any()" && right != "" { + assert!(right.starts_with("\"")); + assert!(right.ends_with("\"")); + } + assert!(!left.contains("\"")); + } else { + assert!(!l.contains("\"")); + } + assert!(recorded.insert(l.to_string()), "{}", &l); + if contains.contains(&l) { + assert!(found.insert(l.to_string()), "{}", &l); + } + } + + let should_found = HashSet::::from_iter(contains.iter().map(|s| s.to_string())); + let diff: Vec<_> = should_found.difference(&found).collect(); + + assert_eq!(found_any, has_any); + assert_eq!(found_any_any, has_any_any); + assert_eq!(found_any_any, recorded.len() == 1); + assert!(diff.is_empty(), "{:?} != {:?} (~ {:?})", &should_found, &found, &diff); +} diff --git a/tests/ui/feature-gates/feature-gate-print-check-cfg.rs b/tests/ui/feature-gates/feature-gate-print-check-cfg.rs new file mode 100644 index 000000000000..304e0c132e50 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-print-check-cfg.rs @@ -0,0 +1,3 @@ +//@ compile-flags: --print=check-cfg + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr b/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr new file mode 100644 index 000000000000..62ee44b94a48 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr @@ -0,0 +1,2 @@ +error: the `-Z unstable-options` flag must also be passed to enable the check-cfg print option + diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr index 0a032aabdfe8..70b4a394dd02 100644 --- a/tests/ui/invalid-compile-flags/print.stderr +++ b/tests/ui/invalid-compile-flags/print.stderr @@ -1,4 +1,4 @@ error: unknown print request: `yyyy` | - = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` From 40f0172c6aed0b2fb055c19108d226f8fb410f8c Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Fri, 3 May 2024 14:32:01 +0200 Subject: [PATCH 002/104] Add -Zfixed-x18 Signed-off-by: Alice Ryhl --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 5 +++ compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 ++ .../src/compiler-flags/fixed-x18.md | 32 +++++++++++++++++++ tests/codegen/fixed-x18.rs | 22 +++++++++++++ 5 files changed, 62 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/fixed-x18.md create mode 100644 tests/codegen/fixed-x18.rs diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 5552b3810251..dbce7f43e62c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -615,6 +615,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec = (None, parse_opt_bool, [TRACKED], "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \ (default: no)"), + fixed_x18: bool = (false, parse_bool, [TRACKED], + "make the x18 register reserved on AArch64 (default: no)"), flatten_format_args: bool = (true, parse_bool, [TRACKED], "flatten nested format_args!() and literals into a simplified format_args!() call \ (default: yes)"), diff --git a/src/doc/unstable-book/src/compiler-flags/fixed-x18.md b/src/doc/unstable-book/src/compiler-flags/fixed-x18.md new file mode 100644 index 000000000000..8c8bff5fa296 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/fixed-x18.md @@ -0,0 +1,32 @@ +# `fixed-x18` + +This option prevents the compiler from using the x18 register. It is only +supported on aarch64. + +From the [ABI spec][arm-abi]: + +> X18 is the platform register and is reserved for the use of platform ABIs. +> This is an additional temporary register on platforms that don't assign a +> special meaning to it. + +This flag only has an effect when the x18 register would otherwise be considered +a temporary register. When the flag is applied, x18 is always a reserved +register. + +This flag is intended for use with the shadow call stack sanitizer. Generally, +when that sanitizer is enabled, the x18 register is used to store a pointer to +the shadow stack. Enabling this flag prevents the compiler from overwriting the +shadow stack pointer with temporary data, which is necessary for the sanitizer +to work correctly. + +Currently, the `-Zsanitizer=shadow-call-stack` flag is only supported on +platforms that always treat x18 as a reserved register, and the `-Zfixed-x18` +flag is not required to use the sanitizer on such platforms. However, the +sanitizer may be supported on targets where this is not the case in the future. + +It is undefined behavior for `-Zsanitizer=shadow-call-stack` code to call into +code where x18 is a temporary register. On the other hand, when you are *not* +using the shadow call stack sanitizer, compilation units compiled with and +without the `-Zfixed-x18` flag are compatible with each other. + +[arm-abi]: https://developer.arm.com/documentation/den0024/a/The-ABI-for-ARM-64-bit-Architecture/Register-use-in-the-AArch64-Procedure-Call-Standard/Parameters-in-general-purpose-registers diff --git a/tests/codegen/fixed-x18.rs b/tests/codegen/fixed-x18.rs new file mode 100644 index 000000000000..4997a39a7263 --- /dev/null +++ b/tests/codegen/fixed-x18.rs @@ -0,0 +1,22 @@ +// Test that the `reserve-x18` target feature is (not) emitted when +// the `-Zfixed-x18` flag is (not) set. + +//@ revisions: unset set +//@ needs-llvm-components: aarch64 +//@ compile-flags: --target aarch64-unknown-none +//@ [set] compile-flags: -Zfixed-x18 + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[no_mangle] +pub fn foo() { + // CHECK: @foo() unnamed_addr #0 + + // unset-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+reserve-x18{{.*}} } + // set: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+reserve-x18{{.*}} } +} From ead02ba0f14f8d54c3c05d8382d317d9b320072a Mon Sep 17 00:00:00 2001 From: Kjetil Kjeka Date: Fri, 10 May 2024 18:39:05 +0200 Subject: [PATCH 003/104] NVPTX: Avoid PassMode::Direct for args in C abi --- compiler/rustc_target/src/abi/call/nvptx64.rs | 9 +- tests/assembly/nvptx-c-abi-arg-v7.rs | 206 ++++++++++++++++ tests/assembly/nvptx-c-abi-ret-v7.rs | 230 ++++++++++++++++++ 3 files changed, 440 insertions(+), 5 deletions(-) create mode 100644 tests/assembly/nvptx-c-abi-arg-v7.rs create mode 100644 tests/assembly/nvptx-c-abi-ret-v7.rs diff --git a/compiler/rustc_target/src/abi/call/nvptx64.rs b/compiler/rustc_target/src/abi/call/nvptx64.rs index f85fa2419f0f..c6b6f66e6be8 100644 --- a/compiler/rustc_target/src/abi/call/nvptx64.rs +++ b/compiler/rustc_target/src/abi/call/nvptx64.rs @@ -11,11 +11,10 @@ fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { } fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { - if arg.layout.is_aggregate() && arg.layout.size.bits() > 64 { - arg.make_indirect(); - } else { - // FIXME: this is wrong! Need to decide which ABI we really want here. - arg.make_direct_deprecated(); + if arg.layout.is_aggregate() { + arg.make_indirect_byval(None); + } else if arg.layout.size.bits() < 32 { + arg.extend_integer_width_to(32); } } diff --git a/tests/assembly/nvptx-c-abi-arg-v7.rs b/tests/assembly/nvptx-c-abi-arg-v7.rs new file mode 100644 index 000000000000..99f90ea526e1 --- /dev/null +++ b/tests/assembly/nvptx-c-abi-arg-v7.rs @@ -0,0 +1,206 @@ +//@ assembly-output: ptx-linker +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc +//@ only-nvptx64 + +// The PTX ABI stability is tied to major versions of the PTX ISA +// These tests assume major version 7 + +// CHECK: .version 7 + +#![feature(abi_ptx, lang_items, no_core)] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[repr(C)] +pub struct SingleU8 { + f: u8, +} + +#[repr(C)] +pub struct DoubleU8 { + f: u8, + g: u8, +} + +#[repr(C)] +pub struct TripleU8 { + f: u8, + g: u8, + h: u8, +} + +#[repr(C)] +pub struct TripleU16 { + f: u16, + g: u16, + h: u16, +} +#[repr(C)] +pub struct TripleU32 { + f: u32, + g: u32, + h: u32, +} +#[repr(C)] +pub struct TripleU64 { + f: u64, + g: u64, + h: u64, +} + +#[repr(C)] +pub struct DoubleFloat { + f: f32, + g: f32, +} + +#[repr(C)] +pub struct TripleFloat { + f: f32, + g: f32, + h: f32, +} + +#[repr(C)] +pub struct TripleDouble { + f: f64, + g: f64, + h: f64, +} + +#[repr(C)] +pub struct ManyIntegers { + f: u8, + g: u16, + h: u32, + i: u64, +} + +#[repr(C)] +pub struct ManyNumerics { + f: u8, + g: u16, + h: u32, + i: u64, + j: f32, + k: f64, +} + +// CHECK: .visible .func f_u8_arg( +// CHECK: .param .b32 f_u8_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_u8_arg(_a: u8) {} + +// CHECK: .visible .func f_u16_arg( +// CHECK: .param .b32 f_u16_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_u16_arg(_a: u16) {} + +// CHECK: .visible .func f_u32_arg( +// CHECK: .param .b32 f_u32_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_u32_arg(_a: u32) {} + +// CHECK: .visible .func f_u64_arg( +// CHECK: .param .b64 f_u64_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_u64_arg(_a: u64) {} + +// CHECK: .visible .func f_u128_arg( +// CHECK: .param .align 16 .b8 f_u128_arg_param_0[16] +#[no_mangle] +pub unsafe extern "C" fn f_u128_arg(_a: u128) {} + +// CHECK: .visible .func f_i8_arg( +// CHECK: .param .b32 f_i8_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_i8_arg(_a: i8) {} + +// CHECK: .visible .func f_i16_arg( +// CHECK: .param .b32 f_i16_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_i16_arg(_a: i16) {} + +// CHECK: .visible .func f_i32_arg( +// CHECK: .param .b32 f_i32_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_i32_arg(_a: i32) {} + +// CHECK: .visible .func f_i64_arg( +// CHECK: .param .b64 f_i64_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_i64_arg(_a: i64) {} + +// CHECK: .visible .func f_i128_arg( +// CHECK: .param .align 16 .b8 f_i128_arg_param_0[16] +#[no_mangle] +pub unsafe extern "C" fn f_i128_arg(_a: i128) {} + +// CHECK: .visible .func f_f32_arg( +// CHECK: .param .b32 f_f32_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_f32_arg(_a: f32) {} + +// CHECK: .visible .func f_f64_arg( +// CHECK: .param .b64 f_f64_arg_param_0 +#[no_mangle] +pub unsafe extern "C" fn f_f64_arg(_a: f64) {} + +// CHECK: .visible .func f_single_u8_arg( +// CHECK: .param .align 1 .b8 f_single_u8_arg_param_0[1] +#[no_mangle] +pub unsafe extern "C" fn f_single_u8_arg(_a: SingleU8) {} + +// CHECK: .visible .func f_double_u8_arg( +// CHECK: .param .align 1 .b8 f_double_u8_arg_param_0[2] +#[no_mangle] +pub unsafe extern "C" fn f_double_u8_arg(_a: DoubleU8) {} + +// CHECK: .visible .func f_triple_u8_arg( +// CHECK: .param .align 1 .b8 f_triple_u8_arg_param_0[3] +#[no_mangle] +pub unsafe extern "C" fn f_triple_u8_arg(_a: TripleU8) {} + +// CHECK: .visible .func f_triple_u16_arg( +// CHECK: .param .align 2 .b8 f_triple_u16_arg_param_0[6] +#[no_mangle] +pub unsafe extern "C" fn f_triple_u16_arg(_a: TripleU16) {} + +// CHECK: .visible .func f_triple_u32_arg( +// CHECK: .param .align 4 .b8 f_triple_u32_arg_param_0[12] +#[no_mangle] +pub unsafe extern "C" fn f_triple_u32_arg(_a: TripleU32) {} + +// CHECK: .visible .func f_triple_u64_arg( +// CHECK: .param .align 8 .b8 f_triple_u64_arg_param_0[24] +#[no_mangle] +pub unsafe extern "C" fn f_triple_u64_arg(_a: TripleU64) {} + +// CHECK: .visible .func f_many_integers_arg( +// CHECK: .param .align 8 .b8 f_many_integers_arg_param_0[16] +#[no_mangle] +pub unsafe extern "C" fn f_many_integers_arg(_a: ManyIntegers) {} + +// CHECK: .visible .func f_double_float_arg( +// CHECK: .param .align 4 .b8 f_double_float_arg_param_0[8] +#[no_mangle] +pub unsafe extern "C" fn f_double_float_arg(_a: DoubleFloat) {} + +// CHECK: .visible .func f_triple_float_arg( +// CHECK: .param .align 4 .b8 f_triple_float_arg_param_0[12] +#[no_mangle] +pub unsafe extern "C" fn f_triple_float_arg(_a: TripleFloat) {} + +// CHECK: .visible .func f_triple_double_arg( +// CHECK: .param .align 8 .b8 f_triple_double_arg_param_0[24] +#[no_mangle] +pub unsafe extern "C" fn f_triple_double_arg(_a: TripleDouble) {} + +// CHECK: .visible .func f_many_numerics_arg( +// CHECK: .param .align 8 .b8 f_many_numerics_arg_param_0[32] +#[no_mangle] +pub unsafe extern "C" fn f_many_numerics_arg(_a: ManyNumerics) {} diff --git a/tests/assembly/nvptx-c-abi-ret-v7.rs b/tests/assembly/nvptx-c-abi-ret-v7.rs new file mode 100644 index 000000000000..0c1594a5f200 --- /dev/null +++ b/tests/assembly/nvptx-c-abi-ret-v7.rs @@ -0,0 +1,230 @@ +//@ assembly-output: ptx-linker +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc +//@ only-nvptx64 +//@ ignore-nvptx64 + +// The PTX ABI stability is tied to major versions of the PTX ISA +// These tests assume major version 7 + +// CHECK: .version 7 + +#![feature(abi_ptx, lang_items, no_core)] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[repr(C)] +pub struct SingleU8 { + f: u8, +} + +#[repr(C)] +pub struct DoubleU8 { + f: u8, + g: u8, +} + +#[repr(C)] +pub struct TripleU8 { + f: u8, + g: u8, + h: u8, +} + +#[repr(C)] +pub struct TripleU16 { + f: u16, + g: u16, + h: u16, +} +#[repr(C)] +pub struct TripleU32 { + f: u32, + g: u32, + h: u32, +} +#[repr(C)] +pub struct TripleU64 { + f: u64, + g: u64, + h: u64, +} + +#[repr(C)] +pub struct DoubleFloat { + f: f32, + g: f32, +} + +#[repr(C)] +pub struct TripleFloat { + f: f32, + g: f32, + h: f32, +} + +#[repr(C)] +pub struct TripleDouble { + f: f64, + g: f64, + h: f64, +} + +#[repr(C)] +pub struct ManyIntegers { + f: u8, + g: u16, + h: u32, + i: u64, +} + +#[repr(C)] +pub struct ManyNumerics { + f: u8, + g: u16, + h: u32, + i: u64, + j: f32, + k: f64, +} + +// CHECK: .visible .func (.param .b32 func_retval0) f_u8_ret( +#[no_mangle] +pub unsafe extern "C" fn f_u8_ret() -> u8 { + 0 +} + +// CHECK: .visible .func (.param .b32 func_retval0) f_u16_ret( +#[no_mangle] +pub unsafe extern "C" fn f_u16_ret() -> u16 { + 1 +} + +// CHECK: .visible .func (.param .b32 func_retval0) f_u32_ret( +#[no_mangle] +pub unsafe extern "C" fn f_u32_ret() -> u32 { + 2 +} + +// CHECK: .visible .func (.param .b64 func_retval0) f_u64_ret( +#[no_mangle] +pub unsafe extern "C" fn f_u64_ret() -> u64 { + 3 +} + +// CHECK: .visible .func (.param .align 16 .b8 func_retval0[16]) f_u128_ret( +#[no_mangle] +pub unsafe extern "C" fn f_u128_ret() -> u128 { + 4 +} + +// CHECK: .visible .func (.param .b32 func_retval0) f_i8_ret( +#[no_mangle] +pub unsafe extern "C" fn f_i8_ret() -> i8 { + 5 +} + +// CHECK: .visible .func (.param .b32 func_retval0) f_i16_ret( +#[no_mangle] +pub unsafe extern "C" fn f_i16_ret() -> i16 { + 6 +} + +// CHECK: .visible .func (.param .b32 func_retval0) f_i32_ret( +#[no_mangle] +pub unsafe extern "C" fn f_i32_ret() -> i32 { + 7 +} + +// CHECK: .visible .func (.param .b64 func_retval0) f_i64_ret( +#[no_mangle] +pub unsafe extern "C" fn f_i64_ret() -> i64 { + 8 +} + +// CHECK: .visible .func (.param .align 16 .b8 func_retval0[16]) f_i128_ret( +#[no_mangle] +pub unsafe extern "C" fn f_i128_ret() -> i128 { + 9 +} + +// CHECK: .visible .func (.param .b32 func_retval0) f_f32_ret( +#[no_mangle] +pub unsafe extern "C" fn f_f32_ret() -> f32 { + 10.0 +} + +// CHECK: .visible .func (.param .b64 func_retval0) f_f64_ret( +#[no_mangle] +pub unsafe extern "C" fn f_f64_ret() -> f64 { + 11.0 +} + +// CHECK: .visible .func (.param .align 1 .b8 func_retval0[1]) f_single_u8_ret( +#[no_mangle] +pub unsafe extern "C" fn f_single_u8_ret() -> SingleU8 { + SingleU8 { f: 12 } +} + +// CHECK: .visible .func (.param .align 1 .b8 func_retval0[2]) f_double_u8_ret( +#[no_mangle] +pub unsafe extern "C" fn f_double_u8_ret() -> DoubleU8 { + DoubleU8 { f: 13, g: 14 } +} + +// CHECK: .visible .func (.param .align 1 .b8 func_retval0[3]) f_triple_u8_ret( +#[no_mangle] +pub unsafe extern "C" fn f_triple_u8_ret() -> TripleU8 { + TripleU8 { f: 15, g: 16, h: 17 } +} + +// CHECK: .visible .func (.param .align 2 .b8 func_retval0[6]) f_triple_u16_ret( +#[no_mangle] +pub unsafe extern "C" fn f_triple_u16_ret() -> TripleU16 { + TripleU16 { f: 18, g: 19, h: 20 } +} + +// CHECK: .visible .func (.param .align 4 .b8 func_retval0[12]) f_triple_u32_ret( +#[no_mangle] +pub unsafe extern "C" fn f_triple_u32_ret() -> TripleU32 { + TripleU32 { f: 20, g: 21, h: 22 } +} + +// CHECK: .visible .func (.param .align 8 .b8 func_retval0[24]) f_triple_u64_ret( +#[no_mangle] +pub unsafe extern "C" fn f_triple_u64_ret() -> TripleU64 { + TripleU64 { f: 23, g: 24, h: 25 } +} + +// CHECK: .visible .func (.param .align 8 .b8 func_retval0[16]) f_many_integers_ret( +#[no_mangle] +pub unsafe extern "C" fn f_many_integers_ret() -> ManyIntegers { + ManyIntegers { f: 26, g: 27, h: 28, i: 29 } +} + +// CHECK: .visible .func (.param .align 4 .b8 func_retval0[8]) f_double_float_ret( +#[no_mangle] +pub unsafe extern "C" fn f_double_float_ret() -> DoubleFloat { + DoubleFloat { f: 29.0, g: 30.0 } +} + +// CHECK: .visible .func (.param .align 4 .b8 func_retval0[12]) f_triple_float_ret( +#[no_mangle] +pub unsafe extern "C" fn f_triple_float_ret() -> TripleFloat { + TripleFloat { f: 31.0, g: 32.0, h: 33.0 } +} + +// CHECK: .visible .func (.param .align 8 .b8 func_retval0[24]) f_triple_double_ret( +#[no_mangle] +pub unsafe extern "C" fn f_triple_double_ret() -> TripleDouble { + TripleDouble { f: 34.0, g: 35.0, h: 36.0 } +} + +// CHECK: .visible .func (.param .align 8 .b8 func_retval0[32]) f_many_numerics_ret( +#[no_mangle] +pub unsafe extern "C" fn f_many_numerics_ret() -> ManyNumerics { + ManyNumerics { f: 37, g: 38, h: 39, i: 40, j: 41.0, k: 43.0 } +} From 518becf5ea30807f98b89002a70e5640e6e8bbf4 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 14 May 2024 21:09:42 +0200 Subject: [PATCH 004/104] Fail on non-aarch64 targets --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index dbce7f43e62c..b3359b816025 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -617,6 +617,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Date: Wed, 15 May 2024 10:01:55 +0200 Subject: [PATCH 005/104] Use an error struct instead of a panic --- compiler/rustc_codegen_llvm/messages.ftl | 2 ++ compiler/rustc_codegen_llvm/src/errors.rs | 6 +++++ compiler/rustc_codegen_llvm/src/llvm_util.rs | 9 ++++---- tests/ui/abi/fixed_x18.aarch64.stderr | 2 ++ tests/ui/abi/fixed_x18.arm.stderr | 2 ++ tests/ui/abi/fixed_x18.i686.stderr | 2 ++ tests/ui/abi/fixed_x18.riscv32.stderr | 2 ++ tests/ui/abi/fixed_x18.riscv64.stderr | 2 ++ tests/ui/abi/fixed_x18.rs | 23 ++++++++++++++++++++ tests/ui/abi/fixed_x18.x64.stderr | 2 ++ 10 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 tests/ui/abi/fixed_x18.aarch64.stderr create mode 100644 tests/ui/abi/fixed_x18.arm.stderr create mode 100644 tests/ui/abi/fixed_x18.i686.stderr create mode 100644 tests/ui/abi/fixed_x18.riscv32.stderr create mode 100644 tests/ui/abi/fixed_x18.riscv64.stderr create mode 100644 tests/ui/abi/fixed_x18.rs create mode 100644 tests/ui/abi/fixed_x18.x64.stderr diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index d14fe0299e64..1c126e797621 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -18,6 +18,8 @@ codegen_llvm_error_creating_import_library = codegen_llvm_error_writing_def_file = Error writing .DEF file: {$error} +codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture + codegen_llvm_from_llvm_diag = {$message} codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message} diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index e15eda7c66c1..9d83dc811633 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -254,3 +254,9 @@ pub struct MismatchedDataLayout<'a> { pub(crate) struct InvalidTargetFeaturePrefix<'a> { pub feature: &'a str, } + +#[derive(Diagnostic)] +#[diag(codegen_llvm_fixed_x18_invalid_arch)] +pub(crate) struct FixedX18InvalidArch<'a> { + pub arch: &'a str, +} diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index b3359b816025..53b9b530e9bd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,6 +1,6 @@ use crate::back::write::create_informational_target_machine; use crate::errors::{ - InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable, + FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature, }; use crate::llvm; @@ -618,11 +618,10 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Date: Wed, 15 May 2024 12:35:39 +0200 Subject: [PATCH 006/104] Remove fixed_x18.aarch64.stderr --- tests/ui/abi/fixed_x18.aarch64.stderr | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 tests/ui/abi/fixed_x18.aarch64.stderr diff --git a/tests/ui/abi/fixed_x18.aarch64.stderr b/tests/ui/abi/fixed_x18.aarch64.stderr deleted file mode 100644 index 6dc367f9edce..000000000000 --- a/tests/ui/abi/fixed_x18.aarch64.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Zfixed-x18` flag is not supported on the `x86_64` architecture - From 7677ff2879dda850c4e0622116be7751a77a2810 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Wed, 15 May 2024 13:09:02 +0200 Subject: [PATCH 007/104] Remove aarch64 from revisions list --- tests/ui/abi/fixed_x18.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/abi/fixed_x18.rs b/tests/ui/abi/fixed_x18.rs index e62b9c24d223..6d00cb2709da 100644 --- a/tests/ui/abi/fixed_x18.rs +++ b/tests/ui/abi/fixed_x18.rs @@ -1,7 +1,7 @@ // This tests that -Zfixed-x18 causes a compilation failure on targets other than aarch64. // Behavior on aarch64 is tested by tests/codegen/fixed-x18.rs. // -//@ revisions: x64 i686 aarch64 arm riscv32 riscv64 +//@ revisions: x64 i686 arm riscv32 riscv64 // //@ compile-flags: -Zfixed-x18 //@ [x64] needs-llvm-components: x86 From 37aeb75eb6c68dfee49e9ecdbd0c46e137b28bc7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 21 May 2024 14:07:02 +0200 Subject: [PATCH 008/104] don't inhibit random field reordering on repr(packed(1)) --- compiler/rustc_abi/src/layout.rs | 10 ++++++---- compiler/rustc_abi/src/lib.rs | 15 ++++----------- .../src/transmute/transmute_undefined_repr.rs | 2 +- .../miri/tests/fail/reading_half_a_pointer.rs | 2 +- .../field_requires_parent_struct_alignment2.rs | 2 +- tests/mir-opt/const_allocation3.rs | 2 +- 6 files changed, 14 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index a95ef4c460f4..9165b4f2df3d 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -970,7 +970,7 @@ fn univariant< let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; let mut inverse_memory_index: IndexVec = fields.indices().collect(); - let optimize = !repr.inhibit_struct_field_reordering_opt(); + let optimize = !repr.inhibit_struct_field_reordering(); if optimize && fields.len() > 1 { let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; let optimizing = &mut inverse_memory_index.raw[..end]; @@ -1007,13 +1007,15 @@ fn univariant< // Calculates a sort key to group fields by their alignment or possibly some // size-derived pseudo-alignment. let alignment_group_key = |layout: &F| { + // The two branches here return values that cannot be meaningfully compared with + // each other. However, we know that consistently for all executions of + // `alignment_group_key`, one or the other branch will be taken, so this is okay. if let Some(pack) = pack { // Return the packed alignment in bytes. layout.align.abi.min(pack).bytes() } else { - // Returns `log2(effective-align)`. This is ok since `pack` applies to all - // fields equally. The calculation assumes that size is an integer multiple of - // align, except for ZSTs. + // Returns `log2(effective-align)`. The calculation assumes that size is an + // integer multiple of align, except for ZSTs. let align = layout.align.abi.bytes(); let size = layout.size.bytes(); let niche_size = layout.largest_niche.map(|n| n.available(dl)).unwrap_or(0); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 53aa8ad7cca5..b1a17d5a24b6 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -137,23 +137,16 @@ impl ReprOptions { self.c() || self.int.is_some() } - /// Returns `true` if this `#[repr()]` should inhibit struct field reordering - /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr()`. - pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - if let Some(pack) = self.pack { - if pack.bytes() == 1 { - return true; - } - } - + /// Returns `true` if this `#[repr()]` guarantees a fixed field order, + /// e.g. `repr(C)` or `repr()`. + pub fn inhibit_struct_field_reordering(&self) -> bool { self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() } /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` /// was enabled for its declaration crate. pub fn can_randomize_type_layout(&self) -> bool { - !self.inhibit_struct_field_reordering_opt() - && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) + !self.inhibit_struct_field_reordering() && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) } /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 9c8dd37d53dc..3b32e4396b9f 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -278,7 +278,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> ty = sized_ty; continue; } - if def.repr().inhibit_struct_field_reordering_opt() { + if def.repr().inhibit_struct_field_reordering() { ReducedTy::OrderedFields(Some(sized_ty)) } else { ReducedTy::UnorderedFields(ty) diff --git a/src/tools/miri/tests/fail/reading_half_a_pointer.rs b/src/tools/miri/tests/fail/reading_half_a_pointer.rs index 7dd98eab7852..feac30b83c30 100644 --- a/src/tools/miri/tests/fail/reading_half_a_pointer.rs +++ b/src/tools/miri/tests/fail/reading_half_a_pointer.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] // We use packed structs to get around alignment restrictions -#[repr(packed)] +#[repr(C, packed)] struct Data { pad: u8, ptr: &'static i32, diff --git a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.rs b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.rs index 8459c64ed2d3..06dd97deedae 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.rs +++ b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.rs @@ -7,7 +7,7 @@ pub struct Aligned { _pad: [u8; 11], packed: Packed, } -#[repr(packed)] +#[repr(C, packed)] #[derive(Default, Copy, Clone)] pub struct Packed { _pad: [u8; 5], diff --git a/tests/mir-opt/const_allocation3.rs b/tests/mir-opt/const_allocation3.rs index 46be3e1e36e8..9d2006b6fe80 100644 --- a/tests/mir-opt/const_allocation3.rs +++ b/tests/mir-opt/const_allocation3.rs @@ -7,7 +7,7 @@ fn main() { FOO; } -#[repr(packed)] +#[repr(C, packed)] struct Packed { a: [u8; 28], b: &'static i32, From 09c8e39adb5b19d4ff412e8f77ea42c569a8e02d Mon Sep 17 00:00:00 2001 From: surechen Date: Wed, 22 May 2024 18:25:26 +0800 Subject: [PATCH 009/104] A small diagnostic improvement for dropping_copy_types fixes #125189 --- compiler/rustc_lint/messages.ftl | 1 + .../rustc_lint/src/drop_forget_useless.rs | 21 +++++++++-- compiler/rustc_lint/src/lints.rs | 16 +++++++- .../defaults-unsound-62211-1.next.stderr | 6 ++- .../defaults-unsound-62211-2.next.stderr | 6 ++- ...g_copy_types-issue-125189-can-not-fixed.rs | 14 +++++++ ...py_types-issue-125189-can-not-fixed.stderr | 37 +++++++++++++++++++ .../dropping_copy_types-issue-125189.fixed | 10 +++++ .../lint/dropping_copy_types-issue-125189.rs | 10 +++++ .../dropping_copy_types-issue-125189.stderr | 35 ++++++++++++++++++ tests/ui/lint/dropping_copy_types.stderr | 24 ++++++++++-- 11 files changed, 169 insertions(+), 11 deletions(-) create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189.fixed create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189.rs create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 82b90e1660a9..289005e00054 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -197,6 +197,7 @@ lint_drop_trait_constraints = lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result + .suggestion = use `let _ = ...` to ignore the expression or result lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 78ac7f9b2354..5033d194a21e 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -1,11 +1,11 @@ -use rustc_hir::{Arm, Expr, ExprKind, Node}; +use rustc_hir::{Arm, Expr, ExprKind, Node, StmtKind}; use rustc_middle::ty; use rustc_span::sym; use crate::{ lints::{ - DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag, - UndroppedManuallyDropsSuggestion, + DropCopyDiag, DropCopySuggestion, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, + UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, }, LateContext, LateLintPass, LintContext, }; @@ -163,10 +163,23 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { ); } sym::mem_drop if is_copy && !drop_is_single_call_in_arm => { + let sugg = if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) + && let Node::Stmt(stmt) = node + && let StmtKind::Semi(e) = stmt.kind + && e.hir_id == expr.hir_id + { + DropCopySuggestion::Suggestion { + start_span: expr.span.shrink_to_lo().until(arg.span), + end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + } + } else { + DropCopySuggestion::Note + }; + cx.emit_span_lint( DROPPING_COPY_TYPES, expr.span, - DropCopyDiag { arg_ty, label: arg.span }, + DropCopyDiag { arg_ty, label: arg.span, sugg }, ); } sym::mem_forget if is_copy => { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a034bebc85ec..084e818a2758 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -669,11 +669,25 @@ pub struct DropRefDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_dropping_copy_types)] -#[note] pub struct DropCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: DropCopySuggestion, +} + +#[derive(Subdiagnostic)] +pub enum DropCopySuggestion { + #[note(lint_note)] + Note, + #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + Suggestion { + #[suggestion_part(code = "let _ = ")] + start_span: Span, + #[suggestion_part(code = "")] + end_span: Span, + }, } #[derive(LintDiagnostic)] diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr index 834ae00a8d85..ffb02eccc77d 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr @@ -6,8 +6,12 @@ LL | drop(origin); | | | argument has type `::Output` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_copy_types)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(origin); +LL + let _ = origin; + | warning: 1 warning emitted diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr index 0f944a18ed58..e6ae8183e77d 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr @@ -6,8 +6,12 @@ LL | drop(origin); | | | argument has type `::Output` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_copy_types)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(origin); +LL + let _ = origin; + | warning: 1 warning emitted diff --git a/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs new file mode 100644 index 000000000000..12c984c932ac --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs @@ -0,0 +1,14 @@ +//@ check-fail + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + let z = 2; + match y { + 0 => drop(y), //~ ERROR calls to `std::mem::drop` + 1 => drop(z), //~ ERROR calls to `std::mem::drop` + 2 => drop(3), //~ ERROR calls to `std::mem::drop` + _ => {}, + } +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr new file mode 100644 index 000000000000..6c73e5ea90b4 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr @@ -0,0 +1,37 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:9:14 + | +LL | 0 => drop(y), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result +note: the lint level is defined here + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:3:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:10:14 + | +LL | 1 => drop(z), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:11:14 + | +LL | 2 => drop(3), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.fixed b/tests/ui/lint/dropping_copy_types-issue-125189.fixed new file mode 100644 index 000000000000..2dfd68d4cc16 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.fixed @@ -0,0 +1,10 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + let _ = 3.2; //~ ERROR calls to `std::mem::drop` + let _ = y; //~ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.rs b/tests/ui/lint/dropping_copy_types-issue-125189.rs new file mode 100644 index 000000000000..1f42efabba9f --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.rs @@ -0,0 +1,10 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + drop(3.2); //~ ERROR calls to `std::mem::drop` + drop(y); //~ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.stderr b/tests/ui/lint/dropping_copy_types-issue-125189.stderr new file mode 100644 index 000000000000..ba3e36f5b6ec --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.stderr @@ -0,0 +1,35 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189.rs:8:5 + | +LL | drop(3.2); + | ^^^^^---^ + | | + | argument has type `f64` + | +note: the lint level is defined here + --> $DIR/dropping_copy_types-issue-125189.rs:4:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(3.2); +LL + let _ = 3.2; + | + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189.rs:9:5 + | +LL | drop(y); + | ^^^^^-^ + | | + | argument has type `i32` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(y); +LL + let _ = y; + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/dropping_copy_types.stderr b/tests/ui/lint/dropping_copy_types.stderr index b6291aa5ed63..bdeb0c290fe9 100644 --- a/tests/ui/lint/dropping_copy_types.stderr +++ b/tests/ui/lint/dropping_copy_types.stderr @@ -6,12 +6,16 @@ LL | drop(s1); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/dropping_copy_types.rs:3:9 | LL | #![warn(dropping_copy_types)] | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s1); +LL + let _ = s1; + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:35:5 @@ -21,7 +25,11 @@ LL | drop(s2); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s2); +LL + let _ = s2; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:36:5 @@ -42,7 +50,11 @@ LL | drop(s4); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s4); +LL + let _ = s4; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:38:5 @@ -82,7 +94,11 @@ LL | drop(println_and(13)); | | | argument has type `i32` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(println_and(13)); +LL + let _ = println_and(13); + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:74:14 From 0d42cf7afe7e8aa9ded41a503fe852e94b7caa13 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sat, 25 May 2024 14:58:15 -0400 Subject: [PATCH 010/104] Stabilise ip_bits feature --- library/core/src/lib.rs | 1 - library/core/src/net/ip_addr.rs | 28 ++++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 206d1ab88529..d39c0375470b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -174,7 +174,6 @@ #![feature(duration_consts_float)] #![feature(internal_impls_macro)] #![feature(ip)] -#![feature(ip_bits)] #![feature(is_ascii_octdigit)] #![feature(isqrt)] #![feature(link_cfg)] diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 959c3289affb..e008215ebe96 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -460,12 +460,11 @@ impl Ipv4Addr { /// # Examples /// /// ``` - /// #![feature(ip_bits)] /// use std::net::Ipv4Addr; /// /// assert_eq!(Ipv4Addr::BITS, 32); /// ``` - #[unstable(feature = "ip_bits", issue = "113744")] + #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] pub const BITS: u32 = 32; /// Converts an IPv4 address into a `u32` representation using native byte order. @@ -479,7 +478,6 @@ impl Ipv4Addr { /// # Examples /// /// ``` - /// #![feature(ip_bits)] /// use std::net::Ipv4Addr; /// /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); @@ -487,7 +485,6 @@ impl Ipv4Addr { /// ``` /// /// ``` - /// #![feature(ip_bits)] /// use std::net::Ipv4Addr; /// /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); @@ -495,8 +492,8 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x00), Ipv4Addr::from_bits(addr_bits)); /// /// ``` - #[rustc_const_unstable(feature = "ip_bits", issue = "113744")] - #[unstable(feature = "ip_bits", issue = "113744")] + #[rustc_const_stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn to_bits(self) -> u32 { @@ -510,14 +507,13 @@ impl Ipv4Addr { /// # Examples /// /// ``` - /// #![feature(ip_bits)] /// use std::net::Ipv4Addr; /// /// let addr = Ipv4Addr::from(0x12345678); /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr); /// ``` - #[rustc_const_unstable(feature = "ip_bits", issue = "113744")] - #[unstable(feature = "ip_bits", issue = "113744")] + #[rustc_const_stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_bits(bits: u32) -> Ipv4Addr { @@ -1238,12 +1234,11 @@ impl Ipv6Addr { /// # Examples /// /// ``` - /// #![feature(ip_bits)] /// use std::net::Ipv6Addr; /// /// assert_eq!(Ipv6Addr::BITS, 128); /// ``` - #[unstable(feature = "ip_bits", issue = "113744")] + #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] pub const BITS: u32 = 128; /// Converts an IPv6 address into a `u128` representation using native byte order. @@ -1257,7 +1252,6 @@ impl Ipv6Addr { /// # Examples /// /// ``` - /// #![feature(ip_bits)] /// use std::net::Ipv6Addr; /// /// let addr = Ipv6Addr::new( @@ -1268,7 +1262,6 @@ impl Ipv6Addr { /// ``` /// /// ``` - /// #![feature(ip_bits)] /// use std::net::Ipv6Addr; /// /// let addr = Ipv6Addr::new( @@ -1284,8 +1277,8 @@ impl Ipv6Addr { /// Ipv6Addr::from_bits(addr_bits)); /// /// ``` - #[rustc_const_unstable(feature = "ip_bits", issue = "113744")] - #[unstable(feature = "ip_bits", issue = "113744")] + #[rustc_const_stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn to_bits(self) -> u128 { @@ -1299,7 +1292,6 @@ impl Ipv6Addr { /// # Examples /// /// ``` - /// #![feature(ip_bits)] /// use std::net::Ipv6Addr; /// /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128); @@ -1310,8 +1302,8 @@ impl Ipv6Addr { /// ), /// addr); /// ``` - #[rustc_const_unstable(feature = "ip_bits", issue = "113744")] - #[unstable(feature = "ip_bits", issue = "113744")] + #[rustc_const_stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_bits(bits: u128) -> Ipv6Addr { From f63931bc1a8cc44e7fd5cea772da87dfac44bedc Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 26 May 2024 22:00:43 +0000 Subject: [PATCH 011/104] Cleanup custom mingw in CI --- .github/workflows/ci.yml | 3 --- src/ci/github-actions/jobs.yml | 4 ---- src/ci/scripts/install-mingw.sh | 17 ++++------------- src/ci/scripts/install-msys2.sh | 27 --------------------------- 4 files changed, 4 insertions(+), 47 deletions(-) delete mode 100755 src/ci/scripts/install-msys2.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0551d44649cd..3f9936dc5b23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -155,9 +155,6 @@ jobs: - name: checkout submodules run: src/ci/scripts/checkout-submodules.sh - - name: install MSYS2 - run: src/ci/scripts/install-msys2.sh - - name: install MinGW run: src/ci/scripts/install-mingw.sh diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 05470eebf014..ca86f3f0110e 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -378,7 +378,6 @@ auto: # We are intentionally allowing an old toolchain on this builder (and that's # incompatible with LLVM downloads today). NO_DOWNLOAD_CI_LLVM: 1 - CUSTOM_MINGW: 1 <<: *job-windows-8c - image: x86_64-mingw @@ -390,7 +389,6 @@ auto: # We are intentionally allowing an old toolchain on this builder (and that's # incompatible with LLVM downloads today). NO_DOWNLOAD_CI_LLVM: 1 - CUSTOM_MINGW: 1 <<: *job-windows-8c - image: dist-x86_64-msvc @@ -439,7 +437,6 @@ auto: # incompatible with LLVM downloads today). NO_DOWNLOAD_CI_LLVM: 1 SCRIPT: python x.py dist bootstrap --include-default-paths - CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c @@ -453,7 +450,6 @@ auto: # We are intentionally allowing an old toolchain on this builder (and that's # incompatible with LLVM downloads today). NO_DOWNLOAD_CI_LLVM: 1 - CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh index 45541b8b6934..38af8b6acebb 100755 --- a/src/ci/scripts/install-mingw.sh +++ b/src/ci/scripts/install-mingw.sh @@ -1,8 +1,6 @@ #!/bin/bash # If we need to download a custom MinGW, do so here and set the path # appropriately. -# -# Otherwise install MinGW through `pacman` set -euo pipefail IFS=$'\n\t' @@ -16,19 +14,16 @@ if isWindows && isKnownToBeMingwBuild; then case "${CI_JOB_NAME}" in *i686*) bits=32 - arch=i686 mingw_archive="${MINGW_ARCHIVE_32}" ;; *x86_64*) bits=64 - arch=x86_64 mingw_archive="${MINGW_ARCHIVE_64}" ;; *aarch64*) # aarch64 is a cross-compiled target. Use the x86_64 # mingw, since that's the host architecture. bits=64 - arch=x86_64 mingw_archive="${MINGW_ARCHIVE_64}" ;; *) @@ -38,13 +33,9 @@ if isWindows && isKnownToBeMingwBuild; then ;; esac - if [[ "${CUSTOM_MINGW:-0}" == 0 ]]; then - pacman -S --noconfirm --needed mingw-w64-$arch-toolchain - else - mingw_dir="mingw${bits}" + mingw_dir="mingw${bits}" - curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}" - 7z x -y mingw.7z > /dev/null - ciCommandAddPath "$(pwd)/${mingw_dir}/bin" - fi + curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}" + 7z x -y mingw.7z > /dev/null + ciCommandAddPath "$(pwd)/${mingw_dir}/bin" fi diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh deleted file mode 100755 index 968b1e572e43..000000000000 --- a/src/ci/scripts/install-msys2.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# Clean up and prepare the MSYS2 installation. -# MSYS2 is used by the MinGW toolchain for assembling things. - -set -euo pipefail -IFS=$'\n\t' - -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -if isWindows; then - # Detect the native Python version installed on the agent. On GitHub - # Actions, the C:\hostedtoolcache\windows\Python directory contains a - # subdirectory for each installed Python version. - # - # The -V flag of the sort command sorts the input by version number. - native_python_version="$(ls /c/hostedtoolcache/windows/Python | sort -Vr | head -n 1)" - - # Make sure we use the native python interpreter instead of some msys equivalent - # one way or another. The msys interpreters seem to have weird path conversions - # baked in which break LLVM's build system one way or another, so let's use the - # native version which keeps everything as native as possible. - python_home="/c/hostedtoolcache/windows/Python/${native_python_version}/x64" - if ! [[ -f "${python_home}/python3.exe" ]]; then - cp "${python_home}/python.exe" "${python_home}/python3.exe" - fi - ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64" - ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64\\Scripts" -fi From 19cfe8d9e6989c4ea49be203757cd086e0ab015c Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 26 May 2024 22:01:26 +0000 Subject: [PATCH 012/104] Add "Setup Python" action to github-hosted runners --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f9936dc5b23..c9d6c56076a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,6 +154,12 @@ jobs: - name: checkout submodules run: src/ci/scripts/checkout-submodules.sh + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + if: runner.environment == 'github-hosted' - name: install MinGW run: src/ci/scripts/install-mingw.sh From f931290949b215dbf1789dddb66bf6f33c914ba0 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 27 May 2024 09:32:25 +0000 Subject: [PATCH 013/104] Update description of install-mingw --- src/ci/scripts/install-mingw.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh index 38af8b6acebb..31aa3785bc36 100755 --- a/src/ci/scripts/install-mingw.sh +++ b/src/ci/scripts/install-mingw.sh @@ -1,6 +1,5 @@ #!/bin/bash -# If we need to download a custom MinGW, do so here and set the path -# appropriately. +# For mingw builds use a vendored mingw. set -euo pipefail IFS=$'\n\t' From 4c002fce9d8421096538273c9b78db7d68529b94 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 17 Mar 2024 17:42:37 -0400 Subject: [PATCH 014/104] Omit non-needs_drop drop_in_place in vtables This replaces the drop_in_place reference with null in vtables. On librustc_driver.so, this drops about ~17k dynamic relocations from the output, since many vtables can now be placed in read-only memory, rather than having a relocated pointer included. This makes a tradeoff by adding a null check at vtable call sites. That's hard to avoid without changing the vtable format (e.g., to use a pc-relative relocation instead of an absolute address, and avoid the dynamic relocation that way). But it seems likely that the check is cheap at runtime. --- .../rustc_codegen_cranelift/src/abi/mod.rs | 16 ++ compiler/rustc_codegen_cranelift/src/base.rs | 5 +- compiler/rustc_codegen_ssa/src/meth.rs | 27 ++- compiler/rustc_codegen_ssa/src/mir/block.rs | 200 ++++++++++-------- compiler/rustc_middle/src/ty/vtable.rs | 12 +- .../partitioning/vtable-through-const.rs | 43 ++-- tests/codegen/vtable-loads.rs | 16 ++ 7 files changed, 203 insertions(+), 116 deletions(-) create mode 100644 tests/codegen/vtable-loads.rs diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 4bcef15ad047..bd5a88769059 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -593,6 +593,7 @@ pub(crate) fn codegen_drop<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, source_info: mir::SourceInfo, drop_place: CPlace<'tcx>, + target: BasicBlock, ) { let ty = drop_place.layout().ty; let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty).polymorphize(fx.tcx); @@ -620,6 +621,12 @@ pub(crate) fn codegen_drop<'tcx>( let ptr = ptr.get_addr(fx); let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable); + let is_null = fx.bcx.ins().icmp_imm(IntCC::Equal, drop_fn, 0); + let target_block = fx.get_block(target); + let continued = fx.bcx.create_block(); + fx.bcx.ins().brif(is_null, target_block, &[], continued, &[]); + fx.bcx.switch_to_block(continued); + // FIXME(eddyb) perhaps move some of this logic into // `Instance::resolve_drop_in_place`? let virtual_drop = Instance { @@ -659,6 +666,12 @@ pub(crate) fn codegen_drop<'tcx>( let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx); let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable); + let is_null = fx.bcx.ins().icmp_imm(IntCC::Equal, drop_fn, 0); + let target_block = fx.get_block(target); + let continued = fx.bcx.create_block(); + fx.bcx.ins().brif(is_null, target_block, &[], continued, &[]); + fx.bcx.switch_to_block(continued); + let virtual_drop = Instance { def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), args: drop_instance.args, @@ -697,4 +710,7 @@ pub(crate) fn codegen_drop<'tcx>( } } } + + let target_block = fx.get_block(target); + fx.bcx.ins().jump(target_block, &[]); } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 8d778f736d67..c394844e6259 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -548,10 +548,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { } TerminatorKind::Drop { place, target, unwind: _, replace: _ } => { let drop_place = codegen_place(fx, *place); - crate::abi::codegen_drop(fx, source_info, drop_place); - - let target_block = fx.get_block(*target); - fx.bcx.ins().jump(target_block, &[]); + crate::abi::codegen_drop(fx, source_info, drop_place, *target); } }; } diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index d6fc8e536b44..ddc6797388e7 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -15,12 +15,13 @@ impl<'a, 'tcx> VirtualIndex { VirtualIndex(index as u64) } - pub fn get_fn>( + fn get_fn_inner>( self, bx: &mut Bx, llvtable: Bx::Value, ty: Ty<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + nonnull: bool, ) -> Bx::Value { // Load the function pointer from the object. debug!("get_fn({llvtable:?}, {ty:?}, {self:?})"); @@ -41,13 +42,35 @@ impl<'a, 'tcx> VirtualIndex { } else { let gep = bx.inbounds_ptradd(llvtable, bx.const_usize(vtable_byte_offset)); let ptr = bx.load(llty, gep, ptr_align); - bx.nonnull_metadata(ptr); // VTable loads are invariant. bx.set_invariant_load(ptr); + if nonnull { + bx.nonnull_metadata(ptr); + } ptr } } + pub fn get_optional_fn>( + self, + bx: &mut Bx, + llvtable: Bx::Value, + ty: Ty<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + ) -> Bx::Value { + self.get_fn_inner(bx, llvtable, ty, fn_abi, false) + } + + pub fn get_fn>( + self, + bx: &mut Bx, + llvtable: Bx::Value, + ty: Ty<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + ) -> Bx::Value { + self.get_fn_inner(bx, llvtable, ty, fn_abi, true) + } + pub fn get_usize>( self, bx: &mut Bx, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 1cb1ba99a5ab..bd9704b37aea 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -500,6 +500,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, helper: TerminatorCodegenHelper<'tcx>, bx: &mut Bx, + source_info: &mir::SourceInfo, location: mir::Place<'tcx>, target: mir::BasicBlock, unwind: mir::UnwindAction, @@ -523,90 +524,106 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { args1 = [place.val.llval]; &args1[..] }; - let (drop_fn, fn_abi, drop_instance) = - match ty.kind() { - // FIXME(eddyb) perhaps move some of this logic into - // `Instance::resolve_drop_in_place`? - ty::Dynamic(_, _, ty::Dyn) => { - // IN THIS ARM, WE HAVE: - // ty = *mut (dyn Trait) - // which is: exists ( *mut T, Vtable ) - // args[0] args[1] - // - // args = ( Data, Vtable ) - // | - // v - // /-------\ - // | ... | - // \-------/ - // - let virtual_drop = Instance { - def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function - args: drop_fn.args, - }; - debug!("ty = {:?}", ty); - debug!("drop_fn = {:?}", drop_fn); - debug!("args = {:?}", args); - let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty()); - let vtable = args[1]; - // Truncate vtable off of args list - args = &args[..1]; - ( - meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) - .get_fn(bx, vtable, ty, fn_abi), - fn_abi, - virtual_drop, - ) - } - ty::Dynamic(_, _, ty::DynStar) => { - // IN THIS ARM, WE HAVE: - // ty = *mut (dyn* Trait) - // which is: *mut exists (T, Vtable) - // - // args = [ * ] - // | - // v - // ( Data, Vtable ) - // | - // v - // /-------\ - // | ... | - // \-------/ - // - // - // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING - // - // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer) - // vtable = (*args[0]).1 // loads the vtable out - // (data, vtable) // an equivalent Rust `*mut dyn Trait` - // - // SO THEN WE CAN USE THE ABOVE CODE. - let virtual_drop = Instance { - def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function - args: drop_fn.args, - }; - debug!("ty = {:?}", ty); - debug!("drop_fn = {:?}", drop_fn); - debug!("args = {:?}", args); - let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty()); - let meta_ptr = place.project_field(bx, 1); - let meta = bx.load_operand(meta_ptr); - // Truncate vtable off of args list - args = &args[..1]; - debug!("args' = {:?}", args); - ( - meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) - .get_fn(bx, meta.immediate(), ty, fn_abi), - fn_abi, - virtual_drop, - ) - } - _ => ( - bx.get_fn_addr(drop_fn), - bx.fn_abi_of_instance(drop_fn, ty::List::empty()), - drop_fn, - ), - }; + let (maybe_null, drop_fn, fn_abi, drop_instance) = match ty.kind() { + // FIXME(eddyb) perhaps move some of this logic into + // `Instance::resolve_drop_in_place`? + ty::Dynamic(_, _, ty::Dyn) => { + // IN THIS ARM, WE HAVE: + // ty = *mut (dyn Trait) + // which is: exists ( *mut T, Vtable ) + // args[0] args[1] + // + // args = ( Data, Vtable ) + // | + // v + // /-------\ + // | ... | + // \-------/ + // + let virtual_drop = Instance { + def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function + args: drop_fn.args, + }; + debug!("ty = {:?}", ty); + debug!("drop_fn = {:?}", drop_fn); + debug!("args = {:?}", args); + let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty()); + let vtable = args[1]; + // Truncate vtable off of args list + args = &args[..1]; + ( + true, + meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) + .get_optional_fn(bx, vtable, ty, fn_abi), + fn_abi, + virtual_drop, + ) + } + ty::Dynamic(_, _, ty::DynStar) => { + // IN THIS ARM, WE HAVE: + // ty = *mut (dyn* Trait) + // which is: *mut exists (T, Vtable) + // + // args = [ * ] + // | + // v + // ( Data, Vtable ) + // | + // v + // /-------\ + // | ... | + // \-------/ + // + // + // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING + // + // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer) + // vtable = (*args[0]).1 // loads the vtable out + // (data, vtable) // an equivalent Rust `*mut dyn Trait` + // + // SO THEN WE CAN USE THE ABOVE CODE. + let virtual_drop = Instance { + def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function + args: drop_fn.args, + }; + debug!("ty = {:?}", ty); + debug!("drop_fn = {:?}", drop_fn); + debug!("args = {:?}", args); + let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty()); + let meta_ptr = place.project_field(bx, 1); + let meta = bx.load_operand(meta_ptr); + // Truncate vtable off of args list + args = &args[..1]; + debug!("args' = {:?}", args); + ( + true, + meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) + .get_optional_fn(bx, meta.immediate(), ty, fn_abi), + fn_abi, + virtual_drop, + ) + } + _ => ( + false, + bx.get_fn_addr(drop_fn), + bx.fn_abi_of_instance(drop_fn, ty::List::empty()), + drop_fn, + ), + }; + + // We generate a null check for the drop_fn. This saves a bunch of relocations being + // generated for no-op drops. + if maybe_null { + let is_not_null = bx.append_sibling_block("is_not_null"); + let llty = bx.fn_ptr_backend_type(fn_abi); + let null = bx.const_null(llty); + let non_null = + bx.icmp(base::bin_op_to_icmp_predicate(mir::BinOp::Ne, false), drop_fn, null); + bx.cond_br(non_null, is_not_null, helper.llbb_with_cleanup(self, target)); + bx.switch_to_block(is_not_null); + self.set_debug_loc(bx, *source_info); + } + helper.do_call( self, bx, @@ -617,7 +634,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { unwind, &[], Some(drop_instance), - mergeable_succ, + !maybe_null && mergeable_succ, ) } @@ -1346,9 +1363,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { MergingSucc::False } - mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => { - self.codegen_drop_terminator(helper, bx, place, target, unwind, mergeable_succ()) - } + mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => self + .codegen_drop_terminator( + helper, + bx, + &terminator.source_info, + place, + target, + unwind, + mergeable_succ(), + ), mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self .codegen_assert_terminator( diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 2ad194313100..b8371cc2bca5 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -84,10 +84,14 @@ pub(super) fn vtable_allocation_provider<'tcx>( let idx: u64 = u64::try_from(idx).unwrap(); let scalar = match entry { VtblEntry::MetadataDropInPlace => { - let instance = ty::Instance::resolve_drop_in_place(tcx, ty); - let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance); - let fn_ptr = Pointer::from(fn_alloc_id); - Scalar::from_pointer(fn_ptr, &tcx) + if ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) { + let instance = ty::Instance::resolve_drop_in_place(tcx, ty); + let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance); + let fn_ptr = Pointer::from(fn_alloc_id); + Scalar::from_pointer(fn_ptr, &tcx) + } else { + Scalar::from_maybe_pointer(Pointer::null(), &tcx) + } } VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size), VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size), diff --git a/tests/codegen-units/partitioning/vtable-through-const.rs b/tests/codegen-units/partitioning/vtable-through-const.rs index ca4d3822b549..f91c0c0bfdbf 100644 --- a/tests/codegen-units/partitioning/vtable-through-const.rs +++ b/tests/codegen-units/partitioning/vtable-through-const.rs @@ -9,19 +9,25 @@ #![feature(start)] mod mod1 { + struct NeedsDrop; + + impl Drop for NeedsDrop { + fn drop(&mut self) {} + } + pub trait Trait1 { fn do_something(&self) {} fn do_something_else(&self) {} } - impl Trait1 for u32 {} + impl Trait1 for NeedsDrop {} pub trait Trait1Gen { fn do_something(&self, x: T) -> T; fn do_something_else(&self, x: T) -> T; } - impl Trait1Gen for u32 { + impl Trait1Gen for NeedsDrop { fn do_something(&self, x: T) -> T { x } fn do_something_else(&self, x: T) -> T { x } } @@ -30,8 +36,8 @@ mod mod1 { fn id(x: T) -> T { x } // These are referenced, so they produce mono-items (see start()) - pub const TRAIT1_REF: &'static Trait1 = &0u32 as &Trait1; - pub const TRAIT1_GEN_REF: &'static Trait1Gen = &0u32 as &Trait1Gen; + pub const TRAIT1_REF: &'static Trait1 = &NeedsDrop as &Trait1; + pub const TRAIT1_GEN_REF: &'static Trait1Gen = &NeedsDrop as &Trait1Gen; pub const ID_CHAR: fn(char) -> char = id::; @@ -41,47 +47,48 @@ mod mod1 { fn do_something_else(&self) {} } - //~ MONO_ITEM fn ::do_something @@ vtable_through_const-mod1.volatile[Internal] - //~ MONO_ITEM fn ::do_something_else @@ vtable_through_const-mod1.volatile[Internal] - impl Trait2 for u32 {} + //~ MONO_ITEM fn ::do_something @@ vtable_through_const-mod1.volatile[Internal] + //~ MONO_ITEM fn ::do_something_else @@ vtable_through_const-mod1.volatile[Internal] + impl Trait2 for NeedsDrop {} pub trait Trait2Gen { fn do_something(&self, x: T) -> T; fn do_something_else(&self, x: T) -> T; } - impl Trait2Gen for u32 { + impl Trait2Gen for NeedsDrop { fn do_something(&self, x: T) -> T { x } fn do_something_else(&self, x: T) -> T { x } } // These are not referenced, so they do not produce mono-items - pub const TRAIT2_REF: &'static Trait2 = &0u32 as &Trait2; - pub const TRAIT2_GEN_REF: &'static Trait2Gen = &0u32 as &Trait2Gen; + pub const TRAIT2_REF: &'static Trait2 = &NeedsDrop as &Trait2; + pub const TRAIT2_GEN_REF: &'static Trait2Gen = &NeedsDrop as &Trait2Gen; pub const ID_I64: fn(i64) -> i64 = id::; } //~ MONO_ITEM fn start #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(None) @@ vtable_through_const[Internal] + //~ MONO_ITEM fn ::drop @@ vtable_through_const-fallback.cgu[Internal] + //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(Some(mod1::NeedsDrop)) @@ vtable_through_const-fallback.cgu[External] // Since Trait1::do_something() is instantiated via its default implementation, // it is considered a generic and is instantiated here only because it is // referenced in this module. - //~ MONO_ITEM fn ::do_something_else @@ vtable_through_const-mod1.volatile[External] + //~ MONO_ITEM fn ::do_something_else @@ vtable_through_const-mod1.volatile[External] // Although it is never used, Trait1::do_something_else() has to be - // instantiated locally here too, otherwise the <&u32 as &Trait1> vtable + // instantiated locally here too, otherwise the <&NeedsDrop as &Trait1> vtable // could not be fully constructed. - //~ MONO_ITEM fn ::do_something @@ vtable_through_const-mod1.volatile[External] + //~ MONO_ITEM fn ::do_something @@ vtable_through_const-mod1.volatile[External] mod1::TRAIT1_REF.do_something(); // Same as above - //~ MONO_ITEM fn >::do_something @@ vtable_through_const-mod1.volatile[External] - //~ MONO_ITEM fn >::do_something_else @@ vtable_through_const-mod1.volatile[External] - //~ MONO_ITEM fn >::do_something @@ vtable_through_const-mod1.volatile[Internal] - //~ MONO_ITEM fn >::do_something_else @@ vtable_through_const-mod1.volatile[Internal] + //~ MONO_ITEM fn >::do_something @@ vtable_through_const-mod1.volatile[External] + //~ MONO_ITEM fn >::do_something_else @@ vtable_through_const-mod1.volatile[External] + //~ MONO_ITEM fn >::do_something @@ vtable_through_const-mod1.volatile[Internal] + //~ MONO_ITEM fn >::do_something_else @@ vtable_through_const-mod1.volatile[Internal] mod1::TRAIT1_GEN_REF.do_something(0u8); //~ MONO_ITEM fn mod1::id:: @@ vtable_through_const-mod1.volatile[External] diff --git a/tests/codegen/vtable-loads.rs b/tests/codegen/vtable-loads.rs new file mode 100644 index 000000000000..1dd6ca51063b --- /dev/null +++ b/tests/codegen/vtable-loads.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @loop_skips_vtable_load +#[no_mangle] +pub fn loop_skips_vtable_load(x: &dyn Fn()) { + // CHECK: load ptr, ptr %0{{.*}}, !invariant.load + // CHECK-NEXT: tail call void %1 + // CHECK-NOT: load ptr + x(); + for _ in 0..100 { + // CHECK: tail call void %1 + x(); + } +} From 869306418d47f9755f81e1dec9749a167e98d155 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 27 May 2024 23:28:32 +0200 Subject: [PATCH 015/104] miri: avoid making a full copy of all new allocations --- .../src/const_eval/dummy_machine.rs | 2 +- .../src/const_eval/machine.rs | 2 +- .../src/interpret/eval_context.rs | 2 +- .../rustc_const_eval/src/interpret/machine.rs | 58 +++++++++++++------ .../rustc_const_eval/src/interpret/memory.rs | 14 +++-- .../src/mir/interpret/allocation.rs | 43 +++++++------- src/tools/miri/src/concurrency/thread.rs | 13 +++-- src/tools/miri/src/machine.rs | 43 ++++---------- 8 files changed, 92 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index 62979af8a601..9a98677a8448 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -174,7 +174,7 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine { unimplemented!() } - fn init_frame_extra( + fn init_frame( _ecx: &mut InterpCx<'tcx, Self>, _frame: interpret::Frame<'tcx, Self::Provenance>, ) -> interpret::InterpResult<'tcx, interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>> diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 950e7c12da2e..2c0cbc924935 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -655,7 +655,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> { } #[inline(always)] - fn init_frame_extra( + fn init_frame( ecx: &mut InterpCx<'tcx, Self>, frame: Frame<'tcx>, ) -> InterpResult<'tcx, Frame<'tcx>> { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 5cd50a928704..7c2100fcbe38 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -819,7 +819,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { tracing_span: SpanGuard::new(), extra: (), }; - let frame = M::init_frame_extra(self, pre_frame)?; + let frame = M::init_frame(self, pre_frame)?; self.stack_mut().push(frame); // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check). diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 5713e7bd82b3..4ae0aca5a0c0 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -329,27 +329,41 @@ pub trait Machine<'tcx>: Sized { ptr: Pointer, ) -> Option<(AllocId, Size, Self::ProvenanceExtra)>; - /// Called to adjust allocations to the Provenance and AllocExtra of this machine. + /// Called to adjust global allocations to the Provenance and AllocExtra of this machine. /// /// If `alloc` contains pointers, then they are all pointing to globals. /// - /// The way we construct allocations is to always first construct it without extra and then add - /// the extra. This keeps uniform code paths for handling both allocations created by CTFE for - /// globals, and allocations created by Miri during evaluation. - /// - /// `kind` is the kind of the allocation being adjusted; it can be `None` when - /// it's a global and `GLOBAL_KIND` is `None`. - /// /// This should avoid copying if no work has to be done! If this returns an owned /// allocation (because a copy had to be done to adjust things), machine memory will /// cache the result. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) - fn adjust_allocation<'b>( + fn adjust_global_allocation<'b>( ecx: &InterpCx<'tcx, Self>, id: AllocId, - alloc: Cow<'b, Allocation>, - kind: Option>, - ) -> InterpResult<'tcx, Cow<'b, Allocation>>; + alloc: &'b Allocation, + ) -> InterpResult<'tcx, Cow<'b, Allocation>> + { + // The default implementation does a copy; CTFE machines have a more efficient implementation + // based on their particular choice for `Provenance`, `AllocExtra`, and `Bytes`. + let kind = Self::GLOBAL_KIND + .expect("if GLOBAL_KIND is None, adjust_global_allocation must be overwritten"); + let alloc = alloc.adjust_from_tcx(&ecx.tcx, |ptr| ecx.global_root_pointer(ptr))?; + let extra = + Self::init_alloc_extra(ecx, id, MemoryKind::Machine(kind), alloc.size(), alloc.align)?; + Ok(Cow::Owned(alloc.with_extra(extra))) + } + + /// Initialize the extra state of an allocation. + /// + /// This is guaranteed to be called exactly once on all allocations that are accessed by the + /// program. + fn init_alloc_extra( + ecx: &InterpCx<'tcx, Self>, + id: AllocId, + kind: MemoryKind, + size: Size, + align: Align, + ) -> InterpResult<'tcx, Self::AllocExtra>; /// Return a "root" pointer for the given allocation: the one that is used for direct /// accesses to this static/const/fn allocation, or the one returned from the heap allocator. @@ -473,7 +487,7 @@ pub trait Machine<'tcx>: Sized { } /// Called immediately before a new stack frame gets pushed. - fn init_frame_extra( + fn init_frame( ecx: &mut InterpCx<'tcx, Self>, frame: Frame<'tcx, Self::Provenance>, ) -> InterpResult<'tcx, Frame<'tcx, Self::Provenance, Self::FrameExtra>>; @@ -590,13 +604,23 @@ pub macro compile_time_machine(<$tcx: lifetime>) { } #[inline(always)] - fn adjust_allocation<'b>( + fn adjust_global_allocation<'b>( _ecx: &InterpCx<$tcx, Self>, _id: AllocId, - alloc: Cow<'b, Allocation>, - _kind: Option>, + alloc: &'b Allocation, ) -> InterpResult<$tcx, Cow<'b, Allocation>> { - Ok(alloc) + // Overwrite default implementation: no need to adjust anything. + Ok(Cow::Borrowed(alloc)) + } + + fn init_alloc_extra( + _ecx: &InterpCx<$tcx, Self>, + _id: AllocId, + _kind: MemoryKind, + _size: Size, + _align: Align, + ) -> InterpResult<$tcx, Self::AllocExtra> { + Ok(()) } fn extern_static_pointer( diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 40bbfaa92c6f..521f28b7123e 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -239,7 +239,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn allocate_raw_ptr( &mut self, - alloc: Allocation, + alloc: Allocation, kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { let id = self.tcx.reserve_alloc_id(); @@ -248,8 +248,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { M::GLOBAL_KIND.map(MemoryKind::Machine), "dynamically allocating global memory" ); - let alloc = M::adjust_allocation(self, id, Cow::Owned(alloc), Some(kind))?; - self.memory.alloc_map.insert(id, (kind, alloc.into_owned())); + // We have set things up so we don't need to call `adjust_from_tcx` here, + // so we avoid copying the entire allocation contents. + let extra = M::init_alloc_extra(self, id, kind, alloc.size(), alloc.align)?; + let alloc = alloc.with_extra(extra); + self.memory.alloc_map.insert(id, (kind, alloc)); M::adjust_alloc_root_pointer(self, Pointer::from(id), Some(kind)) } @@ -583,11 +586,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; M::before_access_global(self.tcx, &self.machine, id, alloc, def_id, is_write)?; // We got tcx memory. Let the machine initialize its "extra" stuff. - M::adjust_allocation( + M::adjust_global_allocation( self, id, // always use the ID we got as input, not the "hidden" one. - Cow::Borrowed(alloc.inner()), - M::GLOBAL_KIND.map(MemoryKind::Machine), + alloc.inner(), ) } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 791e87735f40..b0f8a047b82f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -266,19 +266,6 @@ impl AllocRange { // The constructors are all without extra; the extra gets added by a machine hook later. impl Allocation { - /// Creates an allocation from an existing `Bytes` value - this is needed for miri FFI support - pub fn from_raw_bytes(bytes: Bytes, align: Align, mutability: Mutability) -> Self { - let size = Size::from_bytes(bytes.len()); - Self { - bytes, - provenance: ProvenanceMap::new(), - init_mask: InitMask::new(size, true), - align, - mutability, - extra: (), - } - } - /// Creates an allocation initialized by the given bytes pub fn from_bytes<'a>( slice: impl Into>, @@ -342,18 +329,30 @@ impl Allocation { Err(x) => x, } } + + /// Add the extra. + pub fn with_extra(self, extra: Extra) -> Allocation { + Allocation { + bytes: self.bytes, + provenance: self.provenance, + init_mask: self.init_mask, + align: self.align, + mutability: self.mutability, + extra, + } + } } impl Allocation { /// Adjust allocation from the ones in `tcx` to a custom Machine instance - /// with a different `Provenance`, `Extra` and `Byte` type. - pub fn adjust_from_tcx( - self, + /// with a different `Provenance` and `Byte` type. + pub fn adjust_from_tcx( + &self, cx: &impl HasDataLayout, - extra: Extra, mut adjust_ptr: impl FnMut(Pointer) -> Result, Err>, - ) -> Result, Err> { - let mut bytes = self.bytes; + ) -> Result, Err> { + // Copy the data. + let mut bytes = Bytes::from_bytes(Cow::Borrowed(&*self.bytes), self.align); // Adjust provenance of pointers stored in this allocation. let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); @@ -369,12 +368,12 @@ impl Allocation { } // Create allocation. Ok(Allocation { - bytes: AllocBytes::from_bytes(Cow::Owned(Vec::from(bytes)), self.align), + bytes, provenance: ProvenanceMap::from_presorted_ptrs(new_provenance), - init_mask: self.init_mask, + init_mask: self.init_mask.clone(), align: self.align, mutability: self.mutability, - extra, + extra: self.extra, }) } } diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 8e8e1182bfff..06af72dadbd3 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -862,14 +862,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if tcx.is_foreign_item(def_id) { throw_unsup_format!("foreign thread-local statics are not supported"); } - let allocation = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?; - let mut allocation = allocation.inner().clone(); + let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?; + // We make a full copy of this allocation. + let mut alloc = alloc.inner().adjust_from_tcx(&this.tcx, |ptr| this.global_root_pointer(ptr))?; // This allocation will be deallocated when the thread dies, so it is not in read-only memory. - allocation.mutability = Mutability::Mut; + alloc.mutability = Mutability::Mut; // Create a fresh allocation with this content. - let new_alloc = this.allocate_raw_ptr(allocation, MiriMemoryKind::Tls.into())?; - this.machine.threads.set_thread_local_alloc(def_id, new_alloc); - Ok(new_alloc) + let ptr = this.allocate_raw_ptr(alloc, MiriMemoryKind::Tls.into())?; + this.machine.threads.set_thread_local_alloc(def_id, ptr); + Ok(ptr) } } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index fc1a655c1232..c9b390eb67e1 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1,7 +1,6 @@ //! Global machine state as well as implementation of the interpreter engine //! `Machine` trait. -use std::borrow::Cow; use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fmt; @@ -1086,40 +1085,33 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } } - fn adjust_allocation<'b>( + fn init_alloc_extra( ecx: &MiriInterpCx<'tcx>, id: AllocId, - alloc: Cow<'b, Allocation>, - kind: Option, - ) -> InterpResult<'tcx, Cow<'b, Allocation>> - { - let kind = kind.expect("we set our STATIC_KIND so this cannot be None"); + kind: MemoryKind, + size: Size, + align: Align, + ) -> InterpResult<'tcx, Self::AllocExtra> { if ecx.machine.tracked_alloc_ids.contains(&id) { - ecx.emit_diagnostic(NonHaltingDiagnostic::CreatedAlloc( - id, - alloc.size(), - alloc.align, - kind, - )); + ecx.emit_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id, size, align, kind)); } - let alloc = alloc.into_owned(); let borrow_tracker = ecx .machine .borrow_tracker .as_ref() - .map(|bt| bt.borrow_mut().new_allocation(id, alloc.size(), kind, &ecx.machine)); + .map(|bt| bt.borrow_mut().new_allocation(id, size, kind, &ecx.machine)); - let race_alloc = ecx.machine.data_race.as_ref().map(|data_race| { + let data_race = ecx.machine.data_race.as_ref().map(|data_race| { data_race::AllocState::new_allocation( data_race, &ecx.machine.threads, - alloc.size(), + size, kind, ecx.machine.current_span(), ) }); - let buffer_alloc = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation); + let weak_memory = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation); // If an allocation is leaked, we want to report a backtrace to indicate where it was // allocated. We don't need to record a backtrace for allocations which are allowed to @@ -1130,17 +1122,6 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { Some(ecx.generate_stacktrace()) }; - let alloc: Allocation = alloc.adjust_from_tcx( - &ecx.tcx, - AllocExtra { - borrow_tracker, - data_race: race_alloc, - weak_memory: buffer_alloc, - backtrace, - }, - |ptr| ecx.global_root_pointer(ptr), - )?; - if matches!(kind, MemoryKind::Machine(kind) if kind.should_save_allocation_span()) { ecx.machine .allocation_spans @@ -1148,7 +1129,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { .insert(id, (ecx.machine.current_span(), None)); } - Ok(Cow::Owned(alloc)) + Ok(AllocExtra { borrow_tracker, data_race, weak_memory, backtrace }) } fn adjust_alloc_root_pointer( @@ -1357,7 +1338,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } #[inline(always)] - fn init_frame_extra( + fn init_frame( ecx: &mut InterpCx<'tcx, Self>, frame: Frame<'tcx, Provenance>, ) -> InterpResult<'tcx, Frame<'tcx, Provenance, FrameExtra<'tcx>>> { From 5ad4ad7aee5e0e63d8a2d95fd5dabf194e56836b Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 13 May 2024 19:35:52 +0200 Subject: [PATCH 016/104] non_local_defs: move out from `#[derive(LintDiagnostic)]` to manual impl --- compiler/rustc_lint/src/lints.rs | 80 +++++++++++++++++++----- compiler/rustc_lint/src/non_local_def.rs | 1 - 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 42963a11f71a..deaf56c8f251 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1329,40 +1329,88 @@ pub struct SuspiciousDoubleRefCloneDiag<'a> { } // non_local_defs.rs -#[derive(LintDiagnostic)] pub enum NonLocalDefinitionsDiag { - #[diag(lint_non_local_definitions_impl)] - #[help] - #[note(lint_non_local)] - #[note(lint_exception)] - #[note(lint_non_local_definitions_deprecation)] Impl { depth: u32, body_kind_descr: &'static str, body_name: String, - #[subdiagnostic] cargo_update: Option, - #[suggestion(lint_const_anon, code = "_", applicability = "machine-applicable")] const_anon: Option, }, - #[diag(lint_non_local_definitions_macro_rules)] MacroRules { depth: u32, body_kind_descr: &'static str, body_name: String, - #[help] help: Option<()>, - #[help(lint_help_doctest)] doctest_help: Option<()>, - #[note(lint_non_local)] - #[note(lint_exception)] - #[note(lint_non_local_definitions_deprecation)] - notes: (), - #[subdiagnostic] cargo_update: Option, }, } +impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { + fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { + match self { + NonLocalDefinitionsDiag::Impl { + depth, + body_kind_descr, + body_name, + cargo_update, + const_anon, + } => { + diag.primary_message(fluent::lint_non_local_definitions_impl); + diag.arg("depth", depth); + diag.arg("body_kind_descr", body_kind_descr); + diag.arg("body_name", body_name); + + diag.help(fluent::lint_help); + diag.note(fluent::lint_non_local); + diag.note(fluent::lint_exception); + diag.note(fluent::lint_non_local_definitions_deprecation); + + if let Some(cargo_update) = cargo_update { + diag.subdiagnostic(&diag.dcx, cargo_update); + } + if let Some(const_anon) = const_anon { + diag.span_suggestion( + const_anon, + fluent::lint_const_anon, + "_", + Applicability::MachineApplicable, + ); + } + } + NonLocalDefinitionsDiag::MacroRules { + depth, + body_kind_descr, + body_name, + help, + doctest_help, + cargo_update, + } => { + diag.primary_message(fluent::lint_non_local_definitions_macro_rules); + diag.arg("depth", depth); + diag.arg("body_kind_descr", body_kind_descr); + diag.arg("body_name", body_name); + + if let Some(()) = help { + diag.help(fluent::lint_help); + } + if let Some(()) = doctest_help { + diag.help(fluent::lint_help_doctest); + } + + diag.note(fluent::lint_non_local); + diag.note(fluent::lint_exception); + diag.note(fluent::lint_non_local_definitions_deprecation); + + if let Some(cargo_update) = cargo_update { + diag.subdiagnostic(&diag.dcx, cargo_update); + } + } + } + } +} + #[derive(Subdiagnostic)] #[note(lint_non_local_definitions_cargo_update)] pub struct NonLocalDefinitionsCargoUpdateNote { diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 87ee5f536280..f112048bb263 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -250,7 +250,6 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { cargo_update: cargo_update(), help: (!is_at_toplevel_doctest).then_some(()), doctest_help: is_at_toplevel_doctest.then_some(()), - notes: (), }, ) } From 06c6a2d9d680c16399fa1e0fffa993ce60fd09f0 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 13 May 2024 19:58:40 +0200 Subject: [PATCH 017/104] non_local_defs: switch to more friendly primary message --- compiler/rustc_lint/messages.ftl | 4 +- .../rustdoc-ui/doctest/non_local_defs.stderr | 2 +- .../lint/non-local-defs/cargo-update.stderr | 2 +- tests/ui/lint/non-local-defs/consts.stderr | 16 ++++---- .../non-local-defs/exhaustive-trait.stderr | 12 +++--- .../ui/lint/non-local-defs/exhaustive.stderr | 40 +++++++++---------- .../from-local-for-global.stderr | 10 ++--- tests/ui/lint/non-local-defs/generics.stderr | 16 ++++---- .../non-local-defs/inside-macro_rules.stderr | 2 +- .../ui/lint/non-local-defs/macro_rules.stderr | 8 ++-- .../trait-solver-overflow-123573.stderr | 2 +- .../ui/lint/non-local-defs/weird-exprs.stderr | 12 +++--- tests/ui/proc-macro/nested-macro-rules.stderr | 2 +- 13 files changed, 64 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index a9304f27fe55..9d3ae7312ee0 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -542,7 +542,7 @@ lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may lint_non_local_definitions_deprecation = this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -lint_non_local_definitions_impl = non-local `impl` definition, they should be avoided as they go against expectation +lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks should be written at the same level as their item .help = move this `impl` block outside the of the current {$body_kind_descr} {$depth -> [one] `{$body_name}` @@ -552,7 +552,7 @@ lint_non_local_definitions_impl = non-local `impl` definition, they should be av .exception = one exception to the rule are anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module and anon-const at the same nesting as the trait or type .const_anon = use a const-anon item to suppress this lint -lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, they should be avoided as they go against expectation +lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module .help = remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> [one] `{$body_name}` diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stderr b/tests/rustdoc-ui/doctest/non_local_defs.stderr index 39a25de1aae7..f8dffe10c11f 100644 --- a/tests/rustdoc-ui/doctest/non_local_defs.stderr +++ b/tests/rustdoc-ui/doctest/non_local_defs.stderr @@ -1,4 +1,4 @@ -warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation +warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/non_local_defs.rs:9:1 | LL | macro_rules! a_macro { () => {} } diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index e9e33b9aa173..640a462c2cfe 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -1,4 +1,4 @@ -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/cargo-update.rs:17:1 | LL | non_local_macro::non_local_impl!(LocalStruct); diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index d15b452b004e..ef86d735b7a8 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -1,4 +1,4 @@ -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:13:5 | LL | const Z: () = { @@ -13,7 +13,7 @@ LL | impl Uto for &Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:24:5 | LL | impl Uto2 for Test {} @@ -24,7 +24,7 @@ LL | impl Uto2 for Test {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:32:5 | LL | impl Uto3 for Test {} @@ -35,7 +35,7 @@ LL | impl Uto3 for Test {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:43:5 | LL | / impl Test { @@ -49,7 +49,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:50:9 | LL | / impl Test { @@ -63,7 +63,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:59:9 | LL | / impl Test { @@ -77,7 +77,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:72:9 | LL | impl Uto9 for Test {} @@ -88,7 +88,7 @@ LL | impl Uto9 for Test {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:79:9 | LL | impl Uto10 for Test {} diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index 8d58d4dd27c5..ea75dcf0c66a 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -1,4 +1,4 @@ -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:7:5 | LL | / impl PartialEq<()> for Dog { @@ -15,7 +15,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:14:5 | LL | / impl PartialEq<()> for &Dog { @@ -31,7 +31,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:21:5 | LL | / impl PartialEq for () { @@ -47,7 +47,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:28:5 | LL | / impl PartialEq<&Dog> for () { @@ -63,7 +63,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:35:5 | LL | / impl PartialEq for &Dog { @@ -79,7 +79,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:42:5 | LL | / impl PartialEq<&Dog> for &Dog { diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index b3697969c4f8..c8f0bbf8c144 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -1,4 +1,4 @@ -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:10:5 | LL | / impl Test { @@ -13,7 +13,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:15:5 | LL | / impl Display for Test { @@ -29,7 +29,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:22:5 | LL | impl dyn Trait {} @@ -40,7 +40,7 @@ LL | impl dyn Trait {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:25:5 | LL | impl Trait for Vec { } @@ -51,7 +51,7 @@ LL | impl Trait for Vec { } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:28:5 | LL | impl Trait for &dyn Trait {} @@ -62,7 +62,7 @@ LL | impl Trait for &dyn Trait {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:31:5 | LL | impl Trait for *mut Test {} @@ -73,7 +73,7 @@ LL | impl Trait for *mut Test {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:34:5 | LL | impl Trait for *mut [Test] {} @@ -84,7 +84,7 @@ LL | impl Trait for *mut [Test] {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:37:5 | LL | impl Trait for [Test; 8] {} @@ -95,7 +95,7 @@ LL | impl Trait for [Test; 8] {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:40:5 | LL | impl Trait for (Test,) {} @@ -106,7 +106,7 @@ LL | impl Trait for (Test,) {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:43:5 | LL | impl Trait for fn(Test) -> () {} @@ -117,7 +117,7 @@ LL | impl Trait for fn(Test) -> () {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:46:5 | LL | impl Trait for fn() -> Test {} @@ -128,7 +128,7 @@ LL | impl Trait for fn() -> Test {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:50:9 | LL | impl Trait for Test {} @@ -139,7 +139,7 @@ LL | impl Trait for Test {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:58:5 | LL | impl Trait for *mut InsideMain {} @@ -150,7 +150,7 @@ LL | impl Trait for *mut InsideMain {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:60:5 | LL | impl Trait for *mut [InsideMain] {} @@ -161,7 +161,7 @@ LL | impl Trait for *mut [InsideMain] {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:62:5 | LL | impl Trait for [InsideMain; 8] {} @@ -172,7 +172,7 @@ LL | impl Trait for [InsideMain; 8] {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:64:5 | LL | impl Trait for (InsideMain,) {} @@ -183,7 +183,7 @@ LL | impl Trait for (InsideMain,) {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:66:5 | LL | impl Trait for fn(InsideMain) -> () {} @@ -194,7 +194,7 @@ LL | impl Trait for fn(InsideMain) -> () {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:68:5 | LL | impl Trait for fn() -> InsideMain {} @@ -205,7 +205,7 @@ LL | impl Trait for fn() -> InsideMain {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:72:9 | LL | / impl Display for InsideMain { @@ -221,7 +221,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:79:9 | LL | / impl InsideMain { diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index 0cd385049aa6..05a8cc06609a 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -1,4 +1,4 @@ -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:8:5 | LL | / impl From for () { @@ -15,7 +15,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:18:5 | LL | / impl From>> for () { @@ -31,7 +31,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:32:5 | LL | impl StillNonLocal for &Foo {} @@ -42,7 +42,7 @@ LL | impl StillNonLocal for &Foo {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:40:5 | LL | / impl From for GlobalSameFunction { @@ -58,7 +58,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:48:5 | LL | / impl From for GlobalSameFunction { diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index 681d9e45e7a0..fd4b844a5bfa 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -1,4 +1,4 @@ -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:9:5 | LL | impl Global for Vec { } @@ -10,7 +10,7 @@ LL | impl Global for Vec { } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:20:5 | LL | impl Uto7 for Test where Local: std::any::Any {} @@ -21,7 +21,7 @@ LL | impl Uto7 for Test where Local: std::any::Any {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:23:5 | LL | impl Uto8 for T {} @@ -32,7 +32,7 @@ LL | impl Uto8 for T {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:32:5 | LL | / impl Default for UwU { @@ -48,7 +48,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:43:5 | LL | / impl AsRef for () { @@ -62,7 +62,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:54:5 | LL | / impl PartialEq for G { @@ -78,7 +78,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:69:5 | LL | / impl From>> for () { @@ -94,7 +94,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:76:5 | LL | / impl From<()> for Wrap { diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index 319682b973d5..531776246637 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -1,4 +1,4 @@ -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/inside-macro_rules.rs:9:13 | LL | impl MacroTrait for OutsideStruct {} diff --git a/tests/ui/lint/non-local-defs/macro_rules.stderr b/tests/ui/lint/non-local-defs/macro_rules.stderr index 125d8e97d87f..57dbdef1ae3e 100644 --- a/tests/ui/lint/non-local-defs/macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/macro_rules.stderr @@ -1,4 +1,4 @@ -warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation +warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/macro_rules.rs:10:5 | LL | macro_rules! m0 { () => { } }; @@ -10,7 +10,7 @@ LL | macro_rules! m0 { () => { } }; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default -warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation +warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/macro_rules.rs:16:1 | LL | non_local_macro::non_local_macro_rules!(my_macro); @@ -23,7 +23,7 @@ LL | non_local_macro::non_local_macro_rules!(my_macro); = note: the macro `non_local_macro::non_local_macro_rules` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` = note: this warning originates in the macro `non_local_macro::non_local_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation +warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/macro_rules.rs:21:5 | LL | macro_rules! m { () => { } }; @@ -34,7 +34,7 @@ LL | macro_rules! m { () => { } }; = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation +warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/macro_rules.rs:29:13 | LL | macro_rules! m2 { () => { } }; diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr index 9a8ab810835c..3dfdca691387 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr @@ -1,4 +1,4 @@ -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/trait-solver-overflow-123573.rs:12:5 | LL | impl Test for &Local {} diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index 015a0cce43b2..e7ce780e51c0 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -1,4 +1,4 @@ -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:8:5 | LL | impl Uto for *mut Test {} @@ -10,7 +10,7 @@ LL | impl Uto for *mut Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:16:9 | LL | impl Uto for Test {} @@ -21,7 +21,7 @@ LL | impl Uto for Test {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:25:9 | LL | / impl Test { @@ -35,7 +35,7 @@ LL | | } = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:34:9 | LL | impl Uto for &Test {} @@ -46,7 +46,7 @@ LL | impl Uto for &Test {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:41:9 | LL | impl Uto for &(Test,) {} @@ -57,7 +57,7 @@ LL | impl Uto for &(Test,) {} = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: non-local `impl` definition, they should be avoided as they go against expectation +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:48:9 | LL | impl Uto for &(Test,Test) {} diff --git a/tests/ui/proc-macro/nested-macro-rules.stderr b/tests/ui/proc-macro/nested-macro-rules.stderr index 270e9161b033..7b5258a15747 100644 --- a/tests/ui/proc-macro/nested-macro-rules.stderr +++ b/tests/ui/proc-macro/nested-macro-rules.stderr @@ -1,4 +1,4 @@ -warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation +warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/auxiliary/nested-macro-rules.rs:7:9 | LL | macro_rules! outer_macro { From de1c122950ac14801f5b1edf25f17e5297f797fd Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 13 May 2024 20:15:57 +0200 Subject: [PATCH 018/104] non_local_defs: improve some notes around trait, bounds, consts - Restrict const-anon exception diag to relevant places - Invoke bounds (and type-inference) in non_local_defs - Specialize diagnostic for impl without Trait --- compiler/rustc_lint/messages.ftl | 6 +- compiler/rustc_lint/src/lints.rs | 30 +++++--- compiler/rustc_lint/src/non_local_def.rs | 9 ++- .../lint/non-local-defs/cargo-update.stderr | 7 +- tests/ui/lint/non-local-defs/consts.stderr | 33 ++++---- .../non-local-defs/exhaustive-trait.stderr | 24 +++--- .../ui/lint/non-local-defs/exhaustive.stderr | 77 +++++++++---------- .../from-local-for-global.stderr | 20 ++--- tests/ui/lint/non-local-defs/generics.stderr | 32 ++++---- .../non-local-defs/inside-macro_rules.stderr | 4 +- .../trait-solver-overflow-123573.stderr | 4 +- .../ui/lint/non-local-defs/weird-exprs.stderr | 23 +++--- 12 files changed, 141 insertions(+), 128 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 9d3ae7312ee0..52d8def425f4 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -548,8 +548,10 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho [one] `{$body_name}` *[other] `{$body_name}` and up {$depth} bodies } - .non_local = an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - .exception = one exception to the rule are anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module and anon-const at the same nesting as the trait or type + .without_trait = methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + .with_trait = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` + .bounds = `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + .exception = anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level .const_anon = use a const-anon item to suppress this lint lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index deaf56c8f251..d3c409bb6e54 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1335,7 +1335,8 @@ pub enum NonLocalDefinitionsDiag { body_kind_descr: &'static str, body_name: String, cargo_update: Option, - const_anon: Option, + const_anon: Option>, + has_trait: bool, }, MacroRules { depth: u32, @@ -1356,6 +1357,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { body_name, cargo_update, const_anon, + has_trait, } => { diag.primary_message(fluent::lint_non_local_definitions_impl); diag.arg("depth", depth); @@ -1363,21 +1365,29 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { diag.arg("body_name", body_name); diag.help(fluent::lint_help); - diag.note(fluent::lint_non_local); - diag.note(fluent::lint_exception); - diag.note(fluent::lint_non_local_definitions_deprecation); + if has_trait { + diag.note(fluent::lint_bounds); + diag.note(fluent::lint_with_trait); + } else { + diag.note(fluent::lint_without_trait); + } if let Some(cargo_update) = cargo_update { diag.subdiagnostic(&diag.dcx, cargo_update); } if let Some(const_anon) = const_anon { - diag.span_suggestion( - const_anon, - fluent::lint_const_anon, - "_", - Applicability::MachineApplicable, - ); + diag.note(fluent::lint_exception); + if let Some(const_anon) = const_anon { + diag.span_suggestion( + const_anon, + fluent::lint_const_anon, + "_", + Applicability::MachineApplicable, + ); + } } + + diag.note(fluent::lint_non_local_definitions_deprecation); } NonLocalDefinitionsDiag::MacroRules { depth, diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index f112048bb263..dc65db5e9ecf 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -202,8 +202,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // Get the span of the parent const item ident (if it's a not a const anon). // // Used to suggest changing the const item to a const anon. - let span_for_const_anon_suggestion = if self.body_depth == 1 - && parent_def_kind == DefKind::Const + let span_for_const_anon_suggestion = if parent_def_kind == DefKind::Const && parent_opt_item_name != Some(kw::Underscore) && let Some(parent) = parent.as_local() && let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent) @@ -215,6 +214,9 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { None }; + let const_anon = matches!(parent_def_kind, DefKind::Const | DefKind::Static { .. }) + .then_some(span_for_const_anon_suggestion); + cx.emit_span_lint( NON_LOCAL_DEFINITIONS, item.span, @@ -225,7 +227,8 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { .map(|s| s.to_ident_string()) .unwrap_or_else(|| "".to_string()), cargo_update: cargo_update(), - const_anon: span_for_const_anon_suggestion, + const_anon, + has_trait: impl_.of_trait.is_some(), }, ) } diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index 640a462c2cfe..af9ca5b0abde 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -5,10 +5,11 @@ LL | non_local_macro::non_local_impl!(LocalStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant `_IMPL_DEBUG` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` + = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level + = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default = note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index ef86d735b7a8..868b65457d1d 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -8,8 +8,9 @@ LL | impl Uto for &Test {} | ^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant `Z` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` + = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -20,8 +21,9 @@ LL | impl Uto2 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current static `A` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` + = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -31,8 +33,9 @@ LL | impl Uto3 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant `B` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` + = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -45,8 +48,7 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -59,8 +61,7 @@ LL | | } | |_________^ | = help: move this `impl` block outside the of the current inline constant `` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -73,8 +74,8 @@ LL | | } | |_________^ | = help: move this `impl` block outside the of the current constant `_` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -84,8 +85,8 @@ LL | impl Uto9 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current closure `` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -95,8 +96,8 @@ LL | impl Uto10 for Test {} | ^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 8 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index ea75dcf0c66a..ca4eec5e5d05 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -10,8 +10,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -27,8 +27,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -43,8 +43,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -59,8 +59,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -75,8 +75,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -91,8 +91,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index c8f0bbf8c144..1fabf84dac66 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -8,8 +8,7 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -25,8 +24,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -36,8 +35,7 @@ LL | impl dyn Trait {} | ^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -47,8 +45,8 @@ LL | impl Trait for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -58,8 +56,8 @@ LL | impl Trait for &dyn Trait {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -69,8 +67,8 @@ LL | impl Trait for *mut Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -80,8 +78,8 @@ LL | impl Trait for *mut [Test] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -91,8 +89,8 @@ LL | impl Trait for [Test; 8] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -102,8 +100,8 @@ LL | impl Trait for (Test,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -113,8 +111,8 @@ LL | impl Trait for fn(Test) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -124,8 +122,8 @@ LL | impl Trait for fn() -> Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -135,8 +133,8 @@ LL | impl Trait for Test {} | ^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current closure `` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -146,8 +144,8 @@ LL | impl Trait for *mut InsideMain {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -157,8 +155,8 @@ LL | impl Trait for *mut [InsideMain] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -168,8 +166,8 @@ LL | impl Trait for [InsideMain; 8] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -179,8 +177,8 @@ LL | impl Trait for (InsideMain,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -190,8 +188,8 @@ LL | impl Trait for fn(InsideMain) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -201,8 +199,8 @@ LL | impl Trait for fn() -> InsideMain {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -217,8 +215,8 @@ LL | | } | |_________^ | = help: move this `impl` block outside the of the current function `inside_inside` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -231,8 +229,7 @@ LL | | } | |_________^ | = help: move this `impl` block outside the of the current function `inside_inside` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 20 warnings emitted diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index 05a8cc06609a..b4ad3f3585cb 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -10,8 +10,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -27,8 +27,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -38,8 +38,8 @@ LL | impl StillNonLocal for &Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `only_global` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -54,8 +54,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `same_function` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -70,8 +70,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `same_function` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 5 warnings emitted diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index fd4b844a5bfa..b62c25b828cf 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -5,8 +5,8 @@ LL | impl Global for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -17,8 +17,8 @@ LL | impl Uto7 for Test where Local: std::any::Any {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `bad` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -28,8 +28,8 @@ LL | impl Uto8 for T {} | ^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `bad` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -44,8 +44,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `fun` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -58,8 +58,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `meow` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -74,8 +74,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `fun2` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -90,8 +90,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `rawr` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -106,8 +106,8 @@ LL | | } | |_____^ | = help: move this `impl` block outside the of the current function `rawr` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 8 warnings emitted diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index 531776246637..8c0a71a67650 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -8,8 +8,8 @@ LL | m!(); | ---- in this macro invocation | = help: move this `impl` block outside the of the current function `my_func` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr index 3dfdca691387..30e46555053d 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr @@ -5,8 +5,8 @@ LL | impl Test for &Local {} | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index e7ce780e51c0..2e0e0695f59d 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -5,8 +5,8 @@ LL | impl Uto for *mut Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -17,8 +17,8 @@ LL | impl Uto for Test {} | ^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -31,8 +31,7 @@ LL | | } | |_________^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -42,8 +41,8 @@ LL | impl Uto for &Test {} | ^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -53,8 +52,8 @@ LL | impl Uto for &(Test,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -64,8 +63,8 @@ LL | impl Uto for &(Test,Test) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies - = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted From 26b873d030f5f6bcc21ea1037c6d546f28f98e52 Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 14 May 2024 12:54:26 +0200 Subject: [PATCH 019/104] non_local_defs: use span of the impl def and not the impl block --- compiler/rustc_lint/src/non_local_def.rs | 2 +- tests/ui/lint/non-local-defs/consts.stderr | 31 ++++----- .../non-local-defs/exhaustive-trait.stderr | 54 ++++------------ .../ui/lint/non-local-defs/exhaustive.stderr | 64 +++++++------------ .../from-local-for-global.stderr | 38 +++-------- tests/ui/lint/non-local-defs/generics.stderr | 49 ++++---------- .../non-local-defs/inside-macro_rules.stderr | 2 +- .../trait-solver-overflow-123573.stderr | 2 +- .../ui/lint/non-local-defs/weird-exprs.stderr | 17 ++--- 9 files changed, 79 insertions(+), 180 deletions(-) diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index dc65db5e9ecf..d4d3afcce3bd 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -219,7 +219,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { cx.emit_span_lint( NON_LOCAL_DEFINITIONS, - item.span, + item.span.shrink_to_lo().to(impl_.self_ty.span), NonLocalDefinitionsDiag::Impl { depth: self.body_depth, body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent), diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 868b65457d1d..e49256e7f35c 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -5,7 +5,7 @@ LL | const Z: () = { | - help: use a const-anon item to suppress this lint: `_` ... LL | impl Uto for &Test {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant `Z` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -18,7 +18,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:24:5 | LL | impl Uto2 for Test {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current static `A` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -30,7 +30,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:32:5 | LL | impl Uto3 for Test {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant `B` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -41,11 +41,8 @@ LL | impl Uto3 for Test {} warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:43:5 | -LL | / impl Test { -LL | | -LL | | fn foo() {} -LL | | } - | |_____^ +LL | impl Test { + | ^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block @@ -54,11 +51,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:50:9 | -LL | / impl Test { -LL | | -LL | | fn hoo() {} -LL | | } - | |_________^ +LL | impl Test { + | ^^^^^^^^^ | = help: move this `impl` block outside the of the current inline constant `` and up 2 bodies = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block @@ -67,11 +61,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:59:9 | -LL | / impl Test { -LL | | -LL | | fn foo2() {} -LL | | } - | |_________^ +LL | impl Test { + | ^^^^^^^^^ | = help: move this `impl` block outside the of the current constant `_` and up 2 bodies = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block @@ -82,7 +73,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:72:9 | LL | impl Uto9 for Test {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current closure `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -93,7 +84,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:79:9 | LL | impl Uto10 for Test {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index ca4eec5e5d05..639957158741 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -1,13 +1,8 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:7:5 | -LL | / impl PartialEq<()> for Dog { -LL | | -LL | | fn eq(&self, _: &()) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl PartialEq<()> for Dog { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -18,13 +13,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:14:5 | -LL | / impl PartialEq<()> for &Dog { -LL | | -LL | | fn eq(&self, _: &()) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl PartialEq<()> for &Dog { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -34,13 +24,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:21:5 | -LL | / impl PartialEq for () { -LL | | -LL | | fn eq(&self, _: &Dog) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl PartialEq for () { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -50,13 +35,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:28:5 | -LL | / impl PartialEq<&Dog> for () { -LL | | -LL | | fn eq(&self, _: &&Dog) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl PartialEq<&Dog> for () { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -66,13 +46,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:35:5 | -LL | / impl PartialEq for &Dog { -LL | | -LL | | fn eq(&self, _: &Dog) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl PartialEq for &Dog { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -82,13 +57,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:42:5 | -LL | / impl PartialEq<&Dog> for &Dog { -LL | | -LL | | fn eq(&self, _: &&Dog) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl PartialEq<&Dog> for &Dog { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index 1fabf84dac66..317838554707 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -1,11 +1,8 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:10:5 | -LL | / impl Test { -LL | | -LL | | fn foo() {} -LL | | } - | |_____^ +LL | impl Test { + | ^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block @@ -15,13 +12,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:15:5 | -LL | / impl Display for Test { -LL | | -LL | | fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl Display for Test { + | ^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -32,7 +24,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:22:5 | LL | impl dyn Trait {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block @@ -42,7 +34,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:25:5 | LL | impl Trait for Vec { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -53,7 +45,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:28:5 | LL | impl Trait for &dyn Trait {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -64,7 +56,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:31:5 | LL | impl Trait for *mut Test {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -75,7 +67,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:34:5 | LL | impl Trait for *mut [Test] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -86,7 +78,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:37:5 | LL | impl Trait for [Test; 8] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -97,7 +89,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:40:5 | LL | impl Trait for (Test,) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -108,7 +100,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:43:5 | LL | impl Trait for fn(Test) -> () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -119,7 +111,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:46:5 | LL | impl Trait for fn() -> Test {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -130,7 +122,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:50:9 | LL | impl Trait for Test {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current closure `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -141,7 +133,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:58:5 | LL | impl Trait for *mut InsideMain {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -152,7 +144,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:60:5 | LL | impl Trait for *mut [InsideMain] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -163,7 +155,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:62:5 | LL | impl Trait for [InsideMain; 8] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -174,7 +166,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:64:5 | LL | impl Trait for (InsideMain,) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -185,7 +177,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:66:5 | LL | impl Trait for fn(InsideMain) -> () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -196,7 +188,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:68:5 | LL | impl Trait for fn() -> InsideMain {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -206,13 +198,8 @@ LL | impl Trait for fn() -> InsideMain {} warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:72:9 | -LL | / impl Display for InsideMain { -LL | | -LL | | fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -LL | | todo!() -LL | | } -LL | | } - | |_________^ +LL | impl Display for InsideMain { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `inside_inside` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -222,11 +209,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:79:9 | -LL | / impl InsideMain { -LL | | -LL | | fn bar() {} -LL | | } - | |_________^ +LL | impl InsideMain { + | ^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `inside_inside` and up 2 bodies = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index b4ad3f3585cb..e5e91e787465 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -1,13 +1,8 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:8:5 | -LL | / impl From for () { -LL | | -LL | | fn from(_: Cat) -> () { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl From for () { + | ^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -18,13 +13,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:18:5 | -LL | / impl From>> for () { -LL | | -LL | | fn from(_: Wrap>) -> Self { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl From>> for () { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -35,7 +25,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/from-local-for-global.rs:32:5 | LL | impl StillNonLocal for &Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `only_global` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -45,13 +35,8 @@ LL | impl StillNonLocal for &Foo {} warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:40:5 | -LL | / impl From for GlobalSameFunction { -LL | | -LL | | fn from(x: Local1) -> GlobalSameFunction { -LL | | x.0 -LL | | } -LL | | } - | |_____^ +LL | impl From for GlobalSameFunction { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `same_function` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -61,13 +46,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:48:5 | -LL | / impl From for GlobalSameFunction { -LL | | -LL | | fn from(x: Local2) -> GlobalSameFunction { -LL | | x.0 -LL | | } -LL | | } - | |_____^ +LL | impl From for GlobalSameFunction { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `same_function` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index b62c25b828cf..26cdb0896b46 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -2,7 +2,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:9:5 | LL | impl Global for Vec { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -14,7 +14,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:20:5 | LL | impl Uto7 for Test where Local: std::any::Any {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `bad` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -25,7 +25,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:23:5 | LL | impl Uto8 for T {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `bad` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -35,13 +35,8 @@ LL | impl Uto8 for T {} warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:32:5 | -LL | / impl Default for UwU { -LL | | -LL | | fn default() -> Self { -LL | | UwU(OwO) -LL | | } -LL | | } - | |_____^ +LL | impl Default for UwU { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `fun` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -51,11 +46,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:43:5 | -LL | / impl AsRef for () { -LL | | -LL | | fn as_ref(&self) -> &Cat { &Cat } -LL | | } - | |_____^ +LL | impl AsRef for () { + | ^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `meow` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -65,13 +57,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:54:5 | -LL | / impl PartialEq for G { -LL | | -LL | | fn eq(&self, _: &B) -> bool { -LL | | true -LL | | } -LL | | } - | |_____^ +LL | impl PartialEq for G { + | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `fun2` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -81,13 +68,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:69:5 | -LL | / impl From>> for () { -LL | | -LL | | fn from(_: Wrap>) -> Self { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl From>> for () { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `rawr` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -97,13 +79,8 @@ LL | | } warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:76:5 | -LL | / impl From<()> for Wrap { -LL | | -LL | | fn from(_: ()) -> Self { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | impl From<()> for Wrap { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `rawr` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index 8c0a71a67650..cace400082ac 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -2,7 +2,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/inside-macro_rules.rs:9:13 | LL | impl MacroTrait for OutsideStruct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | m!(); | ---- in this macro invocation diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr index 30e46555053d..45bc86162ebf 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr @@ -2,7 +2,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/trait-solver-overflow-123573.rs:12:5 | LL | impl Test for &Local {} - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index 2e0e0695f59d..af6df2165d16 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -2,7 +2,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:8:5 | LL | impl Uto for *mut Test {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -14,7 +14,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:16:9 | LL | impl Uto for Test {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -24,11 +24,8 @@ LL | impl Uto for Test {} warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:25:9 | -LL | / impl Test { -LL | | -LL | | fn bar() {} -LL | | } - | |_________^ +LL | impl Test { + | ^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block @@ -38,7 +35,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:34:9 | LL | impl Uto for &Test {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -49,7 +46,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:41:9 | LL | impl Uto for &(Test,) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type @@ -60,7 +57,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:48:9 | LL | impl Uto for &(Test,Test) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type From 22095fbd8d71d46231d0acc7217594ee2fff133b Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 14 May 2024 12:41:27 +0200 Subject: [PATCH 020/104] non_local_defs: use labels to indicate what may need to be moved --- compiler/rustc_lint/messages.ftl | 4 +- compiler/rustc_lint/src/lints.rs | 15 +- compiler/rustc_lint/src/non_local_def.rs | 3 + .../lint/non-local-defs/cargo-update.stderr | 9 +- tests/ui/lint/non-local-defs/consts.stderr | 81 ++++++- .../non-local-defs/exhaustive-trait.stderr | 90 +++++++- .../ui/lint/non-local-defs/exhaustive.stderr | 197 ++++++++++++++++-- .../from-local-for-global.stderr | 69 +++++- tests/ui/lint/non-local-defs/generics.stderr | 100 ++++++++- .../non-local-defs/inside-macro_rules.stderr | 12 +- .../trait-solver-overflow-123573.stderr | 9 +- .../ui/lint/non-local-defs/weird-exprs.stderr | 57 ++++- 12 files changed, 587 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 52d8def425f4..8582148e26cf 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -544,7 +544,7 @@ lint_non_local_definitions_deprecation = this lint may become deny-by-default in lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks should be written at the same level as their item .help = - move this `impl` block outside the of the current {$body_kind_descr} {$depth -> + move this `impl` block outside of the current {$body_kind_descr} {$depth -> [one] `{$body_name}` *[other] `{$body_name}` and up {$depth} bodies } @@ -565,6 +565,8 @@ lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `# .non_local = a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute .exception = one exception to the rule are anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module +lint_non_local_definitions_may_move = may need to be moved as well + lint_non_snake_case = {$sort} `{$name}` should have a snake case name .rename_or_convert_suggestion = rename the identifier or convert it to a snake case raw identifier .cannot_convert_note = `{$sc}` cannot be used as a raw identifier diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index d3c409bb6e54..305cc67c1ee8 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,7 +6,7 @@ use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, - ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, SubdiagMessageOp, + ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, }; use rustc_hir::{def::Namespace, def_id::DefId}; @@ -1336,6 +1336,9 @@ pub enum NonLocalDefinitionsDiag { body_name: String, cargo_update: Option, const_anon: Option>, + move_help: Span, + self_ty: Span, + of_trait: Option, has_trait: bool, }, MacroRules { @@ -1357,6 +1360,9 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { body_name, cargo_update, const_anon, + move_help, + self_ty, + of_trait, has_trait, } => { diag.primary_message(fluent::lint_non_local_definitions_impl); @@ -1364,13 +1370,18 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { diag.arg("body_kind_descr", body_kind_descr); diag.arg("body_name", body_name); - diag.help(fluent::lint_help); if has_trait { diag.note(fluent::lint_bounds); diag.note(fluent::lint_with_trait); } else { diag.note(fluent::lint_without_trait); } + let mut ms = MultiSpan::from_span(move_help); + ms.push_span_label(self_ty, fluent::lint_non_local_definitions_may_move); + if let Some(of_trait) = of_trait { + ms.push_span_label(of_trait, fluent::lint_non_local_definitions_may_move); + } + diag.span_help(ms, fluent::lint_help); if let Some(cargo_update) = cargo_update { diag.subdiagnostic(&diag.dcx, cargo_update); diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index d4d3afcce3bd..6b75e546a66d 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -222,6 +222,9 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { item.span.shrink_to_lo().to(impl_.self_ty.span), NonLocalDefinitionsDiag::Impl { depth: self.body_depth, + move_help: item.span, + self_ty: impl_.self_ty.span, + of_trait: impl_.of_trait.map(|t| t.path.span), body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent), body_name: parent_opt_item_name .map(|s| s.to_ident_string()) diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index af9ca5b0abde..9c9f24cd2e9f 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -4,9 +4,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | non_local_macro::non_local_impl!(LocalStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant `_IMPL_DEBUG` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current constant `_IMPL_DEBUG` + --> $DIR/cargo-update.rs:17:1 + | +LL | non_local_macro::non_local_impl!(LocalStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | may need to be moved as well + | may need to be moved as well = note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index e49256e7f35c..7abf795079e4 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -7,9 +7,16 @@ LL | const Z: () = { LL | impl Uto for &Test {} | ^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant `Z` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current constant `Z` + --> $DIR/consts.rs:13:5 + | +LL | impl Uto for &Test {} + | ^^^^^---^^^^^-----^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -20,9 +27,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto2 for Test {} | ^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current static `A` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current static `A` + --> $DIR/consts.rs:24:5 + | +LL | impl Uto2 for Test {} + | ^^^^^----^^^^^----^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue @@ -32,9 +46,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto3 for Test {} | ^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant `B` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current constant `B` + --> $DIR/consts.rs:32:5 + | +LL | impl Uto3 for Test {} + | ^^^^^----^^^^^----^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue @@ -44,8 +65,18 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block +help: move this `impl` block outside of the current function `main` + --> $DIR/consts.rs:43:5 + | +LL | impl Test { + | ^ ---- may need to be moved as well + | _____| + | | +LL | | +LL | | fn foo() {} +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -54,8 +85,18 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = help: move this `impl` block outside the of the current inline constant `` and up 2 bodies = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block +help: move this `impl` block outside of the current inline constant `` and up 2 bodies + --> $DIR/consts.rs:50:9 + | +LL | impl Test { + | ^ ---- may need to be moved as well + | _________| + | | +LL | | +LL | | fn hoo() {} +LL | | } + | |_________^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -64,8 +105,18 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant `_` and up 2 bodies = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block +help: move this `impl` block outside of the current constant `_` and up 2 bodies + --> $DIR/consts.rs:59:9 + | +LL | impl Test { + | ^ ---- may need to be moved as well + | _________| + | | +LL | | +LL | | fn foo2() {} +LL | | } + | |_________^ = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue @@ -75,9 +126,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto9 for Test {} | ^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current closure `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current closure `` and up 2 bodies + --> $DIR/consts.rs:72:9 + | +LL | impl Uto9 for Test {} + | ^^^^^----^^^^^----^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -86,9 +144,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto10 for Test {} | ^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current constant expression `` and up 2 bodies + --> $DIR/consts.rs:79:9 + | +LL | impl Uto10 for Test {} + | ^^^^^-----^^^^^----^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 8 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index 639957158741..031927ba6692 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -4,9 +4,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl PartialEq<()> for Dog { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive-trait.rs:7:5 + | +LL | impl PartialEq<()> for Dog { + | ^ ------------- --- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn eq(&self, _: &()) -> bool { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -16,9 +29,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl PartialEq<()> for &Dog { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive-trait.rs:14:5 + | +LL | impl PartialEq<()> for &Dog { + | ^ ------------- ---- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn eq(&self, _: &()) -> bool { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -27,9 +53,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl PartialEq for () { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive-trait.rs:21:5 + | +LL | impl PartialEq for () { + | ^ -------------- -- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn eq(&self, _: &Dog) -> bool { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -38,9 +77,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl PartialEq<&Dog> for () { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive-trait.rs:28:5 + | +LL | impl PartialEq<&Dog> for () { + | ^ --------------- -- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn eq(&self, _: &&Dog) -> bool { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -49,9 +101,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl PartialEq for &Dog { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive-trait.rs:35:5 + | +LL | impl PartialEq for &Dog { + | ^ -------------- ---- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn eq(&self, _: &Dog) -> bool { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -60,9 +125,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl PartialEq<&Dog> for &Dog { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive-trait.rs:42:5 + | +LL | impl PartialEq<&Dog> for &Dog { + | ^ --------------- ---- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn eq(&self, _: &&Dog) -> bool { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index 317838554707..91d4b2d4f654 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -4,8 +4,18 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:10:5 + | +LL | impl Test { + | ^ ---- may need to be moved as well + | _____| + | | +LL | | +LL | | fn foo() {} +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -15,9 +25,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Display for Test { | ^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:15:5 + | +LL | impl Display for Test { + | ^ ------- ---- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -26,8 +49,14 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl dyn Trait {} | ^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:22:5 + | +LL | impl dyn Trait {} + | ^^^^^---------^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -36,9 +65,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:25:5 + | +LL | impl Trait for Vec { } + | ^^^^^^^^^^^^^^^-----^^^^^------^^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -47,9 +83,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for &dyn Trait {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:28:5 + | +LL | impl Trait for &dyn Trait {} + | ^^^^^-----^^^^^----------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -58,9 +101,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for *mut Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:31:5 + | +LL | impl Trait for *mut Test {} + | ^^^^^-----^^^^^---------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -69,9 +119,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for *mut [Test] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:34:5 + | +LL | impl Trait for *mut [Test] {} + | ^^^^^-----^^^^^-----------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -80,9 +137,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for [Test; 8] {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:37:5 + | +LL | impl Trait for [Test; 8] {} + | ^^^^^-----^^^^^---------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -91,9 +155,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for (Test,) {} | ^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:40:5 + | +LL | impl Trait for (Test,) {} + | ^^^^^-----^^^^^-------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -102,9 +173,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for fn(Test) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:43:5 + | +LL | impl Trait for fn(Test) -> () {} + | ^^^^^-----^^^^^--------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -113,9 +191,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for fn() -> Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:46:5 + | +LL | impl Trait for fn() -> Test {} + | ^^^^^-----^^^^^------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -124,9 +209,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for Test {} | ^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current closure `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current closure `` and up 2 bodies + --> $DIR/exhaustive.rs:50:9 + | +LL | impl Trait for Test {} + | ^^^^^-----^^^^^----^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -135,9 +227,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for *mut InsideMain {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:58:5 + | +LL | impl Trait for *mut InsideMain {} + | ^^^^^-----^^^^^---------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -146,9 +245,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for *mut [InsideMain] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:60:5 + | +LL | impl Trait for *mut [InsideMain] {} + | ^^^^^-----^^^^^-----------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -157,9 +263,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for [InsideMain; 8] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:62:5 + | +LL | impl Trait for [InsideMain; 8] {} + | ^^^^^-----^^^^^---------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -168,9 +281,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for (InsideMain,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:64:5 + | +LL | impl Trait for (InsideMain,) {} + | ^^^^^-----^^^^^-------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -179,9 +299,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for fn(InsideMain) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:66:5 + | +LL | impl Trait for fn(InsideMain) -> () {} + | ^^^^^-----^^^^^--------------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -190,9 +317,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Trait for fn() -> InsideMain {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/exhaustive.rs:68:5 + | +LL | impl Trait for fn() -> InsideMain {} + | ^^^^^-----^^^^^------------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -201,9 +335,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Display for InsideMain { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `inside_inside` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `inside_inside` and up 2 bodies + --> $DIR/exhaustive.rs:72:9 + | +LL | impl Display for InsideMain { + | ^ ------- ---------- may need to be moved as well + | | | + | _________| may need to be moved as well + | | +LL | | +LL | | fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +LL | | todo!() +LL | | } +LL | | } + | |_________^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -212,8 +359,18 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl InsideMain { | ^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `inside_inside` and up 2 bodies = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block +help: move this `impl` block outside of the current function `inside_inside` and up 2 bodies + --> $DIR/exhaustive.rs:79:9 + | +LL | impl InsideMain { + | ^ ---------- may need to be moved as well + | _________| + | | +LL | | +LL | | fn bar() {} +LL | | } + | |_________^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 20 warnings emitted diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index e5e91e787465..de3fabc97f49 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -4,9 +4,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl From for () { | ^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/from-local-for-global.rs:8:5 + | +LL | impl From for () { + | ^ --------- -- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn from(_: Cat) -> () { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -16,9 +29,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl From>> for () { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/from-local-for-global.rs:18:5 + | +LL | impl From>> for () { + | ^ -------------------------- -- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn from(_: Wrap>) -> Self { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -27,9 +53,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl StillNonLocal for &Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `only_global` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `only_global` + --> $DIR/from-local-for-global.rs:32:5 + | +LL | impl StillNonLocal for &Foo {} + | ^^^^^-------------^^^^^----^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -38,9 +71,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl From for GlobalSameFunction { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `same_function` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `same_function` + --> $DIR/from-local-for-global.rs:40:5 + | +LL | impl From for GlobalSameFunction { + | ^ ------------ ------------------ may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn from(x: Local1) -> GlobalSameFunction { +LL | | x.0 +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -49,9 +95,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl From for GlobalSameFunction { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `same_function` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `same_function` + --> $DIR/from-local-for-global.rs:48:5 + | +LL | impl From for GlobalSameFunction { + | ^ ------------ ------------------ may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn from(x: Local2) -> GlobalSameFunction { +LL | | x.0 +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 5 warnings emitted diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index 26cdb0896b46..8ef6e3b71daf 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -4,9 +4,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Global for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/generics.rs:9:5 + | +LL | impl Global for Vec { } + | ^^^^^^^^^^^^^^^------^^^^^------^^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -16,9 +23,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto7 for Test where Local: std::any::Any {} | ^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `bad` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `bad` + --> $DIR/generics.rs:20:5 + | +LL | impl Uto7 for Test where Local: std::any::Any {} + | ^^^^^----^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -27,9 +41,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto8 for T {} | ^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `bad` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `bad` + --> $DIR/generics.rs:23:5 + | +LL | impl Uto8 for T {} + | ^^^^^^^^----^^^^^-^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -38,9 +59,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Default for UwU { | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `fun` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `fun` + --> $DIR/generics.rs:32:5 + | +LL | impl Default for UwU { + | ^ ------- -------- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn default() -> Self { +LL | | UwU(OwO) +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -49,9 +83,20 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl AsRef for () { | ^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `meow` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `meow` + --> $DIR/generics.rs:43:5 + | +LL | impl AsRef for () { + | ^ ---------- -- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn as_ref(&self) -> &Cat { &Cat } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -60,9 +105,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl PartialEq for G { | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `fun2` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `fun2` + --> $DIR/generics.rs:54:5 + | +LL | impl PartialEq for G { + | ^ ------------ - may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn eq(&self, _: &B) -> bool { +LL | | true +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -71,9 +129,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl From>> for () { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `rawr` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `rawr` + --> $DIR/generics.rs:69:5 + | +LL | impl From>> for () { + | ^ ---------------------- -- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn from(_: Wrap>) -> Self { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -82,9 +153,22 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl From<()> for Wrap { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `rawr` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `rawr` + --> $DIR/generics.rs:76:5 + | +LL | impl From<()> for Wrap { + | ^ -------- ---------- may need to be moved as well + | | | + | _____| may need to be moved as well + | | +LL | | +LL | | fn from(_: ()) -> Self { +LL | | todo!() +LL | | } +LL | | } + | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 8 warnings emitted diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index cace400082ac..0325fd2bdc7f 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -7,9 +7,19 @@ LL | impl MacroTrait for OutsideStruct {} LL | m!(); | ---- in this macro invocation | - = help: move this `impl` block outside the of the current function `my_func` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `my_func` + --> $DIR/inside-macro_rules.rs:9:13 + | +LL | impl MacroTrait for OutsideStruct {} + | ^^^^^----------^^^^^-------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well +... +LL | m!(); + | ---- in this macro invocation = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr index 45bc86162ebf..b52ea62230a7 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr @@ -4,9 +4,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test for &Local {} | ^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current function `main` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/trait-solver-overflow-123573.rs:12:5 + | +LL | impl Test for &Local {} + | ^^^^^----^^^^^------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index af6df2165d16..d49e2b777ddb 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -4,9 +4,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto for *mut Test {} | ^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant expression `` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current constant expression `` + --> $DIR/weird-exprs.rs:8:5 + | +LL | impl Uto for *mut Test {} + | ^^^^^---^^^^^---------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -16,9 +23,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto for Test {} | ^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant expression `` = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current constant expression `` + --> $DIR/weird-exprs.rs:16:9 + | +LL | impl Uto for Test {} + | ^^^^^---^^^^^----^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -27,8 +41,18 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block +help: move this `impl` block outside of the current constant expression `` and up 2 bodies + --> $DIR/weird-exprs.rs:25:9 + | +LL | impl Test { + | ^ ---- may need to be moved as well + | _________| + | | +LL | | +LL | | fn bar() {} +LL | | } + | |_________^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -37,9 +61,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto for &Test {} | ^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current constant expression `` and up 2 bodies + --> $DIR/weird-exprs.rs:34:9 + | +LL | impl Uto for &Test {} + | ^^^^^---^^^^^-----^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -48,9 +79,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto for &(Test,) {} | ^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current constant expression `` and up 2 bodies + --> $DIR/weird-exprs.rs:41:9 + | +LL | impl Uto for &(Test,) {} + | ^^^^^---^^^^^--------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -59,9 +97,16 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Uto for &(Test,Test) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: move this `impl` block outside the of the current constant expression `` and up 2 bodies = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current constant expression `` and up 2 bodies + --> $DIR/weird-exprs.rs:48:9 + | +LL | impl Uto for &(Test,Test) {} + | ^^^^^---^^^^^------------^^^ + | | | + | | may need to be moved as well + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted From 402580bcd5ade168a3a7edd0713821fa7d06dc2c Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 15 May 2024 07:54:37 +0200 Subject: [PATCH 021/104] non_local_defs: improve exception note for impl and macro_rules! - Remove wrong exception text for non-local macro_rules! - Simplify anonymous const exception note --- compiler/rustc_lint/messages.ftl | 3 +-- compiler/rustc_lint/src/lints.rs | 1 - tests/rustdoc-ui/doctest/non_local_defs.stderr | 1 - tests/ui/lint/non-local-defs/cargo-update.stderr | 2 +- tests/ui/lint/non-local-defs/consts.stderr | 8 ++++---- tests/ui/lint/non-local-defs/macro_rules.stderr | 4 ---- tests/ui/proc-macro/nested-macro-rules.stderr | 1 - 7 files changed, 6 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 8582148e26cf..13f6d116b816 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -551,7 +551,7 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho .without_trait = methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block .with_trait = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` .bounds = `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type - .exception = anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level + .exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration .const_anon = use a const-anon item to suppress this lint lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module @@ -563,7 +563,6 @@ lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `# .help_doctest = remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}` .non_local = a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - .exception = one exception to the rule are anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module lint_non_local_definitions_may_move = may need to be moved as well diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 305cc67c1ee8..800cd398adb7 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1421,7 +1421,6 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { } diag.note(fluent::lint_non_local); - diag.note(fluent::lint_exception); diag.note(fluent::lint_non_local_definitions_deprecation); if let Some(cargo_update) = cargo_update { diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stderr b/tests/rustdoc-ui/doctest/non_local_defs.stderr index f8dffe10c11f..2b47e6b5bc4d 100644 --- a/tests/rustdoc-ui/doctest/non_local_defs.stderr +++ b/tests/rustdoc-ui/doctest/non_local_defs.stderr @@ -6,7 +6,6 @@ LL | macro_rules! a_macro { () => {} } | = help: remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() { ... }` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index 9c9f24cd2e9f..617a45aaec87 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -15,7 +15,7 @@ LL | non_local_macro::non_local_impl!(LocalStruct); | may need to be moved as well | may need to be moved as well = note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` - = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level + = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default = note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 7abf795079e4..c05c68d0b55e 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -17,7 +17,7 @@ LL | impl Uto for &Test {} | | | | | may need to be moved as well | may need to be moved as well - = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level + = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -37,7 +37,7 @@ LL | impl Uto2 for Test {} | | | | | may need to be moved as well | may need to be moved as well - = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level + = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -56,7 +56,7 @@ LL | impl Uto3 for Test {} | | | | | may need to be moved as well | may need to be moved as well - = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level + = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -117,7 +117,7 @@ LL | | LL | | fn foo2() {} LL | | } | |_________^ - = note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level + = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item diff --git a/tests/ui/lint/non-local-defs/macro_rules.stderr b/tests/ui/lint/non-local-defs/macro_rules.stderr index 57dbdef1ae3e..4e86fc7b987e 100644 --- a/tests/ui/lint/non-local-defs/macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/macro_rules.stderr @@ -6,7 +6,6 @@ LL | macro_rules! m0 { () => { } }; | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current constant `B` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -18,7 +17,6 @@ LL | non_local_macro::non_local_macro_rules!(my_macro); | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current constant `_MACRO_EXPORT` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: the macro `non_local_macro::non_local_macro_rules` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` = note: this warning originates in the macro `non_local_macro::non_local_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -31,7 +29,6 @@ LL | macro_rules! m { () => { } }; | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module @@ -42,7 +39,6 @@ LL | macro_rules! m2 { () => { } }; | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current associated function `bar` and up 2 bodies = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 4 warnings emitted diff --git a/tests/ui/proc-macro/nested-macro-rules.stderr b/tests/ui/proc-macro/nested-macro-rules.stderr index 7b5258a15747..8fe041d61b81 100644 --- a/tests/ui/proc-macro/nested-macro-rules.stderr +++ b/tests/ui/proc-macro/nested-macro-rules.stderr @@ -19,7 +19,6 @@ LL | nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue note: the lint level is defined here --> $DIR/nested-macro-rules.rs:8:9 From d3dfe14b53e2211138e3a4eae5915351ff62f5bc Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 15 May 2024 14:08:28 +0200 Subject: [PATCH 022/104] non_local_defs: be more precise about what needs to be moved --- compiler/rustc_lint/src/lints.rs | 12 +- compiler/rustc_lint/src/non_local_def.rs | 40 ++++++- .../lint/non-local-defs/cargo-update.stderr | 3 - tests/ui/lint/non-local-defs/consts.stderr | 40 ++----- .../non-local-defs/exhaustive-trait.stderr | 36 +----- .../ui/lint/non-local-defs/exhaustive.stderr | 113 +++++------------- .../from-local-for-global.stderr | 28 ++--- tests/ui/lint/non-local-defs/generics.stderr | 44 +++---- .../non-local-defs/inside-macro_rules.stderr | 5 +- .../non-local-defs/suggest-moving-inner.rs | 17 +++ .../suggest-moving-inner.stderr | 28 +++++ .../trait-solver-overflow-123573.stderr | 7 +- .../ui/lint/non-local-defs/weird-exprs.stderr | 30 +---- 13 files changed, 171 insertions(+), 232 deletions(-) create mode 100644 tests/ui/lint/non-local-defs/suggest-moving-inner.rs create mode 100644 tests/ui/lint/non-local-defs/suggest-moving-inner.stderr diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 800cd398adb7..ad6e7b958c72 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1337,8 +1337,7 @@ pub enum NonLocalDefinitionsDiag { cargo_update: Option, const_anon: Option>, move_help: Span, - self_ty: Span, - of_trait: Option, + may_move: Vec, has_trait: bool, }, MacroRules { @@ -1361,8 +1360,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { cargo_update, const_anon, move_help, - self_ty, - of_trait, + may_move, has_trait, } => { diag.primary_message(fluent::lint_non_local_definitions_impl); @@ -1376,10 +1374,10 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { } else { diag.note(fluent::lint_without_trait); } + let mut ms = MultiSpan::from_span(move_help); - ms.push_span_label(self_ty, fluent::lint_non_local_definitions_may_move); - if let Some(of_trait) = of_trait { - ms.push_span_label(of_trait, fluent::lint_non_local_definitions_may_move); + for sp in may_move { + ms.push_span_label(sp, fluent::lint_non_local_definitions_may_move); } diag.span_help(ms, fluent::lint_help); diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 6b75e546a66d..0805c2e27668 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -1,3 +1,5 @@ +use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::HirId; use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, TyKind}; use rustc_hir::{Path, QPath}; use rustc_infer::infer::InferCtxt; @@ -214,6 +216,29 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { None }; + let mut collector = PathCollector { paths: Vec::new() }; + collector.visit_ty(&impl_.self_ty); + if let Some(of_trait) = &impl_.of_trait { + collector.visit_trait_ref(of_trait); + } + collector.visit_generics(&impl_.generics); + + let may_move: Vec = collector + .paths + .into_iter() + .filter_map(|path| { + if path_has_local_parent(&path, cx, parent, parent_parent) { + if let Some(args) = &path.segments.last().unwrap().args { + Some(path.span.until(args.span_ext)) + } else { + Some(path.span) + } + } else { + None + } + }) + .collect(); + let const_anon = matches!(parent_def_kind, DefKind::Const | DefKind::Static { .. }) .then_some(span_for_const_anon_suggestion); @@ -223,14 +248,13 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { NonLocalDefinitionsDiag::Impl { depth: self.body_depth, move_help: item.span, - self_ty: impl_.self_ty.span, - of_trait: impl_.of_trait.map(|t| t.path.span), body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent), body_name: parent_opt_item_name .map(|s| s.to_ident_string()) .unwrap_or_else(|| "".to_string()), cargo_update: cargo_update(), const_anon, + may_move, has_trait: impl_.of_trait.is_some(), }, ) @@ -348,6 +372,18 @@ impl<'a, 'tcx, F: FnMut(DefId) -> bool> TypeFolder> } } +/// Simple hir::Path collector +struct PathCollector<'tcx> { + paths: Vec>, +} + +impl<'tcx> Visitor<'tcx> for PathCollector<'tcx> { + fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) { + self.paths.push(path.clone()); // need to clone, bc of the restricted lifetime + intravisit::walk_path(self, path) + } +} + /// Given a path and a parent impl def id, this checks if the if parent resolution /// def id correspond to the def id of the parent impl definition. /// diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index 617a45aaec87..30696b0f8e50 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -11,9 +11,6 @@ help: move this `impl` block outside of the current constant `_IMPL_DEBUG` | LL | non_local_macro::non_local_impl!(LocalStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | may need to be moved as well - | may need to be moved as well = note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index c05c68d0b55e..820e3a2d6e0c 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -13,10 +13,7 @@ help: move this `impl` block outside of the current constant `Z` --> $DIR/consts.rs:13:5 | LL | impl Uto for &Test {} - | ^^^^^---^^^^^-----^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^ = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -33,10 +30,7 @@ help: move this `impl` block outside of the current static `A` --> $DIR/consts.rs:24:5 | LL | impl Uto2 for Test {} - | ^^^^^----^^^^^----^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^ = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue @@ -52,10 +46,7 @@ help: move this `impl` block outside of the current constant `B` --> $DIR/consts.rs:32:5 | LL | impl Uto3 for Test {} - | ^^^^^----^^^^^----^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^ = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue @@ -69,10 +60,7 @@ LL | impl Test { help: move this `impl` block outside of the current function `main` --> $DIR/consts.rs:43:5 | -LL | impl Test { - | ^ ---- may need to be moved as well - | _____| - | | +LL | / impl Test { LL | | LL | | fn foo() {} LL | | } @@ -89,10 +77,7 @@ LL | impl Test { help: move this `impl` block outside of the current inline constant `` and up 2 bodies --> $DIR/consts.rs:50:9 | -LL | impl Test { - | ^ ---- may need to be moved as well - | _________| - | | +LL | / impl Test { LL | | LL | | fn hoo() {} LL | | } @@ -109,10 +94,7 @@ LL | impl Test { help: move this `impl` block outside of the current constant `_` and up 2 bodies --> $DIR/consts.rs:59:9 | -LL | impl Test { - | ^ ---- may need to be moved as well - | _________| - | | +LL | / impl Test { LL | | LL | | fn foo2() {} LL | | } @@ -132,10 +114,7 @@ help: move this `impl` block outside of the current closure `` and u --> $DIR/consts.rs:72:9 | LL | impl Uto9 for Test {} - | ^^^^^----^^^^^----^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -150,10 +129,7 @@ help: move this `impl` block outside of the current constant expression ` $DIR/consts.rs:79:9 | LL | impl Uto10 for Test {} - | ^^^^^-----^^^^^----^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 8 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index 031927ba6692..a9e3624fde50 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -9,11 +9,7 @@ LL | impl PartialEq<()> for Dog { help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive-trait.rs:7:5 | -LL | impl PartialEq<()> for Dog { - | ^ ------------- --- may need to be moved as well - | | | - | _____| may need to be moved as well - | | +LL | / impl PartialEq<()> for Dog { LL | | LL | | fn eq(&self, _: &()) -> bool { LL | | todo!() @@ -34,11 +30,7 @@ LL | impl PartialEq<()> for &Dog { help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive-trait.rs:14:5 | -LL | impl PartialEq<()> for &Dog { - | ^ ------------- ---- may need to be moved as well - | | | - | _____| may need to be moved as well - | | +LL | / impl PartialEq<()> for &Dog { LL | | LL | | fn eq(&self, _: &()) -> bool { LL | | todo!() @@ -58,11 +50,7 @@ LL | impl PartialEq for () { help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive-trait.rs:21:5 | -LL | impl PartialEq for () { - | ^ -------------- -- may need to be moved as well - | | | - | _____| may need to be moved as well - | | +LL | / impl PartialEq for () { LL | | LL | | fn eq(&self, _: &Dog) -> bool { LL | | todo!() @@ -82,11 +70,7 @@ LL | impl PartialEq<&Dog> for () { help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive-trait.rs:28:5 | -LL | impl PartialEq<&Dog> for () { - | ^ --------------- -- may need to be moved as well - | | | - | _____| may need to be moved as well - | | +LL | / impl PartialEq<&Dog> for () { LL | | LL | | fn eq(&self, _: &&Dog) -> bool { LL | | todo!() @@ -106,11 +90,7 @@ LL | impl PartialEq for &Dog { help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive-trait.rs:35:5 | -LL | impl PartialEq for &Dog { - | ^ -------------- ---- may need to be moved as well - | | | - | _____| may need to be moved as well - | | +LL | / impl PartialEq for &Dog { LL | | LL | | fn eq(&self, _: &Dog) -> bool { LL | | todo!() @@ -130,11 +110,7 @@ LL | impl PartialEq<&Dog> for &Dog { help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive-trait.rs:42:5 | -LL | impl PartialEq<&Dog> for &Dog { - | ^ --------------- ---- may need to be moved as well - | | | - | _____| may need to be moved as well - | | +LL | / impl PartialEq<&Dog> for &Dog { LL | | LL | | fn eq(&self, _: &&Dog) -> bool { LL | | todo!() diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index 91d4b2d4f654..c6b8dc26e31c 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -8,10 +8,7 @@ LL | impl Test { help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:10:5 | -LL | impl Test { - | ^ ---- may need to be moved as well - | _____| - | | +LL | / impl Test { LL | | LL | | fn foo() {} LL | | } @@ -30,11 +27,7 @@ LL | impl Display for Test { help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:15:5 | -LL | impl Display for Test { - | ^ ------- ---- may need to be moved as well - | | | - | _____| may need to be moved as well - | | +LL | / impl Display for Test { LL | | LL | | fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { LL | | todo!() @@ -54,9 +47,7 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:22:5 | LL | impl dyn Trait {} - | ^^^^^---------^^^ - | | - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -71,10 +62,7 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:25:5 | LL | impl Trait for Vec { } - | ^^^^^^^^^^^^^^^-----^^^^^------^^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -89,10 +77,7 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:28:5 | LL | impl Trait for &dyn Trait {} - | ^^^^^-----^^^^^----------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -107,10 +92,7 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:31:5 | LL | impl Trait for *mut Test {} - | ^^^^^-----^^^^^---------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -125,10 +107,7 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:34:5 | LL | impl Trait for *mut [Test] {} - | ^^^^^-----^^^^^-----------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -143,10 +122,7 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:37:5 | LL | impl Trait for [Test; 8] {} - | ^^^^^-----^^^^^---------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -161,10 +137,7 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:40:5 | LL | impl Trait for (Test,) {} - | ^^^^^-----^^^^^-------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -179,10 +152,7 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:43:5 | LL | impl Trait for fn(Test) -> () {} - | ^^^^^-----^^^^^--------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -197,10 +167,7 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:46:5 | LL | impl Trait for fn() -> Test {} - | ^^^^^-----^^^^^------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -215,10 +182,7 @@ help: move this `impl` block outside of the current closure `` and u --> $DIR/exhaustive.rs:50:9 | LL | impl Trait for Test {} - | ^^^^^-----^^^^^----^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -233,10 +197,9 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:58:5 | LL | impl Trait for *mut InsideMain {} - | ^^^^^-----^^^^^---------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^----------^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -251,10 +214,9 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:60:5 | LL | impl Trait for *mut [InsideMain] {} - | ^^^^^-----^^^^^-----------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^----------^^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -269,10 +231,9 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:62:5 | LL | impl Trait for [InsideMain; 8] {} - | ^^^^^-----^^^^^---------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^----------^^^^^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -287,10 +248,9 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:64:5 | LL | impl Trait for (InsideMain,) {} - | ^^^^^-----^^^^^-------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^----------^^^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -305,10 +265,9 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:66:5 | LL | impl Trait for fn(InsideMain) -> () {} - | ^^^^^-----^^^^^--------------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^----------^^^^^^^^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -323,10 +282,9 @@ help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:68:5 | LL | impl Trait for fn() -> InsideMain {} - | ^^^^^-----^^^^^------------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^----------^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -340,11 +298,7 @@ LL | impl Display for InsideMain { help: move this `impl` block outside of the current function `inside_inside` and up 2 bodies --> $DIR/exhaustive.rs:72:9 | -LL | impl Display for InsideMain { - | ^ ------- ---------- may need to be moved as well - | | | - | _________| may need to be moved as well - | | +LL | / impl Display for InsideMain { LL | | LL | | fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { LL | | todo!() @@ -363,10 +317,7 @@ LL | impl InsideMain { help: move this `impl` block outside of the current function `inside_inside` and up 2 bodies --> $DIR/exhaustive.rs:79:9 | -LL | impl InsideMain { - | ^ ---------- may need to be moved as well - | _________| - | | +LL | / impl InsideMain { LL | | LL | | fn bar() {} LL | | } diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index de3fabc97f49..27ffe35532a3 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -9,11 +9,7 @@ LL | impl From for () { help: move this `impl` block outside of the current function `main` --> $DIR/from-local-for-global.rs:8:5 | -LL | impl From for () { - | ^ --------- -- may need to be moved as well - | | | - | _____| may need to be moved as well - | | +LL | / impl From for () { LL | | LL | | fn from(_: Cat) -> () { LL | | todo!() @@ -35,9 +31,8 @@ help: move this `impl` block outside of the current function `main` --> $DIR/from-local-for-global.rs:18:5 | LL | impl From>> for () { - | ^ -------------------------- -- may need to be moved as well - | | | - | _____| may need to be moved as well + | ^ -------- may need to be moved as well + | _____| | | LL | | LL | | fn from(_: Wrap>) -> Self { @@ -59,10 +54,9 @@ help: move this `impl` block outside of the current function `only_global` --> $DIR/from-local-for-global.rs:32:5 | LL | impl StillNonLocal for &Foo {} - | ^^^^^-------------^^^^^----^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^---^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -77,9 +71,8 @@ help: move this `impl` block outside of the current function `same_function` --> $DIR/from-local-for-global.rs:40:5 | LL | impl From for GlobalSameFunction { - | ^ ------------ ------------------ may need to be moved as well - | | | - | _____| may need to be moved as well + | ^ ------ may need to be moved as well + | _____| | | LL | | LL | | fn from(x: Local1) -> GlobalSameFunction { @@ -101,9 +94,8 @@ help: move this `impl` block outside of the current function `same_function` --> $DIR/from-local-for-global.rs:48:5 | LL | impl From for GlobalSameFunction { - | ^ ------------ ------------------ may need to be moved as well - | | | - | _____| may need to be moved as well + | ^ ------ may need to be moved as well + | _____| | | LL | | LL | | fn from(x: Local2) -> GlobalSameFunction { diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index 8ef6e3b71daf..1adefd40ffb0 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -10,10 +10,9 @@ help: move this `impl` block outside of the current function `main` --> $DIR/generics.rs:9:5 | LL | impl Global for Vec { } - | ^^^^^^^^^^^^^^^------^^^^^------^^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -29,10 +28,9 @@ help: move this `impl` block outside of the current function `bad` --> $DIR/generics.rs:20:5 | LL | impl Uto7 for Test where Local: std::any::Any {} - | ^^^^^----^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -47,10 +45,7 @@ help: move this `impl` block outside of the current function `bad` --> $DIR/generics.rs:23:5 | LL | impl Uto8 for T {} - | ^^^^^^^^----^^^^^-^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -65,9 +60,8 @@ help: move this `impl` block outside of the current function `fun` --> $DIR/generics.rs:32:5 | LL | impl Default for UwU { - | ^ ------- -------- may need to be moved as well - | | | - | _____| may need to be moved as well + | ^ --- may need to be moved as well + | _____| | | LL | | LL | | fn default() -> Self { @@ -89,9 +83,8 @@ help: move this `impl` block outside of the current function `meow` --> $DIR/generics.rs:43:5 | LL | impl AsRef for () { - | ^ ---------- -- may need to be moved as well - | | | - | _____| may need to be moved as well + | ^ --- may need to be moved as well + | _____| | | LL | | LL | | fn as_ref(&self) -> &Cat { &Cat } @@ -111,9 +104,8 @@ help: move this `impl` block outside of the current function `fun2` --> $DIR/generics.rs:54:5 | LL | impl PartialEq for G { - | ^ ------------ - may need to be moved as well - | | | - | _____| may need to be moved as well + | ^ - may need to be moved as well + | _____| | | LL | | LL | | fn eq(&self, _: &B) -> bool { @@ -135,9 +127,8 @@ help: move this `impl` block outside of the current function `rawr` --> $DIR/generics.rs:69:5 | LL | impl From>> for () { - | ^ ---------------------- -- may need to be moved as well - | | | - | _____| may need to be moved as well + | ^ ---- may need to be moved as well + | _____| | | LL | | LL | | fn from(_: Wrap>) -> Self { @@ -159,9 +150,8 @@ help: move this `impl` block outside of the current function `rawr` --> $DIR/generics.rs:76:5 | LL | impl From<()> for Wrap { - | ^ -------- ---------- may need to be moved as well - | | | - | _____| may need to be moved as well + | ^ ---- may need to be moved as well + | _____| | | LL | | LL | | fn from(_: ()) -> Self { diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index 0325fd2bdc7f..fea211a4e507 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -13,10 +13,7 @@ help: move this `impl` block outside of the current function `my_func` --> $DIR/inside-macro_rules.rs:9:13 | LL | impl MacroTrait for OutsideStruct {} - | ^^^^^----------^^^^^-------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | m!(); | ---- in this macro invocation diff --git a/tests/ui/lint/non-local-defs/suggest-moving-inner.rs b/tests/ui/lint/non-local-defs/suggest-moving-inner.rs new file mode 100644 index 000000000000..61b32e5bad9f --- /dev/null +++ b/tests/ui/lint/non-local-defs/suggest-moving-inner.rs @@ -0,0 +1,17 @@ +//@ check-pass + +trait Trait {} + +fn main() { + mod below { + pub struct Type(T); + } + struct InsideMain; + trait HasFoo {} + + impl Trait for &Vec> + //~^ WARN non-local `impl` definition + where + T: HasFoo + {} +} diff --git a/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr b/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr new file mode 100644 index 000000000000..83557a7b9a27 --- /dev/null +++ b/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr @@ -0,0 +1,28 @@ +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item + --> $DIR/suggest-moving-inner.rs:12:5 + | +LL | impl Trait for &Vec> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` +help: move this `impl` block outside of the current function `main` + --> $DIR/suggest-moving-inner.rs:12:5 + | +LL | impl Trait for &Vec> + | ^ ---------- ----------- ---------- may need to be moved as well + | | | | + | | | may need to be moved as well + | _____| may need to be moved as well + | | +LL | | +LL | | where +LL | | T: HasFoo + | | ------ may need to be moved as well +LL | | {} + | |______^ + = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue + = note: `#[warn(non_local_definitions)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr index b52ea62230a7..252296099f60 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr @@ -10,10 +10,9 @@ help: move this `impl` block outside of the current function `main` --> $DIR/trait-solver-overflow-123573.rs:12:5 | LL | impl Test for &Local {} - | ^^^^^----^^^^^------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^-----^^^ + | | + | may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index d49e2b777ddb..e8cd4ffef095 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -10,10 +10,7 @@ help: move this `impl` block outside of the current constant expression ` $DIR/weird-exprs.rs:8:5 | LL | impl Uto for *mut Test {} - | ^^^^^---^^^^^---------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -29,10 +26,7 @@ help: move this `impl` block outside of the current constant expression ` $DIR/weird-exprs.rs:16:9 | LL | impl Uto for Test {} - | ^^^^^---^^^^^----^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -45,10 +39,7 @@ LL | impl Test { help: move this `impl` block outside of the current constant expression `` and up 2 bodies --> $DIR/weird-exprs.rs:25:9 | -LL | impl Test { - | ^ ---- may need to be moved as well - | _________| - | | +LL | / impl Test { LL | | LL | | fn bar() {} LL | | } @@ -67,10 +58,7 @@ help: move this `impl` block outside of the current constant expression ` $DIR/weird-exprs.rs:34:9 | LL | impl Uto for &Test {} - | ^^^^^---^^^^^-----^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -85,10 +73,7 @@ help: move this `impl` block outside of the current constant expression ` $DIR/weird-exprs.rs:41:9 | LL | impl Uto for &(Test,) {} - | ^^^^^---^^^^^--------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -103,10 +88,7 @@ help: move this `impl` block outside of the current constant expression ` $DIR/weird-exprs.rs:48:9 | LL | impl Uto for &(Test,Test) {} - | ^^^^^---^^^^^------------^^^ - | | | - | | may need to be moved as well - | may need to be moved as well + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted From ab23fd8dea02b9e525771ed8ec6cca1ff6d414e4 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 15 May 2024 14:17:30 +0200 Subject: [PATCH 023/104] non_local_defs: improve main without a trait note --- compiler/rustc_lint/messages.ftl | 2 +- tests/ui/lint/non-local-defs/consts.stderr | 6 +++--- tests/ui/lint/non-local-defs/exhaustive.stderr | 6 +++--- tests/ui/lint/non-local-defs/weird-exprs.stderr | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 13f6d116b816..f1273b8bf4b5 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -548,7 +548,7 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho [one] `{$body_name}` *[other] `{$body_name}` and up {$depth} bodies } - .without_trait = methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + .without_trait = methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` .with_trait = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` .bounds = `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type .exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 820e3a2d6e0c..0528f63ac9c5 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -56,7 +56,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current function `main` --> $DIR/consts.rs:43:5 | @@ -73,7 +73,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current inline constant `` and up 2 bodies --> $DIR/consts.rs:50:9 | @@ -90,7 +90,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current constant `_` and up 2 bodies --> $DIR/consts.rs:59:9 | diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index c6b8dc26e31c..29f5f14ef0d7 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -4,7 +4,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:10:5 | @@ -42,7 +42,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl dyn Trait {} | ^^^^^^^^^^^^^^ | - = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current function `main` --> $DIR/exhaustive.rs:22:5 | @@ -313,7 +313,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl InsideMain { | ^^^^^^^^^^^^^^^ | - = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current function `inside_inside` and up 2 bodies --> $DIR/exhaustive.rs:79:9 | diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index e8cd4ffef095..cced11719032 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -35,7 +35,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam LL | impl Test { | ^^^^^^^^^ | - = note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block + = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current constant expression `` and up 2 bodies --> $DIR/weird-exprs.rs:25:9 | From b71952904df8b48eb78ba54a1706680c722cb2cb Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 15 May 2024 14:55:40 +0200 Subject: [PATCH 024/104] non_local_defs: suggest removing leading ref/ptr to make the impl local --- compiler/rustc_lint/messages.ftl | 3 +- compiler/rustc_lint/src/lints.rs | 14 +++- compiler/rustc_lint/src/non_local_def.rs | 80 ++++++++++++------- .../ui/lint/non-local-defs/exhaustive.stderr | 4 +- .../from-local-for-global.stderr | 4 +- .../trait-solver-overflow-123573.stderr | 4 +- 6 files changed, 75 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index f1273b8bf4b5..f93534c316f9 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -543,11 +543,12 @@ lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may lint_non_local_definitions_deprecation = this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks should be written at the same level as their item - .help = + .move_help = move this `impl` block outside of the current {$body_kind_descr} {$depth -> [one] `{$body_name}` *[other] `{$body_name}` and up {$depth} bodies } + .remove_help = remove `{$may_remove_part}` to make the `impl` local .without_trait = methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` .with_trait = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` .bounds = `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ad6e7b958c72..ca980d33e8ee 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1338,6 +1338,7 @@ pub enum NonLocalDefinitionsDiag { const_anon: Option>, move_help: Span, may_move: Vec, + may_remove: Option<(Span, String)>, has_trait: bool, }, MacroRules { @@ -1361,6 +1362,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { const_anon, move_help, may_move, + may_remove, has_trait, } => { diag.primary_message(fluent::lint_non_local_definitions_impl); @@ -1379,7 +1381,17 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { for sp in may_move { ms.push_span_label(sp, fluent::lint_non_local_definitions_may_move); } - diag.span_help(ms, fluent::lint_help); + diag.span_help(ms, fluent::lint_move_help); + + if let Some((span, part)) = may_remove { + diag.arg("may_remove_part", part); + diag.span_suggestion( + span, + fluent::lint_remove_help, + "", + Applicability::MaybeIncorrect, + ); + } if let Some(cargo_update) = cargo_update { diag.subdiagnostic(&diag.dcx, cargo_update); diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 0805c2e27668..ed932e1c235c 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -136,35 +136,8 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { }; // Part 1: Is the Self type local? - let self_ty_has_local_parent = match impl_.self_ty.kind { - TyKind::Path(QPath::Resolved(_, ty_path)) => { - path_has_local_parent(ty_path, cx, parent, parent_parent) - } - TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => { - path_has_local_parent( - principle_poly_trait_ref.trait_ref.path, - cx, - parent, - parent_parent, - ) - } - TyKind::TraitObject([], _, _) - | TyKind::InferDelegation(_, _) - | TyKind::Slice(_) - | TyKind::Array(_, _) - | TyKind::Ptr(_) - | TyKind::Ref(_, _) - | TyKind::BareFn(_) - | TyKind::Never - | TyKind::Tup(_) - | TyKind::Path(_) - | TyKind::Pat(..) - | TyKind::AnonAdt(_) - | TyKind::OpaqueDef(_, _, _) - | TyKind::Typeof(_) - | TyKind::Infer - | TyKind::Err(_) => false, - }; + let self_ty_has_local_parent = + ty_has_local_parent(&impl_.self_ty.kind, cx, parent, parent_parent); if self_ty_has_local_parent { return; @@ -242,6 +215,18 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { let const_anon = matches!(parent_def_kind, DefKind::Const | DefKind::Static { .. }) .then_some(span_for_const_anon_suggestion); + let may_remove = match &impl_.self_ty.kind { + TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) + if ty_has_local_parent(&mut_ty.ty.kind, cx, parent, parent_parent) => + { + let type_ = + if matches!(impl_.self_ty.kind, TyKind::Ptr(_)) { "*" } else { "&" }; + let part = format!("{}{}", type_, mut_ty.mutbl.prefix_str()); + Some((impl_.self_ty.span.shrink_to_lo().until(mut_ty.ty.span), part)) + } + _ => None, + }; + cx.emit_span_lint( NON_LOCAL_DEFINITIONS, item.span.shrink_to_lo().to(impl_.self_ty.span), @@ -255,6 +240,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { cargo_update: cargo_update(), const_anon, may_move, + may_remove, has_trait: impl_.of_trait.is_some(), }, ) @@ -384,6 +370,42 @@ impl<'tcx> Visitor<'tcx> for PathCollector<'tcx> { } } +/// Given a `Ty` we check if the (outermost) type is local. +fn ty_has_local_parent( + ty_kind: &TyKind<'_>, + cx: &LateContext<'_>, + impl_parent: DefId, + impl_parent_parent: Option, +) -> bool { + match ty_kind { + TyKind::Path(QPath::Resolved(_, ty_path)) => { + path_has_local_parent(ty_path, cx, impl_parent, impl_parent_parent) + } + TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => path_has_local_parent( + principle_poly_trait_ref.trait_ref.path, + cx, + impl_parent, + impl_parent_parent, + ), + TyKind::TraitObject([], _, _) + | TyKind::InferDelegation(_, _) + | TyKind::Slice(_) + | TyKind::Array(_, _) + | TyKind::Ptr(_) + | TyKind::Ref(_, _) + | TyKind::BareFn(_) + | TyKind::Never + | TyKind::Tup(_) + | TyKind::Path(_) + | TyKind::Pat(..) + | TyKind::AnonAdt(_) + | TyKind::OpaqueDef(_, _, _) + | TyKind::Typeof(_) + | TyKind::Infer + | TyKind::Err(_) => false, + } +} + /// Given a path and a parent impl def id, this checks if the if parent resolution /// def id correspond to the def id of the parent impl definition. /// diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index 29f5f14ef0d7..7316182a4df0 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -189,7 +189,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:58:5 | LL | impl Trait for *mut InsideMain {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^-----^^^^^^^^^^ + | | + | help: remove `*mut ` to make the `impl` local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index 27ffe35532a3..683f80acbac7 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -46,7 +46,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/from-local-for-global.rs:32:5 | LL | impl StillNonLocal for &Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^-^^^ + | | + | help: remove `&` to make the `impl` local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr index 252296099f60..de4eacbecca4 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr @@ -2,7 +2,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/trait-solver-overflow-123573.rs:12:5 | LL | impl Test for &Local {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^-^^^^^ + | | + | help: remove `&` to make the `impl` local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` From 98273ec61272644b8bc14f2039f5c00cfa5dab95 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 15 May 2024 19:13:02 +0200 Subject: [PATCH 025/104] non_local_defs: point to Self and Trait to give more context --- Cargo.lock | 1 + compiler/rustc_lint/Cargo.toml | 1 + compiler/rustc_lint/messages.ftl | 4 + compiler/rustc_lint/src/lints.rs | 8 ++ compiler/rustc_lint/src/non_local_def.rs | 83 +++++++++++++-- .../lint/non-local-defs/cargo-update.stderr | 3 + tests/ui/lint/non-local-defs/consts.stderr | 37 +++++-- .../non-local-defs/exhaustive-trait.stderr | 30 ++++-- .../ui/lint/non-local-defs/exhaustive.stderr | 100 ++++++++++++++---- .../from-local-for-global.stderr | 27 +++-- tests/ui/lint/non-local-defs/generics.stderr | 39 +++++-- .../non-local-defs/inside-macro_rules.stderr | 5 +- .../suggest-moving-inner.stderr | 5 +- .../trait-solver-overflow-123573.stderr | 8 +- .../ui/lint/non-local-defs/weird-exprs.stderr | 29 +++-- 15 files changed, 311 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e8d179e5365..2f2b6e344741 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4062,6 +4062,7 @@ dependencies = [ "rustc_feature", "rustc_fluent_macro", "rustc_hir", + "rustc_hir_pretty", "rustc_index", "rustc_infer", "rustc_macros", diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index fa1133e7780f..232d4c18fa48 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -13,6 +13,7 @@ rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } +rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index f93534c316f9..8d1f7e150bc1 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -567,6 +567,10 @@ lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `# lint_non_local_definitions_may_move = may need to be moved as well +lint_non_local_definitions_of_trait_not_local = `{$of_trait_str}` is not local + +lint_non_local_definitions_self_ty_not_local = `{$self_ty_str}` is not local + lint_non_snake_case = {$sort} `{$name}` should have a snake case name .rename_or_convert_suggestion = rename the identifier or convert it to a snake case raw identifier .cannot_convert_note = `{$sc}` cannot be used as a raw identifier diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ca980d33e8ee..8c8ab4e0f372 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1340,6 +1340,8 @@ pub enum NonLocalDefinitionsDiag { may_move: Vec, may_remove: Option<(Span, String)>, has_trait: bool, + self_ty_str: String, + of_trait_str: Option, }, MacroRules { depth: u32, @@ -1364,11 +1366,17 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { may_move, may_remove, has_trait, + self_ty_str, + of_trait_str, } => { diag.primary_message(fluent::lint_non_local_definitions_impl); diag.arg("depth", depth); diag.arg("body_kind_descr", body_kind_descr); diag.arg("body_name", body_name); + diag.arg("self_ty_str", self_ty_str); + if let Some(of_trait_str) = of_trait_str { + diag.arg("of_trait_str", of_trait_str); + } if has_trait { diag.note(fluent::lint_bounds); diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index ed932e1c235c..d88c774ed802 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -1,3 +1,4 @@ +use rustc_errors::MultiSpan; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirId; use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, TyKind}; @@ -9,12 +10,13 @@ use rustc_middle::ty::{EarlyBinder, TraitRef, TypeSuperFoldable}; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::Span; -use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind}; +use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind, Symbol}; use rustc_trait_selection::infer::TyCtxtInferExt; use rustc_trait_selection::traits::error_reporting::ambiguity::{ compute_applicable_impls_for_diagnostics, CandidateSource, }; +use crate::fluent_generated as fluent; use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; use crate::{LateContext, LateLintPass, LintContext}; @@ -201,11 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { .into_iter() .filter_map(|path| { if path_has_local_parent(&path, cx, parent, parent_parent) { - if let Some(args) = &path.segments.last().unwrap().args { - Some(path.span.until(args.span_ext)) - } else { - Some(path.span) - } + Some(path_span_without_args(&path)) } else { None } @@ -227,9 +225,29 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { _ => None, }; + let impl_span = item.span.shrink_to_lo().to(impl_.self_ty.span); + let mut ms = MultiSpan::from_span(impl_span); + + let (self_ty_span, self_ty_str) = + self_ty_kind_for_diagnostic(&impl_.self_ty, cx.tcx); + + ms.push_span_label( + self_ty_span, + fluent::lint_non_local_definitions_self_ty_not_local, + ); + let of_trait_str = if let Some(of_trait) = &impl_.of_trait { + ms.push_span_label( + path_span_without_args(&of_trait.path), + fluent::lint_non_local_definitions_of_trait_not_local, + ); + Some(path_name_to_string(&of_trait.path)) + } else { + None + }; + cx.emit_span_lint( NON_LOCAL_DEFINITIONS, - item.span.shrink_to_lo().to(impl_.self_ty.span), + ms, NonLocalDefinitionsDiag::Impl { depth: self.body_depth, move_help: item.span, @@ -239,6 +257,8 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { .unwrap_or_else(|| "".to_string()), cargo_update: cargo_update(), const_anon, + self_ty_str, + of_trait_str, may_move, may_remove, has_trait: impl_.of_trait.is_some(), @@ -447,3 +467,52 @@ fn did_has_local_parent( false } } + +/// Return for a given `Path` the span until the last args +fn path_span_without_args(path: &Path<'_>) -> Span { + if let Some(args) = &path.segments.last().unwrap().args { + path.span.until(args.span_ext) + } else { + path.span + } +} + +/// Return a "error message-able" ident for the last segment of the `Path` +fn path_name_to_string(path: &Path<'_>) -> String { + path.segments.last().unwrap().ident.name.to_ident_string() +} + +/// Compute the `Span` and visual representation for the `Self` we want to point at; +/// It follows part of the actual logic of non-local, and if possible return the least +/// amount possible for the span and representation. +fn self_ty_kind_for_diagnostic(ty: &rustc_hir::Ty<'_>, tcx: TyCtxt<'_>) -> (Span, String) { + match ty.kind { + TyKind::Path(QPath::Resolved(_, ty_path)) => ( + path_span_without_args(ty_path), + ty_path + .res + .opt_def_id() + .map(|did| tcx.opt_item_name(did)) + .flatten() + .as_ref() + .map(|s| Symbol::as_str(s)) + .unwrap_or("") + .to_string(), + ), + TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => { + let path = &principle_poly_trait_ref.trait_ref.path; + ( + path_span_without_args(path), + path.res + .opt_def_id() + .map(|did| tcx.opt_item_name(did)) + .flatten() + .as_ref() + .map(|s| Symbol::as_str(s)) + .unwrap_or("") + .to_string(), + ) + } + _ => (ty.span, rustc_hir_pretty::ty_to_string(&tcx, ty)), + } +} diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index 30696b0f8e50..091c6f3d564e 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -3,6 +3,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam | LL | non_local_macro::non_local_impl!(LocalStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `LocalStruct` is not local + | `Debug` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 0528f63ac9c5..bf2b1541b2d2 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -5,7 +5,10 @@ LL | const Z: () = { | - help: use a const-anon item to suppress this lint: `_` ... LL | impl Uto for &Test {} - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^---^^^^^----- + | | | + | | `&'_ Test` is not local + | `Uto` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -22,7 +25,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:24:5 | LL | impl Uto2 for Test {} - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^---- + | | | + | | `Test` is not local + | `Uto2` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -38,7 +44,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:32:5 | LL | impl Uto3 for Test {} - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^---- + | | | + | | `Test` is not local + | `Uto3` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -54,7 +63,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:43:5 | LL | impl Test { - | ^^^^^^^^^ + | ^^^^^---- + | | + | `Test` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current function `main` @@ -71,7 +82,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:50:9 | LL | impl Test { - | ^^^^^^^^^ + | ^^^^^---- + | | + | `Test` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current inline constant `` and up 2 bodies @@ -88,7 +101,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:59:9 | LL | impl Test { - | ^^^^^^^^^ + | ^^^^^---- + | | + | `Test` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current constant `_` and up 2 bodies @@ -106,7 +121,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:72:9 | LL | impl Uto9 for Test {} - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^---- + | | | + | | `Test` is not local + | `Uto9` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -121,7 +139,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:79:9 | LL | impl Uto10 for Test {} - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^---- + | | | + | | `Test` is not local + | `Uto10` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index a9e3624fde50..8164a16b4d1b 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -2,7 +2,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive-trait.rs:7:5 | LL | impl PartialEq<()> for Dog { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---------^^^^^^^^^--- + | | | + | | `Dog` is not local + | `PartialEq` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -23,7 +26,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive-trait.rs:14:5 | LL | impl PartialEq<()> for &Dog { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---------^^^^^^^^^---- + | | | + | | `&'_ Dog` is not local + | `PartialEq` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -43,7 +49,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive-trait.rs:21:5 | LL | impl PartialEq for () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---------^^^^^^^^^^-- + | | | + | | `()` is not local + | `PartialEq` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -63,7 +72,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive-trait.rs:28:5 | LL | impl PartialEq<&Dog> for () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---------^^^^^^^^^^^-- + | | | + | | `()` is not local + | `PartialEq` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -83,7 +95,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive-trait.rs:35:5 | LL | impl PartialEq for &Dog { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---------^^^^^^^^^^---- + | | | + | | `&'_ Dog` is not local + | `PartialEq` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -103,7 +118,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive-trait.rs:42:5 | LL | impl PartialEq<&Dog> for &Dog { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---------^^^^^^^^^^^---- + | | | + | | `&'_ Dog` is not local + | `PartialEq` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index 7316182a4df0..d6d269674bd1 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -2,7 +2,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:10:5 | LL | impl Test { - | ^^^^^^^^^ + | ^^^^^---- + | | + | `Test` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current function `main` @@ -20,7 +22,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:15:5 | LL | impl Display for Test { - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-------^^^^^---- + | | | + | | `Test` is not local + | `Display` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -40,7 +45,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:22:5 | LL | impl dyn Trait {} - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^----- + | | + | `Trait` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current function `main` @@ -54,7 +61,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:25:5 | LL | impl Trait for Vec { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^-----^^^^^---^^^ + | | | + | | `Vec` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -69,7 +79,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:28:5 | LL | impl Trait for &dyn Trait {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^---------- + | | | + | | `&'_ dyn Trait` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -84,7 +97,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:31:5 | LL | impl Trait for *mut Test {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^--------- + | | | + | | `*mut Test` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -99,7 +115,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:34:5 | LL | impl Trait for *mut [Test] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^----------- + | | | + | | `*mut [Test]` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -114,7 +133,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:37:5 | LL | impl Trait for [Test; 8] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^--------- + | | | + | | `[Test; 8]` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -129,7 +151,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:40:5 | LL | impl Trait for (Test,) {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^------- + | | | + | | `(Test,)` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -144,7 +169,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:43:5 | LL | impl Trait for fn(Test) -> () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^-------------- + | | | + | | `fn(: Test) -> ()` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -159,7 +187,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:46:5 | LL | impl Trait for fn() -> Test {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^------------ + | | | + | | `fn() -> Test` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -174,7 +205,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:50:9 | LL | impl Trait for Test {} - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^---- + | | | + | | `Test` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -189,9 +223,11 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:58:5 | LL | impl Trait for *mut InsideMain {} - | ^^^^^^^^^^^^^^^-----^^^^^^^^^^ - | | - | help: remove `*mut ` to make the `impl` local + | ^^^^^-----^^^^^--------------- + | | | + | | `*mut InsideMain` is not local + | | help: remove `*mut ` to make the `impl` local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -208,7 +244,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:60:5 | LL | impl Trait for *mut [InsideMain] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^----------------- + | | | + | | `*mut [InsideMain]` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -225,7 +264,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:62:5 | LL | impl Trait for [InsideMain; 8] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^--------------- + | | | + | | `[InsideMain; 8]` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -242,7 +284,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:64:5 | LL | impl Trait for (InsideMain,) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^------------- + | | | + | | `(InsideMain,)` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -259,7 +304,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:66:5 | LL | impl Trait for fn(InsideMain) -> () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^-------------------- + | | | + | | `fn(: InsideMain) -> ()` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -276,7 +324,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:68:5 | LL | impl Trait for fn() -> InsideMain {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^------------------ + | | | + | | `fn() -> InsideMain` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -293,7 +344,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:72:9 | LL | impl Display for InsideMain { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-------^^^^^---------- + | | | + | | `InsideMain` is not local + | `Display` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -313,7 +367,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/exhaustive.rs:79:9 | LL | impl InsideMain { - | ^^^^^^^^^^^^^^^ + | ^^^^^---------- + | | + | `InsideMain` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current function `inside_inside` and up 2 bodies diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index 683f80acbac7..1c1dcb65abc5 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -2,7 +2,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/from-local-for-global.rs:8:5 | LL | impl From for () { - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^^^^^^-- + | | | + | | `()` is not local + | `From` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -23,7 +26,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/from-local-for-global.rs:18:5 | LL | impl From>> for () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^-- + | | | + | `From` is not local `()` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -46,9 +51,11 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/from-local-for-global.rs:32:5 | LL | impl StillNonLocal for &Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^-^^^ - | | - | help: remove `&` to make the `impl` local + | ^^^^^-------------^^^^^---- + | | | + | | `&'_ Foo` is not local + | | help: remove `&` to make the `impl` local + | `StillNonLocal` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -65,7 +72,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/from-local-for-global.rs:40:5 | LL | impl From for GlobalSameFunction { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^^^^^^^^^------------------ + | | | + | | `GlobalSameFunction` is not local + | `From` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -88,7 +98,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/from-local-for-global.rs:48:5 | LL | impl From for GlobalSameFunction { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^^^^^^^^^------------------ + | | | + | | `GlobalSameFunction` is not local + | `From` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index 1adefd40ffb0..7d64d9b1b095 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -2,7 +2,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:9:5 | LL | impl Global for Vec { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^------^^^^^---^^^ + | | | + | | `Vec` is not local + | `Global` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -20,7 +23,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:20:5 | LL | impl Uto7 for Test where Local: std::any::Any {} - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^---- + | | | + | | `Test` is not local + | `Uto7` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -37,7 +43,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:23:5 | LL | impl Uto8 for T {} - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^----^^^^^- + | | | + | | `T` is not local + | `Uto8` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -52,7 +61,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:32:5 | LL | impl Default for UwU { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-------^^^^^---^^^^^ + | | | + | | `UwU` is not local + | `Default` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -75,7 +87,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:43:5 | LL | impl AsRef for () { - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-----^^^^^^^^^^-- + | | | + | | `()` is not local + | `AsRef` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -96,7 +111,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:54:5 | LL | impl PartialEq for G { - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---------^^^^^^^^- + | | | + | | `G` is not local + | `PartialEq` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -119,7 +137,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:69:5 | LL | impl From>> for () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^^^^^^^^^^^^^^^^^^^-- + | | | + | `From` is not local `()` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -142,7 +162,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/generics.rs:76:5 | LL | impl From<()> for Wrap { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^----^^^^^^^^^----^^^^^^ + | | | + | | `Wrap` is not local + | `From` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index fea211a4e507..f83894b30826 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -2,7 +2,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/inside-macro_rules.rs:9:13 | LL | impl MacroTrait for OutsideStruct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^----------^^^^^------------- + | | | + | | `OutsideStruct` is not local + | `MacroTrait` is not local ... LL | m!(); | ---- in this macro invocation diff --git a/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr b/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr index 83557a7b9a27..557258d2aef9 100644 --- a/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr +++ b/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr @@ -2,7 +2,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/suggest-moving-inner.rs:12:5 | LL | impl Trait for &Vec> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^-----^^^^^^^^^^^^^^^^^---------------------------------- + | | | + | | `&'_ Vec>` is not local + | `Trait` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr index de4eacbecca4..04db22f213b2 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr @@ -2,9 +2,11 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/trait-solver-overflow-123573.rs:12:5 | LL | impl Test for &Local {} - | ^^^^^^^^^^^^^^-^^^^^ - | | - | help: remove `&` to make the `impl` local + | ^^^^^----^^^^^------ + | | | + | | `&'_ Local` is not local + | | help: remove `&` to make the `impl` local + | `Test` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index cced11719032..c77dab2ef346 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -2,7 +2,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:8:5 | LL | impl Uto for *mut Test {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---^^^^^--------- + | | | + | | `*mut Test` is not local + | `Uto` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -18,7 +21,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:16:9 | LL | impl Uto for Test {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^---^^^^^---- + | | | + | | `Test` is not local + | `Uto` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -33,7 +39,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:25:9 | LL | impl Test { - | ^^^^^^^^^ + | ^^^^^---- + | | + | `Test` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` help: move this `impl` block outside of the current constant expression `` and up 2 bodies @@ -50,7 +58,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:34:9 | LL | impl Uto for &Test {} - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^---^^^^^----- + | | | + | | `&'_ Test` is not local + | `Uto` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -65,7 +76,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:41:9 | LL | impl Uto for &(Test,) {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---^^^^^-------- + | | | + | | `&'_ (Test,)` is not local + | `Uto` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -80,7 +94,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/weird-exprs.rs:48:9 | LL | impl Uto for &(Test,Test) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^---^^^^^------------ + | | | + | | `&'_ (Test, Test)` is not local + | `Uto` is not local | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` From c7d300442ff94cbe60a22400750cd03dbf15bcef Mon Sep 17 00:00:00 2001 From: Urgau Date: Sat, 18 May 2024 15:07:28 +0200 Subject: [PATCH 026/104] non_local_defs: point the parent item when appropriate --- compiler/rustc_lint/messages.ftl | 11 +- compiler/rustc_lint/src/lints.rs | 16 +- compiler/rustc_lint/src/non_local_def.rs | 22 +- .../lint/non-local-defs/cargo-update.stderr | 6 +- tests/ui/lint/non-local-defs/consts.stderr | 96 ++++----- .../non-local-defs/exhaustive-trait.stderr | 77 ++----- .../ui/lint/non-local-defs/exhaustive.stderr | 203 +++++++----------- .../from-local-for-global.stderr | 80 +++---- tests/ui/lint/non-local-defs/generics.stderr | 123 +++++------ .../non-local-defs/inside-macro_rules.stderr | 10 +- .../suggest-moving-inner.stderr | 26 ++- .../trait-solver-overflow-123573.stderr | 12 +- .../ui/lint/non-local-defs/weird-exprs.stderr | 129 +++++------ 13 files changed, 330 insertions(+), 481 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 8d1f7e150bc1..0b1645500960 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -543,11 +543,6 @@ lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may lint_non_local_definitions_deprecation = this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks should be written at the same level as their item - .move_help = - move this `impl` block outside of the current {$body_kind_descr} {$depth -> - [one] `{$body_name}` - *[other] `{$body_name}` and up {$depth} bodies - } .remove_help = remove `{$may_remove_part}` to make the `impl` local .without_trait = methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` .with_trait = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` @@ -555,6 +550,12 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho .exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration .const_anon = use a const-anon item to suppress this lint +lint_non_local_definitions_impl_move_help = + move the `impl` block outside of this {$body_kind_descr} {$depth -> + [one] `{$body_name}` + *[other] `{$body_name}` and up {$depth} bodies + } + lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module .help = remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 8c8ab4e0f372..2edfb8d3df46 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1336,8 +1336,7 @@ pub enum NonLocalDefinitionsDiag { body_name: String, cargo_update: Option, const_anon: Option>, - move_help: Span, - may_move: Vec, + move_to: Option<(Span, Vec)>, may_remove: Option<(Span, String)>, has_trait: bool, self_ty_str: String, @@ -1362,8 +1361,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { body_name, cargo_update, const_anon, - move_help, - may_move, + move_to, may_remove, has_trait, self_ty_str, @@ -1385,11 +1383,13 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { diag.note(fluent::lint_without_trait); } - let mut ms = MultiSpan::from_span(move_help); - for sp in may_move { - ms.push_span_label(sp, fluent::lint_non_local_definitions_may_move); + if let Some((move_help, may_move)) = move_to { + let mut ms = MultiSpan::from_span(move_help); + for sp in may_move { + ms.push_span_label(sp, fluent::lint_non_local_definitions_may_move); + } + diag.span_help(ms, fluent::lint_non_local_definitions_impl_move_help); } - diag.span_help(ms, fluent::lint_move_help); if let Some((span, part)) = may_remove { diag.arg("may_remove_part", part); diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index d88c774ed802..42b03f47a5bc 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -198,17 +198,21 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { } collector.visit_generics(&impl_.generics); - let may_move: Vec = collector + let mut may_move: Vec = collector .paths .into_iter() .filter_map(|path| { - if path_has_local_parent(&path, cx, parent, parent_parent) { - Some(path_span_without_args(&path)) + if let Some(did) = path.res.opt_def_id() + && did_has_local_parent(did, cx.tcx, parent, parent_parent) + { + Some(cx.tcx.def_span(did)) } else { None } }) .collect(); + may_move.sort(); + may_move.dedup(); let const_anon = matches!(parent_def_kind, DefKind::Const | DefKind::Static { .. }) .then_some(span_for_const_anon_suggestion); @@ -244,13 +248,21 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { } else { None }; + let move_to = if may_move.is_empty() { + ms.push_span_label( + cx.tcx.def_span(parent), + fluent::lint_non_local_definitions_impl_move_help, + ); + None + } else { + Some((cx.tcx.def_span(parent), may_move)) + }; cx.emit_span_lint( NON_LOCAL_DEFINITIONS, ms, NonLocalDefinitionsDiag::Impl { depth: self.body_depth, - move_help: item.span, body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent), body_name: parent_opt_item_name .map(|s| s.to_ident_string()) @@ -259,7 +271,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { const_anon, self_ty_str, of_trait_str, - may_move, + move_to, may_remove, has_trait: impl_.of_trait.is_some(), }, diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index 091c6f3d564e..888fd2e61837 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -6,14 +6,10 @@ LL | non_local_macro::non_local_impl!(LocalStruct); | | | `LocalStruct` is not local | `Debug` is not local + | move the `impl` block outside of this constant `_IMPL_DEBUG` | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current constant `_IMPL_DEBUG` - --> $DIR/cargo-update.rs:17:1 - | -LL | non_local_macro::non_local_impl!(LocalStruct); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index bf2b1541b2d2..2756ea401387 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -2,7 +2,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:13:5 | LL | const Z: () = { - | - help: use a const-anon item to suppress this lint: `_` + | ----------- + | | | + | | help: use a const-anon item to suppress this lint: `_` + | move the `impl` block outside of this constant `Z` ... LL | impl Uto for &Test {} | ^^^^^---^^^^^----- @@ -12,11 +15,6 @@ LL | impl Uto for &Test {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current constant `Z` - --> $DIR/consts.rs:13:5 - | -LL | impl Uto for &Test {} - | ^^^^^^^^^^^^^^^^^^^^^ = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -24,6 +22,8 @@ LL | impl Uto for &Test {} warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:24:5 | +LL | static A: u32 = { + | ------------- move the `impl` block outside of this static `A` LL | impl Uto2 for Test {} | ^^^^^----^^^^^---- | | | @@ -32,17 +32,14 @@ LL | impl Uto2 for Test {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current static `A` - --> $DIR/consts.rs:24:5 - | -LL | impl Uto2 for Test {} - | ^^^^^^^^^^^^^^^^^^^^^ = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:32:5 | +LL | const B: u32 = { + | ------------ move the `impl` block outside of this constant `B` LL | impl Uto3 for Test {} | ^^^^^----^^^^^---- | | | @@ -51,75 +48,60 @@ LL | impl Uto3 for Test {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current constant `B` - --> $DIR/consts.rs:32:5 - | -LL | impl Uto3 for Test {} - | ^^^^^^^^^^^^^^^^^^^^^ = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:43:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` LL | impl Test { | ^^^^^---- | | | `Test` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/consts.rs:43:5 - | -LL | / impl Test { -LL | | -LL | | fn foo() {} -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:50:9 | -LL | impl Test { - | ^^^^^---- - | | - | `Test` is not local - | - = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` -help: move this `impl` block outside of the current inline constant `` and up 2 bodies - --> $DIR/consts.rs:50:9 - | -LL | / impl Test { +LL | const { + | ___________- +LL | | impl Test { + | | ^^^^^---- + | | | + | | `Test` is not local LL | | LL | | fn hoo() {} -LL | | } - | |_________^ +... | +LL | | 1 +LL | | }; + | |_____- move the `impl` block outside of this inline constant `` and up 2 bodies + | + = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:59:9 | +LL | const _: u32 = { + | ------------ move the `impl` block outside of this constant `_` and up 2 bodies LL | impl Test { | ^^^^^---- | | | `Test` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` -help: move this `impl` block outside of the current constant `_` and up 2 bodies - --> $DIR/consts.rs:59:9 - | -LL | / impl Test { -LL | | -LL | | fn foo2() {} -LL | | } - | |_________^ = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:72:9 | +LL | let _a = || { + | -- move the `impl` block outside of this closure `` and up 2 bodies LL | impl Uto9 for Test {} | ^^^^^----^^^^^---- | | | @@ -128,29 +110,25 @@ LL | impl Uto9 for Test {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current closure `` and up 2 bodies - --> $DIR/consts.rs:72:9 - | -LL | impl Uto9 for Test {} - | ^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:79:9 | -LL | impl Uto10 for Test {} - | ^^^^^-----^^^^^---- - | | | - | | `Test` is not local - | `Uto10` is not local +LL | type A = [u32; { + | ____________________- +LL | | impl Uto10 for Test {} + | | ^^^^^-----^^^^^---- + | | | | + | | | `Test` is not local + | | `Uto10` is not local +LL | | +... | +LL | | }]; + | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current constant expression `` and up 2 bodies - --> $DIR/consts.rs:79:9 - | -LL | impl Uto10 for Test {} - | ^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 8 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index 8164a16b4d1b..67df0e31d5bd 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -1,6 +1,8 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:7:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` LL | impl PartialEq<()> for Dog { | ^^^^^---------^^^^^^^^^--- | | | @@ -9,22 +11,15 @@ LL | impl PartialEq<()> for Dog { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive-trait.rs:7:5 - | -LL | / impl PartialEq<()> for Dog { -LL | | -LL | | fn eq(&self, _: &()) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:14:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl PartialEq<()> for &Dog { | ^^^^^---------^^^^^^^^^---- | | | @@ -33,21 +28,14 @@ LL | impl PartialEq<()> for &Dog { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive-trait.rs:14:5 - | -LL | / impl PartialEq<()> for &Dog { -LL | | -LL | | fn eq(&self, _: &()) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:21:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl PartialEq for () { | ^^^^^---------^^^^^^^^^^-- | | | @@ -56,21 +44,14 @@ LL | impl PartialEq for () { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive-trait.rs:21:5 - | -LL | / impl PartialEq for () { -LL | | -LL | | fn eq(&self, _: &Dog) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:28:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl PartialEq<&Dog> for () { | ^^^^^---------^^^^^^^^^^^-- | | | @@ -79,21 +60,14 @@ LL | impl PartialEq<&Dog> for () { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive-trait.rs:28:5 - | -LL | / impl PartialEq<&Dog> for () { -LL | | -LL | | fn eq(&self, _: &&Dog) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:35:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl PartialEq for &Dog { | ^^^^^---------^^^^^^^^^^---- | | | @@ -102,21 +76,14 @@ LL | impl PartialEq for &Dog { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive-trait.rs:35:5 - | -LL | / impl PartialEq for &Dog { -LL | | -LL | | fn eq(&self, _: &Dog) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:42:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl PartialEq<&Dog> for &Dog { | ^^^^^---------^^^^^^^^^^^---- | | | @@ -125,16 +92,6 @@ LL | impl PartialEq<&Dog> for &Dog { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive-trait.rs:42:5 - | -LL | / impl PartialEq<&Dog> for &Dog { -LL | | -LL | | fn eq(&self, _: &&Dog) -> bool { -LL | | todo!() -LL | | } -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index d6d269674bd1..1e0d5caec383 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -1,26 +1,23 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:10:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` LL | impl Test { | ^^^^^---- | | | `Test` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:10:5 - | -LL | / impl Test { -LL | | -LL | | fn foo() {} -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:15:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl Display for Test { | ^^^^^-------^^^^^---- | | | @@ -29,37 +26,28 @@ LL | impl Display for Test { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:15:5 - | -LL | / impl Display for Test { -LL | | -LL | | fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -LL | | todo!() -LL | | } -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:22:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl dyn Trait {} | ^^^^^^^^^----- | | | `Trait` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:22:5 - | -LL | impl dyn Trait {} - | ^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:25:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl Trait for Vec { } | ^^^^^^^^^^^^^^^-----^^^^^---^^^ | | | @@ -68,16 +56,14 @@ LL | impl Trait for Vec { } | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:25:5 - | -LL | impl Trait for Vec { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:28:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl Trait for &dyn Trait {} | ^^^^^-----^^^^^---------- | | | @@ -86,16 +72,14 @@ LL | impl Trait for &dyn Trait {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:28:5 - | -LL | impl Trait for &dyn Trait {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:31:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl Trait for *mut Test {} | ^^^^^-----^^^^^--------- | | | @@ -104,16 +88,14 @@ LL | impl Trait for *mut Test {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:31:5 - | -LL | impl Trait for *mut Test {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:34:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl Trait for *mut [Test] {} | ^^^^^-----^^^^^----------- | | | @@ -122,16 +104,14 @@ LL | impl Trait for *mut [Test] {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:34:5 - | -LL | impl Trait for *mut [Test] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:37:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl Trait for [Test; 8] {} | ^^^^^-----^^^^^--------- | | | @@ -140,16 +120,14 @@ LL | impl Trait for [Test; 8] {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:37:5 - | -LL | impl Trait for [Test; 8] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:40:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl Trait for (Test,) {} | ^^^^^-----^^^^^------- | | | @@ -158,16 +136,14 @@ LL | impl Trait for (Test,) {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:40:5 - | -LL | impl Trait for (Test,) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:43:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl Trait for fn(Test) -> () {} | ^^^^^-----^^^^^-------------- | | | @@ -176,16 +152,14 @@ LL | impl Trait for fn(Test) -> () {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:43:5 - | -LL | impl Trait for fn(Test) -> () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:46:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... LL | impl Trait for fn() -> Test {} | ^^^^^-----^^^^^------------ | | | @@ -194,16 +168,13 @@ LL | impl Trait for fn() -> Test {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:46:5 - | -LL | impl Trait for fn() -> Test {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:50:9 | +LL | let _a = || { + | -- move the `impl` block outside of this closure `` and up 2 bodies LL | impl Trait for Test {} | ^^^^^-----^^^^^---- | | | @@ -212,11 +183,6 @@ LL | impl Trait for Test {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current closure `` and up 2 bodies - --> $DIR/exhaustive.rs:50:9 - | -LL | impl Trait for Test {} - | ^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -231,13 +197,14 @@ LL | impl Trait for *mut InsideMain {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:58:5 +help: move the `impl` block outside of this function `main` + --> $DIR/exhaustive.rs:9:1 | -LL | impl Trait for *mut InsideMain {} - | ^^^^^^^^^^^^^^^^^^^^----------^^^ - | | - | may need to be moved as well +LL | fn main() { + | ^^^^^^^^^ +... +LL | struct InsideMain; + | ----------------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -251,13 +218,14 @@ LL | impl Trait for *mut [InsideMain] {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:60:5 +help: move the `impl` block outside of this function `main` + --> $DIR/exhaustive.rs:9:1 | -LL | impl Trait for *mut [InsideMain] {} - | ^^^^^^^^^^^^^^^^^^^^^----------^^^^ - | | - | may need to be moved as well +LL | fn main() { + | ^^^^^^^^^ +... +LL | struct InsideMain; + | ----------------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -271,13 +239,14 @@ LL | impl Trait for [InsideMain; 8] {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:62:5 +help: move the `impl` block outside of this function `main` + --> $DIR/exhaustive.rs:9:1 | -LL | impl Trait for [InsideMain; 8] {} - | ^^^^^^^^^^^^^^^^----------^^^^^^^ - | | - | may need to be moved as well +LL | fn main() { + | ^^^^^^^^^ +... +LL | struct InsideMain; + | ----------------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -291,13 +260,14 @@ LL | impl Trait for (InsideMain,) {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:64:5 +help: move the `impl` block outside of this function `main` + --> $DIR/exhaustive.rs:9:1 | -LL | impl Trait for (InsideMain,) {} - | ^^^^^^^^^^^^^^^^----------^^^^^ - | | - | may need to be moved as well +LL | fn main() { + | ^^^^^^^^^ +... +LL | struct InsideMain; + | ----------------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -311,13 +281,14 @@ LL | impl Trait for fn(InsideMain) -> () {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:66:5 +help: move the `impl` block outside of this function `main` + --> $DIR/exhaustive.rs:9:1 | -LL | impl Trait for fn(InsideMain) -> () {} - | ^^^^^^^^^^^^^^^^^^----------^^^^^^^^^^ - | | - | may need to be moved as well +LL | fn main() { + | ^^^^^^^^^ +... +LL | struct InsideMain; + | ----------------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -331,18 +302,21 @@ LL | impl Trait for fn() -> InsideMain {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/exhaustive.rs:68:5 +help: move the `impl` block outside of this function `main` + --> $DIR/exhaustive.rs:9:1 | -LL | impl Trait for fn() -> InsideMain {} - | ^^^^^^^^^^^^^^^^^^^^^^^----------^^^ - | | - | may need to be moved as well +LL | fn main() { + | ^^^^^^^^^ +... +LL | struct InsideMain; + | ----------------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:72:9 | +LL | fn inside_inside() { + | ------------------ move the `impl` block outside of this function `inside_inside` and up 2 bodies LL | impl Display for InsideMain { | ^^^^^-------^^^^^---------- | | | @@ -351,35 +325,20 @@ LL | impl Display for InsideMain { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `inside_inside` and up 2 bodies - --> $DIR/exhaustive.rs:72:9 - | -LL | / impl Display for InsideMain { -LL | | -LL | | fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -LL | | todo!() -LL | | } -LL | | } - | |_________^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:79:9 | +LL | fn inside_inside() { + | ------------------ move the `impl` block outside of this function `inside_inside` and up 2 bodies +... LL | impl InsideMain { | ^^^^^---------- | | | `InsideMain` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` -help: move this `impl` block outside of the current function `inside_inside` and up 2 bodies - --> $DIR/exhaustive.rs:79:9 - | -LL | / impl InsideMain { -LL | | -LL | | fn bar() {} -LL | | } - | |_________^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 20 warnings emitted diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index 1c1dcb65abc5..67fd937d134c 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -1,6 +1,8 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/from-local-for-global.rs:8:5 | +LL | fn main() { + | --------- move the `impl` block outside of this function `main` LL | impl From for () { | ^^^^^----^^^^^^^^^^-- | | | @@ -9,16 +11,6 @@ LL | impl From for () { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/from-local-for-global.rs:8:5 - | -LL | / impl From for () { -LL | | -LL | | fn from(_: Cat) -> () { -LL | | todo!() -LL | | } -LL | | } - | |_____^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -32,19 +24,14 @@ LL | impl From>> for () { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/from-local-for-global.rs:18:5 +help: move the `impl` block outside of this function `main` + --> $DIR/from-local-for-global.rs:7:1 | -LL | impl From>> for () { - | ^ -------- may need to be moved as well - | _____| - | | -LL | | -LL | | fn from(_: Wrap>) -> Self { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | fn main() { + | ^^^^^^^^^ +... +LL | struct Elephant; + | --------------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -59,13 +46,13 @@ LL | impl StillNonLocal for &Foo {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `only_global` - --> $DIR/from-local-for-global.rs:32:5 +help: move the `impl` block outside of this function `only_global` + --> $DIR/from-local-for-global.rs:30:1 | -LL | impl StillNonLocal for &Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^---^^^ - | | - | may need to be moved as well +LL | fn only_global() { + | ^^^^^^^^^^^^^^^^ +LL | struct Foo; + | ---------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -79,19 +66,13 @@ LL | impl From for GlobalSameFunction { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `same_function` - --> $DIR/from-local-for-global.rs:40:5 +help: move the `impl` block outside of this function `same_function` + --> $DIR/from-local-for-global.rs:38:1 | -LL | impl From for GlobalSameFunction { - | ^ ------ may need to be moved as well - | _____| - | | -LL | | -LL | | fn from(x: Local1) -> GlobalSameFunction { -LL | | x.0 -LL | | } -LL | | } - | |_____^ +LL | fn same_function() { + | ^^^^^^^^^^^^^^^^^^ +LL | struct Local1(GlobalSameFunction); + | ------------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -105,19 +86,14 @@ LL | impl From for GlobalSameFunction { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `same_function` - --> $DIR/from-local-for-global.rs:48:5 +help: move the `impl` block outside of this function `same_function` + --> $DIR/from-local-for-global.rs:38:1 | -LL | impl From for GlobalSameFunction { - | ^ ------ may need to be moved as well - | _____| - | | -LL | | -LL | | fn from(x: Local2) -> GlobalSameFunction { -LL | | x.0 -LL | | } -LL | | } - | |_____^ +LL | fn same_function() { + | ^^^^^^^^^^^^^^^^^^ +... +LL | struct Local2(GlobalSameFunction); + | ------------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 5 warnings emitted diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index 7d64d9b1b095..ed2f87a4ed2d 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -9,13 +9,13 @@ LL | impl Global for Vec { } | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/generics.rs:9:5 +help: move the `impl` block outside of this function `main` + --> $DIR/generics.rs:6:1 | -LL | impl Global for Vec { } - | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^ - | | - | may need to be moved as well +LL | fn main() { + | ^^^^^^^^^ +LL | trait Local {}; + | ----------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default @@ -30,18 +30,21 @@ LL | impl Uto7 for Test where Local: std::any::Any {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `bad` - --> $DIR/generics.rs:20:5 +help: move the `impl` block outside of this function `bad` + --> $DIR/generics.rs:18:1 | -LL | impl Uto7 for Test where Local: std::any::Any {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ - | | - | may need to be moved as well +LL | fn bad() { + | ^^^^^^^^ +LL | struct Local; + | ------------ may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:23:5 | +LL | fn bad() { + | -------- move the `impl` block outside of this function `bad` +... LL | impl Uto8 for T {} | ^^^^^^^^----^^^^^- | | | @@ -50,11 +53,6 @@ LL | impl Uto8 for T {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `bad` - --> $DIR/generics.rs:23:5 - | -LL | impl Uto8 for T {} - | ^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -68,19 +66,14 @@ LL | impl Default for UwU { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `fun` - --> $DIR/generics.rs:32:5 +help: move the `impl` block outside of this function `fun` + --> $DIR/generics.rs:29:1 | -LL | impl Default for UwU { - | ^ --- may need to be moved as well - | _____| - | | -LL | | -LL | | fn default() -> Self { -LL | | UwU(OwO) -LL | | } -LL | | } - | |_____^ +LL | fn fun() { + | ^^^^^^^^ +LL | #[derive(Debug)] +LL | struct OwO; + | ---------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -94,17 +87,14 @@ LL | impl AsRef for () { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `meow` - --> $DIR/generics.rs:43:5 +help: move the `impl` block outside of this function `meow` + --> $DIR/generics.rs:40:1 | -LL | impl AsRef for () { - | ^ --- may need to be moved as well - | _____| - | | -LL | | -LL | | fn as_ref(&self) -> &Cat { &Cat } -LL | | } - | |_____^ +LL | fn meow() { + | ^^^^^^^^^ +LL | #[derive(Debug)] +LL | struct Cat; + | ---------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -118,19 +108,14 @@ LL | impl PartialEq for G { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `fun2` - --> $DIR/generics.rs:54:5 +help: move the `impl` block outside of this function `fun2` + --> $DIR/generics.rs:51:1 | -LL | impl PartialEq for G { - | ^ - may need to be moved as well - | _____| - | | -LL | | -LL | | fn eq(&self, _: &B) -> bool { -LL | | true -LL | | } -LL | | } - | |_____^ +LL | fn fun2() { + | ^^^^^^^^^ +LL | #[derive(Debug, Default)] +LL | struct B; + | -------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -143,19 +128,13 @@ LL | impl From>> for () { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `rawr` - --> $DIR/generics.rs:69:5 +help: move the `impl` block outside of this function `rawr` + --> $DIR/generics.rs:66:1 | -LL | impl From>> for () { - | ^ ---- may need to be moved as well - | _____| - | | -LL | | -LL | | fn from(_: Wrap>) -> Self { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | fn rawr() { + | ^^^^^^^^^ +LL | struct Lion; + | ----------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -169,19 +148,13 @@ LL | impl From<()> for Wrap { | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `rawr` - --> $DIR/generics.rs:76:5 +help: move the `impl` block outside of this function `rawr` + --> $DIR/generics.rs:66:1 | -LL | impl From<()> for Wrap { - | ^ ---- may need to be moved as well - | _____| - | | -LL | | -LL | | fn from(_: ()) -> Self { -LL | | todo!() -LL | | } -LL | | } - | |_____^ +LL | fn rawr() { + | ^^^^^^^^^ +LL | struct Lion; + | ----------- may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 8 warnings emitted diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index f83894b30826..b52301d1aa08 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -1,6 +1,8 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/inside-macro_rules.rs:9:13 | +LL | fn my_func() { + | ------------ move the `impl` block outside of this function `my_func` LL | impl MacroTrait for OutsideStruct {} | ^^^^^----------^^^^^------------- | | | @@ -12,14 +14,6 @@ LL | m!(); | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `my_func` - --> $DIR/inside-macro_rules.rs:9:13 - | -LL | impl MacroTrait for OutsideStruct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | m!(); - | ---- in this macro invocation = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr b/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr index 557258d2aef9..f0de0f72e74f 100644 --- a/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr +++ b/tests/ui/lint/non-local-defs/suggest-moving-inner.stderr @@ -9,21 +9,19 @@ LL | impl Trait for &Vec> | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/suggest-moving-inner.rs:12:5 +help: move the `impl` block outside of this function `main` + --> $DIR/suggest-moving-inner.rs:5:1 | -LL | impl Trait for &Vec> - | ^ ---------- ----------- ---------- may need to be moved as well - | | | | - | | | may need to be moved as well - | _____| may need to be moved as well - | | -LL | | -LL | | where -LL | | T: HasFoo - | | ------ may need to be moved as well -LL | | {} - | |______^ +LL | fn main() { + | ^^^^^^^^^ +LL | mod below { +LL | pub struct Type(T); + | ------------------ may need to be moved as well +LL | } +LL | struct InsideMain; + | ----------------- may need to be moved as well +LL | trait HasFoo {} + | ------------ may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default diff --git a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr index 04db22f213b2..80930ce1bcdf 100644 --- a/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr +++ b/tests/ui/lint/non-local-defs/trait-solver-overflow-123573.stderr @@ -10,13 +10,13 @@ LL | impl Test for &Local {} | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current function `main` - --> $DIR/trait-solver-overflow-123573.rs:12:5 +help: move the `impl` block outside of this function `main` + --> $DIR/trait-solver-overflow-123573.rs:10:1 | -LL | impl Test for &Local {} - | ^^^^^^^^^^^^^^^-----^^^ - | | - | may need to be moved as well +LL | fn main() { + | ^^^^^^^^^ +LL | struct Local {} + | ------------ may need to be moved as well = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index c77dab2ef346..cd414d636d34 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -1,111 +1,116 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:8:5 | -LL | impl Uto for *mut Test {} - | ^^^^^---^^^^^--------- - | | | - | | `*mut Test` is not local - | `Uto` is not local +LL | type A = [u32; { + | ________________- +LL | | impl Uto for *mut Test {} + | | ^^^^^---^^^^^--------- + | | | | + | | | `*mut Test` is not local + | | `Uto` is not local +LL | | +... | +LL | | }]; + | |_- move the `impl` block outside of this constant expression `` | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current constant expression `` - --> $DIR/weird-exprs.rs:8:5 - | -LL | impl Uto for *mut Test {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:16:9 | -LL | impl Uto for Test {} - | ^^^^^---^^^^^---- - | | | - | | `Test` is not local - | `Uto` is not local +LL | Discr = { + | _____________- +LL | | impl Uto for Test {} + | | ^^^^^---^^^^^---- + | | | | + | | | `Test` is not local + | | `Uto` is not local +LL | | +... | +LL | | } + | |_____- move the `impl` block outside of this constant expression `` | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current constant expression `` - --> $DIR/weird-exprs.rs:16:9 - | -LL | impl Uto for Test {} - | ^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:25:9 | -LL | impl Test { - | ^^^^^---- - | | - | `Test` is not local - | - = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` -help: move this `impl` block outside of the current constant expression `` and up 2 bodies - --> $DIR/weird-exprs.rs:25:9 - | -LL | / impl Test { +LL | let _array = [0i32; { + | _________________________- +LL | | impl Test { + | | ^^^^^---- + | | | + | | `Test` is not local LL | | LL | | fn bar() {} -LL | | } - | |_________^ +... | +LL | | 1 +LL | | }]; + | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies + | + = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:34:9 | -LL | impl Uto for &Test {} - | ^^^^^---^^^^^----- - | | | - | | `&'_ Test` is not local - | `Uto` is not local +LL | type A = [u32; { + | ____________________- +LL | | impl Uto for &Test {} + | | ^^^^^---^^^^^----- + | | | | + | | | `&'_ Test` is not local + | | `Uto` is not local +LL | | +... | +LL | | }]; + | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current constant expression `` and up 2 bodies - --> $DIR/weird-exprs.rs:34:9 - | -LL | impl Uto for &Test {} - | ^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:41:9 | -LL | impl Uto for &(Test,) {} - | ^^^^^---^^^^^-------- - | | | - | | `&'_ (Test,)` is not local - | `Uto` is not local +LL | fn a(_: [u32; { + | ___________________- +LL | | impl Uto for &(Test,) {} + | | ^^^^^---^^^^^-------- + | | | | + | | | `&'_ (Test,)` is not local + | | `Uto` is not local +LL | | +... | +LL | | }]) {} + | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current constant expression `` and up 2 bodies - --> $DIR/weird-exprs.rs:41:9 - | -LL | impl Uto for &(Test,) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:48:9 | -LL | impl Uto for &(Test,Test) {} - | ^^^^^---^^^^^------------ - | | | - | | `&'_ (Test, Test)` is not local - | `Uto` is not local +LL | fn b() -> [u32; { + | _____________________- +LL | | impl Uto for &(Test,Test) {} + | | ^^^^^---^^^^^------------ + | | | | + | | | `&'_ (Test, Test)` is not local + | | `Uto` is not local +LL | | +... | +LL | | }] { todo!() } + | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` -help: move this `impl` block outside of the current constant expression `` and up 2 bodies - --> $DIR/weird-exprs.rs:48:9 - | -LL | impl Uto for &(Test,Test) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted From d9d013bec077600b8b0dc25e51191802d1e11cd9 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 27 May 2024 20:57:01 -0400 Subject: [PATCH 027/104] rewrite lto-smoke to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/lto-smoke/Makefile | 31 ------------------- tests/run-make/lto-smoke/rmake.rs | 13 ++++++++ 3 files changed, 13 insertions(+), 32 deletions(-) delete mode 100644 tests/run-make/lto-smoke/Makefile create mode 100644 tests/run-make/lto-smoke/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 2329b8b44dea..baf341277c76 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -145,7 +145,6 @@ run-make/lto-linkage-used-attr/Makefile run-make/lto-no-link-whole-rlib/Makefile run-make/lto-readonly-lib/Makefile run-make/lto-smoke-c/Makefile -run-make/lto-smoke/Makefile run-make/macos-deployment-target/Makefile run-make/macos-fat-archive/Makefile run-make/manual-crate-name/Makefile diff --git a/tests/run-make/lto-smoke/Makefile b/tests/run-make/lto-smoke/Makefile deleted file mode 100644 index 13a09fce7340..000000000000 --- a/tests/run-make/lto-smoke/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: noparam bool_true bool_false thin fat - -noparam: - $(RUSTC) lib.rs - $(RUSTC) main.rs -C lto - $(call RUN,main) - -bool_true: - $(RUSTC) lib.rs - $(RUSTC) main.rs -C lto=yes - $(call RUN,main) - - -bool_false: - $(RUSTC) lib.rs - $(RUSTC) main.rs -C lto=off - $(call RUN,main) - -thin: - $(RUSTC) lib.rs - $(RUSTC) main.rs -C lto=thin - $(call RUN,main) - -fat: - $(RUSTC) lib.rs - $(RUSTC) main.rs -C lto=fat - $(call RUN,main) - diff --git a/tests/run-make/lto-smoke/rmake.rs b/tests/run-make/lto-smoke/rmake.rs new file mode 100644 index 000000000000..7294c32fbf82 --- /dev/null +++ b/tests/run-make/lto-smoke/rmake.rs @@ -0,0 +1,13 @@ +// A simple smoke test to check that link time optimization +// (LTO) works as intended, with its various flags turned on. +// See https://github.com/rust-lang/rust/issues/10741 + +//@ ignore-cross-compile + +fn main() { + let lto_flags = ["-Clto", "-Clto=yes", "-Clto=off", "-Clto=thin", "-Clto=fat"]; + for flag in lto_flags { + rustc().input(lib.rs).run(); + rustc().input(main.rs).arg(flag).run(); + } +} From bcfa67d50d29bbe99ef0ee4d41838e6bdd651b68 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 23 May 2024 09:12:19 +1000 Subject: [PATCH 028/104] Remove out-of-date comment. This comment -- "by default we ignore everything in the repository" -- was added in #65939 when rustfmt was first being introduced for this repository and (briefly) every directory was ignored. Since then lots of directories have opted in to formatting, so it is no longer true. --- rustfmt.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index ef56059feb1c..1f914964e241 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -3,7 +3,6 @@ version = "Two" use_small_heuristics = "Max" merge_derives = false -# by default we ignore everything in the repository # tidy only checks files which are not ignored, each entry follows gitignore style ignore = [ "/build/", From 634270e8da47d36736c4f8d1c92266bed4e0cf82 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 27 May 2024 21:10:57 -0400 Subject: [PATCH 029/104] rewrite mixing-deps in rmake --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/lto-smoke/rmake.rs | 2 ++ tests/run-make/mixing-deps/Makefile | 8 -------- tests/run-make/mixing-formats/rmake.rs | 13 +++++++++++++ 4 files changed, 15 insertions(+), 9 deletions(-) delete mode 100644 tests/run-make/mixing-deps/Makefile create mode 100644 tests/run-make/mixing-formats/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index baf341277c76..6d79711e6864 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -156,7 +156,6 @@ run-make/min-global-align/Makefile run-make/mingw-export-call-convention/Makefile run-make/mismatching-target-triples/Makefile run-make/missing-crate-dependency/Makefile -run-make/mixing-deps/Makefile run-make/mixing-formats/Makefile run-make/mixing-libs/Makefile run-make/msvc-opt-minsize/Makefile diff --git a/tests/run-make/lto-smoke/rmake.rs b/tests/run-make/lto-smoke/rmake.rs index 7294c32fbf82..c0f181c10825 100644 --- a/tests/run-make/lto-smoke/rmake.rs +++ b/tests/run-make/lto-smoke/rmake.rs @@ -4,6 +4,8 @@ //@ ignore-cross-compile +use run_make_support::rustc; + fn main() { let lto_flags = ["-Clto", "-Clto=yes", "-Clto=off", "-Clto=thin", "-Clto=fat"]; for flag in lto_flags { diff --git a/tests/run-make/mixing-deps/Makefile b/tests/run-make/mixing-deps/Makefile deleted file mode 100644 index c2a5a2a0abbe..000000000000 --- a/tests/run-make/mixing-deps/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) both.rs -C prefer-dynamic - $(RUSTC) dylib.rs -C prefer-dynamic - $(RUSTC) prog.rs - $(call RUN,prog) diff --git a/tests/run-make/mixing-formats/rmake.rs b/tests/run-make/mixing-formats/rmake.rs new file mode 100644 index 000000000000..fb31bbef9d19 --- /dev/null +++ b/tests/run-make/mixing-formats/rmake.rs @@ -0,0 +1,13 @@ +// This test invokes the main function in prog.rs, which has dependencies +// in both an rlib and a dylib. This test checks that these different library +// types can be successfully mixed. +//@ ignore-cross-compile + +use run_make_support::{run, rustc}; + +fn main() { + rustc().input("both.rs").arg("-Cprefer-dynamic").run(); + rustc().input("dylib.rs").arg("-Cprefer-dynamic").run(); + rustc().input("prog.rs").run(); + run("prog"); +} From b119e42b187a1f548ddb03bd6a90bc2cc820795e Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 28 May 2024 02:10:06 +0000 Subject: [PATCH 030/104] Add run-make-support to x doc --- src/bootstrap/src/core/build_steps/doc.rs | 8 ++++++++ src/bootstrap/src/core/builder.rs | 1 + 2 files changed, 9 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 38c48bd9570d..30b3edfd3aed 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1028,6 +1028,14 @@ tool_doc!( is_library = true, crates = ["bootstrap"] ); +tool_doc!( + RunMakeSupport, + "run_make_support", + "src/tools/run-make-support", + rustc_tool = false, + is_library = true, + crates = ["run_make_support"] +); #[derive(Ord, PartialOrd, Debug, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 045cde56f411..b3d8465cda98 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -888,6 +888,7 @@ impl<'a> Builder<'a> { doc::Tidy, doc::Bootstrap, doc::Releases, + doc::RunMakeSupport, ), Kind::Dist => describe!( dist::Docs, From ef9e6caabc822fccb038fe8cf61d719fae5ab111 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 28 May 2024 02:11:08 +0000 Subject: [PATCH 031/104] Fix run-make-support doc errors error: redundant explicit link target because label contains path that resolves to same destination --- src/tools/run-make-support/src/lib.rs | 2 +- src/tools/run-make-support/src/rustc.rs | 2 +- src/tools/run-make-support/src/rustdoc.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index d96c8b891278..38e4cfdb5e49 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -351,7 +351,7 @@ macro_rules! impl_common_helpers { self } - /// Inspect what the underlying [`Command`][::std::process::Command] is up to the + /// Inspect what the underlying [`Command`] is up to the /// current construction. pub fn inspect(&mut self, inspector: I) -> &mut Self where diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index 1c83b630861c..b424ae3f4210 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -203,7 +203,7 @@ impl Rustc { self } - /// Get the [`Output`][::std::process::Output] of the finished process. + /// Get the [`Output`] of the finished process. #[track_caller] pub fn command_output(&mut self) -> ::std::process::Output { // let's make sure we piped all the input and outputs diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs index 9c77f1ca4624..61d7448a6bfe 100644 --- a/src/tools/run-make-support/src/rustdoc.rs +++ b/src/tools/run-make-support/src/rustdoc.rs @@ -94,7 +94,7 @@ impl Rustdoc { self } - /// Get the [`Output`][::std::process::Output] of the finished process. + /// Get the [`Output`] of the finished process. #[track_caller] pub fn command_output(&mut self) -> ::std::process::Output { // let's make sure we piped all the input and outputs From 87599ddd86afc706f424870ca1a6f8dc4ae0aa8e Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 21 May 2024 19:30:26 +0000 Subject: [PATCH 032/104] add debug_assert to alias-relate --- compiler/rustc_trait_selection/src/solve/alias_relate.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs index 43e61de955af..33b30bef6832 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs @@ -28,6 +28,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { ) -> QueryResult<'tcx> { let tcx = self.tcx(); let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; + debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some()); // Structurally normalize the lhs. let lhs = if let Some(alias) = lhs.to_alias_term() { From 4d5a9bcb86630417002c9ab6d77ba023d30077b8 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 21 May 2024 19:30:47 +0000 Subject: [PATCH 033/104] change selection test to run-pass --- tests/ui/traits/next-solver/dyn-any-dont-prefer-impl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/traits/next-solver/dyn-any-dont-prefer-impl.rs b/tests/ui/traits/next-solver/dyn-any-dont-prefer-impl.rs index a63fe729fd68..1554d74f2145 100644 --- a/tests/ui/traits/next-solver/dyn-any-dont-prefer-impl.rs +++ b/tests/ui/traits/next-solver/dyn-any-dont-prefer-impl.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Znext-solver -//@ check-pass +//@ run-pass // Test that selection prefers the builtin trait object impl for `Any` // instead of the user defined impl. Both impls apply to the trait From 13ce22904265dbb7ab9d5bd8d508d8ea0ca4c4de Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 21 May 2024 19:56:18 +0000 Subject: [PATCH 034/104] refactor analyse visitor to instantiate states in order --- .../src/solve/inspect/analyse.rs | 86 +++++++++---------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 447357f8b3f6..1f27978e5a62 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -89,10 +89,8 @@ impl<'tcx> NormalizesToTermHack<'tcx> { pub struct InspectCandidate<'a, 'tcx> { goal: &'a InspectGoal<'a, 'tcx>, kind: inspect::ProbeKind>, - nested_goals: - Vec<(GoalSource, inspect::CanonicalState, Goal<'tcx, ty::Predicate<'tcx>>>)>, + steps: Vec<&'a inspect::ProbeStep>>, final_state: inspect::CanonicalState, ()>, - impl_args: Option, ty::GenericArgsRef<'tcx>>>, result: QueryResult<'tcx>, shallow_certainty: Certainty, } @@ -148,7 +146,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { #[instrument( level = "debug", skip_all, - fields(goal = ?self.goal.goal, nested_goals = ?self.nested_goals) + fields(goal = ?self.goal.goal, steps = ?self.steps) )] pub fn instantiate_nested_goals_and_opt_impl_args( &self, @@ -157,22 +155,34 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let infcx = self.goal.infcx; let param_env = self.goal.goal.param_env; let mut orig_values = self.goal.orig_values.to_vec(); - let instantiated_goals: Vec<_> = self - .nested_goals - .iter() - .map(|(source, goal)| { - ( - *source, + + let mut instantiated_goals = vec![]; + let mut opt_impl_args = None; + for step in &self.steps { + match **step { + inspect::ProbeStep::AddGoal(source, goal) => instantiated_goals.push(( + source, canonical::instantiate_canonical_state( infcx, span, param_env, &mut orig_values, - *goal, + goal, ), - ) - }) - .collect(); + )), + inspect::ProbeStep::RecordImplArgs { impl_args } => { + opt_impl_args = Some(canonical::instantiate_canonical_state( + infcx, + span, + param_env, + &mut orig_values, + impl_args, + )); + } + inspect::ProbeStep::MakeCanonicalResponse { .. } + | inspect::ProbeStep::NestedProbe(_) => unreachable!(), + } + } let () = canonical::instantiate_canonical_state( infcx, @@ -182,17 +192,6 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { self.final_state, ); - let impl_args = self.impl_args.map(|impl_args| { - canonical::instantiate_canonical_state( - infcx, - span, - param_env, - &mut orig_values, - impl_args, - ) - .fold_with(&mut EagerResolver::new(infcx)) - }); - if let Some(term_hack) = self.goal.normalizes_to_term_hack { // FIXME: We ignore the expected term of `NormalizesTo` goals // when computing the result of its candidates. This is @@ -200,6 +199,9 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let _ = term_hack.constrain(infcx, span, param_env); } + let opt_impl_args = + opt_impl_args.map(|impl_args| impl_args.fold_with(&mut EagerResolver::new(infcx))); + let goals = instantiated_goals .into_iter() .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() { @@ -249,7 +251,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { }) .collect(); - (goals, impl_args) + (goals, opt_impl_args) } /// Visit all nested goals of this candidate, rolling back @@ -279,17 +281,18 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { fn candidates_recur( &'a self, candidates: &mut Vec>, - nested_goals: &mut Vec<( - GoalSource, - inspect::CanonicalState, Goal<'tcx, ty::Predicate<'tcx>>>, - )>, - probe: &inspect::Probe>, + steps: &mut Vec<&'a inspect::ProbeStep>>, + probe: &'a inspect::Probe>, ) { let mut shallow_certainty = None; - let mut impl_args = None; for step in &probe.steps { match *step { - inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)), + inspect::ProbeStep::AddGoal(..) | inspect::ProbeStep::RecordImplArgs { .. } => { + steps.push(step) + } + inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { + assert_eq!(shallow_certainty.replace(c), None); + } inspect::ProbeStep::NestedProbe(ref probe) => { match probe.kind { // These never assemble candidates for the goal we're trying to solve. @@ -305,18 +308,12 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { // Nested probes have to prove goals added in their parent // but do not leak them, so we truncate the added goals // afterwards. - let num_goals = nested_goals.len(); - self.candidates_recur(candidates, nested_goals, probe); - nested_goals.truncate(num_goals); + let num_steps = steps.len(); + self.candidates_recur(candidates, steps, probe); + steps.truncate(num_steps); } } } - inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { - assert_eq!(shallow_certainty.replace(c), None); - } - inspect::ProbeStep::RecordImplArgs { impl_args: i } => { - assert_eq!(impl_args.replace(i), None); - } } } @@ -338,11 +335,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { candidates.push(InspectCandidate { goal: self, kind: probe.kind, - nested_goals: nested_goals.clone(), + steps: steps.clone(), final_state: probe.final_state, - result, shallow_certainty, - impl_args, + result, }); } } From 98bfd54b0abd938d6b424d45b57766e6f2f41ea2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 21 May 2024 19:56:53 +0000 Subject: [PATCH 035/104] eagerly normalize when adding goals --- compiler/rustc_middle/src/ty/predicate.rs | 9 +- .../src/solve/eval_ctxt/mod.rs | 77 +++++++++++++++- ...ap-unnormalizable-projection-1.next.stderr | 2 +- .../occurs-check/opaques.next.stderr | 2 +- .../as_expression.next.stderr | 20 ++++- .../do_not_recommend/as_expression.rs | 5 +- ...st-region-infer-to-static-in-binder.stderr | 4 +- .../cycles/cycle-modulo-ambig-aliases.rs | 89 +++++++++++++++++++ .../cycles/cycle-modulo-ambig-aliases.stderr | 15 ++++ 9 files changed, 207 insertions(+), 16 deletions(-) create mode 100644 tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs create mode 100644 tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.stderr diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index efb6cf255462..c730f5117c56 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -121,17 +121,14 @@ impl<'tcx> Predicate<'tcx> { #[inline] pub fn allow_normalization(self) -> bool { match self.kind().skip_binder() { - PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, - // `NormalizesTo` is only used in the new solver, so this shouldn't - // matter. Normalizing `term` would be 'wrong' however, as it changes whether - // `normalizes-to(::Assoc, ::Assoc)` holds. - PredicateKind::NormalizesTo(..) => false, + PredicateKind::Clause(ClauseKind::WellFormed(_)) + | PredicateKind::AliasRelate(..) + | PredicateKind::NormalizesTo(..) => false, PredicateKind::Clause(ClauseKind::Trait(_)) | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) | PredicateKind::Clause(ClauseKind::Projection(_)) | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::AliasRelate(..) | PredicateKind::ObjectSafe(_) | PredicateKind::Subtype(_) | PredicateKind::Coerce(_) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index ce408ddea378..4cf0af948119 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -13,11 +13,14 @@ use rustc_middle::traits::solve::{ inspect, CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaquesData, QueryResult, }; use rustc_middle::traits::specialization_graph; +use rustc_middle::ty::AliasRelationDirection; +use rustc_middle::ty::TypeFolder; use rustc_middle::ty::{ self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_span::DUMMY_SP; +use rustc_type_ir::fold::TypeSuperFoldable; use rustc_type_ir::{self as ir, CanonicalVarValues, Interner}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use std::ops::ControlFlow; @@ -455,13 +458,23 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { } #[instrument(level = "trace", skip(self))] - pub(super) fn add_normalizes_to_goal(&mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) { + pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) { + goal.predicate = goal + .predicate + .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal); self.nested_goals.normalizes_to_goals.push(goal); } #[instrument(level = "debug", skip(self))] - pub(super) fn add_goal(&mut self, source: GoalSource, goal: Goal<'tcx, ty::Predicate<'tcx>>) { + pub(super) fn add_goal( + &mut self, + source: GoalSource, + mut goal: Goal<'tcx, ty::Predicate<'tcx>>, + ) { + goal.predicate = goal + .predicate + .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal); self.nested_goals.goals.push((source, goal)); } @@ -1084,3 +1097,63 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { }); } } + +/// Eagerly replace aliases with inference variables, emitting `AliasRelate` +/// goals, used when adding goals to the `EvalCtxt`. We compute the +/// `AliasRelate` goals before evaluating the actual goal to get all the +/// constraints we can. +/// +/// This is a performance optimization to more eagerly detect cycles during trait +/// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs. +struct ReplaceAliasWithInfer<'me, 'a, 'tcx> { + ecx: &'me mut EvalCtxt<'a, InferCtxt<'tcx>>, + param_env: ty::ParamEnv<'tcx>, +} + +impl<'tcx> TypeFolder> for ReplaceAliasWithInfer<'_, '_, 'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { + self.ecx.tcx() + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match *ty.kind() { + ty::Alias(..) if !ty.has_escaping_bound_vars() => { + let infer_ty = self.ecx.next_ty_infer(); + let normalizes_to = ty::PredicateKind::AliasRelate( + ty.into(), + infer_ty.into(), + AliasRelationDirection::Equate, + ); + self.ecx.add_goal( + GoalSource::Misc, + Goal::new(self.interner(), self.param_env, normalizes_to), + ); + infer_ty + } + _ => ty.super_fold_with(self), + } + } + + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + match ct.kind() { + ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => { + let infer_ct = self.ecx.next_const_infer(ct.ty()); + let normalizes_to = ty::PredicateKind::AliasRelate( + ct.into(), + infer_ct.into(), + AliasRelationDirection::Equate, + ); + self.ecx.add_goal( + GoalSource::Misc, + Goal::new(self.interner(), self.param_env, normalizes_to), + ); + infer_ct + } + _ => ct.super_fold_with(self), + } + } + + fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate } + } +} diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr index 49b236f9d2aa..781ab0fcbf76 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr @@ -12,7 +12,7 @@ LL | impl Trait for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` | = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box< as WithAssoc<'a>>::Assoc>` + = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index f6c5255a1869..11d1edcca2f9 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -11,7 +11,7 @@ error[E0282]: type annotations needed --> $DIR/opaques.rs:13:20 | LL | pub fn cast(x: Container, T>) -> Container { - | ^ cannot infer type for associated type `>::Assoc` + | ^ cannot infer type error: aborting due to 2 previous errors diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 47acf5b968b7..568cb8931a19 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -16,6 +16,22 @@ LL | where LL | T: AsExpression, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` -error: aborting due to 1 previous error +error[E0277]: the trait bound `&str: AsExpression` is not satisfied + --> $DIR/as_expression.rs:57:15 + | +LL | SelectInt.check("bar"); + | ^^^^^ the trait `AsExpression` is not implemented for `&str` + | + = help: the trait `AsExpression` is implemented for `&str` + = help: for that trait implementation, expected `Text`, found `Integer` -For more information about this error, try `rustc --explain E0277`. +error[E0271]: type mismatch resolving `<&str as AsExpression<::SqlType>>::Expression == _` + --> $DIR/as_expression.rs:57:5 + | +LL | SelectInt.check("bar"); + | ^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs index 5fd5cc544009..37b4429f694c 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -55,6 +55,7 @@ impl Foo for T where T: Expression {} fn main() { SelectInt.check("bar"); - //[next]~^ ERROR the trait bound `&str: AsExpression<::SqlType>` is not satisfied - //[current]~^^ ERROR the trait bound `&str: AsExpression` is not satisfied + //~^ ERROR the trait bound `&str: AsExpression` is not satisfied + //[next]~| the trait bound `&str: AsExpression<::SqlType>` is not satisfied + //[next]~| type mismatch } diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr index 170f2c7d34c4..9dde1963bd49 100644 --- a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr +++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot satisfy `the constant `{ || {} }` can be evaluated` +error[E0284]: type annotations needed: cannot satisfy `{ || {} } == _` --> $DIR/const-region-infer-to-static-in-binder.rs:4:10 | LL | struct X; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `{ || {} }` can be evaluated` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `{ || {} } == _` error: using function pointers as const generic parameters is forbidden --> $DIR/const-region-infer-to-static-in-binder.rs:4:20 diff --git a/tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs b/tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs new file mode 100644 index 000000000000..5c13a871a7b8 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs @@ -0,0 +1,89 @@ +//@ compile-flags: -Znext-solver + +// A regression test for #125269. We previously ended up +// recursively proving `&<_ as SpeciesPackedElem>::Assoc: Typed` +// for all aliases which ended up causing exponential blowup. +// +// This has been fixed by eagerly normalizing the associated +// type before computing the nested goals, resulting in an +// immediate inductive cycle. + +pub trait Typed {} + +pub struct SpeciesCases(E); + +pub trait SpeciesPackedElim { + type Ogre; + type Cyclops; + type Wendigo; + type Cavetroll; + type Mountaintroll; + type Swamptroll; + type Dullahan; + type Werewolf; + type Occultsaurok; + type Mightysaurok; + type Slysaurok; + type Mindflayer; + type Minotaur; + type Tidalwarrior; + type Yeti; + type Harvester; + type Blueoni; + type Redoni; + type Cultistwarlord; + type Cultistwarlock; + type Huskbrute; + type Tursus; + type Gigasfrost; + type AdletElder; + type SeaBishop; + type HaniwaGeneral; + type TerracottaBesieger; + type TerracottaDemolisher; + type TerracottaPunisher; + type TerracottaPursuer; + type Cursekeeper; +} + +impl<'b, E: SpeciesPackedElim> Typed for &'b SpeciesCases +where + &'b E::Ogre: Typed, + &'b E::Cyclops: Typed, + &'b E::Wendigo: Typed, + &'b E::Cavetroll: Typed, + &'b E::Mountaintroll: Typed, + &'b E::Swamptroll: Typed, + &'b E::Dullahan: Typed, + &'b E::Werewolf: Typed, + &'b E::Occultsaurok: Typed, + &'b E::Mightysaurok: Typed, + &'b E::Slysaurok: Typed, + &'b E::Mindflayer: Typed, + &'b E::Minotaur: Typed, + &'b E::Tidalwarrior: Typed, + &'b E::Yeti: Typed, + &'b E::Harvester: Typed, + &'b E::Blueoni: Typed, + &'b E::Redoni: Typed, + &'b E::Cultistwarlord: Typed, + &'b E::Cultistwarlock: Typed, + &'b E::Huskbrute: Typed, + &'b E::Tursus: Typed, + &'b E::Gigasfrost: Typed, + &'b E::AdletElder: Typed, + &'b E::SeaBishop: Typed, + &'b E::HaniwaGeneral: Typed, + &'b E::TerracottaBesieger: Typed, + &'b E::TerracottaDemolisher: Typed, + &'b E::TerracottaPunisher: Typed, + &'b E::TerracottaPursuer: Typed, + &'b E::Cursekeeper: Typed, +{} + +fn foo() {} + +fn main() { + foo::<&_>(); + //~^ ERROR overflow evaluating the requirement `&_: Typed` +} diff --git a/tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.stderr b/tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.stderr new file mode 100644 index 000000000000..d350eb0f7795 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `&_: Typed` + --> $DIR/cycle-modulo-ambig-aliases.rs:87:11 + | +LL | foo::<&_>(); + | ^^ + | +note: required by a bound in `foo` + --> $DIR/cycle-modulo-ambig-aliases.rs:84:11 + | +LL | fn foo() {} + | ^^^^^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. From 27cdc0df4e73b76466c72ae69ab6545f84089ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 28 May 2024 04:15:54 +0200 Subject: [PATCH 036/104] Don't suggest turning non-char-literal exprs of ty `char` into string literals --- .../src/infer/error_reporting/mod.rs | 13 +++++++---- tests/crashes/125081.rs | 7 ------ tests/ui/inference/str-as-char-butchered.rs | 7 ++++++ .../ui/inference/str-as-char-butchered.stderr | 22 +++++++++++++++++++ tests/ui/inference/str-as-char-non-lit.rs | 9 ++++++++ tests/ui/inference/str-as-char-non-lit.stderr | 19 ++++++++++++++++ 6 files changed, 66 insertions(+), 11 deletions(-) delete mode 100644 tests/crashes/125081.rs create mode 100644 tests/ui/inference/str-as-char-butchered.rs create mode 100644 tests/ui/inference/str-as-char-butchered.stderr create mode 100644 tests/ui/inference/str-as-char-non-lit.rs create mode 100644 tests/ui/inference/str-as-char-non-lit.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e0894ed31bfc..c7affaa17e9d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2064,10 +2064,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // If a string was expected and the found expression is a character literal, // perhaps the user meant to write `"s"` to specify a string literal. (ty::Ref(_, r, _), ty::Char) if r.is_str() => { - suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral { - start: span.with_hi(span.lo() + BytePos(1)), - end: span.with_lo(span.hi() - BytePos(1)), - }) + if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) + && code.starts_with("'") + && code.ends_with("'") + { + suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral { + start: span.with_hi(span.lo() + BytePos(1)), + end: span.with_lo(span.hi() - BytePos(1)), + }); + } } // For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`, // we try to suggest to add the missing `let` for `if let Some(..) = expr` diff --git a/tests/crashes/125081.rs b/tests/crashes/125081.rs deleted file mode 100644 index 7139caaa00df..000000000000 --- a/tests/crashes/125081.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: rust-lang/rust#125081 - -use std::cell::Cell; - -fn main() { - let _: Cell<&str, "a"> = Cell::new('β); -} diff --git a/tests/ui/inference/str-as-char-butchered.rs b/tests/ui/inference/str-as-char-butchered.rs new file mode 100644 index 000000000000..6020cd3422fd --- /dev/null +++ b/tests/ui/inference/str-as-char-butchered.rs @@ -0,0 +1,7 @@ +// issue: rust-lang/rust#125081 + +fn main() { + let _: &str = 'β; + //~^ ERROR expected `while`, `for`, `loop` or `{` after a label + //~| ERROR mismatched types +} diff --git a/tests/ui/inference/str-as-char-butchered.stderr b/tests/ui/inference/str-as-char-butchered.stderr new file mode 100644 index 000000000000..ad465f979d4d --- /dev/null +++ b/tests/ui/inference/str-as-char-butchered.stderr @@ -0,0 +1,22 @@ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/str-as-char-butchered.rs:4:21 + | +LL | let _: &str = 'β; + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: add `'` to close the char literal + | +LL | let _: &str = 'β'; + | + + +error[E0308]: mismatched types + --> $DIR/str-as-char-butchered.rs:4:19 + | +LL | let _: &str = 'β; + | ---- ^^ expected `&str`, found `char` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/str-as-char-non-lit.rs b/tests/ui/inference/str-as-char-non-lit.rs new file mode 100644 index 000000000000..d38b46630dcf --- /dev/null +++ b/tests/ui/inference/str-as-char-non-lit.rs @@ -0,0 +1,9 @@ +// Don't suggest double quotes when encountering an expr of type `char` where a `&str` +// is expected if the expr is not a char literal. +// issue: rust-lang/rust#125595 + +fn main() { + let _: &str = ('a'); //~ ERROR mismatched types + let token = || 'a'; + let _: &str = token(); //~ ERROR mismatched types +} diff --git a/tests/ui/inference/str-as-char-non-lit.stderr b/tests/ui/inference/str-as-char-non-lit.stderr new file mode 100644 index 000000000000..7675fe013307 --- /dev/null +++ b/tests/ui/inference/str-as-char-non-lit.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/str-as-char-non-lit.rs:6:19 + | +LL | let _: &str = ('a'); + | ---- ^^^^^ expected `&str`, found `char` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/str-as-char-non-lit.rs:8:19 + | +LL | let _: &str = token(); + | ---- ^^^^^^^ expected `&str`, found `char` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 402a649e753c2f21c67c641e99dc90796be85566 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 28 May 2024 11:02:03 +0200 Subject: [PATCH 037/104] update tracking issue for lazy_cell_consume --- library/core/src/cell/lazy.rs | 2 +- library/std/src/sync/lazy_lock.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index 47eab6fd0163..80b85b954462 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -78,7 +78,7 @@ impl T> LazyCell { /// assert_eq!(&*lazy, "HELLO, WORLD!"); /// assert_eq!(LazyCell::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string())); /// ``` - #[unstable(feature = "lazy_cell_consume", issue = "109736")] + #[unstable(feature = "lazy_cell_consume", issue = "125623")] pub fn into_inner(this: Self) -> Result { match this.state.into_inner() { State::Init(data) => Ok(data), diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 16d5dc30552f..d3bb3bfdff92 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -126,7 +126,7 @@ impl T> LazyLock { /// assert_eq!(&*lazy, "HELLO, WORLD!"); /// assert_eq!(LazyLock::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string())); /// ``` - #[unstable(feature = "lazy_cell_consume", issue = "109736")] + #[unstable(feature = "lazy_cell_consume", issue = "125623")] pub fn into_inner(mut this: Self) -> Result { let state = this.once.state(); match state { From 56733372b8b78bf4d47877d7e50d6ab514d3e67c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 27 May 2024 11:06:43 +0200 Subject: [PATCH 038/104] Add `assert_not_contains` to `run-make-support` library --- src/tools/run-make-support/src/lib.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index d96c8b891278..35d7b65bec08 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -268,6 +268,17 @@ pub fn recursive_diff(dir1: impl AsRef, dir2: impl AsRef) { } } +/// Check that `haystack` does not contain `needle`. Panic otherwise. +pub fn assert_not_contains(haystack: &str, needle: &str) { + if haystack.contains(needle) { + eprintln!("=== HAYSTACK ==="); + eprintln!("{}", haystack); + eprintln!("=== NEEDLE ==="); + eprintln!("{}", needle); + panic!("needle was unexpectedly found in haystack"); + } +} + /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct /// containing a `cmd: Command` field and a `output` function. The provided helpers are: /// From 404d47ec20cf7606d28156945a6a4fc831c6e7d8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 26 May 2024 13:37:53 +0200 Subject: [PATCH 039/104] Migrate `run-make/allow-warnings-cmdline-stability` to `rmake.rs` --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../allow-warnings-cmdline-stability/Makefile | 16 ---------------- .../allow-warnings-cmdline-stability/rmake.rs | 11 +++++++++++ 3 files changed, 11 insertions(+), 17 deletions(-) delete mode 100644 tests/run-make/allow-warnings-cmdline-stability/Makefile create mode 100644 tests/run-make/allow-warnings-cmdline-stability/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 2329b8b44dea..9ca27834cf72 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,6 +1,5 @@ run-make/allocator-shim-circular-deps/Makefile run-make/allow-non-lint-warnings-cmdline/Makefile -run-make/allow-warnings-cmdline-stability/Makefile run-make/archive-duplicate-names/Makefile run-make/atomic-lock-free/Makefile run-make/bare-outfile/Makefile diff --git a/tests/run-make/allow-warnings-cmdline-stability/Makefile b/tests/run-make/allow-warnings-cmdline-stability/Makefile deleted file mode 100644 index 368a39af6bfe..000000000000 --- a/tests/run-make/allow-warnings-cmdline-stability/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# Test that -A warnings makes the 'empty trait list for derive' warning go away -DEP=$(shell $(RUSTC) bar.rs) -OUT=$(shell $(RUSTC) foo.rs -A warnings 2>&1 | grep "warning" ) - -all: foo bar - test -z '$(OUT)' - -# These are just to ensure that the above commands actually work -bar: - $(RUSTC) bar.rs - -foo: bar - $(RUSTC) foo.rs -A warnings diff --git a/tests/run-make/allow-warnings-cmdline-stability/rmake.rs b/tests/run-make/allow-warnings-cmdline-stability/rmake.rs new file mode 100644 index 000000000000..8f6fe6bd0b66 --- /dev/null +++ b/tests/run-make/allow-warnings-cmdline-stability/rmake.rs @@ -0,0 +1,11 @@ +// Test that `-Awarnings` suppresses warnings for unstable APIs. + +use run_make_support::{assert_not_contains, rustc}; + +fn main() { + rustc().input("bar.rs").run(); + let output = rustc().input("foo.rs").arg("-Awarnings").run(); + + assert_not_contains(&String::from_utf8(output.stdout).unwrap(), "warning"); + assert_not_contains(&String::from_utf8(output.stderr).unwrap(), "warning"); +} From 4702a1c345f1c13e13bdbe9bb3fdb81d6f866d85 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 May 2024 10:36:37 +1000 Subject: [PATCH 040/104] Fix comments. Some are too long, some aren't complete sentences, some are complete sentences but don't bother with an upper case letter at the start. All annoying and hurt readability. --- rustfmt.toml | 14 ++++----- src/bootstrap/src/core/build_steps/format.rs | 31 +++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 1f914964e241..4812c9302dfd 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -3,24 +3,24 @@ version = "Two" use_small_heuristics = "Max" merge_derives = false -# tidy only checks files which are not ignored, each entry follows gitignore style +# Files to ignore. Each entry uses gitignore syntax. ignore = [ "/build/", "/*-build/", "/build-*/", "/vendor/", - # tests for now are not formatted, as they are sometimes pretty-printing constrained - # (and generally rustfmt can move around comments in UI-testing incompatible ways) + # Tests for now are not formatted, as they are sometimes pretty-printing constrained + # (and generally rustfmt can move around comments in UI-testing incompatible ways). "/tests/*", - # but we still want to format rmake.rs files in tests/run-make/ so we need to do this - # dance to avoid the parent directory from being excluded + # But we still want to format rmake.rs files in tests/run-make/ so we need to do this + # dance to avoid the parent directory from being excluded. "!/tests/run-make/", "/tests/run-make/*/*.rs", "!/tests/run-make/*/rmake.rs", - # do not format submodules + # Do not format submodules. # FIXME: sync submodule list with tidy/bootstrap/etc # tidy/src/walk.rs:filter_dirs "library/backtrace", @@ -42,7 +42,7 @@ ignore = [ "src/tools/rustc-perf", "src/tools/rustfmt", - # these are ignored by a standard cargo fmt run + # These are ignored by a standard cargo fmt run. "compiler/rustc_codegen_cranelift/scripts", "compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs", # uses edition 2024 ] diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index d9dc34c01370..7f9d88ca7216 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -12,8 +12,8 @@ use std::sync::mpsc::SyncSender; fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl FnMut(bool) -> bool { let mut cmd = Command::new(rustfmt); - // avoid the submodule config paths from coming into play, - // we only allow a single global config for the workspace for now + // Avoid the submodule config paths from coming into play. We only allow a single global config + // for the workspace for now. cmd.arg("--config-path").arg(&src.canonicalize().unwrap()); cmd.arg("--edition").arg("2021"); cmd.arg("--unstable-features"); @@ -24,7 +24,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F cmd.args(paths); let cmd_debug = format!("{cmd:?}"); let mut cmd = cmd.spawn().expect("running rustfmt"); - // poor man's async: return a closure that'll wait for rustfmt's completion + // Poor man's async: return a closure that'll wait for rustfmt's completion. move |block: bool| -> bool { if !block { match cmd.try_wait() { @@ -72,7 +72,7 @@ fn verify_rustfmt_version(build: &Builder<'_>) -> bool { !program_out_of_date(&stamp_file, &version) } -/// Updates the last rustfmt version used +/// Updates the last rustfmt version used. fn update_rustfmt_version(build: &Builder<'_>) { let Some((version, stamp_file)) = get_rustfmt_version(build) else { return; @@ -168,9 +168,10 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { untracked_count += 1; fmt_override.add(&format!("!/{untracked_path}")).expect(untracked_path); } - // Only check modified files locally to speed up runtime. - // We still check all files in CI to avoid bugs in `get_modified_rs_files` letting regressions slip through; - // we also care about CI time less since this is still very fast compared to building the compiler. + // Only check modified files locally to speed up runtime. We still check all files in + // CI to avoid bugs in `get_modified_rs_files` letting regressions slip through; we + // also care about CI time less since this is still very fast compared to building the + // compiler. if !CiEnv::is_ci() && paths.is_empty() { match get_modified_rs_files(build) { Ok(Some(files)) => { @@ -275,21 +276,23 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { .overrides(fmt_override) .build_parallel(); - // there is a lot of blocking involved in spawning a child process and reading files to format. - // spawn more processes than available concurrency to keep the CPU busy + // There is a lot of blocking involved in spawning a child process and reading files to format. + // Spawn more processes than available concurrency to keep the CPU busy. let max_processes = build.jobs() as usize * 2; - // spawn child processes on a separate thread so we can batch entries we have received from ignore + // Spawn child processes on a separate thread so we can batch entries we have received from + // ignore. let thread = std::thread::spawn(move || { let mut children = VecDeque::new(); while let Ok(path) = rx.recv() { - // try getting more paths from the channel to amortize the overhead of spawning processes + // Try getting more paths from the channel to amortize the overhead of spawning + // processes. let paths: Vec<_> = rx.try_iter().take(63).chain(std::iter::once(path)).collect(); let child = rustfmt(&src, &rustfmt_path, paths.as_slice(), check); children.push_back(child); - // poll completion before waiting + // Poll completion before waiting. for i in (0..children.len()).rev() { if children[i](false) { children.swap_remove_back(i); @@ -298,12 +301,12 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { } if children.len() >= max_processes { - // await oldest child + // Await oldest child. children.pop_front().unwrap()(true); } } - // await remaining children + // Await remaining children. for mut child in children { child(true); } From f1b0ca08a42e9cbfcd91e25174be2e36cdaf2651 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 May 2024 10:03:00 +1000 Subject: [PATCH 041/104] Don't format `tests/run-make/*/rmake.rs`. It's reasonable to want to, but in the current implementation this causes multiple problems. - All the `rmake.rs` files are formatted every time even when they haven't changed. This is because they get whitelisted unconditionally in the `OverrideBuilder`, before the changed files get added. - The way `OverrideBuilder` works, if any files gets whitelisted then no unmentioned files will get traversed. This is surprising, and means that the `rmake.rs` entries broke the use of explicit paths to `x fmt`, and also broke `GITHUB_ACTIONS=true git check --fmt`. The commit removes the `rmake.rs` entries, fixes the formatting of a couple of files that were misformatted (not previously caught due to the `GITHUB_ACTIONS` breakage), and bans `!`-prefixed entries in `rustfmt.toml` because they cause all these problems. --- compiler/rustc_mir_transform/src/instsimplify.rs | 6 ++---- compiler/rustc_mir_transform/src/validate.rs | 2 +- library/core/src/ptr/metadata.rs | 8 ++------ rustfmt.toml | 10 ++-------- src/bootstrap/src/core/build_steps/format.rs | 11 +++++++++-- 5 files changed, 16 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 5e70b300f338..a54332b6f257 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -219,10 +219,8 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { for (i, field) in variant.fields.iter_enumerated() { let field_ty = field.ty(self.tcx, args); if field_ty == *cast_ty { - let place = place.project_deeper( - &[ProjectionElem::Field(i, *cast_ty)], - self.tcx, - ); + let place = place + .project_deeper(&[ProjectionElem::Field(i, *cast_ty)], self.tcx); let operand = if operand.is_move() { Operand::Move(place) } else { diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 6df32169eecb..8d7547d03e8e 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -691,7 +691,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { location, format!( "You can't project to field {f:?} of `DynMetadata` because \ - layout is weird and thinks it doesn't have fields." + layout is weird and thinks it doesn't have fields." ), ); } diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index e501970b580d..6dfeb66694d3 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -209,18 +209,14 @@ impl DynMetadata { // Consider a reference like `&(i32, dyn Send)`: the vtable will only store the size of the // `Send` part! // SAFETY: DynMetadata always contains a valid vtable pointer - return unsafe { - crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) - }; + return unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) }; } /// Returns the alignment of the type associated with this vtable. #[inline] pub fn align_of(self) -> usize { // SAFETY: DynMetadata always contains a valid vtable pointer - return unsafe { - crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) - }; + return unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) }; } /// Returns the size and alignment together as a `Layout` diff --git a/rustfmt.toml b/rustfmt.toml index 4812c9302dfd..b78e96d5872f 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -3,7 +3,7 @@ version = "Two" use_small_heuristics = "Max" merge_derives = false -# Files to ignore. Each entry uses gitignore syntax. +# Files to ignore. Each entry uses gitignore syntax, but `!` prefixes aren't allowed. ignore = [ "/build/", "/*-build/", @@ -12,13 +12,7 @@ ignore = [ # Tests for now are not formatted, as they are sometimes pretty-printing constrained # (and generally rustfmt can move around comments in UI-testing incompatible ways). - "/tests/*", - - # But we still want to format rmake.rs files in tests/run-make/ so we need to do this - # dance to avoid the parent directory from being excluded. - "!/tests/run-make/", - "/tests/run-make/*/*.rs", - "!/tests/run-make/*/rmake.rs", + "/tests/", # Do not format submodules. # FIXME: sync submodule list with tidy/bootstrap/etc diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 7f9d88ca7216..44f575b51da2 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -115,8 +115,15 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config)); let mut fmt_override = ignore::overrides::OverrideBuilder::new(&build.src); for ignore in rustfmt_config.ignore { - if let Some(ignore) = ignore.strip_prefix('!') { - fmt_override.add(ignore).expect(ignore); + if ignore.starts_with('!') { + // A `!`-prefixed entry could be added as a whitelisted entry in `fmt_override`, i.e. + // strip the `!` prefix. But as soon as whitelisted entries are added, an + // `OverrideBuilder` will only traverse those whitelisted entries, and won't traverse + // any files that aren't explicitly mentioned. No bueno! Maybe there's a way to combine + // explicit whitelisted entries and traversal of unmentioned files, but for now just + // forbid such entries. + eprintln!("`!`-prefixed entries are not supported in rustfmt.toml, sorry"); + crate::exit!(1); } else { fmt_override.add(&format!("!{ignore}")).expect(&ignore); } From d82be822a84c6e511cfb586827d0f100290f6581 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 27 May 2024 15:01:04 +0200 Subject: [PATCH 042/104] Enable a few tests on macOS --- tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs | 4 +--- tests/ui/panic-runtime/abort.rs | 4 +--- tests/ui/panic-runtime/link-to-abort.rs | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs b/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs index 11e4929f12e0..ce6644e67586 100644 --- a/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs +++ b/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs @@ -5,12 +5,11 @@ //@ no-prefer-dynamic //@ ignore-wasm32 no processes //@ ignore-sgx no processes -//@ ignore-macos extern crate exit_success_if_unwind; -use std::process::Command; use std::env; +use std::process::Command; fn main() { let mut args = env::args_os(); @@ -25,7 +24,6 @@ fn main() { let mut cmd = Command::new(env::args_os().next().unwrap()); cmd.arg("foo"); - // ARMv6 hanges while printing the backtrace, see #41004 if cfg!(target_arch = "arm") && cfg!(target_env = "gnu") { cmd.env("RUST_BACKTRACE", "0"); diff --git a/tests/ui/panic-runtime/abort.rs b/tests/ui/panic-runtime/abort.rs index 22bd2ecfb00e..caf0243ebdb2 100644 --- a/tests/ui/panic-runtime/abort.rs +++ b/tests/ui/panic-runtime/abort.rs @@ -4,10 +4,9 @@ //@ no-prefer-dynamic //@ ignore-wasm32 no processes //@ ignore-sgx no processes -//@ ignore-macos -use std::process::Command; use std::env; +use std::process::Command; struct Bomb; @@ -23,7 +22,6 @@ fn main() { if let Some(s) = args.next() { if &*s == "foo" { - let _bomb = Bomb; panic!("try to catch me"); diff --git a/tests/ui/panic-runtime/link-to-abort.rs b/tests/ui/panic-runtime/link-to-abort.rs index 2a7052616f2c..a4013f2a6cf7 100644 --- a/tests/ui/panic-runtime/link-to-abort.rs +++ b/tests/ui/panic-runtime/link-to-abort.rs @@ -2,7 +2,6 @@ //@ compile-flags:-C panic=abort //@ no-prefer-dynamic -//@ ignore-macos #![feature(panic_abort)] From 37ae2b68b1631a5f2cb7d2b2f6478acba654d651 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 16 May 2024 12:58:09 +0200 Subject: [PATCH 043/104] Disable stack overflow handler tests on iOS-like platforms --- library/std/src/sys/pal/unix/stack_overflow.rs | 8 ++++++++ tests/ui/abi/stack-probes-lto.rs | 4 ++++ tests/ui/abi/stack-probes.rs | 4 ++++ tests/ui/runtime/out-of-stack.rs | 4 ++++ 4 files changed, 20 insertions(+) diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 26c49257ad00..2e5bd85327a1 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -491,6 +491,14 @@ mod imp { } } +// This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses +// several symbols that might lead to rejections from the App Store, namely +// `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`. +// +// This might be overly cautious, though it is also what Swift does (and they +// usually have fewer qualms about forwards compatibility, since the runtime +// is shipped with the OS): +// #[cfg(not(any( target_os = "linux", target_os = "freebsd", diff --git a/tests/ui/abi/stack-probes-lto.rs b/tests/ui/abi/stack-probes-lto.rs index 5451b72d9792..70343b0599ac 100644 --- a/tests/ui/abi/stack-probes-lto.rs +++ b/tests/ui/abi/stack-probes-lto.rs @@ -10,5 +10,9 @@ //@ compile-flags: -C lto //@ no-prefer-dynamic //@ ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino +//@ ignore-ios Stack probes are enabled, but the SIGSEGV handler isn't +//@ ignore-tvos Stack probes are enabled, but the SIGSEGV handler isn't +//@ ignore-watchos Stack probes are enabled, but the SIGSEGV handler isn't +//@ ignore-visionos Stack probes are enabled, but the SIGSEGV handler isn't include!("stack-probes.rs"); diff --git a/tests/ui/abi/stack-probes.rs b/tests/ui/abi/stack-probes.rs index 32d4d6cd31e6..22304257593f 100644 --- a/tests/ui/abi/stack-probes.rs +++ b/tests/ui/abi/stack-probes.rs @@ -8,6 +8,10 @@ //@ ignore-sgx no processes //@ ignore-fuchsia no exception handler registered for segfault //@ ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino +//@ ignore-ios Stack probes are enabled, but the SIGSEGV handler isn't +//@ ignore-tvos Stack probes are enabled, but the SIGSEGV handler isn't +//@ ignore-watchos Stack probes are enabled, but the SIGSEGV handler isn't +//@ ignore-visionos Stack probes are enabled, but the SIGSEGV handler isn't use std::env; use std::mem::MaybeUninit; diff --git a/tests/ui/runtime/out-of-stack.rs b/tests/ui/runtime/out-of-stack.rs index a62398df8b80..c5300635ad92 100644 --- a/tests/ui/runtime/out-of-stack.rs +++ b/tests/ui/runtime/out-of-stack.rs @@ -7,6 +7,10 @@ //@ ignore-sgx no processes //@ ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590) //@ ignore-nto no stack overflow handler used (no alternate stack available) +//@ ignore-ios stack overflow handlers aren't enabled +//@ ignore-tvos stack overflow handlers aren't enabled +//@ ignore-watchos stack overflow handlers aren't enabled +//@ ignore-visionos stack overflow handlers aren't enabled #![feature(rustc_private)] From e6b9bb7b7200c69b82fd69572a7c0a03ead3d60f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 27 May 2024 15:17:18 +0200 Subject: [PATCH 044/104] Make more of the test suite run on Mac Catalyst This adds the `only-apple`/`ignore-apple` compiletest directive, and uses that basically everywhere instead of `only-macos`/`ignore-macos`. Some of the updates in `run-make` are a bit redundant, as they use `ignore-cross-compile` and won't run on iOS - but using Apple in these is still more correct, so I've made that change anyhow. --- library/std/src/fs/tests.rs | 2 +- src/bootstrap/src/utils/dylib.rs | 2 +- src/tools/compiletest/src/header.rs | 3 +- src/tools/compiletest/src/header/cfg.rs | 6 ++++ src/tools/compiletest/src/runtest.rs | 2 +- src/tools/compiletest/src/util.rs | 2 +- src/tools/tidy/src/issues.txt | 1 - src/tools/tidy/src/ui_tests.rs | 2 +- .../stack-protector-heuristics-effect.rs | 5 +--- .../x86_64-array-pair-load-store-merge.rs | 2 +- tests/assembly/x86_64-function-return.rs | 2 +- tests/codegen/gdb_debug_script_load.rs | 2 +- tests/codegen/instrument-coverage/testprog.rs | 4 +-- .../issues/issue-44056-macos-tls-align.rs | 2 +- tests/codegen/mainsubprogram.rs | 5 ++-- tests/codegen/mainsubprogramstart.rs | 2 +- tests/codegen/pgo-counter-bias.rs | 2 +- tests/run-make/c-dynamic-dylib/Makefile | 2 +- tests/run-make/c-dynamic-rlib/Makefile | 2 +- tests/run-make/emit-stack-sizes/Makefile | 4 +-- tests/run-make/fpic/Makefile | 2 +- tests/run-make/link-framework/Makefile | 2 +- tests/run-make/macos-fat-archive/Makefile | 2 +- .../Makefile | 2 +- tests/run-make/used-cdylib-macos/Makefile | 4 +-- tests/run-pass-valgrind/exit-flushes.rs | 5 ++-- tests/ui/backtrace/apple-no-dsymutil.rs | 2 +- tests/ui/deployment-target/macos-target.rs | 2 +- tests/ui/intrinsics/intrinsic-alignment.rs | 29 +++++++++--------- tests/ui/issues/issue-45731.rs | 13 +++++--- tests/ui/link-section.rs | 24 +++++++-------- tests/ui/linkage-attr/framework.rs | 2 +- .../kind-framework.rs} | 2 +- .../kind-framework.stderr} | 2 +- ...e-attr-does-not-panic-llvm-issue-33992.rs} | 2 +- tests/ui/linkage-attr/linkage1.rs | 2 +- .../auxiliary/lib.rs | 0 .../propagate-generic-issue-18804}/main.rs | 2 +- tests/ui/manual/manual-link-framework.rs | 6 ++-- .../structs-enums/enum-rec/issue-17431-6.rs | 2 +- tests/ui/structs-enums/rec-align-u64.rs | 30 +++++++++---------- 41 files changed, 98 insertions(+), 93 deletions(-) rename tests/ui/{osx-frameworks.rs => linkage-attr/kind-framework.rs} (58%) rename tests/ui/{osx-frameworks.stderr => linkage-attr/kind-framework.stderr} (89%) rename tests/ui/{issues/issue-33992.rs => linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs} (96%) rename tests/ui/{issues/issue-18804 => linkage-attr/propagate-generic-issue-18804}/auxiliary/lib.rs (100%) rename tests/ui/{issues/issue-18804 => linkage-attr/propagate-generic-issue-18804}/main.rs (91%) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index dfa05671ab0f..62a268facb63 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1431,7 +1431,7 @@ fn metadata_access_times() { assert_eq!(check!(a.modified()), check!(a.modified())); assert_eq!(check!(b.accessed()), check!(b.modified())); - if cfg!(target_os = "macos") || cfg!(target_os = "windows") { + if cfg!(target_vendor = "apple") || cfg!(target_os = "windows") { check!(a.created()); check!(b.created()); } diff --git a/src/bootstrap/src/utils/dylib.rs b/src/bootstrap/src/utils/dylib.rs index b6e7aec1756b..90bcff59a647 100644 --- a/src/bootstrap/src/utils/dylib.rs +++ b/src/bootstrap/src/utils/dylib.rs @@ -5,7 +5,7 @@ pub fn dylib_path_var() -> &'static str { if cfg!(target_os = "windows") { "PATH" - } else if cfg!(target_os = "macos") { + } else if cfg!(target_vendor = "apple") { "DYLD_LIBRARY_PATH" } else if cfg!(target_os = "haiku") { "LIBRARY_PATH" diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c7c807d3e684..dc5818201b6d 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -747,6 +747,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-aarch64", "ignore-aarch64-unknown-linux-gnu", "ignore-android", + "ignore-apple", "ignore-arm", "ignore-avr", "ignore-beta", @@ -829,7 +830,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-x32", "ignore-x86", "ignore-x86_64", - "ignore-x86_64-apple-darwin", "ignore-x86_64-unknown-linux-gnu", "incremental", "known-bug", @@ -876,6 +876,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-32bit", "only-64bit", "only-aarch64", + "only-apple", "only-arm", "only-avr", "only-beta", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index df8c80470502..510043e3bfd8 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -159,6 +159,12 @@ pub(super) fn parse_cfg_name_directive<'a>( message: "when the architecture is part of the Thumb family" } + condition! { + name: "apple", + condition: config.target.contains("apple"), + message: "when the target vendor is Apple" + } + // Technically the locally built compiler uses the "dev" channel rather than the "nightly" // channel, even though most people don't know or won't care about it. To avoid confusion, we // treat the "dev" channel as the "nightly" channel when processing the directive. diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 02c9d384ab7e..e8ceff847224 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -98,7 +98,7 @@ fn get_lib_name(lib: &str, aux_type: AuxType) -> Option { AuxType::Lib => Some(format!("lib{}.rlib", lib)), AuxType::Dylib => Some(if cfg!(windows) { format!("{}.dll", lib) - } else if cfg!(target_os = "macos") { + } else if cfg!(target_vendor = "apple") { format!("lib{}.dylib", lib) } else { format!("lib{}.so", lib) diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 8f9425eb0716..09a7f0395cfb 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -57,7 +57,7 @@ impl PathBufExt for PathBuf { pub fn dylib_env_var() -> &'static str { if cfg!(windows) { "PATH" - } else if cfg!(target_os = "macos") { + } else if cfg!(target_vendor = "apple") { "DYLD_LIBRARY_PATH" } else if cfg!(target_os = "haiku") { "LIBRARY_PATH" diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 881b4f84173c..398a6fd0fbaa 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2122,7 +2122,6 @@ ui/issues/issue-33687.rs ui/issues/issue-33770.rs ui/issues/issue-3389.rs ui/issues/issue-33941.rs -ui/issues/issue-33992.rs ui/issues/issue-34047.rs ui/issues/issue-34074.rs ui/issues/issue-34209.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 055d620361fb..cce0fb2c1a25 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: u32 = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1676; +const ISSUES_ENTRY_LIMIT: u32 = 1674; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs index 8e32d170244a..1f15f1a318a6 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -1,6 +1,6 @@ //@ revisions: all strong basic none missing //@ assembly-output: emit-asm -//@ ignore-macos slightly different policy on stack protection of arrays +//@ ignore-apple slightly different policy on stack protection of arrays //@ ignore-msvc stack check code uses different function names //@ ignore-nvptx64 stack protector is not supported //@ ignore-wasm32-bare @@ -17,12 +17,9 @@ // See comments on https://github.com/rust-lang/rust/issues/114903. #![crate_type = "lib"] - #![allow(incomplete_features)] - #![feature(unsized_locals, unsized_fn_params)] - // CHECK-LABEL: emptyfn: #[no_mangle] pub fn emptyfn() { diff --git a/tests/assembly/x86_64-array-pair-load-store-merge.rs b/tests/assembly/x86_64-array-pair-load-store-merge.rs index 9cf54ae14a16..849f34e72e51 100644 --- a/tests/assembly/x86_64-array-pair-load-store-merge.rs +++ b/tests/assembly/x86_64-array-pair-load-store-merge.rs @@ -2,7 +2,7 @@ //@ compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel //@ only-x86_64 //@ ignore-sgx -//@ ignore-macos (manipulates rsp too) +//@ ignore-apple (manipulates rsp too) // Depending on various codegen choices, this might end up copying // a `<2 x i8>`, an `i16`, or two `i8`s. diff --git a/tests/assembly/x86_64-function-return.rs b/tests/assembly/x86_64-function-return.rs index 64eb05062cbc..7cfdf5bce0c1 100644 --- a/tests/assembly/x86_64-function-return.rs +++ b/tests/assembly/x86_64-function-return.rs @@ -9,7 +9,7 @@ //@ [keep-thunk-extern] compile-flags: -Zfunction-return=keep -Zfunction-return=thunk-extern //@ [thunk-extern-keep] compile-flags: -Zfunction-return=thunk-extern -Zfunction-return=keep //@ only-x86_64 -//@ ignore-x86_64-apple-darwin Symbol is called `___x86_return_thunk` (Darwin's extra underscore) +//@ ignore-apple Symbol is called `___x86_return_thunk` (Darwin's extra underscore) //@ ignore-sgx Tests incompatible with LVI mitigations #![crate_type = "lib"] diff --git a/tests/codegen/gdb_debug_script_load.rs b/tests/codegen/gdb_debug_script_load.rs index f15defeaca8b..30d518c0bcb8 100644 --- a/tests/codegen/gdb_debug_script_load.rs +++ b/tests/codegen/gdb_debug_script_load.rs @@ -1,6 +1,6 @@ // //@ ignore-windows -//@ ignore-macos +//@ ignore-apple //@ ignore-wasm //@ ignore-emscripten diff --git a/tests/codegen/instrument-coverage/testprog.rs b/tests/codegen/instrument-coverage/testprog.rs index b352cbdb7557..acc4f35d9054 100644 --- a/tests/codegen/instrument-coverage/testprog.rs +++ b/tests/codegen/instrument-coverage/testprog.rs @@ -11,7 +11,7 @@ //@ [LINUX] filecheck-flags: -DINSTR_PROF_COVFUN=__llvm_covfun //@ [LINUX] filecheck-flags: '-DCOMDAT_IF_SUPPORTED=, comdat' -//@ [DARWIN] only-macos +//@ [DARWIN] only-apple //@ [DARWIN] filecheck-flags: -DINSTR_PROF_DATA=__DATA,__llvm_prf_data,regular,live_support //@ [DARWIN] filecheck-flags: -DINSTR_PROF_NAME=__DATA,__llvm_prf_names //@ [DARWIN] filecheck-flags: -DINSTR_PROF_CNTS=__DATA,__llvm_prf_cnts @@ -49,7 +49,7 @@ where pub fn wrap_with(inner: T, should_wrap: bool, wrapper: F) where - F: FnOnce(&T) + F: FnOnce(&T), { if should_wrap { wrapper(&inner) diff --git a/tests/codegen/issues/issue-44056-macos-tls-align.rs b/tests/codegen/issues/issue-44056-macos-tls-align.rs index c99f0b73038b..972b8490d18f 100644 --- a/tests/codegen/issues/issue-44056-macos-tls-align.rs +++ b/tests/codegen/issues/issue-44056-macos-tls-align.rs @@ -1,5 +1,5 @@ // -//@ only-macos +//@ only-apple //@ compile-flags: -O #![crate_type = "rlib"] diff --git a/tests/codegen/mainsubprogram.rs b/tests/codegen/mainsubprogram.rs index c1933b2b3904..12b24c90229e 100644 --- a/tests/codegen/mainsubprogram.rs +++ b/tests/codegen/mainsubprogram.rs @@ -2,7 +2,7 @@ // before 4.0, formerly backported to the Rust LLVM fork. //@ ignore-windows -//@ ignore-macos +//@ ignore-apple //@ ignore-wasi //@ compile-flags: -g -C no-prepopulate-passes @@ -10,5 +10,4 @@ // CHECK-LABEL: @main // CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}} -pub fn main() { -} +pub fn main() {} diff --git a/tests/codegen/mainsubprogramstart.rs b/tests/codegen/mainsubprogramstart.rs index 84d680b9bff9..20741791db5c 100644 --- a/tests/codegen/mainsubprogramstart.rs +++ b/tests/codegen/mainsubprogramstart.rs @@ -1,5 +1,5 @@ //@ ignore-windows -//@ ignore-macos +//@ ignore-apple //@ ignore-wasi wasi codegens the main symbol differently //@ compile-flags: -g -C no-prepopulate-passes diff --git a/tests/codegen/pgo-counter-bias.rs b/tests/codegen/pgo-counter-bias.rs index 1263eaf206f7..87d31073d5ae 100644 --- a/tests/codegen/pgo-counter-bias.rs +++ b/tests/codegen/pgo-counter-bias.rs @@ -1,6 +1,6 @@ // Test that __llvm_profile_counter_bias does not get internalized by lto. -//@ ignore-macos -runtime-counter-relocation not honored on Mach-O +//@ ignore-apple -runtime-counter-relocation not honored on Mach-O //@ compile-flags: -Cprofile-generate -Cllvm-args=-runtime-counter-relocation -Clto=fat //@ needs-profiler-support //@ no-prefer-dynamic diff --git a/tests/run-make/c-dynamic-dylib/Makefile b/tests/run-make/c-dynamic-dylib/Makefile index 0d4096404867..39561b28222c 100644 --- a/tests/run-make/c-dynamic-dylib/Makefile +++ b/tests/run-make/c-dynamic-dylib/Makefile @@ -4,7 +4,7 @@ # ignore-cross-compile include ../tools.mk -# ignore-macos +# ignore-apple # # This hits an assertion in the linker on older versions of osx apparently diff --git a/tests/run-make/c-dynamic-rlib/Makefile b/tests/run-make/c-dynamic-rlib/Makefile index a64e89cc0dc4..7b05e3d91a09 100644 --- a/tests/run-make/c-dynamic-rlib/Makefile +++ b/tests/run-make/c-dynamic-rlib/Makefile @@ -4,7 +4,7 @@ # ignore-cross-compile include ../tools.mk -# ignore-macos +# ignore-apple # # This hits an assertion in the linker on older versions of osx apparently diff --git a/tests/run-make/emit-stack-sizes/Makefile b/tests/run-make/emit-stack-sizes/Makefile index f636ebd28f2e..b546fcba5121 100644 --- a/tests/run-make/emit-stack-sizes/Makefile +++ b/tests/run-make/emit-stack-sizes/Makefile @@ -1,10 +1,10 @@ include ../tools.mk # ignore-windows -# ignore-macos +# ignore-apple # # This feature only works when the output object format is ELF so we ignore -# macOS and Windows +# Apple and Windows # check that the .stack_sizes section is generated all: diff --git a/tests/run-make/fpic/Makefile b/tests/run-make/fpic/Makefile index c38dd8d6e8c4..d3754d17372f 100644 --- a/tests/run-make/fpic/Makefile +++ b/tests/run-make/fpic/Makefile @@ -2,7 +2,7 @@ include ../tools.mk # ignore-windows -# ignore-macos +# ignore-apple # Test for #39529. # `-z text` causes ld to error if there are any non-PIC sections diff --git a/tests/run-make/link-framework/Makefile b/tests/run-make/link-framework/Makefile index f33347ac7f8f..96d832ad4a83 100644 --- a/tests/run-make/link-framework/Makefile +++ b/tests/run-make/link-framework/Makefile @@ -1,4 +1,4 @@ -# only-macos +# only-apple # # Check that linking to a framework actually makes it to the linker. diff --git a/tests/run-make/macos-fat-archive/Makefile b/tests/run-make/macos-fat-archive/Makefile index b6582c809e8b..0feb39a23cb5 100644 --- a/tests/run-make/macos-fat-archive/Makefile +++ b/tests/run-make/macos-fat-archive/Makefile @@ -1,4 +1,4 @@ -# only-macos +# only-apple include ../tools.mk diff --git a/tests/run-make/native-link-modifier-verbatim-linker/Makefile b/tests/run-make/native-link-modifier-verbatim-linker/Makefile index 256dc2d0664e..47ed2a142918 100644 --- a/tests/run-make/native-link-modifier-verbatim-linker/Makefile +++ b/tests/run-make/native-link-modifier-verbatim-linker/Makefile @@ -1,5 +1,5 @@ # ignore-cross-compile -# ignore-macos +# ignore-apple include ../tools.mk diff --git a/tests/run-make/used-cdylib-macos/Makefile b/tests/run-make/used-cdylib-macos/Makefile index 38a4c31c7b3a..bdf914a1ca95 100644 --- a/tests/run-make/used-cdylib-macos/Makefile +++ b/tests/run-make/used-cdylib-macos/Makefile @@ -1,9 +1,9 @@ include ../tools.mk -# only-macos +# only-apple # # This checks that `#[used]` passes through to the linker on -# darwin. This is subject to change in the future, see +# Apple targets. This is subject to change in the future, see # https://github.com/rust-lang/rust/pull/93718 for discussion all: diff --git a/tests/run-pass-valgrind/exit-flushes.rs b/tests/run-pass-valgrind/exit-flushes.rs index fa9196a3eecb..c2072cf0bf83 100644 --- a/tests/run-pass-valgrind/exit-flushes.rs +++ b/tests/run-pass-valgrind/exit-flushes.rs @@ -1,6 +1,6 @@ //@ ignore-wasm32 no subprocess support //@ ignore-sgx no processes -//@ ignore-macos this needs valgrind 3.11 or higher; see +//@ ignore-apple this needs valgrind 3.11 or higher; see // https://github.com/rust-lang/rust/pull/30365#issuecomment-165763679 use std::env; @@ -11,8 +11,7 @@ fn main() { print!("hello!"); exit(0); } else { - let out = Command::new(env::args().next().unwrap()).arg("foo") - .output().unwrap(); + let out = Command::new(env::args().next().unwrap()).arg("foo").output().unwrap(); assert!(out.status.success()); assert_eq!(String::from_utf8(out.stdout).unwrap(), "hello!"); assert_eq!(String::from_utf8(out.stderr).unwrap(), ""); diff --git a/tests/ui/backtrace/apple-no-dsymutil.rs b/tests/ui/backtrace/apple-no-dsymutil.rs index 9924cd13b0a7..e5aeced25ca3 100644 --- a/tests/ui/backtrace/apple-no-dsymutil.rs +++ b/tests/ui/backtrace/apple-no-dsymutil.rs @@ -2,7 +2,7 @@ //@ compile-flags:-Cstrip=none //@ compile-flags:-g -Csplit-debuginfo=unpacked -//@ only-macos +//@ only-apple use std::process::Command; use std::str; diff --git a/tests/ui/deployment-target/macos-target.rs b/tests/ui/deployment-target/macos-target.rs index be2c32e28141..197edd024746 100644 --- a/tests/ui/deployment-target/macos-target.rs +++ b/tests/ui/deployment-target/macos-target.rs @@ -1,4 +1,4 @@ -//@ only-macos +//@ only-apple //@ compile-flags: --print deployment-target //@ normalize-stdout-test: "\d+\." -> "$$CURRENT_MAJOR_VERSION." //@ normalize-stdout-test: "\d+" -> "$$CURRENT_MINOR_VERSION" diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs index 4856da553a80..138273aadd2f 100644 --- a/tests/ui/intrinsics/intrinsic-alignment.rs +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -10,20 +10,21 @@ mod rusti { } } -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "hurd", - target_os = "illumos", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "vxworks", - target_os = "nto", +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "hurd", + target_os = "illumos", + target_os = "linux", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "vxworks", + target_os = "nto", + target_vendor = "apple", ))] mod m { #[cfg(target_arch = "x86")] diff --git a/tests/ui/issues/issue-45731.rs b/tests/ui/issues/issue-45731.rs index 8e483d08cb51..49335362dd0f 100644 --- a/tests/ui/issues/issue-45731.rs +++ b/tests/ui/issues/issue-45731.rs @@ -2,10 +2,10 @@ #![allow(unused_variables)] //@ compile-flags:--test -g -#[cfg(target_os = "macos")] +#[cfg(target_vendor = "apple")] #[test] fn simple_test() { - use std::{env, panic, fs}; + use std::{env, fs, panic}; // Find our dSYM and replace the DWARF binary with an empty file let mut dsym_path = env::current_exe().unwrap(); @@ -13,8 +13,13 @@ fn simple_test() { assert!(dsym_path.pop()); // Pop executable dsym_path.push(format!("{}.dSYM/Contents/Resources/DWARF/{0}", executable_name)); { - let file = fs::OpenOptions::new().read(false).write(true).truncate(true).create(false) - .open(&dsym_path).unwrap(); + let file = fs::OpenOptions::new() + .read(false) + .write(true) + .truncate(true) + .create(false) + .open(&dsym_path) + .unwrap(); } env::set_var("RUST_BACKTRACE", "1"); diff --git a/tests/ui/link-section.rs b/tests/ui/link-section.rs index 9299b4d08b23..1a791b88ef95 100644 --- a/tests/ui/link-section.rs +++ b/tests/ui/link-section.rs @@ -1,32 +1,32 @@ //@ run-pass #![allow(non_upper_case_globals)] -#[cfg(not(target_os = "macos"))] -#[link_section=".moretext"] +#[cfg(not(target_vendor = "apple"))] +#[link_section = ".moretext"] fn i_live_in_more_text() -> &'static str { "knock knock" } -#[cfg(not(target_os = "macos"))] -#[link_section=".imm"] +#[cfg(not(target_vendor = "apple"))] +#[link_section = ".imm"] static magic: usize = 42; -#[cfg(not(target_os = "macos"))] -#[link_section=".mut"] +#[cfg(not(target_vendor = "apple"))] +#[link_section = ".mut"] static mut frobulator: usize = 0xdeadbeef; -#[cfg(target_os = "macos")] -#[link_section="__TEXT,__moretext"] +#[cfg(target_vendor = "apple")] +#[link_section = "__TEXT,__moretext"] fn i_live_in_more_text() -> &'static str { "knock knock" } -#[cfg(target_os = "macos")] -#[link_section="__RODATA,__imm"] +#[cfg(target_vendor = "apple")] +#[link_section = "__RODATA,__imm"] static magic: usize = 42; -#[cfg(target_os = "macos")] -#[link_section="__DATA,__mut"] +#[cfg(target_vendor = "apple")] +#[link_section = "__DATA,__mut"] static mut frobulator: usize = 0xdeadbeef; pub fn main() { diff --git a/tests/ui/linkage-attr/framework.rs b/tests/ui/linkage-attr/framework.rs index 824adf62206d..08f4394db21f 100644 --- a/tests/ui/linkage-attr/framework.rs +++ b/tests/ui/linkage-attr/framework.rs @@ -1,5 +1,5 @@ // Check that linking frameworks on Apple platforms works. -//@ only-macos +//@ only-apple //@ revisions: omit link weak both //@ [omit]build-fail //@ [link]run-pass diff --git a/tests/ui/osx-frameworks.rs b/tests/ui/linkage-attr/kind-framework.rs similarity index 58% rename from tests/ui/osx-frameworks.rs rename to tests/ui/linkage-attr/kind-framework.rs index b0d7a3a9c07a..c2f90809e03a 100644 --- a/tests/ui/osx-frameworks.rs +++ b/tests/ui/linkage-attr/kind-framework.rs @@ -1,4 +1,4 @@ -//@ ignore-macos this is supposed to succeed on osx +//@ ignore-apple this is supposed to succeed on Apple platforms (though it won't necessarily link) #[link(name = "foo", kind = "framework")] extern "C" {} diff --git a/tests/ui/osx-frameworks.stderr b/tests/ui/linkage-attr/kind-framework.stderr similarity index 89% rename from tests/ui/osx-frameworks.stderr rename to tests/ui/linkage-attr/kind-framework.stderr index 8582b8123bfe..93dacd68e294 100644 --- a/tests/ui/osx-frameworks.stderr +++ b/tests/ui/linkage-attr/kind-framework.stderr @@ -1,5 +1,5 @@ error[E0455]: link kind `framework` is only supported on Apple targets - --> $DIR/osx-frameworks.rs:3:29 + --> $DIR/kind-framework.rs:3:29 | LL | #[link(name = "foo", kind = "framework")] | ^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-33992.rs b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs similarity index 96% rename from tests/ui/issues/issue-33992.rs rename to tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs index 495751436e12..a169997927eb 100644 --- a/tests/ui/issues/issue-33992.rs +++ b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs @@ -1,6 +1,6 @@ //@ run-pass //@ ignore-windows -//@ ignore-macos +//@ ignore-apple //@ ignore-wasm32 common linkage not implemented right now #![feature(linkage)] diff --git a/tests/ui/linkage-attr/linkage1.rs b/tests/ui/linkage-attr/linkage1.rs index 2edb80bf1b02..19bf601d9d20 100644 --- a/tests/ui/linkage-attr/linkage1.rs +++ b/tests/ui/linkage-attr/linkage1.rs @@ -1,6 +1,6 @@ //@ run-pass //@ ignore-windows -//@ ignore-macos +//@ ignore-apple //@ ignore-emscripten doesn't support this linkage //@ ignore-sgx weak linkage not permitted //@ aux-build:linkage1.rs diff --git a/tests/ui/issues/issue-18804/auxiliary/lib.rs b/tests/ui/linkage-attr/propagate-generic-issue-18804/auxiliary/lib.rs similarity index 100% rename from tests/ui/issues/issue-18804/auxiliary/lib.rs rename to tests/ui/linkage-attr/propagate-generic-issue-18804/auxiliary/lib.rs diff --git a/tests/ui/issues/issue-18804/main.rs b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs similarity index 91% rename from tests/ui/issues/issue-18804/main.rs rename to tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs index d83fe697470b..56a9358cce3c 100644 --- a/tests/ui/issues/issue-18804/main.rs +++ b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs @@ -4,7 +4,7 @@ //@ ignore-emscripten no weak symbol support //@ ignore-windows no extern_weak linkage -//@ ignore-macos no extern_weak linkage +//@ ignore-apple no extern_weak linkage //@ aux-build:lib.rs diff --git a/tests/ui/manual/manual-link-framework.rs b/tests/ui/manual/manual-link-framework.rs index 06fd76f68df1..43cdda0a4e6a 100644 --- a/tests/ui/manual/manual-link-framework.rs +++ b/tests/ui/manual/manual-link-framework.rs @@ -1,7 +1,5 @@ -//@ ignore-macos -//@ ignore-ios +//@ ignore-apple //@ compile-flags:-l framework=foo //@ error-pattern: library kind `framework` is only supported on Apple targets -fn main() { -} +fn main() {} diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs index d8343704f12b..0183bdba1119 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs @@ -1,4 +1,4 @@ -//@ ignore-macos: cycle error does not appear on apple +//@ ignore-apple: cycle error does not appear on apple use std::sync::Mutex; diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs index 72601bb16fff..8ea72fdf45c8 100644 --- a/tests/ui/structs-enums/rec-align-u64.rs +++ b/tests/ui/structs-enums/rec-align-u64.rs @@ -30,21 +30,21 @@ struct Outer { t: Inner } - -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "hurd", - target_os = "illumos", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "vxworks", - target_os = "nto", +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "hurd", + target_os = "illumos", + target_os = "linux", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "vxworks", + target_os = "nto", + target_vendor = "apple", ))] mod m { #[cfg(target_arch = "x86")] From be94ca0bcdff9b55a4f15f66f6538e6b3e1b6793 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 26 Apr 2024 14:40:34 +0000 Subject: [PATCH 045/104] Remove a CTFE check that was only ever used to ICE The guarded call will ICE on its own. While this improved diagnostics in the presence of bugs somewhat, it is also a blocker to query feeding of constants. If this case is hit again, we should instead improve diagnostics of the root ICE --- .../rustc_const_eval/src/const_eval/machine.rs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 950e7c12da2e..d13ba4a2b95b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -6,7 +6,6 @@ use std::ops::ControlFlow; use rustc_ast::Mutability; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::IndexEntry; -use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_hir::LangItem; @@ -392,18 +391,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> { instance: ty::InstanceDef<'tcx>, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { match instance { - ty::InstanceDef::Item(def) => { - if ecx.tcx.is_ctfe_mir_available(def) { - Ok(ecx.tcx.mir_for_ctfe(def)) - } else if ecx.tcx.def_kind(def) == DefKind::AssocConst { - ecx.tcx.dcx().bug("This is likely a const item that is missing from its impl"); - } else { - // `find_mir_or_eval_fn` checks that this is a const fn before even calling us, - // so this should be unreachable. - let path = ecx.tcx.def_path_str(def); - bug!("trying to call extern function `{path}` at compile-time"); - } - } + ty::InstanceDef::Item(def) => Ok(ecx.tcx.mir_for_ctfe(def)), _ => Ok(ecx.tcx.instance_mir(instance)), } } From 53e3c3271f313df7e137589f3984772b0db4f031 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 24 May 2024 09:32:20 +0000 Subject: [PATCH 046/104] Make body-visiting logic reusable --- .../rustc_hir_analysis/src/check/region.rs | 112 +++++++++--------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index e51f95eed021..687f0f09a0b4 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -782,6 +782,32 @@ impl<'tcx> RegionResolutionVisitor<'tcx> { } self.enter_scope(Scope { id, data: ScopeData::Node }); } + + fn enter_body(&mut self, hir_id: hir::HirId, f: impl FnOnce(&mut Self)) { + // Save all state that is specific to the outer function + // body. These will be restored once down below, once we've + // visited the body. + let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0); + let outer_cx = self.cx; + let outer_ts = mem::take(&mut self.terminating_scopes); + // The 'pessimistic yield' flag is set to true when we are + // processing a `+=` statement and have to make pessimistic + // control flow assumptions. This doesn't apply to nested + // bodies within the `+=` statements. See #69307. + let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false); + self.terminating_scopes.insert(hir_id.local_id); + + self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::CallSite }); + self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::Arguments }); + + f(self); + + // Restore context we had at the start. + self.expr_and_pat_count = outer_ec; + self.cx = outer_cx; + self.terminating_scopes = outer_ts; + self.pessimistic_yield = outer_pessimistic_yield; + } } impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { @@ -801,60 +827,40 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { self.cx.parent ); - // Save all state that is specific to the outer function - // body. These will be restored once down below, once we've - // visited the body. - let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0); - let outer_cx = self.cx; - let outer_ts = mem::take(&mut self.terminating_scopes); - // The 'pessimistic yield' flag is set to true when we are - // processing a `+=` statement and have to make pessimistic - // control flow assumptions. This doesn't apply to nested - // bodies within the `+=` statements. See #69307. - let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false); - self.terminating_scopes.insert(body.value.hir_id.local_id); + self.enter_body(body.value.hir_id, |this| { + if this.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() { + // The arguments and `self` are parented to the fn. + this.cx.var_parent = this.cx.parent.take(); + for param in body.params { + this.visit_pat(param.pat); + } - self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite }); - self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments }); - - // The arguments and `self` are parented to the fn. - self.cx.var_parent = self.cx.parent.take(); - for param in body.params { - self.visit_pat(param.pat); - } - - // The body of the every fn is a root scope. - self.cx.parent = self.cx.var_parent; - if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() { - self.visit_expr(body.value) - } else { - // Only functions have an outer terminating (drop) scope, while - // temporaries in constant initializers may be 'static, but only - // according to rvalue lifetime semantics, using the same - // syntactical rules used for let initializers. - // - // e.g., in `let x = &f();`, the temporary holding the result from - // the `f()` call lives for the entirety of the surrounding block. - // - // Similarly, `const X: ... = &f();` would have the result of `f()` - // live for `'static`, implying (if Drop restrictions on constants - // ever get lifted) that the value *could* have a destructor, but - // it'd get leaked instead of the destructor running during the - // evaluation of `X` (if at all allowed by CTFE). - // - // However, `const Y: ... = g(&f());`, like `let y = g(&f());`, - // would *not* let the `f()` temporary escape into an outer scope - // (i.e., `'static`), which means that after `g` returns, it drops, - // and all the associated destruction scope rules apply. - self.cx.var_parent = None; - resolve_local(self, None, Some(body.value)); - } - - // Restore context we had at the start. - self.expr_and_pat_count = outer_ec; - self.cx = outer_cx; - self.terminating_scopes = outer_ts; - self.pessimistic_yield = outer_pessimistic_yield; + // The body of the every fn is a root scope. + this.cx.parent = this.cx.var_parent; + this.visit_expr(body.value) + } else { + // Only functions have an outer terminating (drop) scope, while + // temporaries in constant initializers may be 'static, but only + // according to rvalue lifetime semantics, using the same + // syntactical rules used for let initializers. + // + // e.g., in `let x = &f();`, the temporary holding the result from + // the `f()` call lives for the entirety of the surrounding block. + // + // Similarly, `const X: ... = &f();` would have the result of `f()` + // live for `'static`, implying (if Drop restrictions on constants + // ever get lifted) that the value *could* have a destructor, but + // it'd get leaked instead of the destructor running during the + // evaluation of `X` (if at all allowed by CTFE). + // + // However, `const Y: ... = g(&f());`, like `let y = g(&f());`, + // would *not* let the `f()` temporary escape into an outer scope + // (i.e., `'static`), which means that after `g` returns, it drops, + // and all the associated destruction scope rules apply. + this.cx.var_parent = None; + resolve_local(this, None, Some(body.value)); + } + }) } fn visit_arm(&mut self, a: &'tcx Arm<'tcx>) { From e5cba17b84bf7bf755686e8bb36aa3775ef53f77 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 24 May 2024 09:37:57 +0000 Subject: [PATCH 047/104] Use the HIR instead of mir_keys for determining whether something will have a MIR body. --- compiler/rustc_mir_transform/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index e4670633914e..9d88f8bf9bec 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -211,7 +211,7 @@ fn remap_mir_for_const_eval_select<'tcx>( } fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - tcx.mir_keys(()).contains(&def_id) + tcx.hir().maybe_body_owned_by(def_id).is_some() } /// Finds the full set of `DefId`s within the current crate that have From ddc5f9b6c1f21da5d4596bf7980185a00984ac42 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 3 May 2024 09:22:55 +0000 Subject: [PATCH 048/104] Create const block DefIds in typeck instead of ast lowering --- compiler/rustc_ast/src/ast.rs | 2 +- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 9 +----- compiler/rustc_ast_lowering/src/index.rs | 8 ----- .../rustc_ast_pretty/src/pprust/state/expr.rs | 5 +-- .../src/const_eval/fn_queries.rs | 2 +- compiler/rustc_hir/src/hir.rs | 14 +------- compiler/rustc_hir/src/intravisit.rs | 13 +------- .../rustc_hir_analysis/src/check/region.rs | 7 ++-- .../src/collect/generics_of.rs | 10 +++--- .../rustc_hir_analysis/src/collect/type_of.rs | 3 +- compiler/rustc_hir_analysis/src/lib.rs | 8 ++--- compiler/rustc_hir_pretty/src/lib.rs | 5 ++- compiler/rustc_hir_typeck/src/expr.rs | 21 +----------- .../src/fn_ctxt/suggestions.rs | 4 +++ compiler/rustc_hir_typeck/src/upvar.rs | 4 --- compiler/rustc_hir_typeck/src/writeback.rs | 13 ++++---- compiler/rustc_middle/src/hir/map/mod.rs | 21 ++++++------ .../rustc_middle/src/ty/typeck_results.rs | 5 +++ compiler/rustc_mir_build/src/build/mod.rs | 7 ++-- compiler/rustc_mir_build/src/thir/cx/expr.rs | 6 ++-- compiler/rustc_mir_build/src/thir/cx/mod.rs | 21 ++++++++++-- .../rustc_mir_build/src/thir/pattern/mod.rs | 8 ++--- compiler/rustc_mir_transform/src/lib.rs | 6 ++++ compiler/rustc_parse/src/parser/mod.rs | 13 +++----- compiler/rustc_passes/src/check_const.rs | 10 +++--- compiler/rustc_passes/src/dead.rs | 21 ++++++------ compiler/rustc_passes/src/liveness.rs | 8 ++++- compiler/rustc_passes/src/loops.rs | 7 ++-- compiler/rustc_resolve/src/def_collector.rs | 10 ------ compiler/rustc_resolve/src/late.rs | 3 -- src/tools/clippy/clippy_utils/src/consts.rs | 6 ++-- .../clippy/clippy_utils/src/hir_utils.rs | 4 +-- .../tests/ui/arithmetic_side_effects.stderr | 32 ++++++++++++++++--- .../custom/consts.consts.built.after.mir | 2 +- tests/pretty/stmt_expr_attributes.rs | 7 +--- tests/ui/lint/non-local-defs/consts.stderr | 19 ++++------- tests/ui/unpretty/expanded-exhaustive.stdout | 3 +- 39 files changed, 162 insertions(+), 189 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1a166956075c..7e59b4492993 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1393,7 +1393,7 @@ pub enum ExprKind { /// An array (e.g, `[a, b, c, d]`). Array(ThinVec>), /// Allow anonymous constants from an inline `const` block - ConstBlock(AnonConst), + ConstBlock(P), /// A function call /// /// The first field resolves to the function itself, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 566b20c490ef..ede0dd70b305 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1411,7 +1411,7 @@ pub fn noop_visit_expr( match kind { ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis), ExprKind::ConstBlock(anon_const) => { - vis.visit_anon_const(anon_const); + vis.visit_expr(anon_const); } ExprKind::Repeat(expr, count) => { vis.visit_expr(expr); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 93de42b55cc3..182aa6ed085c 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -951,7 +951,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V ExprKind::Array(subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } - ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)), + ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_expr(anon_const)), ExprKind::Repeat(element, count) => { try_visit!(visitor.visit_expr(element)); try_visit!(visitor.visit_anon_const(count)); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a55310909284..c0a424115aad 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -74,14 +74,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), - ExprKind::ConstBlock(c) => { - let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock { - def_id: this.local_def_id(c.id), - hir_id: this.lower_node_id(c.id), - body: this.lower_const_body(c.value.span, Some(&c.value)), - }); - hir::ExprKind::ConstBlock(c) - } + ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_expr(c)), ExprKind::Repeat(expr, count) => { let expr = self.lower_expr(expr); let count = self.lower_array_length(count); diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 7254be2b2f42..ed3046400f60 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -236,14 +236,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_inline_const(&mut self, constant: &'hir ConstBlock) { - self.insert(DUMMY_SP, constant.hir_id, Node::ConstBlock(constant)); - - self.with_parent(constant.hir_id, |this| { - intravisit::walk_inline_const(this, constant); - }); - } - fn visit_expr(&mut self, expr: &'hir Expr<'hir>) { self.insert(expr.span, expr.hir_id, Node::Expr(expr)); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 1e117c46b6e2..993ccc5b9560 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -380,8 +380,9 @@ impl<'a> State<'a> { ast::ExprKind::Array(exprs) => { self.print_expr_vec(exprs); } - ast::ExprKind::ConstBlock(anon_const) => { - self.print_expr_anon_const(anon_const, attrs); + ast::ExprKind::ConstBlock(expr) => { + self.word_space("const"); + self.print_expr(expr, FixupContext::default()); } ast::ExprKind::Repeat(element, count) => { self.print_expr_repeat(element, count); diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 8c66888d1007..3c11d67e7489 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -38,7 +38,6 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { match node { hir::Node::Ctor(_) | hir::Node::AnonConst(_) - | hir::Node::ConstBlock(_) | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => { hir::Constness::Const } @@ -57,6 +56,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { if is_const { hir::Constness::Const } else { hir::Constness::NotConst } } hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness, + hir::Node::Expr(e) if let hir::ExprKind::ConstBlock(_) = e.kind => hir::Constness::Const, _ => { if let Some(fn_kind) = node.fn_kind() { if fn_kind.constness() == hir::Constness::Const { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2f4dcdbdf2b1..a517e67e5d5a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1592,14 +1592,6 @@ pub struct AnonConst { pub span: Span, } -/// An inline constant expression `const { something }`. -#[derive(Copy, Clone, Debug, HashStable_Generic)] -pub struct ConstBlock { - pub hir_id: HirId, - pub def_id: LocalDefId, - pub body: BodyId, -} - /// An expression. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Expr<'hir> { @@ -1886,7 +1878,7 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ExprKind<'hir> { /// Allow anonymous constants from an inline `const` block - ConstBlock(ConstBlock), + ConstBlock(&'hir Expr<'hir>), /// An array (e.g., `[a, b, c, d]`). Array(&'hir [Expr<'hir>]), /// A function call. @@ -3609,7 +3601,6 @@ pub enum Node<'hir> { Variant(&'hir Variant<'hir>), Field(&'hir FieldDef<'hir>), AnonConst(&'hir AnonConst), - ConstBlock(&'hir ConstBlock), Expr(&'hir Expr<'hir>), ExprField(&'hir ExprField<'hir>), Stmt(&'hir Stmt<'hir>), @@ -3670,7 +3661,6 @@ impl<'hir> Node<'hir> { Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident), Node::Param(..) | Node::AnonConst(..) - | Node::ConstBlock(..) | Node::Expr(..) | Node::Stmt(..) | Node::Block(..) @@ -3768,7 +3758,6 @@ impl<'hir> Node<'hir> { } Node::AnonConst(constant) => Some((constant.def_id, constant.body)), - Node::ConstBlock(constant) => Some((constant.def_id, constant.body)), _ => None, } @@ -3837,7 +3826,6 @@ impl<'hir> Node<'hir> { expect_variant, &'hir Variant<'hir>, Node::Variant(n), n; expect_field, &'hir FieldDef<'hir>, Node::Field(n), n; expect_anon_const, &'hir AnonConst, Node::AnonConst(n), n; - expect_inline_const, &'hir ConstBlock, Node::ConstBlock(n), n; expect_expr, &'hir Expr<'hir>, Node::Expr(n), n; expect_expr_field, &'hir ExprField<'hir>, Node::ExprField(n), n; expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n; diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index b202ea8dca37..aba0532f0d1e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -344,9 +344,6 @@ pub trait Visitor<'v>: Sized { fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { walk_anon_const(self, c) } - fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result { - walk_inline_const(self, c) - } fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result { walk_expr(self, ex) } @@ -716,14 +713,6 @@ pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonCo visitor.visit_nested_body(constant.body) } -pub fn walk_inline_const<'v, V: Visitor<'v>>( - visitor: &mut V, - constant: &'v ConstBlock, -) -> V::Result { - try_visit!(visitor.visit_id(constant.hir_id)); - visitor.visit_nested_body(constant.body) -} - pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result { try_visit!(visitor.visit_id(expression.hir_id)); match expression.kind { @@ -731,7 +720,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) walk_list!(visitor, visit_expr, subexpressions); } ExprKind::ConstBlock(ref const_block) => { - try_visit!(visitor.visit_inline_const(const_block)) + try_visit!(visitor.visit_expr(const_block)) } ExprKind::Repeat(ref element, ref count) => { try_visit!(visitor.visit_expr(element)); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 687f0f09a0b4..8b0adebfaf46 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -407,11 +407,14 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h match expr.kind { // Manually recurse over closures and inline consts, because they are the only // case of nested bodies that share the parent environment. - hir::ExprKind::Closure(&hir::Closure { body, .. }) - | hir::ExprKind::ConstBlock(hir::ConstBlock { body, .. }) => { + hir::ExprKind::Closure(&hir::Closure { body, .. }) => { let body = visitor.tcx.hir().body(body); visitor.visit_body(body); } + hir::ExprKind::ConstBlock(expr) => visitor.enter_body(expr.hir_id, |this| { + this.cx.var_parent = None; + resolve_local(this, None, Some(expr)); + }), hir::ExprKind::AssignOp(_, left_expr, right_expr) => { debug!( "resolve_expr - enabling pessimistic_yield, was previously {}", diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index abdf85ad707b..9af959681fbf 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -177,10 +177,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } } } - Node::ConstBlock(_) - | Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => { - Some(tcx.typeck_root_def_id(def_id.to_def_id())) - } + Node::Expr(&hir::Expr { + kind: hir::ExprKind::Closure { .. } | hir::ExprKind::ConstBlock { .. }, + .. + }) => Some(tcx.typeck_root_def_id(def_id.to_def_id())), Node::Item(item) => match item.kind { ItemKind::OpaqueTy(&hir::OpaqueTy { origin: @@ -415,7 +415,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } // provide junk type parameter defs for const blocks. - if let Node::ConstBlock(_) = node { + if let Node::Expr(Expr { kind: ExprKind::ConstBlock(..), .. }) = node { own_params.push(ty::GenericParamDef { index: next_index(), name: Symbol::intern(""), diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index ed942cc50bb4..d497617f6449 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -484,8 +484,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ } Node::AnonConst(_) => anon_const_type_of(tcx, def_id), - - Node::ConstBlock(_) => { + Node::Expr(&Expr { kind: ExprKind::ConstBlock(..), .. }) => { let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id()); args.as_inline_const().ty() } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 8fe81851f932..65b02a2ec565 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -190,10 +190,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } }); - // Freeze definitions as we don't add new ones at this point. This improves performance by - // allowing lock-free access to them. - tcx.untracked().definitions.freeze(); - // FIXME: Remove this when we implement creating `DefId`s // for anon constants during their parents' typeck. // Typeck all body owners in parallel will produce queries @@ -205,6 +201,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } }); + // Freeze definitions as we don't add new ones at this point. This improves performance by + // allowing lock-free access to them. + tcx.untracked().definitions.freeze(); + tcx.ensure().check_unused_traits(()); } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 488537e81bec..62abdf0afabf 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -84,7 +84,6 @@ impl<'a> State<'a> { Node::ImplItem(a) => self.print_impl_item(a), Node::Variant(a) => self.print_variant(a), Node::AnonConst(a) => self.print_anon_const(a), - Node::ConstBlock(a) => self.print_inline_const(a), Node::Expr(a) => self.print_expr(a), Node::ExprField(a) => self.print_expr_field(a), Node::Stmt(a) => self.print_stmt(a), @@ -1049,10 +1048,10 @@ impl<'a> State<'a> { self.end() } - fn print_inline_const(&mut self, constant: &hir::ConstBlock) { + fn print_inline_const(&mut self, constant: &hir::Expr<'_>) { self.ibox(INDENT_UNIT); self.word_space("const"); - self.ann.nested(self, Nested::Body(constant.body)); + self.print_expr(constant); self.end() } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index fade943c5ae3..364f0fec202a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -32,7 +32,6 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath}; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _; @@ -336,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected), ExprKind::Array(args) => self.check_expr_array(args, expected, expr), - ExprKind::ConstBlock(ref block) => self.check_expr_const_block(block, expected), + ExprKind::ConstBlock(ref block) => self.check_expr_with_expectation(block, expected), ExprKind::Repeat(element, ref count) => { self.check_expr_repeat(element, count, expected, expr) } @@ -1460,24 +1459,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn check_expr_const_block( - &self, - block: &'tcx hir::ConstBlock, - expected: Expectation<'tcx>, - ) -> Ty<'tcx> { - let body = self.tcx.hir().body(block.body); - - // Create a new function context. - let def_id = block.def_id; - let fcx = FnCtxt::new(self, self.param_env, def_id); - crate::GatherLocalsVisitor::new(&fcx).visit_body(body); - - let ty = fcx.check_expr_with_expectation(body.value, expected); - fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::ConstSized); - fcx.write_ty(block.hir_id, ty); - ty - } - fn check_expr_repeat( &self, element: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index cfd4dd4d1dd0..0d7f59c48715 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1055,6 +1055,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .take_while(|(_, node)| { // look at parents until we find the first body owner node.body_id().is_none() + && !matches!( + node, + Node::Expr(Expr { kind: ExprKind::ConstBlock { .. }, .. }) + ) }) .any(|(parent_id, _)| self.is_loop(parent_id)); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 466397817dae..4386e68ce867 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -149,10 +149,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { self.visit_body(body); self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause); } - hir::ExprKind::ConstBlock(anon_const) => { - let body = self.fcx.tcx.hir().body(anon_const.body); - self.visit_body(body); - } _ => {} } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index f798deea207a..31caa52d2671 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -3,6 +3,7 @@ // generic parameters. use crate::FnCtxt; +use hir::def::DefKind; use rustc_data_structures::unord::ExtendUnord; use rustc_errors::{ErrorGuaranteed, StashKey}; use rustc_hir as hir; @@ -16,7 +17,7 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::TypeSuperFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::symbol::sym; +use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use rustc_trait_selection::solve; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; @@ -295,11 +296,11 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => { self.visit_field_id(e.hir_id); } - hir::ExprKind::ConstBlock(anon_const) => { - self.visit_node_id(e.span, anon_const.hir_id); - - let body = self.tcx().hir().body(anon_const.body); - self.visit_body(body); + hir::ExprKind::ConstBlock(_) => { + let feed = self.tcx().create_def(self.fcx.body_id, kw::Empty, DefKind::InlineConst); + feed.def_span(e.span); + feed.local_def_id_to_hir_id(e.hir_id); + self.typeck_results.inline_consts.insert(e.hir_id.local_id, feed.def_id()); } _ => {} } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index b17af47fbcd4..ff8d29197055 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -321,7 +321,7 @@ impl<'hir> Map<'hir> { /// Returns an iterator of the `DefId`s for all body-owners in this /// crate. If you would prefer to iterate over the bodies - /// themselves, you can do `self.hir().krate().body_ids.iter()`. + /// themselves, you can do `self.hir().krate().owners.iter()`. #[inline] pub fn body_owners(self) -> impl Iterator + 'hir { self.tcx.hir_crate_items(()).body_owners.iter().copied() @@ -508,7 +508,17 @@ impl<'hir> Map<'hir> { /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context. /// Used exclusively for diagnostics, to avoid suggestion function calls. pub fn is_inside_const_context(self, hir_id: HirId) -> bool { - self.body_const_context(self.enclosing_body_owner(hir_id)).is_some() + for (_, node) in self.parent_iter(hir_id) { + if let Some((def_id, _)) = node.associated_body() { + return self.body_const_context(def_id).is_some(); + } + if let Node::Expr(e) = node { + if let ExprKind::ConstBlock(_) = e.kind { + return true; + } + } + } + false } /// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is @@ -891,7 +901,6 @@ impl<'hir> Map<'hir> { Node::Variant(variant) => variant.span, Node::Field(field) => field.span, Node::AnonConst(constant) => constant.span, - Node::ConstBlock(constant) => self.body(constant.body).value.span, Node::Expr(expr) => expr.span, Node::ExprField(field) => field.span, Node::Stmt(stmt) => stmt.span, @@ -1161,7 +1170,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id)) } Node::AnonConst(_) => node_str("const"), - Node::ConstBlock(_) => node_str("const"), Node::Expr(_) => node_str("expr"), Node::ExprField(_) => node_str("expr field"), Node::Stmt(_) => node_str("stmt"), @@ -1311,11 +1319,6 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { intravisit::walk_anon_const(self, c) } - fn visit_inline_const(&mut self, c: &'hir ConstBlock) { - self.body_owners.push(c.def_id); - intravisit::walk_inline_const(self, c) - } - fn visit_expr(&mut self, ex: &'hir Expr<'hir>) { if let ExprKind::Closure(closure) = ex.kind { self.body_owners.push(closure.def_id); diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 24e3e623ff27..69ea9c9843a0 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -217,6 +217,10 @@ pub struct TypeckResults<'tcx> { /// Container types and field indices of `offset_of!` expressions offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>, + + /// Maps from `HirId`s of const blocks (the `ExprKind::ConstBlock`, not the inner expression's) + /// to the `DefId` of the corresponding inline const. + pub inline_consts: FxIndexMap, } impl<'tcx> TypeckResults<'tcx> { @@ -249,6 +253,7 @@ impl<'tcx> TypeckResults<'tcx> { treat_byte_string_as_slice: Default::default(), closure_size_eval: Default::default(), offset_of_data: Default::default(), + inline_consts: Default::default(), } } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 92cd7f75d628..13112f2b12c8 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -568,11 +568,8 @@ fn construct_const<'a, 'tcx>( .. }) => (*span, ty.span), Node::AnonConst(ct) => (ct.span, ct.span), - Node::ConstBlock(_) => { - let span = tcx.def_span(def); - (span, span) - } - _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def), + Node::Expr(&hir::Expr { span, kind: hir::ExprKind::ConstBlock(_), .. }) => (span, span), + node => span_bug!(tcx.def_span(def), "can't build MIR for {def:?}: {node:#?}"), }; let infcx = tcx.infer_ctxt().build(); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 28f9300b97a8..bd66257e6b68 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -671,9 +671,9 @@ impl<'tcx> Cx<'tcx> { ExprKind::OffsetOf { container, fields } } - hir::ExprKind::ConstBlock(ref anon_const) => { - let ty = self.typeck_results().node_type(anon_const.hir_id); - let did = anon_const.def_id.to_def_id(); + hir::ExprKind::ConstBlock(body) => { + let ty = self.typeck_results().node_type(body.hir_id); + let did = self.typeck_results().inline_consts[&expr.hir_id.local_id].into(); let typeck_root_def_id = tcx.typeck_root_def_id(did); let parent_args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, typeck_root_def_id)); diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 3c0e2521d88f..bd72ef28cb37 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -13,10 +13,10 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::HirId; use rustc_hir::Node; -use rustc_middle::bug; use rustc_middle::middle::region; use rustc_middle::thir::*; use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; +use rustc_middle::{bug, span_bug}; use tracing::instrument; pub(crate) fn thir_body( @@ -24,7 +24,22 @@ pub(crate) fn thir_body( owner_def: LocalDefId, ) -> Result<(&Steal>, ExprId), ErrorGuaranteed> { let hir = tcx.hir(); - let body = hir.body(hir.body_owned_by(owner_def)); + let body; + let body = match tcx.def_kind(owner_def) { + // Inline consts do not have bodies of their own, so create one to make the follow-up logic simpler. + DefKind::InlineConst => { + let e = hir.expect_expr(tcx.local_def_id_to_hir_id(owner_def)); + body = hir::Body { + params: &[], + value: match e.kind { + hir::ExprKind::ConstBlock(body) => body, + _ => span_bug!(e.span, "InlineConst was not a ConstBlock: {e:#?}"), + }, + }; + &body + } + _ => hir.body(hir.body_owned_by(owner_def)), + }; let mut cx = Cx::new(tcx, owner_def); if let Some(reported) = cx.typeck_results.tainted_by_errors { return Err(reported); @@ -165,7 +180,7 @@ impl<'tcx> Cx<'tcx> { &'a mut self, owner_id: HirId, fn_decl: &'tcx hir::FnDecl<'tcx>, - body: &'tcx hir::Body<'tcx>, + body: &hir::Body<'tcx>, ) -> impl Iterator> + 'a { let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id]; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 7408c679f00b..33401cad631a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -637,15 +637,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { /// Converts inline const patterns. fn lower_inline_const( &mut self, - block: &'tcx hir::ConstBlock, + expr: &'tcx hir::Expr<'tcx>, id: hir::HirId, span: Span, ) -> PatKind<'tcx> { let tcx = self.tcx; - let def_id = block.def_id; - let body_id = block.body; - let expr = &tcx.hir().body(body_id).value; - let ty = tcx.typeck(def_id).node_type(block.hir_id); + let def_id = self.typeck_results.inline_consts[&id.local_id]; + let ty = tcx.typeck(def_id).node_type(expr.hir_id); // Special case inline consts that are just literals. This is solely // a performance optimization, as we could also just go through the regular diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9d88f8bf9bec..b66e3d66f4d3 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -222,6 +222,12 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { // All body-owners have MIR associated with them. set.extend(tcx.hir().body_owners()); + // Inline consts' bodies are created in + // typeck instead of during ast lowering, like all other bodies so far. + for def_id in tcx.hir().body_owners() { + set.extend(tcx.typeck(def_id).inline_consts.values()) + } + // Additionally, tuple struct/variant constructors have MIR, but // they don't have a BodyId, so we need to build them separately. struct GatherCtors<'a> { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index c2183258eef1..bab8b6c06ebe 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -25,8 +25,8 @@ use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing}; use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor}; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs, - Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility, + self as ast, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs, Expr, + ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind, DUMMY_NODE_ID, }; use rustc_ast_pretty::pprust; @@ -1260,12 +1260,9 @@ impl<'a> Parser<'a> { } self.eat_keyword(kw::Const); let (attrs, blk) = self.parse_inner_attrs_and_block()?; - let anon_const = AnonConst { - id: DUMMY_NODE_ID, - value: self.mk_expr(blk.span, ExprKind::Block(blk, None)), - }; - let blk_span = anon_const.value.span; - Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(anon_const), attrs)) + let expr = self.mk_expr(blk.span, ExprKind::Block(blk, None)); + let blk_span = expr.span; + Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(expr), attrs)) } /// Parses mutability (`mut` or nothing). diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index eb29a65cb293..fa2c8f69c71d 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -196,11 +196,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon)); } - fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) { - let kind = Some(hir::ConstContext::Const { inline: true }); - self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block)); - } - fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) { let owner = self.tcx.hir().body_owner_def_id(body.id()); let kind = self.tcx.hir().body_const_context(owner); @@ -228,6 +223,11 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { self.const_check_violated(expr, e.span); } } + hir::ExprKind::ConstBlock(expr) => { + let kind = Some(hir::ConstContext::Const { inline: true }); + self.recurse_into(kind, None, |this| intravisit::walk_expr(this, expr)); + return; + } _ => {} } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index ddc50e2b811a..0049afff528c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -587,6 +587,16 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { hir::ExprKind::OffsetOf(..) => { self.handle_offset_of(expr); } + hir::ExprKind::ConstBlock(expr) => { + // When inline const blocks are used in pattern position, paths + // referenced by it should be considered as used. + let in_pat = mem::replace(&mut self.in_pat, false); + + intravisit::walk_expr(self, expr); + + self.in_pat = in_pat; + return; + } _ => (), } @@ -648,17 +658,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.in_pat = in_pat; } - - fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { - // When inline const blocks are used in pattern position, paths - // referenced by it should be considered as used. - let in_pat = mem::replace(&mut self.in_pat, false); - - self.live_symbols.insert(c.def_id); - intravisit::walk_inline_const(self, c); - - self.in_pat = in_pat; - } } fn has_allow_dead_code_or_lang_attr( diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index b0a753604e2e..1f966be26ff4 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -147,6 +147,11 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) { return; } + // Don't run for inline consts, they are collected together with their parent + if let DefKind::InlineConst = tcx.def_kind(def_id) { + return; + } + // Don't run unused pass for #[naked] if tcx.has_attr(def_id.to_def_id(), sym::naked) { return; @@ -1144,12 +1149,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Lit(..) - | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Err(_) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::Path(hir::QPath::LangItem(..)) | hir::ExprKind::OffsetOf(..) => succ, + hir::ExprKind::ConstBlock(expr) => self.propagate_through_expr(expr, succ), + // Note that labels have been resolved, so we don't need to look // at the label ident hir::ExprKind::Block(ref blk, _) => self.propagate_through_block(blk, succ), diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 2587a18b8c89..737310e5c04a 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -93,10 +93,6 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { self.with_context(Constant, |v| intravisit::walk_anon_const(v, c)); } - fn visit_inline_const(&mut self, c: &'hir hir::ConstBlock) { - self.with_context(Constant, |v| intravisit::walk_inline_const(v, c)); - } - fn visit_fn( &mut self, fk: hir::intravisit::FnKind<'hir>, @@ -289,6 +285,9 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { self.cx_stack.len() - 1, ) } + hir::ExprKind::ConstBlock(expr) => { + self.with_context(Constant, |v| intravisit::walk_expr(v, expr)); + } _ => intravisit::walk_expr(self, e), } } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index bd0622428569..cad10571afe6 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -325,16 +325,6 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ExprKind::Gen(_, _, _) => { self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) } - ExprKind::ConstBlock(ref constant) => { - let def = self.create_def( - constant.id, - kw::Empty, - DefKind::InlineConst, - constant.value.span, - ); - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); - return; - } _ => self.parent_def, }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 63d0d6c260db..08326d1ef57e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4502,9 +4502,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.visit_expr(elem); self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes)); } - ExprKind::ConstBlock(ref ct) => { - self.resolve_anon_const(ct, AnonConstKind::InlineConst); - } ExprKind::Index(ref elem, ref idx, _) => { self.resolve_expr(elem, Some(expr)); self.visit_expr(idx); diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 253ae3aca689..f5d3967d130d 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -6,7 +6,7 @@ use crate::{clip, is_direct_expn_of, sext, unsext}; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; +use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{alloc_range, Scalar}; @@ -412,7 +412,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// Simple constant folding: Insert an expression, get a constant or none. pub fn expr(&mut self, e: &Expr<'_>) -> Option> { match e.kind { - ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value), + ExprKind::ConstBlock(e) | ExprKind::DropTemps(e) => self.expr(e), ExprKind::Path(ref qpath) => { self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| { @@ -491,7 +491,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// leaves the local crate. pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option { match e.kind { - ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value), + ExprKind::ConstBlock(e) | ExprKind::DropTemps(e) => self.expr_is_empty(e), ExprKind::Path(ref qpath) => { if !self diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 9f285621e0c9..cc5ccd4053a2 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -295,7 +295,7 @@ impl HirEqInterExpr<'_, '_, '_> { self.eq_expr(lx, rx) && self.eq_ty(lt, rt) }, (&ExprKind::Closure(_l), &ExprKind::Closure(_r)) => false, - (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body), + (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_expr(lb, rb), (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => { both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name) }, @@ -770,7 +770,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(self.cx.tcx.hir().body(body).value); }, ExprKind::ConstBlock(ref l_id) => { - self.hash_body(l_id.body); + self.hash_expr(l_id); }, ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => { self.hash_expr(e); diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr index 8039c0bfa248..df14ff396f6c 100644 --- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr +++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr @@ -1,11 +1,35 @@ +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:188:36 + | +LL | let _ = const { let mut n = 1; n += 1; n }; + | ^^^^^^ + | + = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]` + +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:191:40 + | +LL | let _ = const { let mut n = 1; n = n + 1; n }; + | ^^^^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:194:40 + | +LL | let _ = const { let mut n = 1; n = 1 + n; n }; + | ^^^^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:200:59 + | +LL | let _ = const { let mut n = 1; n = -1; n = -(-1); n = -n; n }; + | ^^ + error: arithmetic operation that can potentially result in unexpected side-effects --> tests/ui/arithmetic_side_effects.rs:304:5 | LL | _n += 1; | ^^^^^^^ - | - = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]` error: arithmetic operation that can potentially result in unexpected side-effects --> tests/ui/arithmetic_side_effects.rs:305:5 @@ -727,5 +751,5 @@ error: arithmetic operation that can potentially result in unexpected side-effec LL | one.sub_assign(1); | ^^^^^^^^^^^^^^^^^ -error: aborting due to 121 previous errors +error: aborting due to 125 previous errors diff --git a/tests/mir-opt/building/custom/consts.consts.built.after.mir b/tests/mir-opt/building/custom/consts.consts.built.after.mir index a011fadcef11..7b6964849d4b 100644 --- a/tests/mir-opt/building/custom/consts.consts.built.after.mir +++ b/tests/mir-opt/building/custom/consts.consts.built.after.mir @@ -10,7 +10,7 @@ fn consts() -> () { bb0: { _1 = const 5_u8; - _2 = const consts::::{constant#0}; + _2 = const consts::::{constant#1}; _3 = const C; _4 = const D; _5 = consts::<10>; diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs index 5eb7d2fcae36..f90412682110 100644 --- a/tests/pretty/stmt_expr_attributes.rs +++ b/tests/pretty/stmt_expr_attributes.rs @@ -206,12 +206,7 @@ fn _11() { let _ = (); () }; - let const { - #![rustc_dummy] - } = - #[rustc_dummy] const { - #![rustc_dummy] - }; + let const {} = #[rustc_dummy] const {}; let mut x = 0; let _ = (#[rustc_dummy] x) = 15; let _ = (#[rustc_dummy] x) += 15; diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 2756ea401387..48bdaa60823f 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -67,18 +67,13 @@ LL | impl Test { warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:50:9 | -LL | const { - | ___________- -LL | | impl Test { - | | ^^^^^---- - | | | - | | `Test` is not local -LL | | -LL | | fn hoo() {} -... | -LL | | 1 -LL | | }; - | |_____- move the `impl` block outside of this inline constant `` and up 2 bodies +LL | fn main() { + | --------- move the `impl` block outside of this function `main` +... +LL | impl Test { + | ^^^^^---- + | | + | `Test` is not local | = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 325bace7b562..8737063bf3cc 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -82,7 +82,8 @@ mod expressions { fn expr_const_block() { const {}; const { 1 }; - const { + const + { struct S; }; } From eae5031ecbda434e92966099e0dc93917de03eff Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 24 May 2024 09:53:20 +0000 Subject: [PATCH 049/104] Cache whether a body has inline consts --- compiler/rustc_ast_lowering/src/expr.rs | 5 ++++- compiler/rustc_ast_lowering/src/lib.rs | 8 +++++++- compiler/rustc_hir/src/hir.rs | 3 +++ compiler/rustc_hir/src/stable_hash_impls.rs | 3 ++- compiler/rustc_middle/src/ty/context.rs | 1 + compiler/rustc_mir_transform/src/lib.rs | 5 ++++- 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c0a424115aad..eb206a09be31 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -74,7 +74,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), - ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_expr(c)), + ExprKind::ConstBlock(c) => { + self.has_inline_consts = true; + hir::ExprKind::ConstBlock(self.lower_expr(c)) + } ExprKind::Repeat(expr, count) => { let expr = self.lower_expr(expr); let count = self.lower_array_length(count); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a9af5ad74592..278049d1347b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -96,6 +96,8 @@ struct LoweringContext<'a, 'hir> { /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, + /// Whether there were inline consts that typeck will split out into bodies + has_inline_consts: bool, /// Attributes inside the owner being lowered. attrs: SortedMap, /// Collect items that were created by lowering the current owner. @@ -158,6 +160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { item_local_id_counter: hir::ItemLocalId::ZERO, node_id_to_local_id: Default::default(), trait_map: Default::default(), + has_inline_consts: false, // Lowering state. catch_scope: None, @@ -567,6 +570,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let current_attrs = std::mem::take(&mut self.attrs); let current_bodies = std::mem::take(&mut self.bodies); + let current_has_inline_consts = std::mem::take(&mut self.has_inline_consts); let current_node_ids = std::mem::take(&mut self.node_id_to_local_id); let current_trait_map = std::mem::take(&mut self.trait_map); let current_owner = @@ -593,6 +597,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.attrs = current_attrs; self.bodies = current_bodies; + self.has_inline_consts = current_has_inline_consts; self.node_id_to_local_id = current_node_ids; self.trait_map = current_trait_map; self.current_hir_id_owner = current_owner; @@ -629,6 +634,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let attrs = std::mem::take(&mut self.attrs); let mut bodies = std::mem::take(&mut self.bodies); let trait_map = std::mem::take(&mut self.trait_map); + let has_inline_consts = std::mem::take(&mut self.has_inline_consts); #[cfg(debug_assertions)] for (id, attrs) in attrs.iter() { @@ -646,7 +652,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.tcx.hash_owner_nodes(node, &bodies, &attrs); let num_nodes = self.item_local_id_counter.as_usize(); let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes); - let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies }; + let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies, has_inline_consts }; let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash }; self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map }) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a517e67e5d5a..e64f7aeb11b3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -876,6 +876,9 @@ pub struct OwnerNodes<'tcx> { pub nodes: IndexVec>, /// Content of local bodies. pub bodies: SortedMap>, + /// Whether the body contains inline constants that are created for the query system during typeck + /// of the body. + pub has_inline_consts: bool, } impl<'tcx> OwnerNodes<'tcx> { diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index baa1635f7313..1ebd4b80e183 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -93,7 +93,8 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerNodes<' // `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing // the body satisfies the condition of two nodes being different have different // `hash_stable` results. - let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _ } = *self; + let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _, has_inline_consts: _ } = + *self; opt_hash_including_bodies.unwrap().hash_stable(hcx, hasher); } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c09cb95de883..51bbe3512187 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -737,6 +737,7 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> { 1, ), bodies, + has_inline_consts: false, }))); self.feed_owner_id().hir_attrs(attrs); } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b66e3d66f4d3..93ae105150cc 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -225,7 +225,10 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { // Inline consts' bodies are created in // typeck instead of during ast lowering, like all other bodies so far. for def_id in tcx.hir().body_owners() { - set.extend(tcx.typeck(def_id).inline_consts.values()) + // Incremental performance optimization: only load typeck results for things that actually have inline consts + if tcx.hir_owner_nodes(tcx.hir().body_owned_by(def_id).hir_id.owner).has_inline_consts { + set.extend(tcx.typeck(def_id).inline_consts.values()) + } } // Additionally, tuple struct/variant constructors have MIR, but From ac7e836834554ec7205fd8bbb5e1c44ce7d8299f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 09:50:47 +0000 Subject: [PATCH 050/104] Bless codegen test --- ...-type-metadata-id-itanium-cxx-abi-paths.rs | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs index 6c3d991af9f1..4e5ad8ad4a93 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs @@ -4,7 +4,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(type_alias_impl_trait)] extern crate core; @@ -14,14 +14,15 @@ pub type Type2 = impl Send; pub type Type3 = impl Send; pub type Type4 = impl Send; -pub fn foo() where +pub fn foo() +where Type1: 'static, Type2: 'static, Type3: 'static, Type4: 'static, { // Type in extern path - extern { + extern "C" { fn bar(); } let _: Type1 = bar; @@ -35,43 +36,44 @@ pub fn foo() where // Type in const path const { pub struct Foo; - fn bar() -> Type3 { Foo } + fn bar() -> Type3 { + Foo + } }; - // Type in impl path struct Foo; impl Foo { - fn bar(&self) { } + fn bar(&self) {} } let _: Type4 = ::bar; } // Force arguments to be passed by using a reference. Otherwise, they may end up PassMode::Ignore -pub fn foo1(_: &Type1) { } +pub fn foo1(_: &Type1) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: &Type1, _: &Type1) { } +pub fn foo2(_: &Type1, _: &Type1) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: &Type1, _: &Type1, _: &Type1) { } +pub fn foo3(_: &Type1, _: &Type1, _: &Type1) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: &Type2) { } +pub fn foo4(_: &Type2) {} // CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: &Type2, _: &Type2) { } +pub fn foo5(_: &Type2, _: &Type2) {} // CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: &Type2, _: &Type2, _: &Type2) { } +pub fn foo6(_: &Type2, _: &Type2, _: &Type2) {} // CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: &Type3) { } +pub fn foo7(_: &Type3) {} // CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: &Type3, _: &Type3) { } +pub fn foo8(_: &Type3, _: &Type3) {} // CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: &Type3, _: &Type3, _: &Type3) { } +pub fn foo9(_: &Type3, _: &Type3, _: &Type3) {} // CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo10(_: &Type4) { } +pub fn foo10(_: &Type4) {} // CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo11(_: &Type4, _: &Type4) { } +pub fn foo11(_: &Type4, _: &Type4) {} // CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo12(_: &Type4, _: &Type4, _: &Type4) { } +pub fn foo12(_: &Type4, _: &Type4, _: &Type4) {} // CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"} @@ -80,9 +82,9 @@ pub fn foo12(_: &Type4, _: &Type4, _: &Type4) { } // CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"} // CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"} // CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"} -// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"} -// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"} -// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"} +// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooEE"} +// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooES0_E"} +// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooES0_S0_E"} // CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"} // CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"} // CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"} From 37c54db477b06ade1cb69b4fd1af46184b650a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 21 May 2024 19:12:05 +0000 Subject: [PATCH 051/104] Silence some resolve errors when there have been glob import errors When encountering `use foo::*;` where `foo` fails to be found, and we later encounter resolution errors, we silence those later errors. A single case of the above, for an *existing* import on a big codebase would otherwise have a huge number of knock-down spurious errors. Ideally, instead of a global flag to silence all subsequent resolve errors, we'd want to introduce an unameable binding in the appropriate rib as a sentinel when there's a failed glob import, so when we encounter a resolve error we can search for that sentinel and if found, and only then, silence that error. The current approach is just a quick proof of concept to iterate over. Partially address #96799. --- compiler/rustc_resolve/src/imports.rs | 22 +++++++--- compiler/rustc_resolve/src/late.rs | 5 ++- compiler/rustc_resolve/src/lib.rs | 4 +- .../ui/imports/import-from-missing-star-2.rs | 12 ++++++ .../imports/import-from-missing-star-2.stderr | 11 +++++ .../ui/imports/import-from-missing-star-3.rs | 43 +++++++++++++++++++ .../imports/import-from-missing-star-3.stderr | 19 ++++++++ tests/ui/imports/import-from-missing-star.rs | 10 +++++ .../imports/import-from-missing-star.stderr | 11 +++++ tests/ui/imports/issue-31212.rs | 2 +- tests/ui/imports/issue-31212.stderr | 11 +---- 11 files changed, 131 insertions(+), 19 deletions(-) create mode 100644 tests/ui/imports/import-from-missing-star-2.rs create mode 100644 tests/ui/imports/import-from-missing-star-2.stderr create mode 100644 tests/ui/imports/import-from-missing-star-3.rs create mode 100644 tests/ui/imports/import-from-missing-star-3.stderr create mode 100644 tests/ui/imports/import-from-missing-star.rs create mode 100644 tests/ui/imports/import-from-missing-star.stderr diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 3d9380a3ebd3..f44eb1aae3ee 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -536,6 +536,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let determined_imports = mem::take(&mut self.determined_imports); let indeterminate_imports = mem::take(&mut self.indeterminate_imports); + let mut glob_error = false; for (is_indeterminate, import) in determined_imports .iter() .map(|i| (false, i)) @@ -547,6 +548,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.import_dummy_binding(*import, is_indeterminate); if let Some(err) = unresolved_import_error { + glob_error |= import.is_glob(); + if let ImportKind::Single { source, ref source_bindings, .. } = import.kind { if source.name == kw::SelfLower { // Silence `unresolved import` error if E0429 is already emitted @@ -562,7 +565,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { { // In the case of a new import line, throw a diagnostic message // for the previous line. - self.throw_unresolved_import_error(errors); + self.throw_unresolved_import_error(errors, glob_error); errors = vec![]; } if seen_spans.insert(err.span) { @@ -573,7 +576,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if !errors.is_empty() { - self.throw_unresolved_import_error(errors); + self.throw_unresolved_import_error(errors, glob_error); return; } @@ -599,9 +602,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - if !errors.is_empty() { - self.throw_unresolved_import_error(errors); - } + self.throw_unresolved_import_error(errors, glob_error); } pub(crate) fn check_hidden_glob_reexports( @@ -673,7 +674,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedImportError)>) { + fn throw_unresolved_import_error( + &mut self, + errors: Vec<(Import<'_>, UnresolvedImportError)>, + glob_error: bool, + ) { if errors.is_empty() { return; } @@ -752,7 +757,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - diag.emit(); + let guar = diag.emit(); + if glob_error { + self.glob_error = Some(guar); + } } /// Attempts to resolve the given import, returning: diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 322f2922f925..37d9b1a573b6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4039,9 +4039,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } #[inline] - /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items. + /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items or + // an invalid `use foo::*;` was found, which can cause unbounded ammounts of "item not found" + // errors. We silence them all. fn should_report_errs(&self) -> bool { !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body) + && !self.r.glob_error.is_some() } // Resolve in alternative namespaces if resolution in the primary namespace fails. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index af0b4792136c..8d4f3c26d954 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -37,7 +37,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{FreezeReadGuard, Lrc}; -use rustc_errors::{Applicability, Diag, ErrCode}; +use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; @@ -1052,6 +1052,7 @@ pub struct Resolver<'a, 'tcx> { /// Maps glob imports to the names of items actually imported. glob_map: FxHashMap>, + glob_error: Option, visibilities_for_hashing: Vec<(LocalDefId, ty::Visibility)>, used_imports: FxHashSet, maybe_unused_trait_imports: FxIndexSet, @@ -1421,6 +1422,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ast_transform_scopes: FxHashMap::default(), glob_map: Default::default(), + glob_error: None, visibilities_for_hashing: Default::default(), used_imports: FxHashSet::default(), maybe_unused_trait_imports: Default::default(), diff --git a/tests/ui/imports/import-from-missing-star-2.rs b/tests/ui/imports/import-from-missing-star-2.rs new file mode 100644 index 000000000000..cb341b0b0ca4 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star-2.rs @@ -0,0 +1,12 @@ +mod foo { + use spam::*; //~ ERROR unresolved import `spam` [E0432] +} + +fn main() { + // Expect this to pass because the compiler knows there's a failed `*` import in `foo` that + // might have caused it. + foo::bar(); + // FIXME: these two should *fail* because they can't be fixed by fixing the glob import in `foo` + ham(); // should error but doesn't + eggs(); // should error but doesn't +} diff --git a/tests/ui/imports/import-from-missing-star-2.stderr b/tests/ui/imports/import-from-missing-star-2.stderr new file mode 100644 index 000000000000..ea3876248c93 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star-2.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `spam` + --> $DIR/import-from-missing-star-2.rs:2:9 + | +LL | use spam::*; + | ^^^^ maybe a missing crate `spam`? + | + = help: consider adding `extern crate spam` to use the `spam` crate + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import-from-missing-star-3.rs b/tests/ui/imports/import-from-missing-star-3.rs new file mode 100644 index 000000000000..bec51fd47b37 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star-3.rs @@ -0,0 +1,43 @@ +mod foo { + use spam::*; //~ ERROR unresolved import `spam` [E0432] + + fn x() { + // Expect these to pass because the compiler knows there's a failed `*` import that might + // fix it. + eggs(); + foo::bar(); + } +} + +mod bar { + fn z() {} + fn x() { + // Expect these to pass because the compiler knows there's a failed `*` import that might + // fix it. + foo::bar(); + z(); + // FIXME: should error but doesn't because as soon as there's a single glob import error, we + // silence all resolve errors. + eggs(); + } +} + +mod baz { + fn x() { + use spam::*; //~ ERROR unresolved import `spam` [E0432] + fn qux() {} + qux(); + // Expect this to pass because the compiler knows there's a local failed `*` import that + // might have caused it. + eggs(); + // Expect this to pass because the compiler knows there's a failed `*` import in `foo` that + // might have caused it. + foo::bar(); + } +} + +fn main() { + // FIXME: should error but doesn't because as soon as there's a single glob import error, we + // silence all resolve errors. + ham(); +} diff --git a/tests/ui/imports/import-from-missing-star-3.stderr b/tests/ui/imports/import-from-missing-star-3.stderr new file mode 100644 index 000000000000..1fe5d4f19a97 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star-3.stderr @@ -0,0 +1,19 @@ +error[E0432]: unresolved import `spam` + --> $DIR/import-from-missing-star-3.rs:2:9 + | +LL | use spam::*; + | ^^^^ maybe a missing crate `spam`? + | + = help: consider adding `extern crate spam` to use the `spam` crate + +error[E0432]: unresolved import `spam` + --> $DIR/import-from-missing-star-3.rs:27:13 + | +LL | use spam::*; + | ^^^^ maybe a missing crate `spam`? + | + = help: consider adding `extern crate spam` to use the `spam` crate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import-from-missing-star.rs b/tests/ui/imports/import-from-missing-star.rs new file mode 100644 index 000000000000..cb21e16ba677 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star.rs @@ -0,0 +1,10 @@ +use spam::*; //~ ERROR unresolved import `spam` [E0432] + +fn main() { + // Expect these to pass because the compiler knows there's a failed `*` import that might have + // caused it. + ham(); + eggs(); + // Even this case, as we might have expected `spam::foo` to exist. + foo::bar(); +} diff --git a/tests/ui/imports/import-from-missing-star.stderr b/tests/ui/imports/import-from-missing-star.stderr new file mode 100644 index 000000000000..f8e295078047 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `spam` + --> $DIR/import-from-missing-star.rs:1:5 + | +LL | use spam::*; + | ^^^^ maybe a missing crate `spam`? + | + = help: consider adding `extern crate spam` to use the `spam` crate + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-31212.rs b/tests/ui/imports/issue-31212.rs index 556f0d18f9f2..fe69c5af2706 100644 --- a/tests/ui/imports/issue-31212.rs +++ b/tests/ui/imports/issue-31212.rs @@ -6,5 +6,5 @@ mod foo { } fn main() { - foo::f(); //~ ERROR cannot find function `f` in module `foo` + foo::f(); // cannot find function `f` in module `foo`, but silenced } diff --git a/tests/ui/imports/issue-31212.stderr b/tests/ui/imports/issue-31212.stderr index 0bb56b361cbb..5bba791fd020 100644 --- a/tests/ui/imports/issue-31212.stderr +++ b/tests/ui/imports/issue-31212.stderr @@ -4,13 +4,6 @@ error[E0432]: unresolved import `self::*` LL | pub use self::*; | ^^^^^^^ cannot glob-import a module into itself -error[E0425]: cannot find function `f` in module `foo` - --> $DIR/issue-31212.rs:9:10 - | -LL | foo::f(); - | ^ not found in `foo` +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0425, E0432. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0432`. From 50a5da16b815d7ff6f145cb86ea5c146b1c95329 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 May 2024 11:37:56 -0400 Subject: [PATCH 052/104] EvalCtxt::tcx() -> EvalCtxt::interner() --- .../src/solve/alias_relate.rs | 2 +- .../src/solve/assembly/mod.rs | 28 +++++----- .../src/solve/assembly/structural_traits.rs | 22 ++++---- .../src/solve/eval_ctxt/canonical.rs | 10 ++-- .../src/solve/eval_ctxt/mod.rs | 22 ++++---- .../rustc_trait_selection/src/solve/mod.rs | 4 +- .../src/solve/normalizes_to/anon_const.rs | 2 +- .../src/solve/normalizes_to/inherent.rs | 2 +- .../src/solve/normalizes_to/mod.rs | 49 ++++++++++-------- .../src/solve/normalizes_to/opaque_types.rs | 4 +- .../src/solve/normalizes_to/weak_types.rs | 2 +- .../src/solve/project_goals.rs | 2 +- .../src/solve/trait_goals.rs | 51 ++++++++++--------- 13 files changed, 108 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs index 33b30bef6832..4d7e2fc2cefa 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs @@ -26,7 +26,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { &mut self, goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>, ) -> QueryResult<'tcx> { - let tcx = self.tcx(); + let tcx = self.interner(); let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some()); diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 115244106928..aae6fa9f635b 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -83,7 +83,7 @@ pub(super) trait GoalKind<'tcx>: assumption: ty::Clause<'tcx>, ) -> Result, NoSolution> { Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { - let tcx = ecx.tcx(); + let tcx = ecx.interner(); let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else { bug!("expected object type in `probe_and_consider_object_bound_candidate`"); }; @@ -288,8 +288,10 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { return self.forced_ambiguity(MaybeCause::Ambiguity).into_iter().collect(); } - let goal: Goal<'tcx, G> = - goal.with(self.tcx(), goal.predicate.with_self_ty(self.tcx(), normalized_self_ty)); + let goal: Goal<'tcx, G> = goal.with( + self.interner(), + goal.predicate.with_self_ty(self.interner(), normalized_self_ty), + ); // Vars that show up in the rest of the goal substs may have been constrained by // normalizing the self type as well, since type variables are not uniquified. let goal = self.resolve_vars_if_possible(goal); @@ -339,7 +341,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - let tcx = self.tcx(); + let tcx = self.interner(); let self_ty = goal.predicate.self_ty(); let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx)); let mut consider_impls_for_simplified_type = |simp| { @@ -455,7 +457,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - let tcx = self.tcx(); + let tcx = self.interner(); let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx)); for &impl_def_id in trait_impls.blanket_impls() { // For every `default impl`, there's always a non-default `impl` @@ -478,7 +480,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - let tcx = self.tcx(); + let tcx = self.interner(); let lang_items = tcx.lang_items(); let trait_def_id = goal.predicate.trait_def_id(tcx); @@ -505,9 +507,9 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { G::consider_builtin_pointer_like_candidate(self, goal) } else if lang_items.fn_ptr_trait() == Some(trait_def_id) { G::consider_builtin_fn_ptr_trait_candidate(self, goal) - } else if let Some(kind) = self.tcx().fn_trait_kind_from_def_id(trait_def_id) { + } else if let Some(kind) = self.interner().fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_fn_trait_candidates(self, goal, kind) - } else if let Some(kind) = self.tcx().async_fn_trait_kind_from_def_id(trait_def_id) { + } else if let Some(kind) = self.interner().async_fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_async_fn_trait_candidates(self, goal, kind) } else if lang_items.async_fn_kind_helper() == Some(trait_def_id) { G::consider_builtin_async_fn_kind_helper_candidate(self, goal) @@ -634,7 +636,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty), ty::Alias(ty::Inherent | ty::Weak, _) => { - self.tcx().sess.dcx().span_delayed_bug( + self.interner().sess.dcx().span_delayed_bug( DUMMY_SP, format!("could not normalize {self_ty}, it is not WF"), ); @@ -643,7 +645,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { }; for assumption in - self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args) + self.interner().item_bounds(alias_ty.def_id).instantiate(self.interner(), alias_ty.args) { candidates.extend(G::probe_and_consider_implied_clause( self, @@ -673,7 +675,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - let tcx = self.tcx(); + let tcx = self.interner(); if !tcx.trait_def(goal.predicate.trait_def_id(tcx)).implement_via_object { return; } @@ -764,7 +766,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - let tcx = self.tcx(); + let tcx = self.interner(); candidates.extend(self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter( |ecx| { @@ -793,7 +795,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - let tcx = self.tcx(); + let tcx = self.interner(); let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> = goal.with(tcx, goal.predicate.trait_ref(tcx)); diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 6f68875e6f63..64d5f725a1f4 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -22,7 +22,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ecx: &EvalCtxt<'_, InferCtxt<'tcx>>, ty: Ty<'tcx>, ) -> Result>>, NoSolution> { - let tcx = ecx.tcx(); + let tcx = ecx.interner(); match *ty.kind() { ty::Uint(_) | ty::Int(_) @@ -75,7 +75,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( } ty::CoroutineWitness(def_id, args) => Ok(ecx - .tcx() + .interner() .bound_coroutine_hidden_types(def_id) .map(|bty| bty.instantiate(tcx, args)) .collect()), @@ -151,8 +151,8 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( // "best effort" optimization and `sized_constraint` may return `Some`, even // if the ADT is sized for all possible args. ty::Adt(def, args) => { - if let Some(sized_crit) = def.sized_constraint(ecx.tcx()) { - Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.tcx(), args))]) + if let Some(sized_crit) = def.sized_constraint(ecx.interner()) { + Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.interner(), args))]) } else { Ok(vec![]) } @@ -210,10 +210,10 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( // only when `coroutine_clone` is enabled and the coroutine is movable // impl Copy/Clone for Coroutine where T: Copy/Clone forall T in (upvars, witnesses) - ty::Coroutine(def_id, args) => match ecx.tcx().coroutine_movability(def_id) { + ty::Coroutine(def_id, args) => match ecx.interner().coroutine_movability(def_id) { Movability::Static => Err(NoSolution), Movability::Movable => { - if ecx.tcx().features().coroutine_clone { + if ecx.interner().features().coroutine_clone { let coroutine = args.as_coroutine(); Ok(vec![ ty::Binder::dummy(coroutine.tupled_upvars_ty()), @@ -227,9 +227,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( // impl Copy/Clone for CoroutineWitness where T: Copy/Clone forall T in coroutine_hidden_types ty::CoroutineWitness(def_id, args) => Ok(ecx - .tcx() + .interner() .bound_coroutine_hidden_types(def_id) - .map(|bty| bty.instantiate(ecx.tcx(), args)) + .map(|bty| bty.instantiate(ecx.interner(), args)) .collect()), } } @@ -666,7 +666,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>( trait_ref: ty::TraitRef<'tcx>, object_bound: &'tcx ty::List>, ) -> Vec>> { - let tcx = ecx.tcx(); + let tcx = ecx.interner(); let mut requirements = vec![]; requirements.extend( tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.args).predicates, @@ -722,7 +722,7 @@ struct ReplaceProjectionWith<'a, 'tcx> { impl<'tcx> TypeFolder> for ReplaceProjectionWith<'_, 'tcx> { fn interner(&self) -> TyCtxt<'tcx> { - self.ecx.tcx() + self.ecx.interner() } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { @@ -739,7 +739,7 @@ impl<'tcx> TypeFolder> for ReplaceProjectionWith<'_, 'tcx> { .eq_and_get_goals( self.param_env, alias_ty, - proj.projection_term.expect_ty(self.ecx.tcx()), + proj.projection_term.expect_ty(self.ecx.interner()), ) .expect("expected to be able to unify goal projection with dyn's projection"), ); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index f6ec65490845..fc10a8a43cc9 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -71,7 +71,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { QueryInput { goal, predefined_opaques_in_body: self - .tcx() + .interner() .mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }), }, ); @@ -144,7 +144,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { Response { var_values, certainty, - external_constraints: self.tcx().mk_external_constraints(external_constraints), + external_constraints: self.interner().mk_external_constraints(external_constraints), }, ); @@ -160,7 +160,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { maybe_cause: MaybeCause, ) -> CanonicalResponse<'tcx> { response_no_constraints_raw( - self.tcx(), + self.interner(), self.max_input_universe, self.variables, Certainty::Maybe(maybe_cause), @@ -194,7 +194,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned(); let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| { make_query_region_constraints( - self.tcx(), + self.interner(), region_obligations.iter().map(|r_o| { (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category()) }), @@ -239,7 +239,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { ); let Response { var_values, external_constraints, certainty } = - response.instantiate(self.tcx(), &instantiation); + response.instantiate(self.interner(), &instantiation); Self::unify_query_var_values(self.infcx, param_env, &original_values, var_values); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 4cf0af948119..72a4096f2aaa 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -347,7 +347,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); let canonical_response = EvalCtxt::evaluate_canonical_goal( - self.tcx(), + self.interner(), self.search_graph, canonical_goal, &mut goal_evaluation, @@ -450,7 +450,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { } } else { self.infcx.enter_forall(kind, |kind| { - let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); + let goal = goal.with(self.interner(), ty::Binder::dummy(kind)); self.add_goal(GoalSource::InstantiateHigherRanked, goal); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) @@ -511,7 +511,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { /// /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`. fn evaluate_added_goals_step(&mut self) -> Result, NoSolution> { - let tcx = self.tcx(); + let tcx = self.interner(); let mut goals = core::mem::take(&mut self.nested_goals); // If this loop did not result in any progress, what's our final certainty. @@ -597,11 +597,13 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { } } -impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { - pub(super) fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx +impl, I: Interner> EvalCtxt<'_, Infcx> { + pub(super) fn interner(&self) -> I { + self.infcx.interner() } +} +impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { pub(super) fn next_ty_infer(&mut self) -> Ty<'tcx> { let ty = self.infcx.next_ty_var(DUMMY_SP); self.inspect.add_var_value(ty); @@ -759,7 +761,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { // NOTE: this check is purely an optimization, the structural eq would // always fail if the term is not an inference variable. if term.is_infer() { - let tcx = self.tcx(); + let tcx = self.interner(); // We need to relate `alias` to `term` treating only the outermost // constructor as rigid, relating any contained generic arguments as // normal. We do this by first structurally equating the `term` @@ -1054,10 +1056,10 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { ) -> Option> { use rustc_middle::mir::interpret::ErrorHandled; match self.infcx.const_eval_resolve(param_env, unevaluated, DUMMY_SP) { - Ok(Some(val)) => Some(ty::Const::new_value(self.tcx(), val, ty)), + Ok(Some(val)) => Some(ty::Const::new_value(self.interner(), val, ty)), Ok(None) | Err(ErrorHandled::TooGeneric(_)) => None, Err(ErrorHandled::Reported(e, _)) => { - Some(ty::Const::new_error(self.tcx(), e.into(), ty)) + Some(ty::Const::new_error(self.interner(), e.into(), ty)) } } } @@ -1070,7 +1072,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { principal: ty::PolyTraitRef<'tcx>, mut supertrait_visitor: impl FnMut(&mut Self, ty::PolyTraitRef<'tcx>, usize, Option), ) { - let tcx = self.tcx(); + let tcx = self.interner(); let mut offset = 0; prepare_vtable_segments::<()>(tcx, principal, |segment| { match segment { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 60722d3618f9..a432090f78cd 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { } fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> { - if self.tcx().check_is_object_safe(trait_def_id) { + if self.interner().check_is_object_safe(trait_def_id) { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { Err(NoSolution) @@ -274,7 +274,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { if let ty::Alias(..) = ty.kind() { let normalized_ty = self.next_ty_infer(); let alias_relate_goal = Goal::new( - self.tcx(), + self.interner(), param_env, ty::PredicateKind::AliasRelate( ty.into(), diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs index c9621e705e57..362c4072278d 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs @@ -12,7 +12,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { if let Some(normalized_const) = self.try_const_eval_resolve( goal.param_env, ty::UnevaluatedConst::new(goal.predicate.alias.def_id, goal.predicate.alias.args), - self.tcx() + self.interner() .type_of(goal.predicate.alias.def_id) .no_bound_vars() .expect("const ty should not rely on other generics"), diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs index 2146a2c2f081..41b2b9cd4d26 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs @@ -15,7 +15,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { &mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, ) -> QueryResult<'tcx> { - let tcx = self.tcx(); + let tcx = self.interner(); let inherent = goal.predicate.alias.expect_ty(tcx); let impl_def_id = tcx.parent(inherent.def_id); diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 7ef8373663ba..7fd2a3801cc4 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -54,7 +54,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { &mut self, goal: Goal<'tcx, NormalizesTo<'tcx>>, ) -> QueryResult<'tcx> { - match goal.predicate.alias.kind(self.tcx()) { + match goal.predicate.alias.kind(self.interner()) { ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => { let candidates = self.assemble_and_evaluate_candidates(goal); self.merge_candidates(candidates) @@ -107,7 +107,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ) -> Result, NoSolution> { if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.projection_def_id() == goal.predicate.def_id() { - let tcx = ecx.tcx(); + let tcx = ecx.interner(); ecx.probe_trait_candidate(source).enter(|ecx| { let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); @@ -142,7 +142,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, NormalizesTo<'tcx>>, impl_def_id: DefId, ) -> Result, NoSolution> { - let tcx = ecx.tcx(); + let tcx = ecx.interner(); let goal_trait_ref = goal.predicate.alias.trait_ref(tcx); let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); @@ -290,8 +290,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, goal: Goal<'tcx, Self>, ) -> Result, NoSolution> { - ecx.tcx().dcx().span_delayed_bug( - ecx.tcx().def_span(goal.predicate.def_id()), + ecx.interner().dcx().span_delayed_bug( + ecx.interner().def_span(goal.predicate.def_id()), "associated types not allowed on auto traits", ); Err(NoSolution) @@ -337,7 +337,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, goal_kind: ty::ClosureKind, ) -> Result, NoSolution> { - let tcx = ecx.tcx(); + let tcx = ecx.interner(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( tcx, @@ -380,7 +380,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, goal_kind: ty::ClosureKind, ) -> Result, NoSolution> { - let tcx = ecx.tcx(); + let tcx = ecx.interner(); let env_region = match goal_kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2), @@ -493,7 +493,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( - ecx.tcx(), + ecx.interner(), goal_kind, tupled_inputs_ty.expect_ty(), tupled_upvars_ty.expect_ty(), @@ -518,7 +518,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, goal: Goal<'tcx, Self>, ) -> Result, NoSolution> { - let tcx = ecx.tcx(); + let tcx = ecx.interner(); let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); assert_eq!(metadata_def_id, goal.predicate.def_id()); ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { @@ -606,7 +606,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { }; // Coroutines are not futures unless they come from `async` desugaring - let tcx = ecx.tcx(); + let tcx = ecx.interner(); if !tcx.coroutine_is_async(def_id) { return Err(NoSolution); } @@ -618,7 +618,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_term: ty::AliasTerm::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), + projection_term: ty::AliasTerm::new( + ecx.interner(), + goal.predicate.def_id(), + [self_ty], + ), term, } .upcast(tcx), @@ -638,7 +642,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { }; // Coroutines are not Iterators unless they come from `gen` desugaring - let tcx = ecx.tcx(); + let tcx = ecx.interner(); if !tcx.coroutine_is_gen(def_id) { return Err(NoSolution); } @@ -650,7 +654,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_term: ty::AliasTerm::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), + projection_term: ty::AliasTerm::new( + ecx.interner(), + goal.predicate.def_id(), + [self_ty], + ), term, } .upcast(tcx), @@ -677,7 +685,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { }; // Coroutines are not AsyncIterators unless they come from `gen` desugaring - let tcx = ecx.tcx(); + let tcx = ecx.interner(); if !tcx.coroutine_is_async_gen(def_id) { return Err(NoSolution); } @@ -713,7 +721,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { }; // `async`-desugared coroutines do not implement the coroutine trait - let tcx = ecx.tcx(); + let tcx = ecx.interner(); if !tcx.is_general_coroutine(def_id) { return Err(NoSolution); } @@ -735,7 +743,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal, ty::ProjectionPredicate { projection_term: ty::AliasTerm::new( - ecx.tcx(), + ecx.interner(), goal.predicate.def_id(), [self_ty, coroutine.resume_ty()], ), @@ -784,7 +792,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::Slice(_) | ty::Dynamic(_, _, _) | ty::Tuple(_) - | ty::Error(_) => self_ty.discriminant_ty(ecx.tcx()), + | ty::Error(_) => self_ty.discriminant_ty(ecx.interner()), // We do not call `Ty::discriminant_ty` on alias, param, or placeholder // types, which return `::Discriminant` @@ -831,7 +839,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::Str | ty::Slice(_) | ty::Tuple(_) - | ty::Error(_) => self_ty.async_destructor_ty(ecx.tcx(), goal.param_env), + | ty::Error(_) => self_ty.async_destructor_ty(ecx.interner(), goal.param_env), // We do not call `Ty::async_destructor_ty` on alias, param, or placeholder // types, which return `::AsyncDestructor` @@ -887,8 +895,9 @@ fn fetch_eligible_assoc_item_def<'tcx>( trait_assoc_def_id: DefId, impl_def_id: DefId, ) -> Result, NoSolution> { - let node_item = specialization_graph::assoc_def(ecx.tcx(), impl_def_id, trait_assoc_def_id) - .map_err(|ErrorGuaranteed { .. }| NoSolution)?; + let node_item = + specialization_graph::assoc_def(ecx.interner(), impl_def_id, trait_assoc_def_id) + .map_err(|ErrorGuaranteed { .. }| NoSolution)?; let eligible = if node_item.is_final() { // Non-specializable items are always projectable. diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs index 3b83d347276f..67ec2f3be481 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs @@ -15,7 +15,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { &mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, ) -> QueryResult<'tcx> { - let tcx = self.tcx(); + let tcx = self.interner(); let opaque_ty = goal.predicate.alias; let expected = goal.predicate.term.ty().expect("no such thing as an opaque const"); @@ -31,7 +31,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { return Err(NoSolution); } // FIXME: This may have issues when the args contain aliases... - match self.tcx().uses_unique_placeholders_ignoring_regions(opaque_ty.args) { + match self.interner().uses_unique_placeholders_ignoring_regions(opaque_ty.args) { Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => { return self.evaluate_added_goals_and_make_canonical_response( Certainty::AMBIGUOUS, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs index 109a9e9671f0..5442b9ccffc8 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs @@ -14,7 +14,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { &mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, ) -> QueryResult<'tcx> { - let tcx = self.tcx(); + let tcx = self.interner(); let weak_ty = goal.predicate.alias; // Check where clauses diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 8fa78e49dc6e..cae73cc2d073 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -11,7 +11,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { &mut self, goal: Goal<'tcx, ProjectionPredicate<'tcx>>, ) -> QueryResult<'tcx> { - let tcx = self.tcx(); + let tcx = self.interner(); let projection_term = goal.predicate.projection_term.to_term(tcx); let goal = goal.with( tcx, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index e59eef22f411..67dd3fa85fa1 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -42,7 +42,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { goal: Goal<'tcx, TraitPredicate<'tcx>>, impl_def_id: DefId, ) -> Result, NoSolution> { - let tcx = ecx.tcx(); + let tcx = ecx.interner(); let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; @@ -181,7 +181,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return Err(NoSolution); } - let tcx = ecx.tcx(); + let tcx = ecx.interner(); ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let nested_obligations = tcx @@ -235,7 +235,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } // The regions of a type don't affect the size of the type - let tcx = ecx.tcx(); + let tcx = ecx.interner(); // We should erase regions from both the param-env and type, since both // may have infer regions. Specifically, after canonicalizing and instantiating, // early bound regions turn into region vars in both the new and old solver. @@ -296,7 +296,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return Err(NoSolution); } - let tcx = ecx.tcx(); + let tcx = ecx.interner(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( tcx, @@ -337,7 +337,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return Err(NoSolution); } - let tcx = ecx.tcx(); + let tcx = ecx.interner(); let (tupled_inputs_and_output_and_coroutine, nested_preds) = structural_traits::extract_tupled_inputs_and_output_from_async_callable( tcx, @@ -447,7 +447,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { }; // Coroutines are not futures unless they come from `async` desugaring - let tcx = ecx.tcx(); + let tcx = ecx.interner(); if !tcx.coroutine_is_async(def_id) { return Err(NoSolution); } @@ -473,7 +473,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { }; // Coroutines are not iterators unless they come from `gen` desugaring - let tcx = ecx.tcx(); + let tcx = ecx.interner(); if !tcx.coroutine_is_gen(def_id) { return Err(NoSolution); } @@ -499,7 +499,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { }; // Coroutines are not iterators unless they come from `gen` desugaring - let tcx = ecx.tcx(); + let tcx = ecx.interner(); if !tcx.coroutine_is_gen(def_id) { return Err(NoSolution); } @@ -523,7 +523,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { }; // Coroutines are not iterators unless they come from `gen` desugaring - let tcx = ecx.tcx(); + let tcx = ecx.interner(); if !tcx.coroutine_is_async_gen(def_id) { return Err(NoSolution); } @@ -550,7 +550,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { }; // `async`-desugared coroutines do not implement the coroutine trait - let tcx = ecx.tcx(); + let tcx = ecx.interner(); if !tcx.is_general_coroutine(def_id) { return Err(NoSolution); } @@ -625,10 +625,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // Erase regions because we compute layouts in `rustc_transmute`, // which will ICE for region vars. - let args = ecx.tcx().erase_regions(goal.predicate.trait_ref.args); + let args = ecx.interner().erase_regions(goal.predicate.trait_ref.args); let Some(assume) = - rustc_transmute::Assume::from_const(ecx.tcx(), goal.param_env, args.const_at(2)) + rustc_transmute::Assume::from_const(ecx.interner(), goal.param_env, args.const_at(2)) else { return Err(NoSolution); }; @@ -675,7 +675,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return vec![]; }; - let goal = goal.with(ecx.tcx(), (a_ty, b_ty)); + let goal = goal.with(ecx.interner(), (a_ty, b_ty)); match (a_ty.kind(), b_ty.kind()) { (ty::Infer(ty::TyVar(..)), ..) => bug!("unexpected infer {a_ty:?} {b_ty:?}"), @@ -741,7 +741,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { b_data: &'tcx ty::List>, b_region: ty::Region<'tcx>, ) -> Vec> { - let tcx = self.tcx(); + let tcx = self.interner(); let Goal { predicate: (a_ty, _b_ty), .. } = goal; let mut responses = vec![]; @@ -787,7 +787,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { b_data: &'tcx ty::List>, b_region: ty::Region<'tcx>, ) -> Result, NoSolution> { - let tcx = self.tcx(); + let tcx = self.interner(); let Goal { predicate: (a_ty, _), .. } = goal; // Can only unsize to an object-safe trait. @@ -837,8 +837,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { let a_auto_traits: FxIndexSet = a_data .auto_traits() .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { - supertrait_def_ids(self.tcx(), principal_def_id) - .filter(|def_id| self.tcx().trait_is_auto(*def_id)) + supertrait_def_ids(self.interner(), principal_def_id) + .filter(|def_id| self.interner().trait_is_auto(*def_id)) })) .collect(); @@ -907,7 +907,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { ecx.add_goal( GoalSource::ImplWhereBound, Goal::new( - ecx.tcx(), + ecx.interner(), param_env, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region)), ), @@ -956,7 +956,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { a_args: ty::GenericArgsRef<'tcx>, b_args: ty::GenericArgsRef<'tcx>, ) -> Result, NoSolution> { - let tcx = self.tcx(); + let tcx = self.interner(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; let unsizing_params = tcx.unsizing_params_for_adt(def.did()); @@ -1017,7 +1017,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { a_tys: &'tcx ty::List>, b_tys: &'tcx ty::List>, ) -> Result, NoSolution> { - let tcx = self.tcx(); + let tcx = self.interner(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); @@ -1077,9 +1077,9 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { // takes precedence over the structural auto trait candidate being // assembled. ty::Coroutine(def_id, _) - if Some(goal.predicate.def_id()) == self.tcx().lang_items().unpin_trait() => + if Some(goal.predicate.def_id()) == self.interner().lang_items().unpin_trait() => { - match self.tcx().coroutine_movability(def_id) { + match self.interner().coroutine_movability(def_id) { Movability::Static => Some(Err(NoSolution)), Movability::Movable => Some( self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { @@ -1124,7 +1124,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { | ty::Tuple(_) | ty::Adt(_, _) => { let mut disqualifying_impl = None; - self.tcx().for_each_relevant_impl( + self.interner().for_each_relevant_impl( goal.predicate.def_id(), goal.predicate.self_ty(), |impl_def_id| { @@ -1164,7 +1164,10 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { .into_iter() .map(|ty| { ecx.enter_forall(ty, |ty| { - goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty)) + goal.with( + ecx.interner(), + goal.predicate.with_self_ty(ecx.interner(), ty), + ) }) }) .collect::>(), From f49403653017bfe5a62b7121b36249c19dcf1a0d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 May 2024 13:20:37 -0400 Subject: [PATCH 053/104] Make ProofTreeBuilder actually generic over interner --- compiler/rustc_middle/src/ty/context.rs | 7 ++ .../src/solve/eval_ctxt/canonical.rs | 28 +++-- .../src/solve/eval_ctxt/mod.rs | 8 +- .../src/solve/inspect/build.rs | 112 +++++++++--------- .../src/solve/search_graph.rs | 11 +- compiler/rustc_type_ir/src/inherent.rs | 9 +- compiler/rustc_type_ir/src/interner.rs | 10 +- 7 files changed, 102 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c09cb95de883..5a04324dc7dc 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -218,6 +218,13 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.check_and_mk_args(def_id, args) } + fn intern_canonical_goal_evaluation_step( + self, + step: solve::inspect::CanonicalGoalEvaluationStep>, + ) -> &'tcx solve::inspect::CanonicalGoalEvaluationStep> { + self.arena.alloc(step) + } + fn parent(self, def_id: Self::DefId) -> Self::DefId { self.parent(def_id) } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index fc10a8a43cc9..4977807aa6cf 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -16,7 +16,6 @@ use crate::solve::{ use rustc_data_structures::fx::FxHashSet; use rustc_index::IndexVec; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; -use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; use rustc_infer::infer::RegionVariableOrigin; use rustc_infer::infer::{InferCtxt, InferOk}; @@ -32,22 +31,24 @@ use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable} use rustc_next_trait_solver::canonicalizer::{CanonicalizeMode, Canonicalizer}; use rustc_next_trait_solver::resolve::EagerResolver; use rustc_span::{Span, DUMMY_SP}; +use rustc_type_ir::CanonicalVarValues; +use rustc_type_ir::{InferCtxtLike, Interner}; use std::assert_matches::assert_matches; use std::iter; use std::ops::Deref; trait ResponseT<'tcx> { - fn var_values(&self) -> CanonicalVarValues<'tcx>; + fn var_values(&self) -> CanonicalVarValues>; } impl<'tcx> ResponseT<'tcx> for Response> { - fn var_values(&self) -> CanonicalVarValues<'tcx> { + fn var_values(&self) -> CanonicalVarValues> { self.var_values } } impl<'tcx, T> ResponseT<'tcx> for inspect::State, T> { - fn var_values(&self) -> CanonicalVarValues<'tcx> { + fn var_values(&self) -> CanonicalVarValues> { self.var_values } } @@ -260,7 +261,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { infcx: &InferCtxt<'tcx>, original_values: &[ty::GenericArg<'tcx>], response: &Canonical<'tcx, T>, - ) -> CanonicalVarValues<'tcx> { + ) -> CanonicalVarValues> { // FIXME: Longterm canonical queries should deal with all placeholders // created inside of the query directly instead of returning them to the // caller. @@ -354,7 +355,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, original_values: &[ty::GenericArg<'tcx>], - var_values: CanonicalVarValues<'tcx>, + var_values: CanonicalVarValues>, ) { assert_eq!(original_values.len(), var_values.len()); @@ -393,13 +394,18 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { /// evaluating a goal. The `var_values` not only include the bound variables /// of the query input, but also contain all unconstrained inference vars /// created while evaluating this goal. -pub(in crate::solve) fn make_canonical_state<'tcx, T: TypeFoldable>>( - infcx: &InferCtxt<'tcx>, - var_values: &[ty::GenericArg<'tcx>], +pub(in crate::solve) fn make_canonical_state( + infcx: &Infcx, + var_values: &[I::GenericArg], max_input_universe: ty::UniverseIndex, data: T, -) -> inspect::CanonicalState, T> { - let var_values = CanonicalVarValues { var_values: infcx.tcx.mk_args(var_values) }; +) -> inspect::CanonicalState +where + Infcx: InferCtxtLike, + I: Interner, + T: TypeFoldable, +{ + let var_values = CanonicalVarValues { var_values: infcx.interner().mk_args(var_values) }; let state = inspect::State { var_values, data }; let state = state.fold_with(&mut EagerResolver::new(infcx)); Canonicalizer::canonicalize( diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 72a4096f2aaa..98ba3feeca13 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -98,7 +98,7 @@ pub struct EvalCtxt< // evaluation code. tainted: Result<(), NoSolution>, - pub(super) inspect: ProofTreeBuilder, + pub(super) inspect: ProofTreeBuilder, } #[derive(derivative::Derivative)] @@ -218,7 +218,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { tcx: TyCtxt<'tcx>, search_graph: &'a mut search_graph::SearchGraph>, canonical_input: CanonicalInput<'tcx>, - canonical_goal_evaluation: &mut ProofTreeBuilder>, + canonical_goal_evaluation: &mut ProofTreeBuilder>, f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>, Goal<'tcx, ty::Predicate<'tcx>>) -> R, ) -> R { let intercrate = match search_graph.solver_mode() { @@ -280,7 +280,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { tcx: TyCtxt<'tcx>, search_graph: &'a mut search_graph::SearchGraph>, canonical_input: CanonicalInput<'tcx>, - goal_evaluation: &mut ProofTreeBuilder>, + goal_evaluation: &mut ProofTreeBuilder>, ) -> QueryResult<'tcx> { let mut canonical_goal_evaluation = goal_evaluation.new_canonical_goal_evaluation(canonical_input); @@ -1114,7 +1114,7 @@ struct ReplaceAliasWithInfer<'me, 'a, 'tcx> { impl<'tcx> TypeFolder> for ReplaceAliasWithInfer<'_, '_, 'tcx> { fn interner(&self) -> TyCtxt<'tcx> { - self.ecx.tcx() + self.ecx.interner() } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs index 3c6333626483..84c04900ae48 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs @@ -3,18 +3,16 @@ //! This code is *a bit* of a mess and can hopefully be //! mostly ignored. For a general overview of how it works, //! see the comment on [ProofTreeBuilder]. +use std::marker::PhantomData; use std::mem; use crate::solve::eval_ctxt::canonical; use crate::solve::{self, inspect, GenerateProofTree}; -use rustc_infer::infer::InferCtxt; use rustc_middle::bug; -use rustc_middle::infer::canonical::CanonicalVarValues; -use rustc_middle::ty::{self, TyCtxt}; use rustc_next_trait_solver::solve::{ CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult, }; -use rustc_type_ir::Interner; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; /// The core data structure when building proof trees. /// @@ -36,7 +34,11 @@ use rustc_type_ir::Interner; /// trees. At the end of trait solving `ProofTreeBuilder::finalize` /// is called to recursively convert the whole structure to a /// finished proof tree. -pub(in crate::solve) struct ProofTreeBuilder { +pub(in crate::solve) struct ProofTreeBuilder< + Infcx: InferCtxtLike, + I: Interner = ::Interner, +> { + _infcx: PhantomData, state: Option>>, } @@ -229,36 +231,36 @@ impl WipProbeStep { } } -// FIXME: Genericize this impl. -impl<'tcx> ProofTreeBuilder> { - fn new(state: impl Into>>) -> ProofTreeBuilder> { - ProofTreeBuilder { state: Some(Box::new(state.into())) } +impl, I: Interner> ProofTreeBuilder { + fn new(state: impl Into>) -> ProofTreeBuilder { + ProofTreeBuilder { state: Some(Box::new(state.into())), _infcx: PhantomData } } - fn opt_nested>>>( - &self, - state: impl FnOnce() -> Option, - ) -> Self { + fn opt_nested>>(&self, state: impl FnOnce() -> Option) -> Self { ProofTreeBuilder { state: self.state.as_ref().and_then(|_| Some(state()?.into())).map(Box::new), + _infcx: PhantomData, } } - fn nested>>>(&self, state: impl FnOnce() -> T) -> Self { - ProofTreeBuilder { state: self.state.as_ref().map(|_| Box::new(state().into())) } + fn nested>>(&self, state: impl FnOnce() -> T) -> Self { + ProofTreeBuilder { + state: self.state.as_ref().map(|_| Box::new(state().into())), + _infcx: PhantomData, + } } - fn as_mut(&mut self) -> Option<&mut DebugSolver>> { + fn as_mut(&mut self) -> Option<&mut DebugSolver> { self.state.as_deref_mut() } - pub fn take_and_enter_probe(&mut self) -> ProofTreeBuilder> { - let mut nested = ProofTreeBuilder { state: self.state.take() }; + pub fn take_and_enter_probe(&mut self) -> ProofTreeBuilder { + let mut nested = ProofTreeBuilder { state: self.state.take(), _infcx: PhantomData }; nested.enter_probe(); nested } - pub fn finalize(self) -> Option>> { + pub fn finalize(self) -> Option> { match *self.state? { DebugSolver::GoalEvaluation(wip_goal_evaluation) => { Some(wip_goal_evaluation.finalize()) @@ -267,21 +269,19 @@ impl<'tcx> ProofTreeBuilder> { } } - pub fn new_maybe_root( - generate_proof_tree: GenerateProofTree, - ) -> ProofTreeBuilder> { + pub fn new_maybe_root(generate_proof_tree: GenerateProofTree) -> ProofTreeBuilder { match generate_proof_tree { GenerateProofTree::No => ProofTreeBuilder::new_noop(), GenerateProofTree::Yes => ProofTreeBuilder::new_root(), } } - pub fn new_root() -> ProofTreeBuilder> { + pub fn new_root() -> ProofTreeBuilder { ProofTreeBuilder::new(DebugSolver::Root) } - pub fn new_noop() -> ProofTreeBuilder> { - ProofTreeBuilder { state: None } + pub fn new_noop() -> ProofTreeBuilder { + ProofTreeBuilder { state: None, _infcx: PhantomData } } pub fn is_noop(&self) -> bool { @@ -290,10 +290,10 @@ impl<'tcx> ProofTreeBuilder> { pub(in crate::solve) fn new_goal_evaluation( &mut self, - goal: Goal, ty::Predicate<'tcx>>, - orig_values: &[ty::GenericArg<'tcx>], + goal: Goal, + orig_values: &[I::GenericArg], kind: solve::GoalEvaluationKind, - ) -> ProofTreeBuilder> { + ) -> ProofTreeBuilder { self.opt_nested(|| match kind { solve::GoalEvaluationKind::Root => Some(WipGoalEvaluation { uncanonicalized_goal: goal, @@ -306,8 +306,8 @@ impl<'tcx> ProofTreeBuilder> { pub fn new_canonical_goal_evaluation( &mut self, - goal: CanonicalInput>, - ) -> ProofTreeBuilder> { + goal: CanonicalInput, + ) -> ProofTreeBuilder { self.nested(|| WipCanonicalGoalEvaluation { goal, kind: None, @@ -318,12 +318,13 @@ impl<'tcx> ProofTreeBuilder> { pub fn finalize_canonical_goal_evaluation( &mut self, - tcx: TyCtxt<'tcx>, - ) -> Option<&'tcx inspect::CanonicalGoalEvaluationStep>> { + tcx: I, + ) -> Option { self.as_mut().map(|this| match this { DebugSolver::CanonicalGoalEvaluation(evaluation) => { let final_revision = mem::take(&mut evaluation.final_revision).unwrap(); - let final_revision = &*tcx.arena.alloc(final_revision.finalize()); + let final_revision = + tcx.intern_canonical_goal_evaluation_step(final_revision.finalize()); let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision }; assert_eq!(evaluation.kind.replace(kind), None); final_revision @@ -334,7 +335,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn canonical_goal_evaluation( &mut self, - canonical_goal_evaluation: ProofTreeBuilder>, + canonical_goal_evaluation: ProofTreeBuilder, ) { if let Some(this) = self.as_mut() { match (this, *canonical_goal_evaluation.state.unwrap()) { @@ -350,10 +351,7 @@ impl<'tcx> ProofTreeBuilder> { } } - pub fn canonical_goal_evaluation_kind( - &mut self, - kind: WipCanonicalGoalEvaluationKind>, - ) { + pub fn canonical_goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { @@ -364,7 +362,7 @@ impl<'tcx> ProofTreeBuilder> { } } - pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder>) { + pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder) { if let Some(this) = self.as_mut() { match this { DebugSolver::Root => *this = *goal_evaluation.state.unwrap(), @@ -378,9 +376,9 @@ impl<'tcx> ProofTreeBuilder> { pub fn new_goal_evaluation_step( &mut self, - var_values: CanonicalVarValues<'tcx>, - instantiated_goal: QueryInput, ty::Predicate<'tcx>>, - ) -> ProofTreeBuilder> { + var_values: ty::CanonicalVarValues, + instantiated_goal: QueryInput, + ) -> ProofTreeBuilder { self.nested(|| WipCanonicalGoalEvaluationStep { var_values: var_values.var_values.to_vec(), instantiated_goal, @@ -394,7 +392,7 @@ impl<'tcx> ProofTreeBuilder> { }) } - pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder>) { + pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder) { if let Some(this) = self.as_mut() { match (this, *goal_evaluation_step.state.unwrap()) { ( @@ -408,7 +406,7 @@ impl<'tcx> ProofTreeBuilder> { } } - pub fn add_var_value>>(&mut self, arg: T) { + pub fn add_var_value>(&mut self, arg: T) { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -435,7 +433,7 @@ impl<'tcx> ProofTreeBuilder> { } } - pub fn probe_kind(&mut self, probe_kind: inspect::ProbeKind>) { + pub fn probe_kind(&mut self, probe_kind: inspect::ProbeKind) { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -446,11 +444,7 @@ impl<'tcx> ProofTreeBuilder> { } } - pub fn probe_final_state( - &mut self, - infcx: &InferCtxt<'tcx>, - max_input_universe: ty::UniverseIndex, - ) { + pub fn probe_final_state(&mut self, infcx: &Infcx, max_input_universe: ty::UniverseIndex) { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -469,24 +463,24 @@ impl<'tcx> ProofTreeBuilder> { pub fn add_normalizes_to_goal( &mut self, - infcx: &InferCtxt<'tcx>, + infcx: &Infcx, max_input_universe: ty::UniverseIndex, - goal: Goal, ty::NormalizesTo<'tcx>>, + goal: Goal>, ) { self.add_goal( infcx, max_input_universe, GoalSource::Misc, - goal.with(infcx.tcx, goal.predicate), + goal.with(infcx.interner(), goal.predicate), ); } pub fn add_goal( &mut self, - infcx: &InferCtxt<'tcx>, + infcx: &Infcx, max_input_universe: ty::UniverseIndex, source: GoalSource, - goal: Goal, ty::Predicate<'tcx>>, + goal: Goal, ) { match self.as_mut() { None => {} @@ -505,9 +499,9 @@ impl<'tcx> ProofTreeBuilder> { pub(crate) fn record_impl_args( &mut self, - infcx: &InferCtxt<'tcx>, + infcx: &Infcx, max_input_universe: ty::UniverseIndex, - impl_args: ty::GenericArgsRef<'tcx>, + impl_args: I::GenericArgs, ) { match self.as_mut() { Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -540,7 +534,7 @@ impl<'tcx> ProofTreeBuilder> { } } - pub fn finish_probe(mut self) -> ProofTreeBuilder> { + pub fn finish_probe(mut self) -> ProofTreeBuilder { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -555,7 +549,7 @@ impl<'tcx> ProofTreeBuilder> { self } - pub fn query_result(&mut self, result: QueryResult>) { + pub fn query_result(&mut self, result: QueryResult) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs index 6be623b6044f..f1b8bf4676ee 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs @@ -3,6 +3,7 @@ use std::mem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::Idx; use rustc_index::IndexVec; +use rustc_infer::infer::InferCtxt; use rustc_middle::dep_graph::dep_kinds; use rustc_middle::traits::solve::CacheData; use rustc_middle::traits::solve::EvaluationCache; @@ -261,10 +262,10 @@ impl<'tcx> SearchGraph> { &mut self, tcx: TyCtxt<'tcx>, input: CanonicalInput>, - inspect: &mut ProofTreeBuilder>, + inspect: &mut ProofTreeBuilder>, mut prove_goal: impl FnMut( &mut Self, - &mut ProofTreeBuilder>, + &mut ProofTreeBuilder>, ) -> QueryResult>, ) -> QueryResult> { self.check_invariants(); @@ -426,7 +427,7 @@ impl<'tcx> SearchGraph> { tcx: TyCtxt<'tcx>, input: CanonicalInput>, available_depth: Limit, - inspect: &mut ProofTreeBuilder>, + inspect: &mut ProofTreeBuilder>, ) -> Option>> { let CacheData { result, proof_tree, additional_depth, encountered_overflow } = self .global_cache(tcx) @@ -473,11 +474,11 @@ impl<'tcx> SearchGraph> { &mut self, tcx: TyCtxt<'tcx>, input: CanonicalInput>, - inspect: &mut ProofTreeBuilder>, + inspect: &mut ProofTreeBuilder>, prove_goal: &mut F, ) -> StepResult> where - F: FnMut(&mut Self, &mut ProofTreeBuilder>) -> QueryResult>, + F: FnMut(&mut Self, &mut ProofTreeBuilder>) -> QueryResult>, { let result = prove_goal(self, inspect); let stack_entry = self.pop_stack(); diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index e7e893f27daa..7b1dfecfee2e 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -132,7 +132,14 @@ pub trait GenericArgs>: } pub trait Predicate>: - Copy + Debug + Hash + Eq + TypeSuperVisitable + TypeSuperFoldable + Flags + Copy + + Debug + + Hash + + Eq + + TypeSuperVisitable + + TypeSuperFoldable + + Flags + + UpcastFrom> { fn is_coinductive(self, interner: I) -> bool; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index e49db171a534..2a228c973d34 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::hash::Hash; use std::ops::Deref; +use crate::fold::TypeFoldable; use crate::inherent::*; use crate::ir_print::IrPrint; use crate::solve::inspect::CanonicalGoalEvaluationStep; @@ -90,7 +91,7 @@ pub trait Interner: type PlaceholderRegion: PlaceholderLike; // Predicates - type ParamEnv: Copy + Debug + Hash + Eq; + type ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable; type Predicate: Predicate; type Clause: Clause; type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags; @@ -114,15 +115,18 @@ pub trait Interner: ) -> (ty::TraitRef, Self::OwnItemArgs); fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs; - fn mk_args_from_iter(self, args: impl Iterator) -> Self::GenericArgs; - fn check_and_mk_args( self, def_id: Self::DefId, args: impl IntoIterator>, ) -> Self::GenericArgs; + fn intern_canonical_goal_evaluation_step( + self, + step: CanonicalGoalEvaluationStep, + ) -> Self::CanonicalGoalEvaluationStepRef; + fn parent(self, def_id: Self::DefId) -> Self::DefId; fn recursion_limit(self) -> usize; From 89f3651402d825d46d5aa974839b82ec0b737fe8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 28 May 2024 11:38:58 -0400 Subject: [PATCH 054/104] Get rid of manual Trace calls --- compiler/rustc_hir_typeck/src/coercion.rs | 1 - compiler/rustc_infer/src/infer/at.rs | 17 +++++++++++++++++ .../src/solve/eval_ctxt/canonical.rs | 1 - .../src/solve/eval_ctxt/mod.rs | 8 ++------ .../rustc_trait_selection/src/traits/fulfill.rs | 7 +++++-- .../src/traits/select/mod.rs | 7 +++++-- 6 files changed, 29 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index ebdc558282a9..93726ce2b3eb 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1158,7 +1158,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (a_sig, b_sig) = self.normalize(new.span, (a_sig, b_sig)); let sig = self .at(cause, self.param_env) - .trace(prev_ty, new_ty) .lub(DefineOpaqueTypes::Yes, a_sig, b_sig) .map(|ok| self.register_infer_ok_obligations(ok))?; diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 16057b6ad9dc..aa37aaf22eb4 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -156,6 +156,23 @@ impl<'a, 'tcx> At<'a, 'tcx> { self.trace(expected, actual).eq(define_opaque_types, expected, actual) } + /// Equates `expected` and `found` while structurally relating aliases. + /// This should only be used inside of the next generation trait solver + /// when relating rigid aliases. + pub fn eq_structurally_relating_aliases( + self, + expected: T, + actual: T, + ) -> InferResult<'tcx, ()> + where + T: ToTrace<'tcx>, + { + self.trace(expected, actual).eq_structurally_relating_aliases( + expected, + actual, + ) + } + pub fn relate( self, define_opaque_types: DefineOpaqueTypes, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index f6ec65490845..bc248754f167 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -362,7 +362,6 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { for (&orig, response) in iter::zip(original_values, var_values.var_values) { let InferOk { value: (), obligations } = infcx .at(&cause, param_env) - .trace(orig, response) .eq_structurally_relating_aliases(orig, response) .unwrap(); assert!(obligations.is_empty()); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 4cf0af948119..9ae0809e96ed 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -774,7 +774,6 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { let InferOk { value: (), obligations } = self .infcx .at(&ObligationCause::dummy(), param_env) - .trace(term, ctor_term) .eq_structurally_relating_aliases(term, ctor_term)?; debug_assert!(obligations.is_empty()); self.relate(param_env, alias, variance, rigid_ctor) @@ -794,11 +793,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { rhs: T, ) -> Result<(), NoSolution> { let cause = ObligationCause::dummy(); - let InferOk { value: (), obligations } = self - .infcx - .at(&cause, param_env) - .trace(lhs, rhs) - .eq_structurally_relating_aliases(lhs, rhs)?; + let InferOk { value: (), obligations } = + self.infcx.at(&cause, param_env).eq_structurally_relating_aliases(lhs, rhs)?; assert!(obligations.is_empty()); Ok(()) } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 07fcf109fdaa..629f6f394af3 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -566,10 +566,13 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { { if let Ok(new_obligations) = infcx .at(&obligation.cause, obligation.param_env) - .trace(c1, c2) // Can define opaque types as this is only reachable with // `generic_const_exprs` - .eq(DefineOpaqueTypes::Yes, a.args, b.args) + .eq( + DefineOpaqueTypes::Yes, + ty::AliasTerm::from(a), + ty::AliasTerm::from(b), + ) { return ProcessResult::Changed(mk_pending( new_obligations.into_obligations(), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 696b1c151153..7aec4e1987ed 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -910,10 +910,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let Ok(InferOk { obligations, value: () }) = self .infcx .at(&obligation.cause, obligation.param_env) - .trace(c1, c2) // Can define opaque types as this is only reachable with // `generic_const_exprs` - .eq(DefineOpaqueTypes::Yes, a.args, b.args) + .eq( + DefineOpaqueTypes::Yes, + ty::AliasTerm::from(a), + ty::AliasTerm::from(b), + ) { return self.evaluate_predicates_recursively( previous_stack, From cc97376adeba686f6d1e1d77c290a02d9d688a68 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 27 May 2024 21:19:58 -0400 Subject: [PATCH 055/104] Rewrite simple-rlib to rmake --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/lto-smoke/rmake.rs | 7 ++++--- .../{mixing-formats => mixing-deps}/rmake.rs | 0 tests/run-make/simple-rlib/Makefile | 6 ------ tests/run-make/simple-rlib/bar.rs | 1 - tests/run-make/simple-rlib/foo.rs | 5 ----- tests/ui/imports/auxiliary/simple-rlib.rs | 2 ++ tests/ui/imports/simple-rlib-import.rs | 12 ++++++++++++ 8 files changed, 18 insertions(+), 16 deletions(-) rename tests/run-make/{mixing-formats => mixing-deps}/rmake.rs (100%) delete mode 100644 tests/run-make/simple-rlib/Makefile delete mode 100644 tests/run-make/simple-rlib/bar.rs delete mode 100644 tests/run-make/simple-rlib/foo.rs create mode 100644 tests/ui/imports/auxiliary/simple-rlib.rs create mode 100644 tests/ui/imports/simple-rlib-import.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 6d79711e6864..7ad5dec8a849 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -237,7 +237,6 @@ run-make/short-ice/Makefile run-make/silly-file-names/Makefile run-make/simd-ffi/Makefile run-make/simple-dylib/Makefile -run-make/simple-rlib/Makefile run-make/split-debuginfo/Makefile run-make/stable-symbol-names/Makefile run-make/static-dylib-by-default/Makefile diff --git a/tests/run-make/lto-smoke/rmake.rs b/tests/run-make/lto-smoke/rmake.rs index c0f181c10825..692945135cd3 100644 --- a/tests/run-make/lto-smoke/rmake.rs +++ b/tests/run-make/lto-smoke/rmake.rs @@ -1,5 +1,6 @@ // A simple smoke test to check that link time optimization -// (LTO) works as intended, with its various flags turned on. +// (LTO) is accepted by the compiler, and that +// passing its various flags still results in successful compilation. // See https://github.com/rust-lang/rust/issues/10741 //@ ignore-cross-compile @@ -9,7 +10,7 @@ use run_make_support::rustc; fn main() { let lto_flags = ["-Clto", "-Clto=yes", "-Clto=off", "-Clto=thin", "-Clto=fat"]; for flag in lto_flags { - rustc().input(lib.rs).run(); - rustc().input(main.rs).arg(flag).run(); + rustc().input("lib.rs").run(); + rustc().input("main.rs").arg(flag).run(); } } diff --git a/tests/run-make/mixing-formats/rmake.rs b/tests/run-make/mixing-deps/rmake.rs similarity index 100% rename from tests/run-make/mixing-formats/rmake.rs rename to tests/run-make/mixing-deps/rmake.rs diff --git a/tests/run-make/simple-rlib/Makefile b/tests/run-make/simple-rlib/Makefile deleted file mode 100644 index 28df61a15478..000000000000 --- a/tests/run-make/simple-rlib/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# ignore-cross-compile -include ../tools.mk -all: - $(RUSTC) bar.rs --crate-type=rlib - $(RUSTC) foo.rs - $(call RUN,foo) diff --git a/tests/run-make/simple-rlib/bar.rs b/tests/run-make/simple-rlib/bar.rs deleted file mode 100644 index c5c0bc606cd6..000000000000 --- a/tests/run-make/simple-rlib/bar.rs +++ /dev/null @@ -1 +0,0 @@ -pub fn bar() {} diff --git a/tests/run-make/simple-rlib/foo.rs b/tests/run-make/simple-rlib/foo.rs deleted file mode 100644 index 8d68535e3b64..000000000000 --- a/tests/run-make/simple-rlib/foo.rs +++ /dev/null @@ -1,5 +0,0 @@ -extern crate bar; - -fn main() { - bar::bar(); -} diff --git a/tests/ui/imports/auxiliary/simple-rlib.rs b/tests/ui/imports/auxiliary/simple-rlib.rs new file mode 100644 index 000000000000..28a6273840f6 --- /dev/null +++ b/tests/ui/imports/auxiliary/simple-rlib.rs @@ -0,0 +1,2 @@ +#![crate_type = "rlib"] +pub fn bar() {} diff --git a/tests/ui/imports/simple-rlib-import.rs b/tests/ui/imports/simple-rlib-import.rs new file mode 100644 index 000000000000..6eab7ba04cfa --- /dev/null +++ b/tests/ui/imports/simple-rlib-import.rs @@ -0,0 +1,12 @@ +// A simple test, where foo.rs has a dependency +// on the rlib (a static Rust-specific library format) bar.rs. If the test passes, +// rlibs can be built and linked into another file successfully.. + +//@ aux-crate:bar=simple-rlib.rs +//@ run-pass + +extern crate bar; + +fn main() { + bar::bar(); +} From 2bd5050e4f30cd854676d0e733d479e50ea79343 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 28 May 2024 11:58:05 -0400 Subject: [PATCH 056/104] Remove Trace --- compiler/rustc_infer/src/infer/at.rs | 186 ++++++------------ compiler/rustc_infer/src/infer/mod.rs | 15 -- .../rustc_infer/src/infer/relate/combine.rs | 11 ++ 3 files changed, 71 insertions(+), 141 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index aa37aaf22eb4..17e6d6250ad5 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -48,11 +48,6 @@ pub struct At<'a, 'tcx> { pub param_env: ty::ParamEnv<'tcx>, } -pub struct Trace<'a, 'tcx> { - at: At<'a, 'tcx>, - trace: TypeTrace<'tcx>, -} - impl<'tcx> InferCtxt<'tcx> { #[inline] pub fn at<'a>( @@ -109,9 +104,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// call like `foo(x)`, where `foo: fn(i32)`, you might have /// `sup(i32, x)`, since the "expected" type is the type that /// appears in the signature. - /// - /// See [`At::trace`] and [`Trace::sub`] for a version of - /// this method that only requires `T: Relate<'tcx>` pub fn sup( self, define_opaque_types: DefineOpaqueTypes, @@ -121,13 +113,19 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).sup(define_opaque_types, expected, actual) + let mut fields = CombineFields::new( + self.infcx, + ToTrace::to_trace(self.cause, true, expected, actual), + self.param_env, + define_opaque_types, + ); + fields + .sup() + .relate(expected, actual) + .map(|_| InferOk { value: (), obligations: fields.obligations }) } /// Makes `expected <: actual`. - /// - /// See [`At::trace`] and [`Trace::sub`] for a version of - /// this method that only requires `T: Relate<'tcx>` pub fn sub( self, define_opaque_types: DefineOpaqueTypes, @@ -137,13 +135,19 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).sub(define_opaque_types, expected, actual) + let mut fields = CombineFields::new( + self.infcx, + ToTrace::to_trace(self.cause, true, expected, actual), + self.param_env, + define_opaque_types, + ); + fields + .sub() + .relate(expected, actual) + .map(|_| InferOk { value: (), obligations: fields.obligations }) } - /// Makes `expected <: actual`. - /// - /// See [`At::trace`] and [`Trace::eq`] for a version of - /// this method that only requires `T: Relate<'tcx>` + /// Makes `expected == actual`. pub fn eq( self, define_opaque_types: DefineOpaqueTypes, @@ -153,7 +157,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).eq(define_opaque_types, expected, actual) + let mut fields = CombineFields::new( + self.infcx, + ToTrace::to_trace(self.cause, true, expected, actual), + self.param_env, + define_opaque_types, + ); + fields + .equate(StructurallyRelateAliases::No) + .relate(expected, actual) + .map(|_| InferOk { value: (), obligations: fields.obligations }) } /// Equates `expected` and `found` while structurally relating aliases. @@ -167,10 +180,17 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).eq_structurally_relating_aliases( - expected, - actual, - ) + assert!(self.infcx.next_trait_solver()); + let mut fields = CombineFields::new( + self.infcx, + ToTrace::to_trace(self.cause, true, expected, actual), + self.param_env, + DefineOpaqueTypes::Yes, + ); + fields + .equate(StructurallyRelateAliases::Yes) + .relate(expected, actual) + .map(|_| InferOk { value: (), obligations: fields.obligations }) } pub fn relate( @@ -202,9 +222,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// this can result in an error (e.g., if asked to compute LUB of /// u32 and i32), it is meaningful to call one of them the /// "expected type". - /// - /// See [`At::trace`] and [`Trace::lub`] for a version of - /// this method that only requires `T: Relate<'tcx>` pub fn lub( self, define_opaque_types: DefineOpaqueTypes, @@ -214,15 +231,21 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).lub(define_opaque_types, expected, actual) + let mut fields = CombineFields::new( + self.infcx, + ToTrace::to_trace(self.cause, true, expected, actual), + self.param_env, + define_opaque_types, + ); + fields + .lub() + .relate(expected, actual) + .map(|value| InferOk { value, obligations: fields.obligations }) } /// Computes the greatest-lower-bound, or mutual subtype, of two /// values. As with `lub` order doesn't matter, except for error /// cases. - /// - /// See [`At::trace`] and [`Trace::glb`] for a version of - /// this method that only requires `T: Relate<'tcx>` pub fn glb( self, define_opaque_types: DefineOpaqueTypes, @@ -232,105 +255,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).glb(define_opaque_types, expected, actual) - } - - /// Sets the "trace" values that will be used for - /// error-reporting, but doesn't actually perform any operation - /// yet (this is useful when you want to set the trace using - /// distinct values from those you wish to operate upon). - pub fn trace(self, expected: T, actual: T) -> Trace<'a, 'tcx> - where - T: ToTrace<'tcx>, - { - let trace = ToTrace::to_trace(self.cause, true, expected, actual); - Trace { at: self, trace } - } -} - -impl<'a, 'tcx> Trace<'a, 'tcx> { - /// Makes `a <: b`. - #[instrument(skip(self), level = "debug")] - pub fn sub(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, ()> - where - T: Relate<'tcx>, - { - let Trace { at, trace } = self; - let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); - fields - .sub() - .relate(a, b) - .map(move |_| InferOk { value: (), obligations: fields.obligations }) - } - - /// Makes `a :> b`. - #[instrument(skip(self), level = "debug")] - pub fn sup(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, ()> - where - T: Relate<'tcx>, - { - let Trace { at, trace } = self; - let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); - fields - .sup() - .relate(a, b) - .map(move |_| InferOk { value: (), obligations: fields.obligations }) - } - - /// Makes `a == b`. - #[instrument(skip(self), level = "debug")] - pub fn eq(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, ()> - where - T: Relate<'tcx>, - { - let Trace { at, trace } = self; - let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); - fields - .equate(StructurallyRelateAliases::No) - .relate(a, b) - .map(move |_| InferOk { value: (), obligations: fields.obligations }) - } - - /// Equates `a` and `b` while structurally relating aliases. This should only - /// be used inside of the next generation trait solver when relating rigid aliases. - #[instrument(skip(self), level = "debug")] - pub fn eq_structurally_relating_aliases(self, a: T, b: T) -> InferResult<'tcx, ()> - where - T: Relate<'tcx>, - { - let Trace { at, trace } = self; - debug_assert!(at.infcx.next_trait_solver()); - let mut fields = at.infcx.combine_fields(trace, at.param_env, DefineOpaqueTypes::Yes); - fields - .equate(StructurallyRelateAliases::Yes) - .relate(a, b) - .map(move |_| InferOk { value: (), obligations: fields.obligations }) - } - - #[instrument(skip(self), level = "debug")] - pub fn lub(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, T> - where - T: Relate<'tcx>, - { - let Trace { at, trace } = self; - let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); - fields - .lub() - .relate(a, b) - .map(move |t| InferOk { value: t, obligations: fields.obligations }) - } - - #[instrument(skip(self), level = "debug")] - pub fn glb(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, T> - where - T: Relate<'tcx>, - { - let Trace { at, trace } = self; - let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); + let mut fields = CombineFields::new( + self.infcx, + ToTrace::to_trace(self.cause, true, expected, actual), + self.param_env, + define_opaque_types, + ); fields .glb() - .relate(a, b) - .map(move |t| InferOk { value: t, obligations: fields.obligations }) + .relate(expected, actual) + .map(|value| InferOk { value, obligations: fields.obligations }) } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6f603d9b612e..c8bb6cf5f9b4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -836,21 +836,6 @@ impl<'tcx> InferCtxt<'tcx> { .collect() } - fn combine_fields<'a>( - &'a self, - trace: TypeTrace<'tcx>, - param_env: ty::ParamEnv<'tcx>, - define_opaque_types: DefineOpaqueTypes, - ) -> CombineFields<'a, 'tcx> { - CombineFields { - infcx: self, - trace, - param_env, - obligations: PredicateObligations::new(), - define_opaque_types, - } - } - pub fn can_sub(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool where T: at::ToTrace<'tcx>, diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 7e7d4f43c7cc..6b41e4506846 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -42,6 +42,17 @@ pub struct CombineFields<'infcx, 'tcx> { pub define_opaque_types: DefineOpaqueTypes, } +impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { + pub fn new( + infcx: &'infcx InferCtxt<'tcx>, + trace: TypeTrace<'tcx>, + param_env: ty::ParamEnv<'tcx>, + define_opaque_types: DefineOpaqueTypes, + ) -> Self { + Self { infcx, trace, param_env, define_opaque_types, obligations: vec![] } + } +} + impl<'tcx> InferCtxt<'tcx> { pub fn super_combine_tys( &self, From 459ce3f6bb5d8827835ed9b9f916eb189420b38a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 21 Apr 2024 16:11:01 -0700 Subject: [PATCH 057/104] Add an intrinsic for `ptr::metadata` --- compiler/rustc_codegen_cranelift/src/base.rs | 38 +++++++---- .../rustc_codegen_cranelift/src/constant.rs | 2 +- .../src/value_and_place.rs | 8 +++ compiler/rustc_codegen_ssa/src/mir/operand.rs | 5 ++ compiler/rustc_codegen_ssa/src/mir/place.rs | 5 ++ compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 34 +++++++--- .../rustc_const_eval/src/interpret/cast.rs | 2 +- .../src/interpret/operator.rs | 28 +++++++-- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 + compiler/rustc_middle/src/mir/syntax.rs | 7 +++ compiler/rustc_middle/src/mir/tcx.rs | 26 +++++++- compiler/rustc_middle/src/ty/print/pretty.rs | 2 + .../src/lower_intrinsics.rs | 17 +++++ .../rustc_mir_transform/src/promote_consts.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 10 +++ .../rustc_smir/src/rustc_internal/internal.rs | 14 ++++- compiler/rustc_smir/src/rustc_smir/context.rs | 10 ++- .../rustc_smir/src/rustc_smir/convert/mir.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_ty_utils/src/consts.rs | 2 +- compiler/stable_mir/src/compiler_interface.rs | 5 +- compiler/stable_mir/src/mir/body.rs | 14 ++++- library/core/src/intrinsics.rs | 15 +++++ library/core/src/ptr/metadata.rs | 21 +++++-- library/core/tests/ptr.rs | 12 ++++ tests/codegen/intrinsics/ptr_metadata.rs | 36 +++++++++++ ..._metadata.LowerIntrinsics.panic-abort.diff | 63 +++++++++++++++++++ ...metadata.LowerIntrinsics.panic-unwind.diff | 63 +++++++++++++++++++ tests/mir-opt/lower_intrinsics.rs | 9 +++ ...e_add_fat.PreCodegen.after.panic-abort.mir | 10 +-- ..._add_fat.PreCodegen.after.panic-unwind.mir | 10 +-- 31 files changed, 422 insertions(+), 52 deletions(-) create mode 100644 tests/codegen/intrinsics/ptr_metadata.rs create mode 100644 tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-abort.diff create mode 100644 tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-unwind.diff diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 8d778f736d67..de1cd9c75c16 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -619,22 +619,34 @@ fn codegen_stmt<'tcx>( Rvalue::UnaryOp(un_op, ref operand) => { let operand = codegen_operand(fx, operand); let layout = operand.layout(); - let val = operand.load_scalar(fx); let res = match un_op { - UnOp::Not => match layout.ty.kind() { - ty::Bool => { - let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0); - CValue::by_val(res, layout) + UnOp::Not => { + let val = operand.load_scalar(fx); + match layout.ty.kind() { + ty::Bool => { + let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0); + CValue::by_val(res, layout) + } + ty::Uint(_) | ty::Int(_) => { + CValue::by_val(fx.bcx.ins().bnot(val), layout) + } + _ => unreachable!("un op Not for {:?}", layout.ty), } - ty::Uint(_) | ty::Int(_) => { - CValue::by_val(fx.bcx.ins().bnot(val), layout) + } + UnOp::Neg => { + let val = operand.load_scalar(fx); + match layout.ty.kind() { + ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout), + ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout), + _ => unreachable!("un op Neg for {:?}", layout.ty), } - _ => unreachable!("un op Not for {:?}", layout.ty), - }, - UnOp::Neg => match layout.ty.kind() { - ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout), - ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout), - _ => unreachable!("un op Neg for {:?}", layout.ty), + } + UnOp::PtrMetadata => match layout.abi { + Abi::Scalar(_) => CValue::zst(dest_layout), + Abi::ScalarPair(_, _) => { + CValue::by_val(operand.load_scalar_pair(fx).1, dest_layout) + } + _ => bug!("Unexpected `PtrToMetadata` operand: {operand:?}"), }, }; lval.write_cvalue(fx, res); diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 64e83e43d327..ba98f2e772cb 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -100,7 +100,7 @@ pub(crate) fn codegen_const_value<'tcx>( assert!(layout.is_sized(), "unsized const value"); if layout.is_zst() { - return CValue::by_ref(crate::Pointer::dangling(layout.align.pref), layout); + return CValue::zst(layout); } match const_val { diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 4146137c2263..512a96450a4b 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -95,6 +95,14 @@ impl<'tcx> CValue<'tcx> { CValue(CValueInner::ByValPair(value, extra), layout) } + /// Create an instance of a ZST + /// + /// The is represented by a dangling pointer of suitable alignment. + pub(crate) fn zst(layout: TyAndLayout<'tcx>) -> CValue<'tcx> { + assert!(layout.is_zst()); + CValue::by_ref(crate::Pointer::dangling(layout.align.pref), layout) + } + pub(crate) fn layout(&self) -> TyAndLayout<'tcx> { self.1 } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 5b2f9a3be279..cc0e91396506 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -565,6 +565,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { for elem in place_ref.projection.iter() { match elem { mir::ProjectionElem::Field(ref f, _) => { + debug_assert!( + !o.layout.ty.is_any_ptr(), + "Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \ + but tried to access field {f:?} of pointer {o:?}", + ); o = o.extract_field(bx, f.index()); } mir::ProjectionElem::Index(_) diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 7c3569a9dd2e..449fd9ae0db9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -480,6 +480,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_base = match *elem { mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()), mir::ProjectionElem::Field(ref field, _) => { + debug_assert!( + !cg_base.layout.ty.is_any_ptr(), + "Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \ + but tried to access field {field:?} of pointer {cg_base:?}", + ); cg_base.project_field(bx, field.index()) } mir::ProjectionElem::OpaqueCast(ty) => { diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 4dd80d34ea70..c23867be3a10 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -623,19 +623,36 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::UnaryOp(op, ref operand) => { let operand = self.codegen_operand(bx, operand); - let lloperand = operand.immediate(); let is_float = operand.layout.ty.is_floating_point(); - let llval = match op { - mir::UnOp::Not => bx.not(lloperand), + let (val, layout) = match op { + mir::UnOp::Not => { + let llval = bx.not(operand.immediate()); + (OperandValue::Immediate(llval), operand.layout) + } mir::UnOp::Neg => { - if is_float { - bx.fneg(lloperand) + let llval = if is_float { + bx.fneg(operand.immediate()) } else { - bx.neg(lloperand) + bx.neg(operand.immediate()) + }; + (OperandValue::Immediate(llval), operand.layout) + } + mir::UnOp::PtrMetadata => { + debug_assert!(operand.layout.ty.is_unsafe_ptr()); + let (_, meta) = operand.val.pointer_parts(); + assert_eq!(operand.layout.fields.count() > 1, meta.is_some()); + if let Some(meta) = meta { + (OperandValue::Immediate(meta), operand.layout.field(self.cx, 1)) + } else { + (OperandValue::ZeroSized, bx.cx().layout_of(bx.tcx().types.unit)) } } }; - OperandRef { val: OperandValue::Immediate(llval), layout: operand.layout } + debug_assert!( + val.is_expected_variant_for_type(self.cx, layout), + "Made wrong variant {val:?} for type {layout:?}", + ); + OperandRef { val, layout } } mir::Rvalue::Discriminant(ref place) => { @@ -718,8 +735,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let values = op.val.immediates_or_place().left_or_else(|p| { bug!("Field {field_idx:?} is {p:?} making {layout:?}"); }); - inputs.extend(values); let scalars = self.value_kind(op.layout).scalars().unwrap(); + debug_assert_eq!(values.len(), scalars.len()); + inputs.extend(values); input_scalars.extend(scalars); } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 737a70f335d0..19414c72c6a4 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -207,7 +207,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert!(cast_to.ty.is_unsafe_ptr()); // Handle casting any ptr to raw ptr (might be a fat ptr). if cast_to.size == src.layout.size { - // Thin or fat pointer that just hast the ptr kind of target type changed. + // Thin or fat pointer that just has the ptr kind of target type changed. return Ok(ImmTy::from_immediate(**src, cast_to)); } else { // Casting the metadata away from a fat ptr. diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index d23f0c4d45b0..6d005dfcd864 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -9,7 +9,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::symbol::sym; use tracing::trace; -use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine}; +use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine, MemPlaceMeta}; impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn three_way_compare(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> { @@ -415,11 +415,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { use rustc_middle::mir::UnOp::*; let layout = val.layout; - let val = val.to_scalar(); trace!("Running unary op {:?}: {:?} ({})", un_op, val, layout.ty); match layout.ty.kind() { ty::Bool => { + let val = val.to_scalar(); let val = val.to_bool()?; let res = match un_op { Not => !val, @@ -428,6 +428,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(ImmTy::from_bool(res, *self.tcx)) } ty::Float(fty) => { + let val = val.to_scalar(); // No NaN adjustment here, `-` is a bitwise operation! let res = match (un_op, fty) { (Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?), @@ -436,8 +437,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; Ok(ImmTy::from_scalar(res, layout)) } - _ => { - assert!(layout.ty.is_integral()); + _ if layout.ty.is_integral() => { + let val = val.to_scalar(); let val = val.to_bits(layout.size)?; let res = match un_op { Not => self.truncate(!val, layout), // bitwise negation, then truncate @@ -450,9 +451,28 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Truncate to target type. self.truncate(res, layout) } + _ => span_bug!(self.cur_span(), "Invalid integer op {:?}", un_op), }; Ok(ImmTy::from_uint(res, layout)) } + ty::RawPtr(..) => { + assert_eq!(un_op, PtrMetadata); + let (_, meta) = val.to_scalar_and_meta(); + Ok(match meta { + MemPlaceMeta::Meta(scalar) => { + let ty = un_op.ty(*self.tcx, val.layout.ty); + let layout = self.layout_of(ty)?; + ImmTy::from_scalar(scalar, layout) + } + MemPlaceMeta::None => { + let unit_layout = self.layout_of(self.tcx.types.unit)?; + ImmTy::uninit(unit_layout) + } + }) + } + _ => { + bug!("Unexpected unary op argument {val:?}") + } } } } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 8506b8d75f95..f7989aeab41b 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -130,6 +130,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::is_val_statically_known | sym::ptr_mask | sym::aggregate_raw_ptr + | sym::ptr_metadata | sym::ub_checks | sym::fadd_algebraic | sym::fsub_algebraic @@ -576,6 +577,7 @@ pub fn check_intrinsic_type( // This type check is not particularly useful, but the `where` bounds // on the definition in `core` do the heavy lifting for checking it. sym::aggregate_raw_ptr => (3, 1, vec![param(1), param(2)], param(0)), + sym::ptr_metadata => (2, 1, vec![Ty::new_imm_ptr(tcx, param(0))], param(1)), sym::ub_checks => (0, 1, Vec::new(), tcx.types.bool), diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 2d4852114332..ebe77a1abfd8 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1434,6 +1434,13 @@ pub enum UnOp { Not, /// The `-` operator for negation Neg, + /// Get the metadata `M` from a `*const/mut impl Pointee`. + /// + /// For example, this will give a `()` from `*const i32`, a `usize` from + /// `*mut [u8]`, or a pointer to a vtable from a `*const dyn Foo`. + /// + /// Allowed only in [`MirPhase::Runtime`]; earlier it's an intrinsic. + PtrMetadata, } #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index a122cffdb876..126387db1d9c 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -180,7 +180,10 @@ impl<'tcx> Rvalue<'tcx> { let rhs_ty = rhs.ty(local_decls, tcx); op.ty(tcx, lhs_ty, rhs_ty) } - Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx), + Rvalue::UnaryOp(op, ref operand) => { + let arg_ty = operand.ty(local_decls, tcx); + op.ty(tcx, arg_ty) + } Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { tcx.types.usize @@ -282,6 +285,27 @@ impl<'tcx> BinOp { } } +impl<'tcx> UnOp { + pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> { + match self { + UnOp::Not | UnOp::Neg => arg_ty, + UnOp::PtrMetadata => { + let pointee_ty = arg_ty + .builtin_deref(true) + .unwrap_or_else(|| bug!("PtrMetadata of non-dereferenceable ty {arg_ty:?}")); + if pointee_ty.is_trivially_sized(tcx) { + tcx.types.unit + } else { + let Some(metadata_def_id) = tcx.lang_items().metadata_type() else { + bug!("No metadata_type lang item while looking at {arg_ty:?}") + }; + Ty::new_projection(tcx, metadata_def_id, [pointee_ty]) + } + } + } + } +} + impl BorrowKind { pub fn to_mutbl_lossy(self) -> hir::Mutability { match self { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3c0f2578284a..83790db99260 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1579,8 +1579,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let formatted_op = match op { UnOp::Not => "!", UnOp::Neg => "-", + UnOp::PtrMetadata => "PtrMetadata", }; let parenthesized = match ct.kind() { + _ if op == UnOp::PtrMetadata => true, ty::ConstKind::Expr(Expr::UnOp(c_op, ..)) => c_op != op, ty::ConstKind::Expr(_) => true, _ => false, diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 221301b2ceb0..3ffc447217d7 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -316,6 +316,23 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } + sym::ptr_metadata => { + let Ok([ptr]) = <[_; 1]>::try_from(std::mem::take(args)) else { + span_bug!( + terminator.source_info.span, + "Wrong number of arguments for ptr_metadata intrinsic", + ); + }; + let target = target.unwrap(); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::UnaryOp(UnOp::PtrMetadata, ptr.node), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; + } _ => {} } } diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index e37f90ae7f40..7ec59cc983f5 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -464,7 +464,7 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::UnaryOp(op, operand) => { match op { // These operations can never fail. - UnOp::Neg | UnOp::Not => {} + UnOp::Neg | UnOp::Not | UnOp::PtrMetadata => {} } self.validate_operand(operand)?; diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 6df32169eecb..d9166d2fcd01 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1109,6 +1109,16 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ty::Int(..) | ty::Uint(..) | ty::Bool ); } + UnOp::PtrMetadata => { + if !matches!(self.mir_phase, MirPhase::Runtime(_)) { + // It would probably be fine to support this in earlier phases, + // but at the time of writing it's only ever introduced from intrinsic lowering, + // so earlier things can just `bug!` on it. + self.fail(location, "PtrMetadata should be in runtime MIR only"); + } + + check_kinds!(a, "Cannot PtrMetadata non-pointer type {:?}", ty::RawPtr(..)); + } } } Rvalue::ShallowInitBox(operand, _) => { diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 6b73c1ebd1ca..6ec710f97d16 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -10,7 +10,7 @@ use rustc_span::Symbol; use stable_mir::abi::Layout; use stable_mir::mir::alloc::AllocId; use stable_mir::mir::mono::{Instance, MonoItem, StaticDef}; -use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, Safety}; +use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, Safety, UnOp}; use stable_mir::ty::{ Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, @@ -582,6 +582,18 @@ impl RustcInternal for BinOp { } } +impl RustcInternal for UnOp { + type T<'tcx> = rustc_middle::mir::UnOp; + + fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { + match self { + UnOp::Not => rustc_middle::mir::UnOp::Not, + UnOp::Neg => rustc_middle::mir::UnOp::Neg, + UnOp::PtrMetadata => rustc_middle::mir::UnOp::PtrMetadata, + } + } +} + impl RustcInternal for &T where T: RustcInternal, diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 7afe46f2cbe1..fa7b2a30ba6c 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -19,7 +19,7 @@ use stable_mir::abi::{FnAbi, Layout, LayoutShape}; use stable_mir::compiler_interface::Context; use stable_mir::mir::alloc::GlobalAlloc; use stable_mir::mir::mono::{InstanceDef, StaticDef}; -use stable_mir::mir::{BinOp, Body, Place}; +use stable_mir::mir::{BinOp, Body, Place, UnOp}; use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::ty::{ AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, @@ -700,6 +700,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let ty = bin_op.internal(&mut *tables, tcx).ty(tcx, rhs_internal, lhs_internal); ty.stable(&mut *tables) } + + fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let arg_internal = arg.internal(&mut *tables, tcx); + let ty = un_op.internal(&mut *tables, tcx).ty(tcx, arg_internal); + ty.stable(&mut *tables) + } } pub struct TablesWrapper<'tcx>(pub RefCell>); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index d89caabab3e1..a1a5c09ef0af 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -526,6 +526,7 @@ impl<'tcx> Stable<'tcx> for mir::UnOp { match self { UnOp::Not => stable_mir::mir::UnOp::Not, UnOp::Neg => stable_mir::mir::UnOp::Neg, + UnOp::PtrMetadata => stable_mir::mir::UnOp::PtrMetadata, } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ace4dff46aa0..b025fe5454c2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1433,6 +1433,7 @@ symbols! { ptr_guaranteed_cmp, ptr_is_null, ptr_mask, + ptr_metadata, ptr_null, ptr_null_mut, ptr_offset_from, diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 58447f6d6a31..e9112d232cbd 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -94,7 +94,7 @@ fn check_binop(op: mir::BinOp) -> bool { fn check_unop(op: mir::UnOp) -> bool { use mir::UnOp::*; match op { - Not | Neg => true, + Not | Neg | PtrMetadata => true, } } diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 4dd64228bbad..858ce5301d84 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -8,7 +8,7 @@ use std::cell::Cell; use crate::abi::{FnAbi, Layout, LayoutShape}; use crate::mir::alloc::{AllocId, GlobalAlloc}; use crate::mir::mono::{Instance, InstanceDef, StaticDef}; -use crate::mir::{BinOp, Body, Place}; +use crate::mir::{BinOp, Body, Place, UnOp}; use crate::target::MachineInfo; use crate::ty::{ AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, @@ -226,6 +226,9 @@ pub trait Context { /// Get the resulting type of binary operation. fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty; + + /// Get the resulting type of unary operation. + fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty; } // A thread local variable that stores a pointer to the tables mapping between TyCtxt diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index a1432acf93cb..4c779ae96a81 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -346,6 +346,15 @@ impl BinOp { pub enum UnOp { Not, Neg, + PtrMetadata, +} + +impl UnOp { + /// Return the type of this operation for the given input Ty. + /// This function does not perform type checking, and it currently doesn't handle SIMD. + pub fn ty(&self, arg_ty: Ty) -> Ty { + with(|ctx| ctx.unop_ty(*self, arg_ty)) + } } #[derive(Clone, Debug, Eq, PartialEq)] @@ -580,7 +589,10 @@ impl Rvalue { let ty = op.ty(lhs_ty, rhs_ty); Ok(Ty::new_tuple(&[ty, Ty::bool_ty()])) } - Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, operand) => operand.ty(locals), + Rvalue::UnaryOp(op, operand) => { + let arg_ty = operand.ty(locals)?; + Ok(op.ty(arg_ty)) + } Rvalue::Discriminant(place) => { let place_ty = place.ty(locals)?; place_ty diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 5a2a4c5ae6eb..89e0b6709951 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2821,6 +2821,21 @@ impl AggregateRawPtr<*mut T> for *mut P { type Metadata =

::Metadata; } +/// Lowers in MIR to `Rvalue::UnaryOp` with `UnOp::PtrMetadata`. +/// +/// This is used to implement functions like `ptr::metadata`. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[cfg(not(bootstrap))] +pub const fn ptr_metadata + ?Sized, M>(_ptr: *const P) -> M { + // To implement a fallback we'd have to assume the layout of the pointer, + // but the whole point of this intrinsic is that we shouldn't do that. + unreachable!() +} + // Some functions are defined here because they accidentally got made // available in this module on stable. See . // (`transmute` also falls into this category, but it cannot be wrapped due to the diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index e501970b580d..84287ec3f514 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -3,6 +3,8 @@ use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::intrinsics::aggregate_raw_ptr; +#[cfg(not(bootstrap))] +use crate::intrinsics::ptr_metadata; use crate::marker::Freeze; /// Provides the pointer metadata type of any pointed-to type. @@ -94,10 +96,17 @@ pub trait Thin = Pointee; #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] pub const fn metadata(ptr: *const T) -> ::Metadata { - // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T - // and PtrComponents have the same memory layouts. Only std can make this - // guarantee. - unsafe { PtrRepr { const_ptr: ptr }.components.metadata } + #[cfg(bootstrap)] + { + // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T + // and PtrComponents have the same memory layouts. Only std can make this + // guarantee. + unsafe { PtrRepr { const_ptr: ptr }.components.metadata } + } + #[cfg(not(bootstrap))] + { + ptr_metadata(ptr) + } } /// Forms a (possibly-wide) raw pointer from a data pointer and metadata. @@ -132,6 +141,7 @@ pub const fn from_raw_parts_mut( } #[repr(C)] +#[cfg(bootstrap)] union PtrRepr { const_ptr: *const T, mut_ptr: *mut T, @@ -139,15 +149,18 @@ union PtrRepr { } #[repr(C)] +#[cfg(bootstrap)] struct PtrComponents { data_pointer: *const (), metadata: ::Metadata, } // Manual impl needed to avoid `T: Copy` bound. +#[cfg(bootstrap)] impl Copy for PtrComponents {} // Manual impl needed to avoid `T: Clone` bound. +#[cfg(bootstrap)] impl Clone for PtrComponents { fn clone(&self) -> Self { *self diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 7b55c2bf8a81..e8d05c2483de 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -1171,3 +1171,15 @@ fn test_ptr_from_raw_parts_in_const() { assert_eq!(EMPTY_SLICE_PTR.addr(), 123); assert_eq!(EMPTY_SLICE_PTR.len(), 456); } + +#[test] +fn test_ptr_metadata_in_const() { + use std::fmt::Debug; + + const ARRAY_META: () = std::ptr::metadata::<[u16; 3]>(&[1, 2, 3]); + const SLICE_META: usize = std::ptr::metadata::<[u16]>(&[1, 2, 3]); + const DYN_META: DynMetadata = std::ptr::metadata::(&[0_u8; 42]); + assert_eq!(ARRAY_META, ()); + assert_eq!(SLICE_META, 3); + assert_eq!(DYN_META.size_of(), 42); +} diff --git a/tests/codegen/intrinsics/ptr_metadata.rs b/tests/codegen/intrinsics/ptr_metadata.rs new file mode 100644 index 000000000000..f4bf5a1f5f17 --- /dev/null +++ b/tests/codegen/intrinsics/ptr_metadata.rs @@ -0,0 +1,36 @@ +//@ compile-flags: -O -C no-prepopulate-passes -Z inline-mir +//@ only-64bit (so I don't need to worry about usize) + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +use std::intrinsics::ptr_metadata; + +// CHECK-LABEL: @thin_metadata( +#[no_mangle] +pub fn thin_metadata(p: *const ()) { + // CHECK: start + // CHECK-NEXT: ret void + ptr_metadata(p) +} + +// CHECK-LABEL: @slice_metadata( +#[no_mangle] +pub fn slice_metadata(p: *const [u8]) -> usize { + // CHECK: start + // CHECK-NEXT: ret i64 %p.1 + ptr_metadata(p) +} + +// CHECK-LABEL: @dyn_byte_offset( +#[no_mangle] +pub unsafe fn dyn_byte_offset( + p: *const dyn std::fmt::Debug, + n: usize, +) -> *const dyn std::fmt::Debug { + // CHECK: %[[Q:.+]] = getelementptr inbounds i8, ptr %p.0, i64 %n + // CHECK: %[[TEMP1:.+]] = insertvalue { ptr, ptr } poison, ptr %[[Q]], 0 + // CHECK: %[[TEMP2:.+]] = insertvalue { ptr, ptr } %[[TEMP1]], ptr %p.1, 1 + // CHECK: ret { ptr, ptr } %[[TEMP2]] + p.byte_add(n) +} diff --git a/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-abort.diff new file mode 100644 index 000000000000..d256058c05ee --- /dev/null +++ b/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-abort.diff @@ -0,0 +1,63 @@ +- // MIR for `get_metadata` before LowerIntrinsics ++ // MIR for `get_metadata` after LowerIntrinsics + + fn get_metadata(_1: *const i32, _2: *const [u8], _3: *const dyn Debug) -> () { + debug a => _1; + debug b => _2; + debug c => _3; + let mut _0: (); + let _4: (); + let mut _5: *const i32; + let mut _7: *const [u8]; + let mut _9: *const dyn std::fmt::Debug; + scope 1 { + debug _unit => _4; + let _6: usize; + scope 2 { + debug _usize => _6; + let _8: std::ptr::DynMetadata; + scope 3 { + debug _vtable => _8; + } + } + } + + bb0: { + StorageLive(_4); + StorageLive(_5); + _5 = _1; +- _4 = ptr_metadata::(move _5) -> [return: bb1, unwind unreachable]; ++ _4 = PtrMetadata(move _5); ++ goto -> bb1; + } + + bb1: { + StorageDead(_5); + StorageLive(_6); + StorageLive(_7); + _7 = _2; +- _6 = ptr_metadata::<[u8], usize>(move _7) -> [return: bb2, unwind unreachable]; ++ _6 = PtrMetadata(move _7); ++ goto -> bb2; + } + + bb2: { + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _9 = _3; +- _8 = ptr_metadata::>(move _9) -> [return: bb3, unwind unreachable]; ++ _8 = PtrMetadata(move _9); ++ goto -> bb3; + } + + bb3: { + StorageDead(_9); + _0 = const (); + StorageDead(_8); + StorageDead(_6); + StorageDead(_4); + return; + } + } + diff --git a/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-unwind.diff new file mode 100644 index 000000000000..d256058c05ee --- /dev/null +++ b/tests/mir-opt/lower_intrinsics.get_metadata.LowerIntrinsics.panic-unwind.diff @@ -0,0 +1,63 @@ +- // MIR for `get_metadata` before LowerIntrinsics ++ // MIR for `get_metadata` after LowerIntrinsics + + fn get_metadata(_1: *const i32, _2: *const [u8], _3: *const dyn Debug) -> () { + debug a => _1; + debug b => _2; + debug c => _3; + let mut _0: (); + let _4: (); + let mut _5: *const i32; + let mut _7: *const [u8]; + let mut _9: *const dyn std::fmt::Debug; + scope 1 { + debug _unit => _4; + let _6: usize; + scope 2 { + debug _usize => _6; + let _8: std::ptr::DynMetadata; + scope 3 { + debug _vtable => _8; + } + } + } + + bb0: { + StorageLive(_4); + StorageLive(_5); + _5 = _1; +- _4 = ptr_metadata::(move _5) -> [return: bb1, unwind unreachable]; ++ _4 = PtrMetadata(move _5); ++ goto -> bb1; + } + + bb1: { + StorageDead(_5); + StorageLive(_6); + StorageLive(_7); + _7 = _2; +- _6 = ptr_metadata::<[u8], usize>(move _7) -> [return: bb2, unwind unreachable]; ++ _6 = PtrMetadata(move _7); ++ goto -> bb2; + } + + bb2: { + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _9 = _3; +- _8 = ptr_metadata::>(move _9) -> [return: bb3, unwind unreachable]; ++ _8 = PtrMetadata(move _9); ++ goto -> bb3; + } + + bb3: { + StorageDead(_9); + _0 = const (); + StorageDead(_8); + StorageDead(_6); + StorageDead(_4); + return; + } + } + diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs index 180bfd0a9246..2569f4f4de5d 100644 --- a/tests/mir-opt/lower_intrinsics.rs +++ b/tests/mir-opt/lower_intrinsics.rs @@ -258,3 +258,12 @@ pub fn make_pointers(a: *const u8, b: *mut (), n: usize) { let _slice_const: *const [u16] = aggregate_raw_ptr(a, n); let _slice_mut: *mut [u64] = aggregate_raw_ptr(b, n); } + +// EMIT_MIR lower_intrinsics.get_metadata.LowerIntrinsics.diff +pub fn get_metadata(a: *const i32, b: *const [u8], c: *const dyn std::fmt::Debug) { + use std::intrinsics::ptr_metadata; + + let _unit = ptr_metadata(a); + let _usize = ptr_metadata(b); + let _vtable = ptr_metadata(c); +} diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir index db0c84bd560f..ea4ed2713056 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir @@ -13,9 +13,8 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { } scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { let mut _5: *const (); - let mut _7: usize; + let mut _6: usize; scope 5 (inlined std::ptr::metadata::<[u32]>) { - let mut _6: std::ptr::metadata::PtrRepr<[u32]>; } scope 6 (inlined std::ptr::from_raw_parts::<[u32]>) { } @@ -30,13 +29,10 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { StorageDead(_3); StorageLive(_5); _5 = _4 as *const () (PtrToPtr); - StorageLive(_7); StorageLive(_6); - _6 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: _1 }; - _7 = ((_6.2: std::ptr::metadata::PtrComponents<[u32]>).1: usize); + _6 = PtrMetadata(_1); + _0 = *const [u32] from (_5, _6); StorageDead(_6); - _0 = *const [u32] from (_5, _7); - StorageDead(_7); StorageDead(_5); StorageDead(_4); return; diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir index db0c84bd560f..ea4ed2713056 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir @@ -13,9 +13,8 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { } scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { let mut _5: *const (); - let mut _7: usize; + let mut _6: usize; scope 5 (inlined std::ptr::metadata::<[u32]>) { - let mut _6: std::ptr::metadata::PtrRepr<[u32]>; } scope 6 (inlined std::ptr::from_raw_parts::<[u32]>) { } @@ -30,13 +29,10 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { StorageDead(_3); StorageLive(_5); _5 = _4 as *const () (PtrToPtr); - StorageLive(_7); StorageLive(_6); - _6 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: _1 }; - _7 = ((_6.2: std::ptr::metadata::PtrComponents<[u32]>).1: usize); + _6 = PtrMetadata(_1); + _0 = *const [u32] from (_5, _6); StorageDead(_6); - _0 = *const [u32] from (_5, _7); - StorageDead(_7); StorageDead(_5); StorageDead(_4); return; From 7150839552b56eb116e1edc7ebafdc949f92ac7e Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 25 May 2024 02:11:45 -0700 Subject: [PATCH 058/104] Add custom mir support for `PtrMetadata` --- .../src/build/custom/parse/instruction.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics/mir.rs | 4 ++++ .../building/custom/operators.g.runtime.after.mir | 13 +++++++++++++ tests/mir-opt/building/custom/operators.rs | 10 ++++++++++ 5 files changed, 29 insertions(+) create mode 100644 tests/mir-opt/building/custom/operators.g.runtime.after.mir diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 6f8cfc3af447..de748b9c85d1 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -212,6 +212,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset)))) }, @call(mir_len, args) => Ok(Rvalue::Len(self.parse_place(args[0])?)), + @call(mir_ptr_metadata, args) => Ok(Rvalue::UnaryOp(UnOp::PtrMetadata, self.parse_operand(args[0])?)), @call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)), ExprKind::Borrow { borrow_kind, arg } => Ok( Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b025fe5454c2..90da220b3f54 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1179,6 +1179,7 @@ symbols! { mir_make_place, mir_move, mir_offset, + mir_ptr_metadata, mir_retag, mir_return, mir_return_to, diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 02665b2676cc..fa5bb28adff9 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -360,6 +360,10 @@ define!("mir_assume", fn Assume(operand: bool)); define!("mir_deinit", fn Deinit(place: T)); define!("mir_checked", fn Checked(binop: T) -> (T, bool)); define!("mir_len", fn Len(place: T) -> usize); +define!( + "mir_ptr_metadata", + fn PtrMetadata(place: *const P) ->

::Metadata +); define!("mir_copy_for_deref", fn CopyForDeref(place: T) -> T); define!("mir_retag", fn Retag(place: T)); define!("mir_move", fn Move(place: T) -> T); diff --git a/tests/mir-opt/building/custom/operators.g.runtime.after.mir b/tests/mir-opt/building/custom/operators.g.runtime.after.mir new file mode 100644 index 000000000000..a0ad7d0f93f4 --- /dev/null +++ b/tests/mir-opt/building/custom/operators.g.runtime.after.mir @@ -0,0 +1,13 @@ +// MIR for `g` after runtime + +fn g(_1: *const i32, _2: *const [i32]) -> () { + let mut _0: (); + let mut _3: (); + let mut _4: usize; + + bb0: { + _3 = PtrMetadata(_1); + _4 = PtrMetadata(_2); + return; + } +} diff --git a/tests/mir-opt/building/custom/operators.rs b/tests/mir-opt/building/custom/operators.rs index eb97bcc73b7e..ff0e8dcbb415 100644 --- a/tests/mir-opt/building/custom/operators.rs +++ b/tests/mir-opt/building/custom/operators.rs @@ -30,3 +30,13 @@ pub fn f(a: i32, b: bool) -> i32 { Return() }) } + +// EMIT_MIR operators.g.runtime.after.mir +#[custom_mir(dialect = "runtime")] +pub fn g(p: *const i32, q: *const [i32]) { + mir!({ + let a = PtrMetadata(p); + let b = PtrMetadata(q); + Return() + }) +} From 5a8c1f372a009f11f7bfd0319dc1293ed40b5f22 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 26 May 2024 14:20:32 -0700 Subject: [PATCH 059/104] Add Miri tests for `PtrMetadata` UB --- .../ptr_metadata_uninit_slice_data.rs | 22 ++++++++++++ .../ptr_metadata_uninit_slice_data.stderr | 20 +++++++++++ .../ptr_metadata_uninit_slice_len.rs | 22 ++++++++++++ .../ptr_metadata_uninit_slice_len.stderr | 35 +++++++++++++++++++ .../intrinsics/ptr_metadata_uninit_thin.rs | 23 ++++++++++++ .../ptr_metadata_uninit_thin.stderr | 20 +++++++++++ 6 files changed, 142 insertions(+) create mode 100644 src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs create mode 100644 src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr create mode 100644 src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs create mode 100644 src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr create mode 100644 src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs create mode 100644 src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs new file mode 100644 index 000000000000..ff23f1e729e8 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs @@ -0,0 +1,22 @@ +//@compile-flags: -Zmiri-disable-validation +#![feature(core_intrinsics, custom_mir)] +use std::intrinsics::mir::*; + +// This disables validation and uses custom MIR hit exactly the UB in the intrinsic, +// rather than getting UB from the typed load or parameter passing. + +#[custom_mir(dialect = "runtime")] +pub unsafe fn deref_meta(p: *const *const [i32]) -> usize { + mir!({ + RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data + Return() + }) +} + +fn main() { + let mut p = std::mem::MaybeUninit::<*const [i32]>::uninit(); + unsafe { + (*p.as_mut_ptr().cast::<[usize; 2]>())[1] = 4; + let _meta = deref_meta(p.as_ptr().cast()); + } +} diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr new file mode 100644 index 000000000000..61e1541d1ee4 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/ptr_metadata_uninit_slice_data.rs:LL:CC + | +LL | RET = PtrMetadata(*p); + | ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `deref_meta` at $DIR/ptr_metadata_uninit_slice_data.rs:LL:CC +note: inside `main` + --> $DIR/ptr_metadata_uninit_slice_data.rs:LL:CC + | +LL | let _meta = deref_meta(p.as_ptr().cast()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs new file mode 100644 index 000000000000..65f74c0acdd6 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs @@ -0,0 +1,22 @@ +//@compile-flags: -Zmiri-disable-validation +#![feature(core_intrinsics, custom_mir)] +use std::intrinsics::mir::*; + +// This disables validation and uses custom MIR hit exactly the UB in the intrinsic, +// rather than getting UB from the typed load or parameter passing. + +#[custom_mir(dialect = "runtime")] +pub unsafe fn deref_meta(p: *const *const [i32]) -> usize { + mir!({ + RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data + Return() + }) +} + +fn main() { + let mut p = std::mem::MaybeUninit::<*const [i32]>::uninit(); + unsafe { + (*p.as_mut_ptr().cast::<[*const i32; 2]>())[0] = 4 as *const i32; + let _meta = deref_meta(p.as_ptr().cast()); + } +} diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr new file mode 100644 index 000000000000..de559263a326 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr @@ -0,0 +1,35 @@ +warning: integer-to-pointer cast + --> $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC + | +LL | (*p.as_mut_ptr().cast::<[*const i32; 2]>())[0] = 4 as *const i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast + | + = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, + = help: which means that Miri might miss pointer bugs in this program. + = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation. + = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead. + = help: You can then pass the `-Zmiri-strict-provenance` flag to Miri, to ensure you are not relying on `with_exposed_provenance` semantics. + = help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning. + = note: BACKTRACE: + = note: inside `main` at $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC + +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC + | +LL | RET = PtrMetadata(*p); + | ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `deref_meta` at $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC +note: inside `main` + --> $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC + | +LL | let _meta = deref_meta(p.as_ptr().cast()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs new file mode 100644 index 000000000000..ad2e9fc800eb --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs @@ -0,0 +1,23 @@ +//@compile-flags: -Zmiri-disable-validation +#![feature(core_intrinsics, custom_mir)] +use std::intrinsics::mir::*; + +// This disables validation and uses custom MIR hit exactly the UB in the intrinsic, +// rather than getting UB from the typed load or parameter passing. + +#[custom_mir(dialect = "runtime")] +pub unsafe fn deref_meta(p: *const *const i32) -> () { + mir!({ + RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data + Return() + }) +} + +fn main() { + // Even though the meta is the trivially-valid `()`, this is still UB + + let p = std::mem::MaybeUninit::<*const i32>::uninit(); + unsafe { + let _meta = deref_meta(p.as_ptr()); + } +} diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr new file mode 100644 index 000000000000..3ab2643afa72 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/ptr_metadata_uninit_thin.rs:LL:CC + | +LL | RET = PtrMetadata(*p); + | ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `deref_meta` at $DIR/ptr_metadata_uninit_thin.rs:LL:CC +note: inside `main` + --> $DIR/ptr_metadata_uninit_thin.rs:LL:CC + | +LL | let _meta = deref_meta(p.as_ptr()); + | ^^^^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 57948c84ecf654bdbf29adcee095e7e10b1c0640 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 27 May 2024 14:45:45 -0700 Subject: [PATCH 060/104] Add Miri smoke pass test for ptr_metadata intrinsic --- src/tools/miri/tests/pass/intrinsics/intrinsics.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass/intrinsics/intrinsics.rs b/src/tools/miri/tests/pass/intrinsics/intrinsics.rs index 0dda5aadce20..89289a25d50a 100644 --- a/src/tools/miri/tests/pass/intrinsics/intrinsics.rs +++ b/src/tools/miri/tests/pass/intrinsics/intrinsics.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(core_intrinsics, layout_for_ptr)] +#![feature(core_intrinsics, layout_for_ptr, ptr_metadata)] //! Tests for various intrinsics that do not fit anywhere else. use std::intrinsics; @@ -57,4 +57,10 @@ fn main() { // Make sure that even if the discriminant is stored together with data, the intrinsic returns // only the discriminant, nothing about the data. assert_eq!(discriminant(&Some(false)), discriminant(&Some(true))); + + let () = intrinsics::ptr_metadata(&[1, 2, 3]); + let len = intrinsics::ptr_metadata(&[1, 2, 3][..]); + assert_eq!(len, 3); + let dyn_meta = intrinsics::ptr_metadata(&[1, 2, 3] as &dyn std::fmt::Debug); + assert_eq!(dyn_meta.size_of(), 12); } From 037577a95ab6963eb4877b183cfcbdbb56e25207 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 28 May 2024 15:31:13 -0400 Subject: [PATCH 061/104] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index a8d72c675ee5..431db31d0dbe 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit a8d72c675ee52dd57f0d8f2bae6655913c15b2fb +Subproject commit 431db31d0dbeda320caf8ef8535ea48eb3093407 From 448d63e9469c293c3855867d29cbff210691db92 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 29 May 2024 14:06:53 +1000 Subject: [PATCH 062/104] Tweak various coverage test files for slightly nicer formatting For coverage tests, splitting code across multiple lines often makes the resulting coverage report easier to interpret, so we force rustfmt to retain line breaks by adding dummy line comments with `//`. --- tests/coverage/auxiliary/used_crate.rs | 10 +++---- tests/coverage/auxiliary/used_inline_crate.rs | 10 +++---- tests/coverage/coroutine.coverage | 4 +-- tests/coverage/coroutine.rs | 4 +-- tests/coverage/inline-dead.coverage | 2 +- tests/coverage/inline-dead.rs | 2 +- tests/coverage/inner_items.coverage | 2 +- tests/coverage/inner_items.rs | 2 +- tests/coverage/partial_eq.coverage | 2 +- tests/coverage/partial_eq.rs | 2 +- tests/coverage/try_error_result.cov-map | 12 ++++----- tests/coverage/try_error_result.coverage | 4 +-- tests/coverage/try_error_result.rs | 4 +-- tests/coverage/uses_crate.coverage | 26 +++++++++---------- tests/coverage/uses_inline_crate.coverage | 26 +++++++++---------- 15 files changed, 54 insertions(+), 58 deletions(-) diff --git a/tests/coverage/auxiliary/used_crate.rs b/tests/coverage/auxiliary/used_crate.rs index 72d479c74a68..c0556a5bb4cd 100644 --- a/tests/coverage/auxiliary/used_crate.rs +++ b/tests/coverage/auxiliary/used_crate.rs @@ -17,23 +17,23 @@ pub fn used_function() { } pub fn used_only_from_bin_crate_generic_function(arg: T) { - println!("used_only_from_bin_crate_generic_function with {:?}", arg); + println!("used_only_from_bin_crate_generic_function with {arg:?}"); } // Expect for above function: `Unexecuted instantiation` (see below) pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); } pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); } pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); } pub fn unused_generic_function(arg: T) { - println!("unused_generic_function with {:?}", arg); + println!("unused_generic_function with {arg:?}"); } pub fn unused_function() { diff --git a/tests/coverage/auxiliary/used_inline_crate.rs b/tests/coverage/auxiliary/used_inline_crate.rs index d5fe7478aa41..165d5c1e3096 100644 --- a/tests/coverage/auxiliary/used_inline_crate.rs +++ b/tests/coverage/auxiliary/used_inline_crate.rs @@ -31,28 +31,28 @@ pub fn used_inline_function() { #[inline(always)] pub fn used_only_from_bin_crate_generic_function(arg: T) { - println!("used_only_from_bin_crate_generic_function with {:?}", arg); + println!("used_only_from_bin_crate_generic_function with {arg:?}"); } // Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`) #[inline(always)] pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); } #[inline(always)] pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); } #[inline(always)] pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); } #[inline(always)] pub fn unused_generic_function(arg: T) { - println!("unused_generic_function with {:?}", arg); + println!("unused_generic_function with {arg:?}"); } #[inline(always)] diff --git a/tests/coverage/coroutine.coverage b/tests/coverage/coroutine.coverage index 68b52d198316..afe13b48ff6d 100644 --- a/tests/coverage/coroutine.coverage +++ b/tests/coverage/coroutine.coverage @@ -10,9 +10,9 @@ LL| |// to handle this condition, and still report dead block coverage. LL| 1|fn get_u32(val: bool) -> Result { LL| 1| if val { - LL| 1| Ok(1) + LL| 1| Ok(1) // LL| | } else { - LL| 0| Err(String::from("some error")) + LL| 0| Err(String::from("some error")) // LL| | } LL| 1|} LL| | diff --git a/tests/coverage/coroutine.rs b/tests/coverage/coroutine.rs index 7f72e0d8bd42..84d1b3304c57 100644 --- a/tests/coverage/coroutine.rs +++ b/tests/coverage/coroutine.rs @@ -10,9 +10,9 @@ use std::pin::Pin; // to handle this condition, and still report dead block coverage. fn get_u32(val: bool) -> Result { if val { - Ok(1) + Ok(1) // } else { - Err(String::from("some error")) + Err(String::from("some error")) // } } diff --git a/tests/coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage index a2d24fd2f6a6..c12668ce89a2 100644 --- a/tests/coverage/inline-dead.coverage +++ b/tests/coverage/inline-dead.coverage @@ -14,7 +14,7 @@ LL| |#[inline] LL| 1|fn live() -> u32 { LL| 1| if B { - LL| 0| dead() + LL| 0| dead() // LL| | } else { LL| 1| 0 LL| | } diff --git a/tests/coverage/inline-dead.rs b/tests/coverage/inline-dead.rs index 327e68c60bb7..4eb397a43fc1 100644 --- a/tests/coverage/inline-dead.rs +++ b/tests/coverage/inline-dead.rs @@ -13,7 +13,7 @@ fn main() { #[inline] fn live() -> u32 { if B { - dead() + dead() // } else { 0 } diff --git a/tests/coverage/inner_items.coverage b/tests/coverage/inner_items.coverage index 65493bcd9db4..152f3da1a221 100644 --- a/tests/coverage/inner_items.coverage +++ b/tests/coverage/inner_items.coverage @@ -52,7 +52,7 @@ ^0 LL| | LL| 1| let mut val = InStruct { - LL| 1| in_struct_field: 101, + LL| 1| in_struct_field: 101, // LL| 1| }; LL| 1| LL| 1| val.default_trait_func(); diff --git a/tests/coverage/inner_items.rs b/tests/coverage/inner_items.rs index bcb62b3031cd..4d513e612f06 100644 --- a/tests/coverage/inner_items.rs +++ b/tests/coverage/inner_items.rs @@ -50,7 +50,7 @@ fn main() { } let mut val = InStruct { - in_struct_field: 101, + in_struct_field: 101, // }; val.default_trait_func(); diff --git a/tests/coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage index 9de1c933570c..c6f9d5bf6a6a 100644 --- a/tests/coverage/partial_eq.coverage +++ b/tests/coverage/partial_eq.coverage @@ -26,7 +26,7 @@ LL| 1| "{:?} < {:?} = {}", LL| 1| version_3_2_1, LL| 1| version_3_3_0, - LL| 1| version_3_2_1 < version_3_3_0 + LL| 1| version_3_2_1 < version_3_3_0, // LL| 1| ); LL| 1|} LL| | diff --git a/tests/coverage/partial_eq.rs b/tests/coverage/partial_eq.rs index 825e266f111f..0e96dc2b6853 100644 --- a/tests/coverage/partial_eq.rs +++ b/tests/coverage/partial_eq.rs @@ -26,7 +26,7 @@ fn main() { "{:?} < {:?} = {}", version_3_2_1, version_3_3_0, - version_3_2_1 < version_3_3_0 + version_3_2_1 < version_3_3_0, // ); } diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index 49e6c7ceefca..9c18827d8e68 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -25,26 +25,26 @@ Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) Function name: try_error_result::call -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 04, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) +- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 20) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Function name: try_error_result::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 73, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 115, 1) to (start + 2, 12) +- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 12) - Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) = (c0 - c1) @@ -81,7 +81,7 @@ Number of file 0 mappings: 11 = (((c4 + Zero) + Zero) + c3) Function name: try_error_result::test2 -Raw bytes (280): 0x[01, 01, 24, 01, 07, 00, 09, 03, 0d, 41, 00, 1e, 00, 41, 00, 1e, 00, 41, 00, 4a, 00, 4e, 00, 52, 41, 03, 0d, 52, 41, 03, 0d, 4e, 00, 52, 41, 03, 0d, 4a, 00, 4e, 00, 52, 41, 03, 0d, 66, 00, 45, 00, 45, 00, 66, 00, 45, 00, 7a, 00, 4d, 00, 4d, 00, 7a, 00, 4d, 00, 83, 01, 0d, 87, 01, 00, 00, 8b, 01, 8f, 01, 00, 19, 00, 28, 01, 3e, 01, 03, 17, 03, 08, 09, 00, 0e, 52, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 00, 00, 2f, 00, 30, 1e, 00, 31, 03, 35, 00, 04, 11, 00, 12, 1a, 02, 11, 04, 12, 00, 05, 11, 00, 14, 1a, 00, 17, 00, 41, 19, 00, 41, 00, 42, 00, 00, 43, 00, 5f, 00, 00, 5f, 00, 60, 00, 01, 0d, 00, 20, 00, 01, 11, 00, 14, 00, 00, 17, 00, 41, 00, 00, 41, 00, 42, 00, 00, 43, 00, 60, 00, 00, 60, 00, 61, 00, 01, 0d, 00, 20, 46, 04, 11, 00, 14, 4e, 00, 17, 00, 42, 00, 00, 42, 00, 43, 4a, 00, 44, 00, 61, 00, 00, 61, 00, 62, 46, 01, 0d, 00, 20, 62, 01, 11, 00, 14, 45, 00, 17, 01, 36, 00, 01, 36, 00, 37, 66, 01, 12, 00, 2f, 00, 00, 2f, 00, 30, 62, 01, 0d, 00, 20, 76, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 00, 02, 11, 00, 12, 7a, 01, 12, 00, 2f, 00, 01, 11, 00, 12, 76, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, 7f, 01, 01, 00, 02] +Raw bytes (280): 0x[01, 01, 24, 01, 07, 00, 09, 03, 0d, 41, 00, 1e, 00, 41, 00, 1e, 00, 41, 00, 4a, 00, 4e, 00, 52, 41, 03, 0d, 52, 41, 03, 0d, 4e, 00, 52, 41, 03, 0d, 4a, 00, 4e, 00, 52, 41, 03, 0d, 66, 00, 45, 00, 45, 00, 66, 00, 45, 00, 7a, 00, 4d, 00, 4d, 00, 7a, 00, 4d, 00, 83, 01, 0d, 87, 01, 00, 00, 8b, 01, 8f, 01, 00, 19, 00, 28, 01, 3d, 01, 03, 17, 03, 08, 09, 00, 0e, 52, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 00, 00, 2f, 00, 30, 1e, 00, 31, 03, 35, 00, 04, 11, 00, 12, 1a, 02, 11, 04, 12, 00, 05, 11, 00, 14, 1a, 00, 17, 00, 41, 19, 00, 41, 00, 42, 00, 00, 43, 00, 5f, 00, 00, 5f, 00, 60, 00, 01, 0d, 00, 20, 00, 01, 11, 00, 14, 00, 00, 17, 00, 41, 00, 00, 41, 00, 42, 00, 00, 43, 00, 60, 00, 00, 60, 00, 61, 00, 01, 0d, 00, 20, 46, 04, 11, 00, 14, 4e, 00, 17, 00, 42, 00, 00, 42, 00, 43, 4a, 00, 44, 00, 61, 00, 00, 61, 00, 62, 46, 01, 0d, 00, 20, 62, 01, 11, 00, 14, 45, 00, 17, 01, 36, 00, 01, 36, 00, 37, 66, 01, 12, 00, 2f, 00, 00, 2f, 00, 30, 62, 01, 0d, 00, 20, 76, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 00, 02, 11, 00, 12, 7a, 01, 12, 00, 2f, 00, 01, 11, 00, 12, 76, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, 7f, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 36 @@ -122,7 +122,7 @@ Number of expressions: 36 - expression 34 operands: lhs = Expression(35, Add), rhs = Zero - expression 35 operands: lhs = Counter(6), rhs = Zero Number of file 0 mappings: 40 -- Code(Counter(0)) at (prev + 62, 1) to (start + 3, 23) +- Code(Counter(0)) at (prev + 61, 1) to (start + 3, 23) - Code(Expression(0, Add)) at (prev + 8, 9) to (start + 0, 14) = (c0 + (Zero + c2)) - Code(Expression(20, Sub)) at (prev + 2, 9) to (start + 4, 26) diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage index 6fbe8b8db13f..7100248f7df8 100644 --- a/tests/coverage/try_error_result.coverage +++ b/tests/coverage/try_error_result.coverage @@ -1,4 +1,5 @@ LL| |#![allow(unused_assignments)] + LL| |#![cfg_attr(rustfmt, rustfmt::skip)] LL| |//@ failure-status: 1 LL| | LL| 6|fn call(return_error: bool) -> Result<(), ()> { @@ -9,7 +10,6 @@ LL| | } LL| 6|} LL| | - LL| |#[rustfmt::skip] LL| 1|fn test1() -> Result<(), ()> { LL| 1| let mut LL| 1| countdown = 10 @@ -59,7 +59,6 @@ LL| 17| } LL| |} LL| | - LL| |#[rustfmt::skip] LL| 1|fn test2() -> Result<(), ()> { LL| 1| let thing1 = Thing1{}; LL| 1| let mut @@ -117,7 +116,6 @@ LL| 0| Ok(()) LL| 1|} LL| | - LL| |#[rustfmt::skip] LL| 1|fn main() -> Result<(), ()> { LL| 1| test1().expect_err("test1 should fail"); LL| 1| test2() diff --git a/tests/coverage/try_error_result.rs b/tests/coverage/try_error_result.rs index f36283c34c8b..1fd176c353d9 100644 --- a/tests/coverage/try_error_result.rs +++ b/tests/coverage/try_error_result.rs @@ -1,4 +1,5 @@ #![allow(unused_assignments)] +#![cfg_attr(rustfmt, rustfmt::skip)] //@ failure-status: 1 fn call(return_error: bool) -> Result<(), ()> { @@ -9,7 +10,6 @@ fn call(return_error: bool) -> Result<(), ()> { } } -#[rustfmt::skip] fn test1() -> Result<(), ()> { let mut countdown = 10 @@ -58,7 +58,6 @@ impl Thing2 { } } -#[rustfmt::skip] fn test2() -> Result<(), ()> { let thing1 = Thing1{}; let mut @@ -111,7 +110,6 @@ fn test2() -> Result<(), ()> { Ok(()) } -#[rustfmt::skip] fn main() -> Result<(), ()> { test1().expect_err("test1 should fail"); test2() diff --git a/tests/coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage index a6a570a08502..d001eeffd863 100644 --- a/tests/coverage/uses_crate.coverage +++ b/tests/coverage/uses_crate.coverage @@ -19,69 +19,69 @@ $DIR/auxiliary/used_crate.rs: LL| 1|} LL| | LL| 2|pub fn used_only_from_bin_crate_generic_function(arg: T) { - LL| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + LL| 2| println!("used_only_from_bin_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_> ------------------ | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec>: | LL| 1|pub fn used_only_from_bin_crate_generic_function(arg: T) { - | LL| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_bin_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_crate::used_only_from_bin_crate_generic_function::<&str>: | LL| 1|pub fn used_only_from_bin_crate_generic_function(arg: T) { - | LL| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_bin_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| |// Expect for above function: `Unexecuted instantiation` (see below) LL| 2|pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - LL| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + LL| 2| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | used_crate::used_only_from_this_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - | LL| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_crate::used_only_from_this_lib_crate_generic_function::>: | LL| 1|pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - | LL| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| | LL| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - LL| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + LL| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_crate::used_from_bin_crate_and_lib_crate_generic_function::>: | LL| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| | LL| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - LL| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + LL| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| | LL| 0|pub fn unused_generic_function(arg: T) { - LL| 0| println!("unused_generic_function with {:?}", arg); + LL| 0| println!("unused_generic_function with {arg:?}"); LL| 0|} LL| | LL| 0|pub fn unused_function() { diff --git a/tests/coverage/uses_inline_crate.coverage b/tests/coverage/uses_inline_crate.coverage index 0c9735990c7e..832a5a6a62b4 100644 --- a/tests/coverage/uses_inline_crate.coverage +++ b/tests/coverage/uses_inline_crate.coverage @@ -34,74 +34,74 @@ $DIR/auxiliary/used_inline_crate.rs: LL| | LL| |#[inline(always)] LL| 2|pub fn used_only_from_bin_crate_generic_function(arg: T) { - LL| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + LL| 2| println!("used_only_from_bin_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_> ------------------ | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec>: | LL| 1|pub fn used_only_from_bin_crate_generic_function(arg: T) { - | LL| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_bin_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>: | LL| 1|pub fn used_only_from_bin_crate_generic_function(arg: T) { - | LL| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_bin_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`) LL| | LL| |#[inline(always)] LL| 4|pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - LL| 4| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + LL| 4| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); LL| 4|} ------------------ | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>: | LL| 2|pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - | LL| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | LL| 2| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); | LL| 2|} ------------------ | used_inline_crate::used_only_from_this_lib_crate_generic_function::>: | LL| 2|pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - | LL| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | LL| 2| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); | LL| 2|} ------------------ LL| | LL| |#[inline(always)] LL| 3|pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - LL| 3| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + LL| 3| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); LL| 3|} ------------------ | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - | LL| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 2|} ------------------ | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::>: | LL| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| | LL| |#[inline(always)] LL| 3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - LL| 3| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + LL| 3| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); LL| 3|} ------------------ | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - | LL| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 2|} ------------------ LL| | LL| |#[inline(always)] LL| 0|pub fn unused_generic_function(arg: T) { - LL| 0| println!("unused_generic_function with {:?}", arg); + LL| 0| println!("unused_generic_function with {arg:?}"); LL| 0|} LL| | LL| |#[inline(always)] From 9dc6e082791fe0f3116c34a922de75947883644c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 29 May 2024 14:27:57 +1000 Subject: [PATCH 063/104] Manually run `x fmt` on all source files in `tests/coverage/` Currently we can't automatically enforce formatting on tests (see #125637), but we can at least keep things relatively tidy by occasionally running the formatter manually. This was done by temporarily commenting out the `"/tests/"` exclusion in `rustfmt.toml`, and then running `x fmt tests/coverage` and `x test coverage --bless`. --- tests/coverage/coroutine.cov-map | 8 ++++---- tests/coverage/coroutine.coverage | 3 ++- tests/coverage/coroutine.rs | 3 ++- tests/coverage/let_else_loop.cov-map | 6 +++--- tests/coverage/let_else_loop.coverage | 6 +----- tests/coverage/let_else_loop.rs | 6 +----- tests/coverage/partial_eq.cov-map | 8 ++++---- tests/coverage/partial_eq.coverage | 6 +----- tests/coverage/partial_eq.rs | 6 +----- tests/coverage/yield.cov-map | 14 +++++++------- tests/coverage/yield.coverage | 6 ++++-- tests/coverage/yield.rs | 6 ++++-- 12 files changed, 34 insertions(+), 44 deletions(-) diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index 6ead788b82f9..6ff5ed74a96d 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -12,7 +12,7 @@ Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Function name: coroutine::main -Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 13, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -26,7 +26,7 @@ Number of expressions: 8 - expression 7 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22) -- Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) +- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 46) - Code(Counter(4)) at (prev + 1, 43) to (start + 0, 45) - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 53) = ((c1 + c2) + c3) @@ -41,11 +41,11 @@ Number of file 0 mappings: 9 = ((c4 - c5) - c6) Function name: coroutine::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 29, 01, 1f, 05, 02, 10, 01, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 16, 08, 01, 1f, 05, 02, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 21, 41) to (start + 1, 31) +- Code(Counter(0)) at (prev + 22, 8) to (start + 1, 31) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) diff --git a/tests/coverage/coroutine.coverage b/tests/coverage/coroutine.coverage index afe13b48ff6d..611470c57738 100644 --- a/tests/coverage/coroutine.coverage +++ b/tests/coverage/coroutine.coverage @@ -18,7 +18,8 @@ LL| | LL| 1|fn main() { LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| let mut coroutine = #[coroutine] || { + LL| 1| let mut coroutine = #[coroutine] + LL| 1| || { LL| 1| yield get_u32(is_true); LL| 1| return "foo"; LL| 1| }; diff --git a/tests/coverage/coroutine.rs b/tests/coverage/coroutine.rs index 84d1b3304c57..bd149764b373 100644 --- a/tests/coverage/coroutine.rs +++ b/tests/coverage/coroutine.rs @@ -18,7 +18,8 @@ fn get_u32(val: bool) -> Result { fn main() { let is_true = std::env::args().len() == 1; - let mut coroutine = #[coroutine] || { + let mut coroutine = #[coroutine] + || { yield get_u32(is_true); return "foo"; }; diff --git a/tests/coverage/let_else_loop.cov-map b/tests/coverage/let_else_loop.cov-map index b0cee3005220..13d0d08adb11 100644 --- a/tests/coverage/let_else_loop.cov-map +++ b/tests/coverage/let_else_loop.cov-map @@ -1,12 +1,12 @@ Function name: let_else_loop::_if (unused) -Raw bytes (19): 0x[01, 01, 00, 03, 00, 16, 01, 01, 0c, 00, 02, 09, 00, 10, 00, 02, 09, 00, 10] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 16, 01, 01, 0c, 00, 01, 0f, 00, 16, 00, 00, 20, 00, 27] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 3 - Code(Zero) at (prev + 22, 1) to (start + 1, 12) -- Code(Zero) at (prev + 2, 9) to (start + 0, 16) -- Code(Zero) at (prev + 2, 9) to (start + 0, 16) +- Code(Zero) at (prev + 1, 15) to (start + 0, 22) +- Code(Zero) at (prev + 0, 32) to (start + 0, 39) Function name: let_else_loop::_loop_either_way (unused) Raw bytes (19): 0x[01, 01, 00, 03, 00, 0f, 01, 01, 14, 00, 01, 1c, 00, 23, 00, 01, 05, 00, 0c] diff --git a/tests/coverage/let_else_loop.coverage b/tests/coverage/let_else_loop.coverage index d193c8ca1b51..bd13f6e56501 100644 --- a/tests/coverage/let_else_loop.coverage +++ b/tests/coverage/let_else_loop.coverage @@ -21,11 +21,7 @@ LL| |// Variant using regular `if` instead of let-else. LL| |// This doesn't trigger the original ICE, but might help detect regressions. LL| 0|fn _if(cond: bool) { - LL| 0| if cond { - LL| 0| loop {} - LL| | } else { - LL| 0| loop {} - LL| | } + LL| 0| if cond { loop {} } else { loop {} } LL| |} LL| | LL| |#[coverage(off)] diff --git a/tests/coverage/let_else_loop.rs b/tests/coverage/let_else_loop.rs index 12e0aeabcab9..8217c0d072a6 100644 --- a/tests/coverage/let_else_loop.rs +++ b/tests/coverage/let_else_loop.rs @@ -20,11 +20,7 @@ fn _loop_either_way(cond: bool) { // Variant using regular `if` instead of let-else. // This doesn't trigger the original ICE, but might help detect regressions. fn _if(cond: bool) { - if cond { - loop {} - } else { - loop {} - } + if cond { loop {} } else { loop {} } } #[coverage(off)] diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 80670fbfa5a7..6c39ac0e378b 100644 --- a/tests/coverage/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map @@ -1,16 +1,16 @@ Function name: ::new -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 05, 06, 06] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 05, 02, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 12, 5) to (start + 6, 6) +- Code(Counter(0)) at (prev + 12, 5) to (start + 2, 6) Function name: partial_eq::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 0a, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 0a, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 1) to (start + 10, 2) +- Code(Counter(0)) at (prev + 17, 1) to (start + 10, 2) diff --git a/tests/coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage index c6f9d5bf6a6a..dc5b82b3c5f1 100644 --- a/tests/coverage/partial_eq.coverage +++ b/tests/coverage/partial_eq.coverage @@ -10,11 +10,7 @@ LL| | LL| |impl Version { LL| 2| pub fn new(major: usize, minor: usize, patch: usize) -> Self { - LL| 2| Self { - LL| 2| major, - LL| 2| minor, - LL| 2| patch, - LL| 2| } + LL| 2| Self { major, minor, patch } LL| 2| } LL| |} LL| | diff --git a/tests/coverage/partial_eq.rs b/tests/coverage/partial_eq.rs index 0e96dc2b6853..081502d4a9d6 100644 --- a/tests/coverage/partial_eq.rs +++ b/tests/coverage/partial_eq.rs @@ -10,11 +10,7 @@ pub struct Version { impl Version { pub fn new(major: usize, minor: usize, patch: usize) -> Self { - Self { - major, - minor, - patch, - } + Self { major, minor, patch } } } diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map index 0347aaaa3676..a273c688e248 100644 --- a/tests/coverage/yield.cov-map +++ b/tests/coverage/yield.cov-map @@ -1,5 +1,5 @@ Function name: yield::main -Raw bytes (106): 0x[01, 01, 0b, 05, 00, 0d, 11, 22, 15, 0d, 11, 11, 15, 22, 15, 0d, 11, 22, 15, 0d, 11, 19, 1d, 25, 29, 10, 01, 07, 01, 01, 16, 01, 06, 0b, 00, 2e, 0d, 01, 27, 00, 29, 03, 01, 0e, 00, 34, 0d, 02, 0b, 00, 2e, 22, 01, 22, 00, 27, 1e, 00, 2c, 00, 2e, 13, 01, 0e, 00, 34, 1e, 03, 09, 00, 16, 1e, 07, 0b, 00, 2e, 21, 01, 27, 00, 29, 27, 01, 0e, 00, 34, 21, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 2b, 01, 0e, 00, 34, 2d, 02, 01, 00, 02] +Raw bytes (106): 0x[01, 01, 0b, 05, 00, 0d, 11, 22, 15, 0d, 11, 11, 15, 22, 15, 0d, 11, 22, 15, 0d, 11, 19, 1d, 25, 29, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 0d, 01, 27, 00, 29, 03, 01, 0e, 00, 34, 0d, 02, 0b, 00, 2e, 22, 01, 22, 00, 27, 1e, 00, 2c, 00, 2e, 13, 01, 0e, 00, 34, 1e, 03, 09, 00, 16, 1e, 08, 0b, 00, 2e, 21, 01, 27, 00, 29, 27, 01, 0e, 00, 34, 21, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 2b, 01, 0e, 00, 34, 2d, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 11 @@ -16,7 +16,7 @@ Number of expressions: 11 - expression 10 operands: lhs = Counter(9), rhs = Counter(10) Number of file 0 mappings: 16 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22) -- Code(Counter(0)) at (prev + 6, 11) to (start + 0, 46) +- Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) - Code(Counter(3)) at (prev + 1, 39) to (start + 0, 41) - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 52) = (c1 + Zero) @@ -29,7 +29,7 @@ Number of file 0 mappings: 16 = (c4 + c5) - Code(Expression(7, Sub)) at (prev + 3, 9) to (start + 0, 22) = ((c3 - c4) - c5) -- Code(Expression(7, Sub)) at (prev + 7, 11) to (start + 0, 46) +- Code(Expression(7, Sub)) at (prev + 8, 11) to (start + 0, 46) = ((c3 - c4) - c5) - Code(Counter(8)) at (prev + 1, 39) to (start + 0, 41) - Code(Expression(9, Add)) at (prev + 1, 14) to (start + 0, 52) @@ -41,21 +41,21 @@ Number of file 0 mappings: 16 - Code(Counter(11)) at (prev + 2, 1) to (start + 0, 2) Function name: yield::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 29, 01, 10, 05, 02, 10, 01, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 09, 08, 01, 10, 05, 02, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 8, 41) to (start + 1, 16) +- Code(Counter(0)) at (prev + 9, 8) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) Function name: yield::main::{closure#1} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 29, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 18, 08, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 22, 41) to (start + 1, 16) +- Code(Counter(0)) at (prev + 24, 8) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 16) - Code(Counter(3)) at (prev + 1, 16) to (start + 1, 6) diff --git a/tests/coverage/yield.coverage b/tests/coverage/yield.coverage index e2fc9196d244..2c133cbec549 100644 --- a/tests/coverage/yield.coverage +++ b/tests/coverage/yield.coverage @@ -5,7 +5,8 @@ LL| |use std::pin::Pin; LL| | LL| 1|fn main() { - LL| 1| let mut coroutine = #[coroutine] || { + LL| 1| let mut coroutine = #[coroutine] + LL| 1| || { LL| 1| yield 1; LL| 1| return "foo"; LL| 1| }; @@ -19,7 +20,8 @@ LL| 0| _ => panic!("unexpected value from resume"), LL| | } LL| | - LL| 1| let mut coroutine = #[coroutine] || { + LL| 1| let mut coroutine = #[coroutine] + LL| 1| || { LL| 1| yield 1; LL| 1| yield 2; LL| 0| yield 3; diff --git a/tests/coverage/yield.rs b/tests/coverage/yield.rs index 64ea27066047..e02e3d356124 100644 --- a/tests/coverage/yield.rs +++ b/tests/coverage/yield.rs @@ -5,7 +5,8 @@ use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; fn main() { - let mut coroutine = #[coroutine] || { + let mut coroutine = #[coroutine] + || { yield 1; return "foo"; }; @@ -19,7 +20,8 @@ fn main() { _ => panic!("unexpected value from resume"), } - let mut coroutine = #[coroutine] || { + let mut coroutine = #[coroutine] + || { yield 1; yield 2; yield 3; From 92af72d1927e972e889c32bfd4b0bb1465b8b209 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 May 2024 08:04:24 +0200 Subject: [PATCH 064/104] fn_arg_sanity_check: fix panic message also update csky comment in abi/compatibility test --- compiler/rustc_ty_utils/src/abi.rs | 3 ++- tests/ui/abi/compatibility.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 6f513f24948a..c5ea85c90dc5 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -520,7 +520,8 @@ fn fn_abi_sanity_check<'tcx>( assert!( matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64") || matches!(spec_abi, SpecAbi::PtxKernel | SpecAbi::Unadjusted), - r#"`PassMode::Direct` for aggregates only allowed for "unadjusted" and "ptx-kernel" functions and on wasm\nProblematic type: {:#?}"#, + "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\ + Problematic type: {:#?}", arg.layout, ); } diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 373d1cce1d73..784c6d488eaf 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -59,6 +59,7 @@ [nvptx64] needs-llvm-components: nvptx */ // FIXME: disabled since it fails on CI saying the csky component is missing +// see https://github.com/rust-lang/rust/issues/125697 /* revisions: csky [csky] compile-flags: --target csky-unknown-linux-gnuabiv2 [csky] needs-llvm-components: csky From 5cf198d0d6dc64b9c255d1eaec48f0fd5802e47f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 May 2024 10:17:59 +1000 Subject: [PATCH 065/104] Remove path choice from `x fmt` and add `--all` option. By default, `x fmt` formats/checks modified files. But it also lets you choose one or more paths instead. This adds significant complexity to `x fmt`. Explicit paths are specified via `WalkBuilder::add` rather than `OverrideBuilder::add`. The `ignore` library is not simple, and predicting the interactions between the two mechanisms is difficult. Here's a particularly interesting case. - You can request a path P that is excluded by the `ignore` list in the `rustfmt.toml`. E.g. `x fmt tests/ui/` or `x fmt tests/ui/bitwise.rs`. - `x fmt` will add P to the walker (via `WalkBuilder::add`), traverse it (paying no attention to the `ignore` list from the `rustfmt.toml` file, due to the different mechanism), and call `rustfmt` on every `.rs` file within it. - `rustfmt` will do nothing to those `.rs` files, because it *also* reads `rustfmt.toml` and sees that they match the `ignore` list! It took me *ages* to debug and understand this behaviour. Not good! `x fmt` even lets you name a path below the current directory. This was intended to let you do things like `x fmt std` that mirror things like `x test std`. This works by looking for `std` and finding `library/std`, and then formatting that. Unfortuantely, this motivating case now gives an error. When support was added in #107944, `library/std` was the only directory named `std`. Since then, `tests/ui/std` was added, and so `x fmt std` now gives an error. In general, explicit paths don't seem particularly useful. The only two cases `x fmt` really needs are: - format/check the files I have modified (99% of uses) - format/check all files (While respecting the `ignore` list in `rustfmt.toml`, of course.) So this commit moves to that model. `x fmt` will now give an error if given an explicit path. `x fmt` now also supports a `--all` option. (And running with `GITHUB_ACTIONS=true` also causes everything to be formatted/checked, as before.) Much simpler! --- src/bootstrap/src/core/build_steps/format.rs | 70 +++++--------------- src/bootstrap/src/core/build_steps/test.rs | 8 ++- src/bootstrap/src/core/config/flags.rs | 8 ++- src/bootstrap/src/lib.rs | 3 +- src/etc/completions/x.py.fish | 1 + src/etc/completions/x.py.ps1 | 1 + src/etc/completions/x.py.sh | 2 +- src/etc/completions/x.py.zsh | 1 + 8 files changed, 34 insertions(+), 60 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 44f575b51da2..209249b7bd43 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -97,10 +97,21 @@ struct RustfmtConfig { ignore: Vec, } -pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { +pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { + if !paths.is_empty() { + eprintln!("path arguments are not accepted"); + crate::exit!(1); + }; if build.config.dry_run() { return; } + + // By default, we only check modified files locally to speed up runtime. Exceptions are if + // `--all` is specified or we are in CI. We check all files in CI to avoid bugs in + // `get_modified_rs_files` letting regressions slip through; we also care about CI time less + // since this is still very fast compared to building the compiler. + let all = all || CiEnv::is_ci(); + let mut builder = ignore::types::TypesBuilder::new(); builder.add_defaults(); builder.select("rust"); @@ -175,11 +186,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { untracked_count += 1; fmt_override.add(&format!("!/{untracked_path}")).expect(untracked_path); } - // Only check modified files locally to speed up runtime. We still check all files in - // CI to avoid bugs in `get_modified_rs_files` letting regressions slip through; we - // also care about CI time less since this is still very fast compared to building the - // compiler. - if !CiEnv::is_ci() && paths.is_empty() { + if !all { match get_modified_rs_files(build) { Ok(Some(files)) => { if files.len() <= 10 { @@ -233,55 +240,8 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { assert!(rustfmt_path.exists(), "{}", rustfmt_path.display()); let src = build.src.clone(); let (tx, rx): (SyncSender, _) = std::sync::mpsc::sync_channel(128); - let walker = match paths.first() { - Some(first) => { - let find_shortcut_candidates = |p: &PathBuf| { - let mut candidates = Vec::new(); - for entry in - WalkBuilder::new(src.clone()).max_depth(Some(3)).build().map_while(Result::ok) - { - if let Some(dir_name) = p.file_name() { - if entry.path().is_dir() && entry.file_name() == dir_name { - candidates.push(entry.into_path()); - } - } - } - candidates - }; - - // Only try to look for shortcut candidates for single component paths like - // `std` and not for e.g. relative paths like `../library/std`. - let should_look_for_shortcut_dir = |p: &PathBuf| p.components().count() == 1; - - let mut walker = if should_look_for_shortcut_dir(first) { - if let [single_candidate] = &find_shortcut_candidates(first)[..] { - WalkBuilder::new(single_candidate) - } else { - WalkBuilder::new(first) - } - } else { - WalkBuilder::new(src.join(first)) - }; - - for path in &paths[1..] { - if should_look_for_shortcut_dir(path) { - if let [single_candidate] = &find_shortcut_candidates(path)[..] { - walker.add(single_candidate); - } else { - walker.add(path); - } - } else { - walker.add(src.join(path)); - } - } - - walker - } - None => WalkBuilder::new(src.clone()), - } - .types(matcher) - .overrides(fmt_override) - .build_parallel(); + let walker = + WalkBuilder::new(src.clone()).types(matcher).overrides(fmt_override).build_parallel(); // There is a lot of blocking involved in spawning a child process and reading files to format. // Spawn more processes than available concurrency to keep the CPU busy. diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 360bd3840d45..215886863624 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1140,7 +1140,13 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to ); crate::exit!(1); } - crate::core::build_steps::format::format(builder, !builder.config.cmd.bless(), &[]); + let all = false; + crate::core::build_steps::format::format( + builder, + !builder.config.cmd.bless(), + all, + &[], + ); } builder.info("tidy check"); diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index f4ed7e76fba1..83def0c6df0c 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -284,8 +284,8 @@ pub enum Subcommand { 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: + 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" )] @@ -294,6 +294,10 @@ pub enum Subcommand { /// check formatting instead of applying #[arg(long)] check: bool, + + /// apply to all appropriate files, not just those that have been modified + #[arg(long)] + all: bool, }, #[command(aliases = ["d"], long_about = "\n Arguments: diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 52c94465cd33..8312885915c5 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -660,10 +660,11 @@ impl Build { // hardcoded subcommands match &self.config.cmd { - Subcommand::Format { check } => { + Subcommand::Format { check, all } => { return core::build_steps::format::format( &builder::Builder::new(self), *check, + *all, &self.config.paths, ); } diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 40a25f13fcbd..7343f3147eed 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -216,6 +216,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-use -d 'us complete -c x.py -n "__fish_seen_subcommand_from fmt" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r complete -c x.py -n "__fish_seen_subcommand_from fmt" -l set -d 'override options in config.toml' -r -f complete -c x.py -n "__fish_seen_subcommand_from fmt" -l check -d 'check formatting instead of applying' +complete -c x.py -n "__fish_seen_subcommand_from fmt" -l all -d 'apply to all appropriate files, not just those that have been modified' complete -c x.py -n "__fish_seen_subcommand_from fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_seen_subcommand_from fmt" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_seen_subcommand_from fmt" -l include-default-paths -d 'include default paths in addition to the provided ones' diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index f3d1d372c733..d9adb1778f2f 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -275,6 +275,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'check formatting instead of applying') + [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'apply to all appropriate files, not just those that have been modified') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index 82cacb52ffee..6cb9e95c8c10 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -1077,7 +1077,7 @@ _x.py() { return 0 ;; x.py__fmt) - opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 12e96dbd40a3..24ddd1c4b7cc 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -271,6 +271,7 @@ _arguments "${_arguments_options[@]}" \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT: ' \ '*--set=[override options in config.toml]:section.option=value:( )' \ '--check[check formatting instead of applying]' \ +'--all[apply to all appropriate files, not just those that have been modified]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ From e98740aa0daa288b44925864a487fab7d4c536d5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 13:06:42 +1000 Subject: [PATCH 066/104] Clarify `x fmt` messages. - Precede them all with `fmt` so it's clear where they are coming from. - Use `error:` and `warning:` when appropriate. - Print warnings to stderr instead of stdout --- src/bootstrap/src/core/build_steps/format.rs | 33 ++++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 209249b7bd43..f3e8d765dba6 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -35,9 +35,9 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F let status = cmd.wait().unwrap(); if !status.success() { eprintln!( - "Running `{}` failed.\nIf you're running `tidy`, \ - try again with `--bless`. Or, if you just want to format \ - code, run `./x.py fmt` instead.", + "fmt error: Running `{}` failed.\nIf you're running `tidy`, \ + try again with `--bless`. Or, if you just want to format \ + code, run `./x.py fmt` instead.", cmd_debug, ); crate::exit!(1); @@ -99,7 +99,7 @@ struct RustfmtConfig { pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { if !paths.is_empty() { - eprintln!("path arguments are not accepted"); + eprintln!("fmt error: path arguments are not accepted"); crate::exit!(1); }; if build.config.dry_run() { @@ -118,8 +118,8 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { let matcher = builder.build().unwrap(); let rustfmt_config = build.src.join("rustfmt.toml"); if !rustfmt_config.exists() { - eprintln!("Not running formatting checks; rustfmt.toml does not exist."); - eprintln!("This may happen in distributed tarballs."); + eprintln!("fmt error: Not running formatting checks; rustfmt.toml does not exist."); + eprintln!("fmt error: This may happen in distributed tarballs."); return; } let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config)); @@ -133,7 +133,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { // any files that aren't explicitly mentioned. No bueno! Maybe there's a way to combine // explicit whitelisted entries and traversal of unmentioned files, but for now just // forbid such entries. - eprintln!("`!`-prefixed entries are not supported in rustfmt.toml, sorry"); + eprintln!("fmt error: `!`-prefixed entries are not supported in rustfmt.toml, sorry"); crate::exit!(1); } else { fmt_override.add(&format!("!{ignore}")).expect(&ignore); @@ -177,7 +177,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { ); let mut untracked_count = 0; for untracked_path in untracked_paths { - println!("skip untracked path {untracked_path} during rustfmt invocations"); + println!("fmt: skip untracked path {untracked_path} during rustfmt invocations"); // The leading `/` makes it an exact match against the // repository root, rather than a glob. Without that, if you // have `foo.rs` in the repository root it will also match @@ -191,7 +191,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { Ok(Some(files)) => { if files.len() <= 10 { for file in &files { - println!("formatting modified file {file}"); + println!("fmt: formatting modified file {file}"); } } else { let pluralized = |count| if count > 1 { "files" } else { "file" }; @@ -205,7 +205,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { ) }; println!( - "formatting {} modified {}{}", + "fmt: formatting {} modified {}{}", files.len(), pluralized(files.len()), untracked_msg @@ -217,24 +217,23 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { } Ok(None) => {} Err(err) => { - println!( - "WARN: Something went wrong when running git commands:\n{err}\n\ - Falling back to formatting all files." - ); + eprintln!("fmt warning: Something went wrong running git commands:"); + eprintln!("fmt warning: {err}"); + eprintln!("fmt warning: Falling back to formatting all files."); } } } } else { - println!("Not in git tree. Skipping git-aware format checks"); + eprintln!("fmt: warning: Not in git tree. Skipping git-aware format checks"); } } else { - println!("Could not find usable git. Skipping git-aware format checks"); + eprintln!("fmt: warning: Could not find usable git. Skipping git-aware format checks"); } let fmt_override = fmt_override.build().unwrap(); let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| { - eprintln!("./x.py fmt is not supported on this channel"); + eprintln!("fmt error: `x fmt` is not supported on this channel"); crate::exit!(1); }); assert!(rustfmt_path.exists(), "{}", rustfmt_path.display()); From 3d5d6d222084db76ac152b6c813a3bc177bec8ce Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 13:18:37 +1000 Subject: [PATCH 067/104] Adjust `x fmt` printed output. Currently, `x fmt` can print two lists of files. - The untracked files that are skipped. Always done if within a git repo. - The modified files that are formatted. But if you run with `--all` (or with `GITHUB_ACTIONS=true`) it doesn't print anything about which files are formatted. This commit increases consistency. - The formatted/checked files are now always printed. And it makes it clear why a file was formatted, e.g. with "modified". - It uses the same code for both untracked files and formatted/checked files. This means that now if there are a lot of untracked files just the number will be printed, which is like the old behaviour for modified files. Example output: ``` fmt: skipped 31 untracked files fmt: formatted modified file compiler/rustc_mir_transform/src/instsimplify.rs fmt: formatted modified file compiler/rustc_mir_transform/src/validate.rs fmt: formatted modified file library/core/src/ptr/metadata.rs fmt: formatted modified file src/bootstrap/src/core/build_steps/format.rs ``` or (with `--all`): ``` fmt: checked 3148 files ``` --- src/bootstrap/src/core/build_steps/format.rs | 74 ++++++++++++-------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index f3e8d765dba6..aca1b82f530f 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -9,6 +9,7 @@ use std::collections::VecDeque; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::sync::mpsc::SyncSender; +use std::sync::Mutex; fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl FnMut(bool) -> bool { let mut cmd = Command::new(rustfmt); @@ -97,6 +98,21 @@ struct RustfmtConfig { ignore: Vec, } +// Prints output describing a collection of paths, with lines such as "formatted modified file +// foo/bar/baz" or "skipped 20 untracked files". +fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) { + let len = paths.len(); + let adjective = + if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() }; + if len <= 10 { + for path in paths { + println!("fmt: {verb} {adjective}file {path}"); + } + } else { + println!("fmt: {verb} {len} {adjective}files"); + } +} + pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { if !paths.is_empty() { eprintln!("fmt error: path arguments are not accepted"); @@ -149,6 +165,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { Err(_) => false, }; + let mut adjective = None; if git_available { let in_working_tree = match build .config @@ -172,45 +189,27 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { .arg("-z") .arg("--untracked-files=normal"), ); - let untracked_paths = untracked_paths_output.split_terminator('\0').filter_map( - |entry| entry.strip_prefix("?? "), // returns None if the prefix doesn't match - ); - let mut untracked_count = 0; + let untracked_paths: Vec<_> = untracked_paths_output + .split_terminator('\0') + .filter_map( + |entry| entry.strip_prefix("?? "), // returns None if the prefix doesn't match + ) + .map(|x| x.to_string()) + .collect(); + print_paths("skipped", Some("untracked"), &untracked_paths); + for untracked_path in untracked_paths { - println!("fmt: skip untracked path {untracked_path} during rustfmt invocations"); // The leading `/` makes it an exact match against the // repository root, rather than a glob. Without that, if you // have `foo.rs` in the repository root it will also match // against anything like `compiler/rustc_foo/src/foo.rs`, // preventing the latter from being formatted. - untracked_count += 1; - fmt_override.add(&format!("!/{untracked_path}")).expect(untracked_path); + fmt_override.add(&format!("!/{untracked_path}")).expect(&untracked_path); } if !all { + adjective = Some("modified"); match get_modified_rs_files(build) { Ok(Some(files)) => { - if files.len() <= 10 { - for file in &files { - println!("fmt: formatting modified file {file}"); - } - } else { - let pluralized = |count| if count > 1 { "files" } else { "file" }; - let untracked_msg = if untracked_count == 0 { - "".to_string() - } else { - format!( - ", skipped {} untracked {}", - untracked_count, - pluralized(untracked_count), - ) - }; - println!( - "fmt: formatting {} modified {}{}", - files.len(), - pluralized(files.len()), - untracked_msg - ); - } for file in files { fmt_override.add(&format!("/{file}")).expect(&file); } @@ -278,16 +277,33 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { } }); + let formatted_paths = Mutex::new(Vec::new()); + let formatted_paths_ref = &formatted_paths; walker.run(|| { let tx = tx.clone(); Box::new(move |entry| { + let cwd = std::env::current_dir(); let entry = t!(entry); if entry.file_type().map_or(false, |t| t.is_file()) { + formatted_paths_ref.lock().unwrap().push({ + // `into_path` produces an absolute path. Try to strip `cwd` to get a shorter + // relative path. + let mut path = entry.clone().into_path(); + if let Ok(cwd) = cwd { + if let Ok(path2) = path.strip_prefix(cwd) { + path = path2.to_path_buf(); + } + } + path.display().to_string() + }); t!(tx.send(entry.into_path())); } ignore::WalkState::Continue }) }); + let mut paths = formatted_paths.into_inner().unwrap(); + paths.sort(); + print_paths(if check { "checked" } else { "formatted" }, adjective, &paths); drop(tx); From a22cfccca2a80d15f6b015697e0ada9379d16f73 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 13:24:05 +1000 Subject: [PATCH 068/104] Rename `fmt_override`. It's a weird name, the `fmt_` prefix seems unnecessary. --- src/bootstrap/src/core/build_steps/format.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index aca1b82f530f..58342f2d902b 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -140,11 +140,11 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { } let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config)); let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config)); - let mut fmt_override = ignore::overrides::OverrideBuilder::new(&build.src); + let mut override_builder = ignore::overrides::OverrideBuilder::new(&build.src); for ignore in rustfmt_config.ignore { if ignore.starts_with('!') { - // A `!`-prefixed entry could be added as a whitelisted entry in `fmt_override`, i.e. - // strip the `!` prefix. But as soon as whitelisted entries are added, an + // A `!`-prefixed entry could be added as a whitelisted entry in `override_builder`, + // i.e. strip the `!` prefix. But as soon as whitelisted entries are added, an // `OverrideBuilder` will only traverse those whitelisted entries, and won't traverse // any files that aren't explicitly mentioned. No bueno! Maybe there's a way to combine // explicit whitelisted entries and traversal of unmentioned files, but for now just @@ -152,7 +152,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { eprintln!("fmt error: `!`-prefixed entries are not supported in rustfmt.toml, sorry"); crate::exit!(1); } else { - fmt_override.add(&format!("!{ignore}")).expect(&ignore); + override_builder.add(&format!("!{ignore}")).expect(&ignore); } } let git_available = match Command::new("git") @@ -204,14 +204,14 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { // have `foo.rs` in the repository root it will also match // against anything like `compiler/rustc_foo/src/foo.rs`, // preventing the latter from being formatted. - fmt_override.add(&format!("!/{untracked_path}")).expect(&untracked_path); + override_builder.add(&format!("!/{untracked_path}")).expect(&untracked_path); } if !all { adjective = Some("modified"); match get_modified_rs_files(build) { Ok(Some(files)) => { for file in files { - fmt_override.add(&format!("/{file}")).expect(&file); + override_builder.add(&format!("/{file}")).expect(&file); } } Ok(None) => {} @@ -229,7 +229,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { eprintln!("fmt: warning: Could not find usable git. Skipping git-aware format checks"); } - let fmt_override = fmt_override.build().unwrap(); + let override_ = override_builder.build().unwrap(); // `override` is a reserved keyword let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| { eprintln!("fmt error: `x fmt` is not supported on this channel"); @@ -238,8 +238,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { assert!(rustfmt_path.exists(), "{}", rustfmt_path.display()); let src = build.src.clone(); let (tx, rx): (SyncSender, _) = std::sync::mpsc::sync_channel(128); - let walker = - WalkBuilder::new(src.clone()).types(matcher).overrides(fmt_override).build_parallel(); + let walker = WalkBuilder::new(src.clone()).types(matcher).overrides(override_).build_parallel(); // There is a lot of blocking involved in spawning a child process and reading files to format. // Spawn more processes than available concurrency to keep the CPU busy. From 4dec0a0e9938c0762b6bfcce8b611d5096e32880 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 15:36:12 +1000 Subject: [PATCH 069/104] Clarify the closure in `rustfmt`. - Avoid calling `try_wait` followed immediately by `wait`. - Make the match exhaustive. - Improve the comment. --- src/bootstrap/src/core/build_steps/format.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 58342f2d902b..601e4e55e094 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -25,16 +25,19 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F cmd.args(paths); let cmd_debug = format!("{cmd:?}"); let mut cmd = cmd.spawn().expect("running rustfmt"); - // Poor man's async: return a closure that'll wait for rustfmt's completion. + // Poor man's async: return a closure that might wait for rustfmt's completion (depending on + // the value of the `block` argument). move |block: bool| -> bool { - if !block { + let status = if !block { match cmd.try_wait() { - Ok(Some(_)) => {} - _ => return false, + Ok(Some(status)) => Ok(status), + Ok(None) => return false, + Err(err) => Err(err), } - } - let status = cmd.wait().unwrap(); - if !status.success() { + } else { + cmd.wait() + }; + if !status.unwrap().success() { eprintln!( "fmt error: Running `{}` failed.\nIf you're running `tidy`, \ try again with `--bless`. Or, if you just want to format \ From bcfefe1c7e8de6c7b3ee79d402bb107303934e63 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 May 2024 08:28:44 +0000 Subject: [PATCH 070/104] Reintroduce name resolution check for trying to access locals from an inline const --- compiler/rustc_resolve/src/late.rs | 5 +++++ tests/ui/inline-const/referencing_local_variables.rs | 6 ++++++ .../inline-const/referencing_local_variables.stderr | 11 +++++++++++ 3 files changed, 22 insertions(+) create mode 100644 tests/ui/inline-const/referencing_local_variables.rs create mode 100644 tests/ui/inline-const/referencing_local_variables.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 08326d1ef57e..98dc507d8632 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4502,6 +4502,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.visit_expr(elem); self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes)); } + ExprKind::ConstBlock(ref expr) => { + self.resolve_anon_const_manual(false, AnonConstKind::InlineConst, |this| { + this.visit_expr(expr) + }); + } ExprKind::Index(ref elem, ref idx, _) => { self.resolve_expr(elem, Some(expr)); self.visit_expr(idx); diff --git a/tests/ui/inline-const/referencing_local_variables.rs b/tests/ui/inline-const/referencing_local_variables.rs new file mode 100644 index 000000000000..f9f0fef07f08 --- /dev/null +++ b/tests/ui/inline-const/referencing_local_variables.rs @@ -0,0 +1,6 @@ +const fn test_me(a: usize) -> usize { + const { a } + //~^ ERROR: attempt to use a non-constant value in a constant +} + +fn main() {} diff --git a/tests/ui/inline-const/referencing_local_variables.stderr b/tests/ui/inline-const/referencing_local_variables.stderr new file mode 100644 index 000000000000..4a0a54066024 --- /dev/null +++ b/tests/ui/inline-const/referencing_local_variables.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/referencing_local_variables.rs:2:13 + | +LL | const fn test_me(a: usize) -> usize { + | - this would need to be a `const` +LL | const { a } + | ^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0435`. From ca68c931351a83f6a796cd9861b5af56dd0c0704 Mon Sep 17 00:00:00 2001 From: surechen Date: Sat, 25 May 2024 09:55:49 +0800 Subject: [PATCH 071/104] Let lint_dropping_references give the suggestion if possible. --- compiler/rustc_lint/messages.ftl | 1 + .../rustc_lint/src/drop_forget_useless.rs | 16 ++- compiler/rustc_lint/src/lints.rs | 16 ++- .../lint/dropping_references-can-fixed.fixed | 31 +++++ .../ui/lint/dropping_references-can-fixed.rs | 31 +++++ .../lint/dropping_references-can-fixed.stderr | 119 ++++++++++++++++++ tests/ui/lint/dropping_references.stderr | 60 +++++++-- 7 files changed, 261 insertions(+), 13 deletions(-) create mode 100644 tests/ui/lint/dropping_references-can-fixed.fixed create mode 100644 tests/ui/lint/dropping_references-can-fixed.rs create mode 100644 tests/ui/lint/dropping_references-can-fixed.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d2b1f50d79cb..805001718eac 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -238,6 +238,7 @@ lint_dropping_copy_types = calls to `std::mem::drop` with a value that implement lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result + .suggestion = use `let _ = ...` to ignore the expression or result lint_duplicate_macro_attribute = duplicated attribute diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 02d324520b85..3166556448b4 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -5,7 +5,7 @@ use rustc_span::sym; use crate::{ lints::{ - DropCopyDiag, DropCopySuggestion, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, + DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, IgnoreDropSuggestion, UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, }, LateContext, LateLintPass, LintContext, @@ -148,12 +148,24 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { let arg_ty = cx.typeck_results().expr_ty(arg); let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); + let sugg = if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) + && let Node::Stmt(stmt) = node + && let StmtKind::Semi(e) = stmt.kind + && e.hir_id == expr.hir_id + { + IgnoreDropSuggestion::Suggestion { + start_span: expr.span.shrink_to_lo().until(arg.span), + end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + } + } else { + IgnoreDropSuggestion::Note + }; match fn_name { sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => { cx.emit_span_lint( DROPPING_REFERENCES, expr.span, - DropRefDiag { arg_ty, label: arg.span }, + DropRefDiag { arg_ty, label: arg.span, sugg }, ); } sym::mem_forget if arg_ty.is_ref() => { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c365e68ba44d..1c061ce25a6f 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -656,14 +656,28 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> { pub end_span: Span, } +#[derive(Subdiagnostic)] +pub enum IgnoreDropSuggestion { + #[note(lint_note)] + Note, + #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + Suggestion { + #[suggestion_part(code = "let _ = ")] + start_span: Span, + #[suggestion_part(code = "")] + end_span: Span, + }, +} + // drop_forget_useless.rs #[derive(LintDiagnostic)] #[diag(lint_dropping_references)] -#[note] pub struct DropRefDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: IgnoreDropSuggestion, } #[derive(LintDiagnostic)] diff --git a/tests/ui/lint/dropping_references-can-fixed.fixed b/tests/ui/lint/dropping_references-can-fixed.fixed new file mode 100644 index 000000000000..f704d3c72df7 --- /dev/null +++ b/tests/ui/lint/dropping_references-can-fixed.fixed @@ -0,0 +1,31 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_references)] + +struct SomeStruct; + +fn main() { + let _ = &SomeStruct; //~ ERROR calls to `std::mem::drop` + + let mut owned1 = SomeStruct; + let _ = &owned1; //~ ERROR calls to `std::mem::drop` + let _ = &&owned1; //~ ERROR calls to `std::mem::drop` + let _ = &mut owned1; //~ ERROR calls to `std::mem::drop` + drop(owned1); + + let reference1 = &SomeStruct; + let _ = reference1; //~ ERROR calls to `std::mem::drop` + + let reference2 = &mut SomeStruct; + let _ = reference2; //~ ERROR calls to `std::mem::drop` + + let ref reference3 = SomeStruct; + let _ = reference3; //~ ERROR calls to `std::mem::drop` +} + +#[allow(dead_code)] +fn test_generic_fn_drop(val: T) { + let _ = &val; //~ ERROR calls to `std::mem::drop` + drop(val); +} diff --git a/tests/ui/lint/dropping_references-can-fixed.rs b/tests/ui/lint/dropping_references-can-fixed.rs new file mode 100644 index 000000000000..70d1c16d66b4 --- /dev/null +++ b/tests/ui/lint/dropping_references-can-fixed.rs @@ -0,0 +1,31 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_references)] + +struct SomeStruct; + +fn main() { + drop(&SomeStruct); //~ ERROR calls to `std::mem::drop` + + let mut owned1 = SomeStruct; + drop(&owned1); //~ ERROR calls to `std::mem::drop` + drop(&&owned1); //~ ERROR calls to `std::mem::drop` + drop(&mut owned1); //~ ERROR calls to `std::mem::drop` + drop(owned1); + + let reference1 = &SomeStruct; + drop(reference1); //~ ERROR calls to `std::mem::drop` + + let reference2 = &mut SomeStruct; + drop(reference2); //~ ERROR calls to `std::mem::drop` + + let ref reference3 = SomeStruct; + drop(reference3); //~ ERROR calls to `std::mem::drop` +} + +#[allow(dead_code)] +fn test_generic_fn_drop(val: T) { + drop(&val); //~ ERROR calls to `std::mem::drop` + drop(val); +} diff --git a/tests/ui/lint/dropping_references-can-fixed.stderr b/tests/ui/lint/dropping_references-can-fixed.stderr new file mode 100644 index 000000000000..42cdb81b524a --- /dev/null +++ b/tests/ui/lint/dropping_references-can-fixed.stderr @@ -0,0 +1,119 @@ +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:9:5 + | +LL | drop(&SomeStruct); + | ^^^^^-----------^ + | | + | argument has type `&SomeStruct` + | +note: the lint level is defined here + --> $DIR/dropping_references-can-fixed.rs:4:9 + | +LL | #![deny(dropping_references)] + | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&SomeStruct); +LL + let _ = &SomeStruct; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:12:5 + | +LL | drop(&owned1); + | ^^^^^-------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&owned1); +LL + let _ = &owned1; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:13:5 + | +LL | drop(&&owned1); + | ^^^^^--------^ + | | + | argument has type `&&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&&owned1); +LL + let _ = &&owned1; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:14:5 + | +LL | drop(&mut owned1); + | ^^^^^-----------^ + | | + | argument has type `&mut SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&mut owned1); +LL + let _ = &mut owned1; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:18:5 + | +LL | drop(reference1); + | ^^^^^----------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference1); +LL + let _ = reference1; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:21:5 + | +LL | drop(reference2); + | ^^^^^----------^ + | | + | argument has type `&mut SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference2); +LL + let _ = reference2; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:24:5 + | +LL | drop(reference3); + | ^^^^^----------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference3); +LL + let _ = reference3; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:29:5 + | +LL | drop(&val); + | ^^^^^----^ + | | + | argument has type `&T` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&val); +LL + let _ = &val; + | + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lint/dropping_references.stderr b/tests/ui/lint/dropping_references.stderr index 7e25a46216ec..312334b82ad4 100644 --- a/tests/ui/lint/dropping_references.stderr +++ b/tests/ui/lint/dropping_references.stderr @@ -6,12 +6,16 @@ LL | drop(&SomeStruct); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/dropping_references.rs:3:9 | LL | #![warn(dropping_references)] | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&SomeStruct); +LL + let _ = &SomeStruct; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:11:5 @@ -21,7 +25,11 @@ LL | drop(&owned1); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&owned1); +LL + let _ = &owned1; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:12:5 @@ -31,7 +39,11 @@ LL | drop(&&owned1); | | | argument has type `&&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&&owned1); +LL + let _ = &&owned1; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:13:5 @@ -41,7 +53,11 @@ LL | drop(&mut owned1); | | | argument has type `&mut SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&mut owned1); +LL + let _ = &mut owned1; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:17:5 @@ -51,7 +67,11 @@ LL | drop(reference1); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference1); +LL + let _ = reference1; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:20:5 @@ -61,7 +81,11 @@ LL | drop(reference2); | | | argument has type `&mut SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference2); +LL + let _ = reference2; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:23:5 @@ -71,7 +95,11 @@ LL | drop(reference3); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference3); +LL + let _ = reference3; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:28:5 @@ -81,7 +109,11 @@ LL | drop(&val); | | | argument has type `&T` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&val); +LL + let _ = &val; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:36:5 @@ -91,7 +123,11 @@ LL | std::mem::drop(&SomeStruct); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - std::mem::drop(&SomeStruct); +LL + let _ = &SomeStruct; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:91:13 @@ -101,7 +137,11 @@ LL | drop(println_and(&13)); | | | argument has type `&i32` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(println_and(&13)); +LL + let _ = println_and(&13); + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:94:14 From d7f0d1f56430d2832629023c259721be131ec6cb Mon Sep 17 00:00:00 2001 From: surechen Date: Sat, 25 May 2024 11:04:13 +0800 Subject: [PATCH 072/104] Let lint_forgetting_copy_types give the suggestion if possible. --- compiler/rustc_lint/messages.ftl | 2 + .../rustc_lint/src/drop_forget_useless.rs | 2 +- compiler/rustc_lint/src/lints.rs | 3 +- .../forgetting_copy_types-can-fixed.fixed | 22 +++++++++ .../lint/forgetting_copy_types-can-fixed.rs | 22 +++++++++ .../forgetting_copy_types-can-fixed.stderr | 49 +++++++++++++++++++ tests/ui/lint/forgetting_copy_types.stderr | 18 +++++-- 7 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 tests/ui/lint/forgetting_copy_types-can-fixed.fixed create mode 100644 tests/ui/lint/forgetting_copy_types-can-fixed.rs create mode 100644 tests/ui/lint/forgetting_copy_types-can-fixed.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 805001718eac..ecd8bafe0ad0 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -274,6 +274,8 @@ lint_for_loops_over_fallibles = lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result + .suggestion = use `let _ = ...` to ignore the expression or result + lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 3166556448b4..8b8a8f732e78 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -199,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { cx.emit_span_lint( FORGETTING_COPY_TYPES, expr.span, - ForgetCopyDiag { arg_ty, label: arg.span }, + ForgetCopyDiag { arg_ty, label: arg.span, sugg }, ); } sym::mem_drop diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1c061ce25a6f..a91180dfb240 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -714,11 +714,12 @@ pub struct ForgetRefDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_forgetting_copy_types)] -#[note] pub struct ForgetCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: IgnoreDropSuggestion, } #[derive(LintDiagnostic)] diff --git a/tests/ui/lint/forgetting_copy_types-can-fixed.fixed b/tests/ui/lint/forgetting_copy_types-can-fixed.fixed new file mode 100644 index 000000000000..c5d65ecc1d42 --- /dev/null +++ b/tests/ui/lint/forgetting_copy_types-can-fixed.fixed @@ -0,0 +1,22 @@ +//@ check-fail +//@ run-rustfix + +#![deny(forgetting_copy_types)] +#![allow(unused_mut)] +#![allow(unused_imports)] + +use std::vec::Vec; +use std::mem::forget; + +#[derive(Copy, Clone)] +struct SomeStruct; + +fn main() { + let s1 = SomeStruct {}; + let s2 = s1; + let mut s3 = s1; + + let _ = s1; //~ ERROR calls to `std::mem::forget` + let _ = s2; //~ ERROR calls to `std::mem::forget` + let _ = s3; //~ ERROR calls to `std::mem::forget` +} diff --git a/tests/ui/lint/forgetting_copy_types-can-fixed.rs b/tests/ui/lint/forgetting_copy_types-can-fixed.rs new file mode 100644 index 000000000000..c55722942800 --- /dev/null +++ b/tests/ui/lint/forgetting_copy_types-can-fixed.rs @@ -0,0 +1,22 @@ +//@ check-fail +//@ run-rustfix + +#![deny(forgetting_copy_types)] +#![allow(unused_mut)] +#![allow(unused_imports)] + +use std::vec::Vec; +use std::mem::forget; + +#[derive(Copy, Clone)] +struct SomeStruct; + +fn main() { + let s1 = SomeStruct {}; + let s2 = s1; + let mut s3 = s1; + + forget(s1); //~ ERROR calls to `std::mem::forget` + forget(s2); //~ ERROR calls to `std::mem::forget` + forget(s3); //~ ERROR calls to `std::mem::forget` +} diff --git a/tests/ui/lint/forgetting_copy_types-can-fixed.stderr b/tests/ui/lint/forgetting_copy_types-can-fixed.stderr new file mode 100644 index 000000000000..cb7bbf02222e --- /dev/null +++ b/tests/ui/lint/forgetting_copy_types-can-fixed.stderr @@ -0,0 +1,49 @@ +error: calls to `std::mem::forget` with a value that implements `Copy` does nothing + --> $DIR/forgetting_copy_types-can-fixed.rs:19:5 + | +LL | forget(s1); + | ^^^^^^^--^ + | | + | argument has type `SomeStruct` + | +note: the lint level is defined here + --> $DIR/forgetting_copy_types-can-fixed.rs:4:9 + | +LL | #![deny(forgetting_copy_types)] + | ^^^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s1); +LL + let _ = s1; + | + +error: calls to `std::mem::forget` with a value that implements `Copy` does nothing + --> $DIR/forgetting_copy_types-can-fixed.rs:20:5 + | +LL | forget(s2); + | ^^^^^^^--^ + | | + | argument has type `SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s2); +LL + let _ = s2; + | + +error: calls to `std::mem::forget` with a value that implements `Copy` does nothing + --> $DIR/forgetting_copy_types-can-fixed.rs:21:5 + | +LL | forget(s3); + | ^^^^^^^--^ + | | + | argument has type `SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s3); +LL + let _ = s3; + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/forgetting_copy_types.stderr b/tests/ui/lint/forgetting_copy_types.stderr index 36d1ef5c53e9..a2b07351d790 100644 --- a/tests/ui/lint/forgetting_copy_types.stderr +++ b/tests/ui/lint/forgetting_copy_types.stderr @@ -6,12 +6,16 @@ LL | forget(s1); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/forgetting_copy_types.rs:3:9 | LL | #![warn(forgetting_copy_types)] | ^^^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s1); +LL + let _ = s1; + | warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing --> $DIR/forgetting_copy_types.rs:35:5 @@ -21,7 +25,11 @@ LL | forget(s2); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s2); +LL + let _ = s2; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:36:5 @@ -42,7 +50,11 @@ LL | forget(s4); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s4); +LL + let _ = s4; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:38:5 From eafe80f5d9c0b0703d548fe9916dac62ba89791c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 May 2024 11:21:17 +0200 Subject: [PATCH 073/104] tier 3 target policy: clarify the point about producing assembly --- src/doc/rustc/src/target-tier-policy.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index 48b58f6f06ad..e9cf2a0d1ae5 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -247,7 +247,8 @@ approved by the appropriate team for that shared code before acceptance. target may not have; use conditional compilation or runtime detection, as appropriate, to let each target run code supported by that target. - Tier 3 targets must be able to produce assembly using at least one of - rustc's supported backends from any host target. + rustc's supported backends from any host target. (Having support in a fork + of the backend is not sufficient, it must be upstream.) If a tier 3 target stops meeting these requirements, or the target maintainers no longer have interest or time, or the target shows no signs of activity and From ac736d6d8887349c4dacb1fa19cccebf7dae13fd Mon Sep 17 00:00:00 2001 From: surechen Date: Sat, 25 May 2024 11:44:14 +0800 Subject: [PATCH 074/104] Let lint_forgetting_references give the suggestion if possible --- compiler/rustc_lint/messages.ftl | 7 +- .../rustc_lint/src/drop_forget_useless.rs | 39 +++-- compiler/rustc_lint/src/lints.rs | 17 ++- tests/ui/lint/dropping_copy_types.stderr | 24 +++- tests/ui/lint/forgetting_copy_types.stderr | 30 +++- .../forgetting_references-can-fixed.fixed | 40 ++++++ .../lint/forgetting_references-can-fixed.rs | 40 ++++++ .../forgetting_references-can-fixed.stderr | 133 ++++++++++++++++++ tests/ui/lint/forgetting_references.rs | 10 ++ tests/ui/lint/forgetting_references.stderr | 88 ++++++++++-- 10 files changed, 383 insertions(+), 45 deletions(-) create mode 100644 tests/ui/lint/forgetting_references-can-fixed.fixed create mode 100644 tests/ui/lint/forgetting_references-can-fixed.rs create mode 100644 tests/ui/lint/forgetting_references-can-fixed.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index ecd8bafe0ad0..49c95ad935d4 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -237,8 +237,6 @@ lint_dropping_copy_types = calls to `std::mem::drop` with a value that implement lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` - .note = use `let _ = ...` to ignore the expression or result - .suggestion = use `let _ = ...` to ignore the expression or result lint_duplicate_macro_attribute = duplicated attribute @@ -273,12 +271,9 @@ lint_for_loops_over_fallibles = lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing .label = argument has type `{$arg_ty}` - .note = use `let _ = ...` to ignore the expression or result - .suggestion = use `let _ = ...` to ignore the expression or result lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` - .note = use `let _ = ...` to ignore the expression or result lint_hidden_glob_reexport = private item shadows public glob re-export .note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here @@ -897,6 +892,8 @@ lint_unused_op = unused {$op} that must be used lint_unused_result = unused result of type `{$ty}` +lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result + lint_variant_size_differences = enum variant is more than three times larger ({$largest} bytes) than the next largest diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 8b8a8f732e78..2c0973404eef 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -5,8 +5,9 @@ use rustc_span::sym; use crate::{ lints::{ - DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, IgnoreDropSuggestion, + DropCopyDiag, DropCopySuggestion, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, + UseLetUnderscoreIgnoreSuggestion, }, LateContext, LateLintPass, LintContext, }; @@ -148,31 +149,37 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { let arg_ty = cx.typeck_results().expr_ty(arg); let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); - let sugg = if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) - && let Node::Stmt(stmt) = node - && let StmtKind::Semi(e) = stmt.kind - && e.hir_id == expr.hir_id - { - IgnoreDropSuggestion::Suggestion { - start_span: expr.span.shrink_to_lo().until(arg.span), - end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + let let_underscore_ignore_sugg = || { + if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) + && let Node::Stmt(stmt) = node + && let StmtKind::Semi(e) = stmt.kind + && e.hir_id == expr.hir_id + { + UseLetUnderscoreIgnoreSuggestion::Suggestion { + start_span: expr.span.shrink_to_lo().until(arg.span), + end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + } + } else { + UseLetUnderscoreIgnoreSuggestion::Note } - } else { - IgnoreDropSuggestion::Note }; match fn_name { sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => { cx.emit_span_lint( DROPPING_REFERENCES, expr.span, - DropRefDiag { arg_ty, label: arg.span, sugg }, + DropRefDiag { arg_ty, label: arg.span, sugg: let_underscore_ignore_sugg() }, ); } sym::mem_forget if arg_ty.is_ref() => { cx.emit_span_lint( FORGETTING_REFERENCES, expr.span, - ForgetRefDiag { arg_ty, label: arg.span }, + ForgetRefDiag { + arg_ty, + label: arg.span, + sugg: let_underscore_ignore_sugg(), + }, ); } sym::mem_drop if is_copy && !drop_is_single_call_in_arm => { @@ -199,7 +206,11 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { cx.emit_span_lint( FORGETTING_COPY_TYPES, expr.span, - ForgetCopyDiag { arg_ty, label: arg.span, sugg }, + ForgetCopyDiag { + arg_ty, + label: arg.span, + sugg: let_underscore_ignore_sugg(), + }, ); } sym::mem_drop diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a91180dfb240..4705bbd5bf6a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -657,10 +657,14 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> { } #[derive(Subdiagnostic)] -pub enum IgnoreDropSuggestion { - #[note(lint_note)] +pub enum UseLetUnderscoreIgnoreSuggestion { + #[note(lint_use_let_underscore_ignore_suggestion)] Note, - #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + #[multipart_suggestion( + lint_use_let_underscore_ignore_suggestion, + style = "verbose", + applicability = "maybe-incorrect" + )] Suggestion { #[suggestion_part(code = "let _ = ")] start_span: Span, @@ -677,7 +681,7 @@ pub struct DropRefDiag<'a> { #[label] pub label: Span, #[subdiagnostic] - pub sugg: IgnoreDropSuggestion, + pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] @@ -705,11 +709,12 @@ pub enum DropCopySuggestion { #[derive(LintDiagnostic)] #[diag(lint_forgetting_references)] -#[note] pub struct ForgetRefDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] @@ -719,7 +724,7 @@ pub struct ForgetCopyDiag<'a> { #[label] pub label: Span, #[subdiagnostic] - pub sugg: IgnoreDropSuggestion, + pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] diff --git a/tests/ui/lint/dropping_copy_types.stderr b/tests/ui/lint/dropping_copy_types.stderr index bdeb0c290fe9..41aa66a4efc6 100644 --- a/tests/ui/lint/dropping_copy_types.stderr +++ b/tests/ui/lint/dropping_copy_types.stderr @@ -39,8 +39,12 @@ LL | drop(s3); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_references)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s3); +LL + let _ = s3; + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:37:5 @@ -64,7 +68,11 @@ LL | drop(s5); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s5); +LL + let _ = s5; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:50:5 @@ -74,7 +82,11 @@ LL | drop(a2); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(a2); +LL + let _ = a2; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:52:5 @@ -84,7 +96,11 @@ LL | drop(a4); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(a4); +LL + let _ = a4; + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:71:13 diff --git a/tests/ui/lint/forgetting_copy_types.stderr b/tests/ui/lint/forgetting_copy_types.stderr index a2b07351d790..980ee6caba25 100644 --- a/tests/ui/lint/forgetting_copy_types.stderr +++ b/tests/ui/lint/forgetting_copy_types.stderr @@ -39,8 +39,12 @@ LL | forget(s3); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(forgetting_references)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s3); +LL + let _ = s3; + | warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing --> $DIR/forgetting_copy_types.rs:37:5 @@ -64,7 +68,11 @@ LL | forget(s5); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s5); +LL + let _ = s5; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:50:5 @@ -74,7 +82,11 @@ LL | forget(a2); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(a2); +LL + let _ = a2; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:52:5 @@ -84,7 +96,11 @@ LL | forget(a3); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(a3); +LL + let _ = a3; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:53:5 @@ -94,7 +110,11 @@ LL | forget(a4); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(a4); +LL + let _ = a4; + | warning: 8 warnings emitted diff --git a/tests/ui/lint/forgetting_references-can-fixed.fixed b/tests/ui/lint/forgetting_references-can-fixed.fixed new file mode 100644 index 000000000000..64475f042840 --- /dev/null +++ b/tests/ui/lint/forgetting_references-can-fixed.fixed @@ -0,0 +1,40 @@ +//@ check-fail +//@ run-rustfix + +#![deny(forgetting_references)] + +use std::mem::forget; + +struct SomeStruct; + +fn main() { + let _ = &SomeStruct; //~ ERROR calls to `std::mem::forget` + + let mut owned = SomeStruct; + let _ = &owned; //~ ERROR calls to `std::mem::forget` + let _ = &&owned; //~ ERROR calls to `std::mem::forget` + let _ = &mut owned; //~ ERROR calls to `std::mem::forget` + forget(owned); + + let reference1 = &SomeStruct; + let _ = &*reference1; //~ ERROR calls to `std::mem::forget` + + let reference2 = &mut SomeStruct; + let _ = reference2; //~ ERROR calls to `std::mem::forget` + + let ref reference3 = SomeStruct; + let _ = reference3; //~ ERROR calls to `std::mem::forget` +} + +#[allow(dead_code)] +fn test_generic_fn_forget(val: T) { + let _ = &val; //~ ERROR calls to `std::mem::forget` + forget(val); +} + +#[allow(dead_code)] +fn test_similarly_named_function() { + fn forget(_val: T) {} + forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name + let _ = &SomeStruct; //~ ERROR calls to `std::mem::forget` +} diff --git a/tests/ui/lint/forgetting_references-can-fixed.rs b/tests/ui/lint/forgetting_references-can-fixed.rs new file mode 100644 index 000000000000..4c9ef541d341 --- /dev/null +++ b/tests/ui/lint/forgetting_references-can-fixed.rs @@ -0,0 +1,40 @@ +//@ check-fail +//@ run-rustfix + +#![deny(forgetting_references)] + +use std::mem::forget; + +struct SomeStruct; + +fn main() { + forget(&SomeStruct); //~ ERROR calls to `std::mem::forget` + + let mut owned = SomeStruct; + forget(&owned); //~ ERROR calls to `std::mem::forget` + forget(&&owned); //~ ERROR calls to `std::mem::forget` + forget(&mut owned); //~ ERROR calls to `std::mem::forget` + forget(owned); + + let reference1 = &SomeStruct; + forget(&*reference1); //~ ERROR calls to `std::mem::forget` + + let reference2 = &mut SomeStruct; + forget(reference2); //~ ERROR calls to `std::mem::forget` + + let ref reference3 = SomeStruct; + forget(reference3); //~ ERROR calls to `std::mem::forget` +} + +#[allow(dead_code)] +fn test_generic_fn_forget(val: T) { + forget(&val); //~ ERROR calls to `std::mem::forget` + forget(val); +} + +#[allow(dead_code)] +fn test_similarly_named_function() { + fn forget(_val: T) {} + forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name + std::mem::forget(&SomeStruct); //~ ERROR calls to `std::mem::forget` +} diff --git a/tests/ui/lint/forgetting_references-can-fixed.stderr b/tests/ui/lint/forgetting_references-can-fixed.stderr new file mode 100644 index 000000000000..05eb636ab459 --- /dev/null +++ b/tests/ui/lint/forgetting_references-can-fixed.stderr @@ -0,0 +1,133 @@ +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:11:5 + | +LL | forget(&SomeStruct); + | ^^^^^^^-----------^ + | | + | argument has type `&SomeStruct` + | +note: the lint level is defined here + --> $DIR/forgetting_references-can-fixed.rs:4:9 + | +LL | #![deny(forgetting_references)] + | ^^^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&SomeStruct); +LL + let _ = &SomeStruct; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:14:5 + | +LL | forget(&owned); + | ^^^^^^^------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&owned); +LL + let _ = &owned; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:15:5 + | +LL | forget(&&owned); + | ^^^^^^^-------^ + | | + | argument has type `&&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&&owned); +LL + let _ = &&owned; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:16:5 + | +LL | forget(&mut owned); + | ^^^^^^^----------^ + | | + | argument has type `&mut SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&mut owned); +LL + let _ = &mut owned; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:20:5 + | +LL | forget(&*reference1); + | ^^^^^^^------------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&*reference1); +LL + let _ = &*reference1; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:23:5 + | +LL | forget(reference2); + | ^^^^^^^----------^ + | | + | argument has type `&mut SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(reference2); +LL + let _ = reference2; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:26:5 + | +LL | forget(reference3); + | ^^^^^^^----------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(reference3); +LL + let _ = reference3; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:31:5 + | +LL | forget(&val); + | ^^^^^^^----^ + | | + | argument has type `&T` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&val); +LL + let _ = &val; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:39:5 + | +LL | std::mem::forget(&SomeStruct); + | ^^^^^^^^^^^^^^^^^-----------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - std::mem::forget(&SomeStruct); +LL + let _ = &SomeStruct; + | + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/forgetting_references.rs b/tests/ui/lint/forgetting_references.rs index ecfa23ee4970..d0ec2a77ab1c 100644 --- a/tests/ui/lint/forgetting_references.rs +++ b/tests/ui/lint/forgetting_references.rs @@ -23,6 +23,16 @@ fn main() { let ref reference3 = SomeStruct; forget(reference3); //~ WARN calls to `std::mem::forget` + + let ref reference4 = SomeStruct; + + let a = 1; + match a { + 1 => forget(&*reference1), //~ WARN calls to `std::mem::forget` + 2 => forget(reference3), //~ WARN calls to `std::mem::forget` + 3 => forget(reference4), //~ WARN calls to `std::mem::forget` + _ => {} + } } #[allow(dead_code)] diff --git a/tests/ui/lint/forgetting_references.stderr b/tests/ui/lint/forgetting_references.stderr index 5624b690789f..afd5030a6805 100644 --- a/tests/ui/lint/forgetting_references.stderr +++ b/tests/ui/lint/forgetting_references.stderr @@ -6,12 +6,16 @@ LL | forget(&SomeStruct); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/forgetting_references.rs:3:9 | LL | #![warn(forgetting_references)] | ^^^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&SomeStruct); +LL + let _ = &SomeStruct; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:13:5 @@ -21,7 +25,11 @@ LL | forget(&owned); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&owned); +LL + let _ = &owned; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:14:5 @@ -31,7 +39,11 @@ LL | forget(&&owned); | | | argument has type `&&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&&owned); +LL + let _ = &&owned; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:15:5 @@ -41,7 +53,11 @@ LL | forget(&mut owned); | | | argument has type `&mut SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&mut owned); +LL + let _ = &mut owned; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:19:5 @@ -51,7 +67,11 @@ LL | forget(&*reference1); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&*reference1); +LL + let _ = &*reference1; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:22:5 @@ -61,7 +81,11 @@ LL | forget(reference2); | | | argument has type `&mut SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(reference2); +LL + let _ = reference2; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:25:5 @@ -71,27 +95,69 @@ LL | forget(reference3); | | | argument has type `&SomeStruct` | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(reference3); +LL + let _ = reference3; + | + +warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references.rs:31:14 + | +LL | 1 => forget(&*reference1), + | ^^^^^^^------------^ + | | + | argument has type `&SomeStruct` + | = note: use `let _ = ...` to ignore the expression or result warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing - --> $DIR/forgetting_references.rs:30:5 + --> $DIR/forgetting_references.rs:32:14 + | +LL | 2 => forget(reference3), + | ^^^^^^^----------^ + | | + | argument has type `&SomeStruct` + | + = note: use `let _ = ...` to ignore the expression or result + +warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references.rs:33:14 + | +LL | 3 => forget(reference4), + | ^^^^^^^----------^ + | | + | argument has type `&SomeStruct` + | + = note: use `let _ = ...` to ignore the expression or result + +warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references.rs:40:5 | LL | forget(&val); | ^^^^^^^----^ | | | argument has type `&T` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&val); +LL + let _ = &val; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing - --> $DIR/forgetting_references.rs:38:5 + --> $DIR/forgetting_references.rs:48:5 | LL | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^-----------^ | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - std::mem::forget(&SomeStruct); +LL + let _ = &SomeStruct; + | -warning: 9 warnings emitted +warning: 12 warnings emitted From 7845c6e09ca2b9fec6494bbfd5ca3e8af257314b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 29 May 2024 16:16:45 +1000 Subject: [PATCH 075/104] coverage: Avoid overflow when the MC/DC condition limit is exceeded If we perform this subtraction and then add 1, the subtraction can sometimes overflow to -1 before the addition can bring its value back to 0. That behaviour seems to be benign, but it nevertheless causes test failures in compiler configurations that check for overflow. We can avoid the overflow by instead subtracting (N - 1), which is algebraically equivalent, and more closely matches what the code is actually trying to do. --- compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs index 9cfb25e663d1..728b63d5b21b 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs @@ -217,12 +217,13 @@ impl MCDCInfoBuilder { } _ => { // Do not generate mcdc mappings and statements for decisions with too many conditions. - let rebase_idx = self.branch_spans.len() - decision.conditions_num + 1; + // Therefore, first erase the condition info of the (N-1) previous branch spans. + let rebase_idx = self.branch_spans.len() - (decision.conditions_num - 1); for branch in &mut self.branch_spans[rebase_idx..] { branch.condition_info = None; } - // ConditionInfo of this branch shall also be reset. + // Then, erase this last branch span's info too, for a total of N. condition_info = None; tcx.dcx().emit_warn(MCDCExceedsConditionNumLimit { From 9d1ed80a8af72ad6918809861697e76ec38df178 Mon Sep 17 00:00:00 2001 From: surechen Date: Wed, 29 May 2024 18:09:20 +0800 Subject: [PATCH 076/104] Change lint_dropping_copy_types to use UseLetUnderscoreIgnoreSuggestion as suggestion. --- compiler/rustc_lint/messages.ftl | 2 -- .../rustc_lint/src/drop_forget_useless.rs | 24 ++++++------------- compiler/rustc_lint/src/lints.rs | 15 +----------- 3 files changed, 8 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 49c95ad935d4..fb71cb601402 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -232,8 +232,6 @@ lint_drop_trait_constraints = lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing .label = argument has type `{$arg_ty}` - .note = use `let _ = ...` to ignore the expression or result - .suggestion = use `let _ = ...` to ignore the expression or result lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 2c0973404eef..eea0898d83fa 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -5,9 +5,8 @@ use rustc_span::sym; use crate::{ lints::{ - DropCopyDiag, DropCopySuggestion, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, - UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, - UseLetUnderscoreIgnoreSuggestion, + DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag, + UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion, }, LateContext, LateLintPass, LintContext, }; @@ -183,23 +182,14 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { ); } sym::mem_drop if is_copy && !drop_is_single_call_in_arm => { - let sugg = if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) - && let Node::Stmt(stmt) = node - && let StmtKind::Semi(e) = stmt.kind - && e.hir_id == expr.hir_id - { - DropCopySuggestion::Suggestion { - start_span: expr.span.shrink_to_lo().until(arg.span), - end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), - } - } else { - DropCopySuggestion::Note - }; - cx.emit_span_lint( DROPPING_COPY_TYPES, expr.span, - DropCopyDiag { arg_ty, label: arg.span, sugg }, + DropCopyDiag { + arg_ty, + label: arg.span, + sugg: let_underscore_ignore_sugg(), + }, ); } sym::mem_forget if is_copy => { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 4705bbd5bf6a..84d46ef3b65d 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -691,20 +691,7 @@ pub struct DropCopyDiag<'a> { #[label] pub label: Span, #[subdiagnostic] - pub sugg: DropCopySuggestion, -} - -#[derive(Subdiagnostic)] -pub enum DropCopySuggestion { - #[note(lint_note)] - Note, - #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] - Suggestion { - #[suggestion_part(code = "let _ = ")] - start_span: Span, - #[suggestion_part(code = "")] - end_span: Span, - }, + pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] From 34a1828feab6bc634e629849ad73db7042e5c8a5 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 1 May 2024 10:44:31 +1000 Subject: [PATCH 077/104] coverage: Add tests for the MC/DC condition limit --- tests/coverage/mcdc/condition-limit.cov-map | 162 ++++++++++++++++++ tests/coverage/mcdc/condition-limit.coverage | 76 ++++++++ tests/coverage/mcdc/condition-limit.rs | 32 ++++ .../mcdc-condition-limit.bad.stderr | 8 + .../mcdc-condition-limit.rs | 32 ++++ 5 files changed, 310 insertions(+) create mode 100644 tests/coverage/mcdc/condition-limit.cov-map create mode 100644 tests/coverage/mcdc/condition-limit.coverage create mode 100644 tests/coverage/mcdc/condition-limit.rs create mode 100644 tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr create mode 100644 tests/ui/instrument-coverage/mcdc-condition-limit.rs diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map new file mode 100644 index 000000000000..b4447a33691a --- /dev/null +++ b/tests/coverage/mcdc/condition-limit.cov-map @@ -0,0 +1,162 @@ +Function name: condition_limit::bad +Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 14, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 44 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Counter(7) +- expression 2 operands: lhs = Counter(1), rhs = Counter(7) +- expression 3 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 4 operands: lhs = Counter(1), rhs = Counter(7) +- expression 5 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 6 operands: lhs = Counter(1), rhs = Counter(7) +- expression 7 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 8 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 9 operands: lhs = Counter(1), rhs = Counter(7) +- expression 10 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 11 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 12 operands: lhs = Counter(1), rhs = Counter(7) +- expression 13 operands: lhs = Expression(28, Sub), rhs = Counter(4) +- expression 14 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 15 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 16 operands: lhs = Counter(1), rhs = Counter(7) +- expression 17 operands: lhs = Expression(28, Sub), rhs = Counter(4) +- expression 18 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 19 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 20 operands: lhs = Counter(1), rhs = Counter(7) +- expression 21 operands: lhs = Expression(27, Sub), rhs = Counter(3) +- expression 22 operands: lhs = Expression(28, Sub), rhs = Counter(4) +- expression 23 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 24 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 25 operands: lhs = Counter(1), rhs = Counter(7) +- expression 26 operands: lhs = Expression(27, Sub), rhs = Counter(3) +- expression 27 operands: lhs = Expression(28, Sub), rhs = Counter(4) +- expression 28 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 29 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 30 operands: lhs = Counter(1), rhs = Counter(7) +- expression 31 operands: lhs = Expression(39, Add), rhs = Expression(0, Sub) +- expression 32 operands: lhs = Expression(40, Add), rhs = Counter(7) +- expression 33 operands: lhs = Expression(41, Add), rhs = Counter(6) +- expression 34 operands: lhs = Expression(42, Add), rhs = Counter(5) +- expression 35 operands: lhs = Expression(43, Add), rhs = Counter(4) +- expression 36 operands: lhs = Counter(2), rhs = Counter(3) +- expression 37 operands: lhs = Counter(8), rhs = Expression(38, Add) +- expression 38 operands: lhs = Expression(39, Add), rhs = Expression(0, Sub) +- expression 39 operands: lhs = Expression(40, Add), rhs = Counter(7) +- expression 40 operands: lhs = Expression(41, Add), rhs = Counter(6) +- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(5) +- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4) +- expression 43 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 17 +- Code(Counter(0)) at (prev + 20, 1) to (start + 3, 9) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 3, 8) to (start + 0, 9) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Expression(30, Sub), false: Counter(7) } at (prev + 0, 13) to (start + 0, 14) + true = (c1 - c7) + false = c7 +- Code(Expression(30, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c1 - c7) +- Branch { true: Expression(29, Sub), false: Counter(6) } at (prev + 0, 18) to (start + 0, 19) + true = ((c1 - c7) - c6) + false = c6 +- Code(Expression(29, Sub)) at (prev + 0, 23) to (start + 0, 24) + = ((c1 - c7) - c6) +- Branch { true: Expression(28, Sub), false: Counter(5) } at (prev + 0, 23) to (start + 0, 24) + true = (((c1 - c7) - c6) - c5) + false = c5 +- Code(Expression(28, Sub)) at (prev + 0, 28) to (start + 0, 29) + = (((c1 - c7) - c6) - c5) +- Branch { true: Expression(27, Sub), false: Counter(4) } at (prev + 0, 28) to (start + 0, 29) + true = ((((c1 - c7) - c6) - c5) - c4) + false = c4 +- Code(Expression(27, Sub)) at (prev + 0, 33) to (start + 0, 34) + = ((((c1 - c7) - c6) - c5) - c4) +- Branch { true: Expression(26, Sub), false: Counter(3) } at (prev + 0, 33) to (start + 0, 34) + true = (((((c1 - c7) - c6) - c5) - c4) - c3) + false = c3 +- Code(Expression(26, Sub)) at (prev + 0, 38) to (start + 0, 39) + = (((((c1 - c7) - c6) - c5) - c4) - c3) +- Branch { true: Counter(8), false: Counter(2) } at (prev + 0, 38) to (start + 0, 39) + true = c8 + false = c2 +- Code(Counter(8)) at (prev + 0, 40) to (start + 2, 6) +- Code(Expression(38, Add)) at (prev + 2, 6) to (start + 0, 7) + = ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)) +- Code(Expression(37, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1))) + +Function name: condition_limit::good +Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0c, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 32 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Counter(6) +- expression 2 operands: lhs = Counter(1), rhs = Counter(6) +- expression 3 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 4 operands: lhs = Counter(1), rhs = Counter(6) +- expression 5 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 6 operands: lhs = Counter(1), rhs = Counter(6) +- expression 7 operands: lhs = Expression(19, Sub), rhs = Counter(4) +- expression 8 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 9 operands: lhs = Counter(1), rhs = Counter(6) +- expression 10 operands: lhs = Expression(19, Sub), rhs = Counter(4) +- expression 11 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 12 operands: lhs = Counter(1), rhs = Counter(6) +- expression 13 operands: lhs = Expression(18, Sub), rhs = Counter(3) +- expression 14 operands: lhs = Expression(19, Sub), rhs = Counter(4) +- expression 15 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 16 operands: lhs = Counter(1), rhs = Counter(6) +- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(3) +- expression 18 operands: lhs = Expression(19, Sub), rhs = Counter(4) +- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 20 operands: lhs = Counter(1), rhs = Counter(6) +- expression 21 operands: lhs = Expression(28, Add), rhs = Expression(0, Sub) +- expression 22 operands: lhs = Expression(29, Add), rhs = Counter(6) +- expression 23 operands: lhs = Expression(30, Add), rhs = Counter(5) +- expression 24 operands: lhs = Expression(31, Add), rhs = Counter(4) +- expression 25 operands: lhs = Counter(2), rhs = Counter(3) +- expression 26 operands: lhs = Counter(7), rhs = Expression(27, Add) +- expression 27 operands: lhs = Expression(28, Add), rhs = Expression(0, Sub) +- expression 28 operands: lhs = Expression(29, Add), rhs = Counter(6) +- expression 29 operands: lhs = Expression(30, Add), rhs = Counter(5) +- expression 30 operands: lhs = Expression(31, Add), rhs = Counter(4) +- expression 31 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 16 +- Code(Counter(0)) at (prev + 12, 1) to (start + 3, 9) +- MCDCDecision { bitmap_idx: 0, conditions_num: 6 } at (prev + 3, 8) to (start + 0, 34) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 6, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14) +- MCDCBranch { true: Expression(20, Sub), false: Counter(6), condition_id: 6, true_next_id: 5, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) + true = (c1 - c6) + false = c6 +- Code(Expression(20, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c1 - c6) +- MCDCBranch { true: Expression(19, Sub), false: Counter(5), condition_id: 5, true_next_id: 4, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) + true = ((c1 - c6) - c5) + false = c5 +- Code(Expression(19, Sub)) at (prev + 0, 23) to (start + 0, 24) + = ((c1 - c6) - c5) +- MCDCBranch { true: Expression(18, Sub), false: Counter(4), condition_id: 4, true_next_id: 3, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) + true = (((c1 - c6) - c5) - c4) + false = c4 +- Code(Expression(18, Sub)) at (prev + 0, 28) to (start + 0, 29) + = (((c1 - c6) - c5) - c4) +- MCDCBranch { true: Expression(17, Sub), false: Counter(3), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29) + true = ((((c1 - c6) - c5) - c4) - c3) + false = c3 +- Code(Expression(17, Sub)) at (prev + 0, 33) to (start + 0, 34) + = ((((c1 - c6) - c5) - c4) - c3) +- MCDCBranch { true: Counter(7), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34) + true = c7 + false = c2 +- Code(Counter(7)) at (prev + 0, 35) to (start + 2, 6) +- Code(Expression(27, Add)) at (prev + 2, 6) to (start + 0, 7) + = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) +- Code(Expression(26, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c7 + (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))) + diff --git a/tests/coverage/mcdc/condition-limit.coverage b/tests/coverage/mcdc/condition-limit.coverage new file mode 100644 index 000000000000..4eb87432fab4 --- /dev/null +++ b/tests/coverage/mcdc/condition-limit.coverage @@ -0,0 +1,76 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| |//@ min-llvm-version: 18 + LL| |//@ compile-flags: -Zcoverage-options=mcdc + LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc + LL| | + LL| |// Check that MC/DC instrumentation can gracefully handle conditions that + LL| |// exceed LLVM's limit of 6 conditions per decision. + LL| |// + LL| |// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.) + LL| | + LL| 1|fn good() { + LL| 1| // With only 6 conditions, perform full MC/DC instrumentation. + LL| 1| let [a, b, c, d, e, f] = <[bool; 6]>::default(); + LL| 1| if a && b && c && d && e && f { + ^0 ^0 ^0 ^0 ^0 + ------------------ + | Branch (LL:8): [True: 0, False: 1] + | Branch (LL:13): [True: 0, False: 0] + | Branch (LL:18): [True: 0, False: 0] + | Branch (LL:23): [True: 0, False: 0] + | Branch (LL:28): [True: 0, False: 0] + | Branch (LL:33): [True: 0, False: 0] + ------------------ + |---> MC/DC Decision Region (LL:8) to (LL:34) + | + | Number of Conditions: 6 + | Condition C1 --> (LL:8) + | Condition C2 --> (LL:13) + | Condition C3 --> (LL:18) + | Condition C4 --> (LL:23) + | Condition C5 --> (LL:28) + | Condition C6 --> (LL:33) + | + | Executed MC/DC Test Vectors: + | + | C1, C2, C3, C4, C5, C6 Result + | 1 { F, -, -, -, -, - = F } + | + | C1-Pair: not covered + | C2-Pair: not covered + | C3-Pair: not covered + | C4-Pair: not covered + | C5-Pair: not covered + | C6-Pair: not covered + | MC/DC Coverage for Decision: 0.00% + | + ------------------ + LL| 0| core::hint::black_box("hello"); + LL| 1| } + LL| 1|} + LL| | + LL| 1|fn bad() { + LL| 1| // With 7 conditions, fall back to branch instrumentation only. + LL| 1| let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); + LL| 1| if a && b && c && d && e && f && g { + ^0 ^0 ^0 ^0 ^0 ^0 + ------------------ + | Branch (LL:8): [True: 0, False: 1] + | Branch (LL:13): [True: 0, False: 0] + | Branch (LL:18): [True: 0, False: 0] + | Branch (LL:23): [True: 0, False: 0] + | Branch (LL:28): [True: 0, False: 0] + | Branch (LL:33): [True: 0, False: 0] + | Branch (LL:38): [True: 0, False: 0] + ------------------ + LL| 0| core::hint::black_box("hello"); + LL| 1| } + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | good(); + LL| | bad(); + LL| |} + diff --git a/tests/coverage/mcdc/condition-limit.rs b/tests/coverage/mcdc/condition-limit.rs new file mode 100644 index 000000000000..571c600ebd09 --- /dev/null +++ b/tests/coverage/mcdc/condition-limit.rs @@ -0,0 +1,32 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 +//@ min-llvm-version: 18 +//@ compile-flags: -Zcoverage-options=mcdc +//@ llvm-cov-flags: --show-branches=count --show-mcdc + +// Check that MC/DC instrumentation can gracefully handle conditions that +// exceed LLVM's limit of 6 conditions per decision. +// +// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.) + +fn good() { + // With only 6 conditions, perform full MC/DC instrumentation. + let [a, b, c, d, e, f] = <[bool; 6]>::default(); + if a && b && c && d && e && f { + core::hint::black_box("hello"); + } +} + +fn bad() { + // With 7 conditions, fall back to branch instrumentation only. + let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); + if a && b && c && d && e && f && g { + core::hint::black_box("hello"); + } +} + +#[coverage(off)] +fn main() { + good(); + bad(); +} diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr new file mode 100644 index 000000000000..4d8d7e1560d0 --- /dev/null +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr @@ -0,0 +1,8 @@ +warning: Conditions number of the decision (7) exceeds limit (6). MCDC analysis will not count this expression. + --> $DIR/mcdc-condition-limit.rs:29:8 + | +LL | if a && b && c && d && e && f && g { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.rs b/tests/ui/instrument-coverage/mcdc-condition-limit.rs new file mode 100644 index 000000000000..64c5f8e9b779 --- /dev/null +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.rs @@ -0,0 +1,32 @@ +//@ edition: 2021 +//@ min-llvm-version: 18 +//@ revisions: good bad +//@ check-pass +//@ compile-flags: -Cinstrument-coverage -Zcoverage-options=mcdc -Zno-profiler-runtime + +// Check that we emit some kind of diagnostic when MC/DC instrumentation sees +// code that exceeds the limit of 6 conditions per decision, and falls back +// to only instrumenting that code for branch coverage. +// +// See also `tests/coverage/mcdc/condition-limit.rs`, which tests the actual +// effect on instrumentation. +// +// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.) + +#[cfg(good)] +fn main() { + // 6 conditions is OK, so no diagnostic. + let [a, b, c, d, e, f] = <[bool; 6]>::default(); + if a && b && c && d && e && f { + core::hint::black_box("hello"); + } +} + +#[cfg(bad)] +fn main() { + // 7 conditions is too many, so issue a diagnostic. + let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); + if a && b && c && d && e && f && g { //[bad]~ WARNING Conditions number of the decision + core::hint::black_box("hello"); + } +} From bb865cb83f835a746db13bc6d186f22464f80fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 29 May 2024 10:37:21 +0000 Subject: [PATCH 078/104] remove unneeded extern crate in rmake test --- tests/run-make/rust-lld-by-default/rmake.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/run-make/rust-lld-by-default/rmake.rs b/tests/run-make/rust-lld-by-default/rmake.rs index 876968727f3c..6a8dae1043e3 100644 --- a/tests/run-make/rust-lld-by-default/rmake.rs +++ b/tests/run-make/rust-lld-by-default/rmake.rs @@ -4,8 +4,6 @@ //@ needs-rust-lld //@ only-x86_64-unknown-linux-gnu -extern crate run_make_support; - use run_make_support::regex::Regex; use run_make_support::rustc; use std::process::Output; From 268b9a74e38595c5ee71d7bb9152ee1a3bbf9242 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 29 May 2024 21:12:47 +1000 Subject: [PATCH 079/104] Extract coverage-specific code out of `compiletest::runtest` This moves a few hundred lines of coverage-specific code out of the main module, making navigation a bit easier. --- src/tools/compiletest/src/runtest.rs | 363 +---------------- src/tools/compiletest/src/runtest/coverage.rs | 367 ++++++++++++++++++ src/tools/compiletest/src/runtest/tests.rs | 68 ---- 3 files changed, 372 insertions(+), 426 deletions(-) create mode 100644 src/tools/compiletest/src/runtest/coverage.rs diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e8ceff847224..910a829fbea1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -9,7 +9,7 @@ use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc}; use crate::common::{CompareMode, FailMode, PassMode}; use crate::common::{Config, TestPaths}; use crate::common::{CoverageMap, CoverageRun, Pretty, RunPassValgrind}; -use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP, UI_RUN_STDERR, UI_RUN_STDOUT}; +use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; @@ -41,6 +41,7 @@ use tracing::*; use crate::extract_gdb_version; use crate::is_android_gdb_target; +mod coverage; mod debugger; use debugger::DebuggerCommands; @@ -53,6 +54,7 @@ macro_rules! static_regex { RE.get_or_init(|| ::regex::Regex::new($re).unwrap()) }}; } +use static_regex; const FAKE_SRC_BASE: &str = "fake-test-src-base"; @@ -267,8 +269,8 @@ impl<'test> TestCx<'test> { MirOpt => self.run_mir_opt_test(), Assembly => self.run_assembly_test(), JsDocTest => self.run_js_doc_test(), - CoverageMap => self.run_coverage_map_test(), - CoverageRun => self.run_coverage_run_test(), + CoverageMap => self.run_coverage_map_test(), // see self::coverage + CoverageRun => self.run_coverage_run_test(), // see self::coverage Crashes => self.run_crash_test(), } } @@ -504,224 +506,6 @@ impl<'test> TestCx<'test> { } } - fn run_coverage_map_test(&self) { - let Some(coverage_dump_path) = &self.config.coverage_dump_path else { - self.fatal("missing --coverage-dump"); - }; - - let (proc_res, llvm_ir_path) = self.compile_test_and_save_ir(); - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - drop(proc_res); - - let mut dump_command = Command::new(coverage_dump_path); - dump_command.arg(llvm_ir_path); - let proc_res = self.run_command_to_procres(&mut dump_command); - if !proc_res.status.success() { - self.fatal_proc_rec("coverage-dump failed!", &proc_res); - } - - let kind = UI_COVERAGE_MAP; - - let expected_coverage_dump = self.load_expected_output(kind); - let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]); - - let coverage_dump_errors = - self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump); - - if coverage_dump_errors > 0 { - self.fatal_proc_rec( - &format!("{coverage_dump_errors} errors occurred comparing coverage output."), - &proc_res, - ); - } - } - - fn run_coverage_run_test(&self) { - let should_run = self.run_if_enabled(); - let proc_res = self.compile_test(should_run, Emit::None); - - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - drop(proc_res); - - if let WillExecute::Disabled = should_run { - return; - } - - let profraw_path = self.output_base_dir().join("default.profraw"); - let profdata_path = self.output_base_dir().join("default.profdata"); - - // Delete any existing profraw/profdata files to rule out unintended - // interference between repeated test runs. - if profraw_path.exists() { - std::fs::remove_file(&profraw_path).unwrap(); - } - if profdata_path.exists() { - std::fs::remove_file(&profdata_path).unwrap(); - } - - let proc_res = self.exec_compiled_test_general( - &[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())], - false, - ); - if self.props.failure_status.is_some() { - self.check_correct_failure_status(&proc_res); - } else if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); - } - drop(proc_res); - - let mut profraw_paths = vec![profraw_path]; - let mut bin_paths = vec![self.make_exe_name()]; - - if self.config.suite == "coverage-run-rustdoc" { - self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths); - } - - // Run `llvm-profdata merge` to index the raw coverage output. - let proc_res = self.run_llvm_tool("llvm-profdata", |cmd| { - cmd.args(["merge", "--sparse", "--output"]); - cmd.arg(&profdata_path); - cmd.args(&profraw_paths); - }); - if !proc_res.status.success() { - self.fatal_proc_rec("llvm-profdata merge failed!", &proc_res); - } - drop(proc_res); - - // Run `llvm-cov show` to produce a coverage report in text format. - let proc_res = self.run_llvm_tool("llvm-cov", |cmd| { - cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]); - - cmd.arg("--Xdemangler"); - cmd.arg(self.config.rust_demangler_path.as_ref().unwrap()); - - cmd.arg("--instr-profile"); - cmd.arg(&profdata_path); - - for bin in &bin_paths { - cmd.arg("--object"); - cmd.arg(bin); - } - - cmd.args(&self.props.llvm_cov_flags); - }); - if !proc_res.status.success() { - self.fatal_proc_rec("llvm-cov show failed!", &proc_res); - } - - let kind = UI_COVERAGE; - - let expected_coverage = self.load_expected_output(kind); - let normalized_actual_coverage = - self.normalize_coverage_output(&proc_res.stdout).unwrap_or_else(|err| { - self.fatal_proc_rec(&err, &proc_res); - }); - - let coverage_errors = - self.compare_output(kind, &normalized_actual_coverage, &expected_coverage); - - if coverage_errors > 0 { - self.fatal_proc_rec( - &format!("{} errors occurred comparing coverage output.", coverage_errors), - &proc_res, - ); - } - } - - /// Run any doctests embedded in this test file, and add any resulting - /// `.profraw` files and doctest executables to the given vectors. - fn run_doctests_for_coverage( - &self, - profraw_paths: &mut Vec, - bin_paths: &mut Vec, - ) { - // Put .profraw files and doctest executables in dedicated directories, - // to make it easier to glob them all later. - let profraws_dir = self.output_base_dir().join("doc_profraws"); - let bins_dir = self.output_base_dir().join("doc_bins"); - - // Remove existing directories to prevent cross-run interference. - if profraws_dir.try_exists().unwrap() { - std::fs::remove_dir_all(&profraws_dir).unwrap(); - } - if bins_dir.try_exists().unwrap() { - std::fs::remove_dir_all(&bins_dir).unwrap(); - } - - let mut rustdoc_cmd = - Command::new(self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed")); - - // In general there will be multiple doctest binaries running, so we - // tell the profiler runtime to write their coverage data into separate - // profraw files. - rustdoc_cmd.env("LLVM_PROFILE_FILE", profraws_dir.join("%p-%m.profraw")); - - rustdoc_cmd.args(["--test", "-Cinstrument-coverage"]); - - // Without this, the doctests complain about not being able to find - // their enclosing file's crate for some reason. - rustdoc_cmd.args(["--crate-name", "workaround_for_79771"]); - - // Persist the doctest binaries so that `llvm-cov show` can read their - // embedded coverage mappings later. - rustdoc_cmd.arg("-Zunstable-options"); - rustdoc_cmd.arg("--persist-doctests"); - rustdoc_cmd.arg(&bins_dir); - - rustdoc_cmd.arg("-L"); - rustdoc_cmd.arg(self.aux_output_dir_name()); - - rustdoc_cmd.arg(&self.testpaths.file); - - let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None); - if !proc_res.status.success() { - self.fatal_proc_rec("rustdoc --test failed!", &proc_res) - } - - fn glob_iter(path: impl AsRef) -> impl Iterator { - let path_str = path.as_ref().to_str().unwrap(); - let iter = glob(path_str).unwrap(); - iter.map(Result::unwrap) - } - - // Find all profraw files in the profraw directory. - for p in glob_iter(profraws_dir.join("*.profraw")) { - profraw_paths.push(p); - } - // Find all executables in the `--persist-doctests` directory, while - // avoiding other file types (e.g. `.pdb` on Windows). This doesn't - // need to be perfect, as long as it can handle the files actually - // produced by `rustdoc --test`. - for p in glob_iter(bins_dir.join("**/*")) { - let is_bin = p.is_file() - && match p.extension() { - None => true, - Some(ext) => ext == OsStr::new("exe"), - }; - if is_bin { - bin_paths.push(p); - } - } - } - - fn run_llvm_tool(&self, name: &str, configure_cmd_fn: impl FnOnce(&mut Command)) -> ProcRes { - let tool_path = self - .config - .llvm_bin_dir - .as_ref() - .expect("this test expects the LLVM bin dir to be available") - .join(name); - - let mut cmd = Command::new(tool_path); - configure_cmd_fn(&mut cmd); - - self.run_command_to_procres(&mut cmd) - } - fn run_command_to_procres(&self, cmd: &mut Command) -> ProcRes { let output = cmd.output().unwrap_or_else(|e| panic!("failed to exec `{cmd:?}`: {e:?}")); @@ -737,143 +521,6 @@ impl<'test> TestCx<'test> { proc_res } - fn normalize_coverage_output(&self, coverage: &str) -> Result { - let normalized = self.normalize_output(coverage, &[]); - let normalized = Self::anonymize_coverage_line_numbers(&normalized); - - let mut lines = normalized.lines().collect::>(); - - Self::sort_coverage_file_sections(&mut lines)?; - Self::sort_coverage_subviews(&mut lines)?; - - let joined_lines = lines.iter().flat_map(|line| [line, "\n"]).collect::(); - Ok(joined_lines) - } - - /// Replace line numbers in coverage reports with the placeholder `LL`, - /// so that the tests are less sensitive to lines being added/removed. - fn anonymize_coverage_line_numbers(coverage: &str) -> String { - // The coverage reporter prints line numbers at the start of a line. - // They are truncated or left-padded to occupy exactly 5 columns. - // (`LineNumberColumnWidth` in `SourceCoverageViewText.cpp`.) - // A pipe character `|` appears immediately after the final digit. - // - // Line numbers that appear inside expansion/instantiation subviews - // have an additional prefix of ` |` for each nesting level. - // - // Branch views also include the relevant line number, so we want to - // redact those too. (These line numbers don't have padding.) - // - // Note: The pattern `(?m:^)` matches the start of a line. - - // ` 1|` => ` LL|` - // ` 10|` => ` LL|` - // ` 100|` => ` LL|` - // ` | 1000|` => ` | LL|` - // ` | | 1000|` => ` | | LL|` - let coverage = static_regex!(r"(?m:^)(?(?: \|)*) *[0-9]+\|") - .replace_all(&coverage, "${prefix} LL|"); - - // ` | Branch (1:` => ` | Branch (LL:` - // ` | | Branch (10:` => ` | | Branch (LL:` - let coverage = static_regex!(r"(?m:^)(?(?: \|)+ Branch \()[0-9]+:") - .replace_all(&coverage, "${prefix}LL:"); - - // ` |---> MC/DC Decision Region (1:30) to (2:` => ` |---> MC/DC Decision Region (LL:30) to (LL:` - let coverage = - static_regex!(r"(?m:^)(?(?: \|)+---> MC/DC Decision Region \()[0-9]+:(?[0-9]+\) to \()[0-9]+:") - .replace_all(&coverage, "${prefix}LL:${middle}LL:"); - - // ` | Condition C1 --> (1:` => ` | Condition C1 --> (LL:` - let coverage = - static_regex!(r"(?m:^)(?(?: \|)+ Condition C[0-9]+ --> \()[0-9]+:") - .replace_all(&coverage, "${prefix}LL:"); - - coverage.into_owned() - } - - /// Coverage reports can describe multiple source files, separated by - /// blank lines. The order of these files is unpredictable (since it - /// depends on implementation details), so we need to sort the file - /// sections into a consistent order before comparing against a snapshot. - fn sort_coverage_file_sections(coverage_lines: &mut Vec<&str>) -> Result<(), String> { - // Group the lines into file sections, separated by blank lines. - let mut sections = coverage_lines.split(|line| line.is_empty()).collect::>(); - - // The last section should be empty, representing an extra trailing blank line. - if !sections.last().is_some_and(|last| last.is_empty()) { - return Err("coverage report should end with an extra blank line".to_owned()); - } - - // Sort the file sections (not including the final empty "section"). - let except_last = sections.len() - 1; - (&mut sections[..except_last]).sort(); - - // Join the file sections back into a flat list of lines, with - // sections separated by blank lines. - let joined = sections.join(&[""] as &[_]); - assert_eq!(joined.len(), coverage_lines.len()); - *coverage_lines = joined; - - Ok(()) - } - - fn sort_coverage_subviews(coverage_lines: &mut Vec<&str>) -> Result<(), String> { - let mut output_lines = Vec::new(); - - // We accumulate a list of zero or more "subviews", where each - // subview is a list of one or more lines. - let mut subviews: Vec> = Vec::new(); - - fn flush<'a>(subviews: &mut Vec>, output_lines: &mut Vec<&'a str>) { - if subviews.is_empty() { - return; - } - - // Take and clear the list of accumulated subviews. - let mut subviews = std::mem::take(subviews); - - // The last "subview" should be just a boundary line on its own, - // so exclude it when sorting the other subviews. - let except_last = subviews.len() - 1; - (&mut subviews[..except_last]).sort(); - - for view in subviews { - for line in view { - output_lines.push(line); - } - } - } - - for (line, line_num) in coverage_lines.iter().zip(1..) { - if line.starts_with(" ------------------") { - // This is a subview boundary line, so start a new subview. - subviews.push(vec![line]); - } else if line.starts_with(" |") { - // Add this line to the current subview. - subviews - .last_mut() - .ok_or(format!( - "unexpected subview line outside of a subview on line {line_num}" - ))? - .push(line); - } else { - // This line is not part of a subview, so sort and print any - // accumulated subviews, and then print the line as-is. - flush(&mut subviews, &mut output_lines); - output_lines.push(line); - } - } - - flush(&mut subviews, &mut output_lines); - assert!(subviews.is_empty()); - - assert_eq!(output_lines.len(), coverage_lines.len()); - *coverage_lines = output_lines; - - Ok(()) - } - fn run_pretty_test(&self) { if self.props.pp_exact.is_some() { logv(self.config, "testing for exact pretty-printing".to_owned()); diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs new file mode 100644 index 000000000000..dad3fb301333 --- /dev/null +++ b/src/tools/compiletest/src/runtest/coverage.rs @@ -0,0 +1,367 @@ +//! Code specific to the coverage test suites. + +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use glob::glob; + +use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP}; +use crate::runtest::{static_regex, Emit, ProcRes, TestCx, WillExecute}; + +impl<'test> TestCx<'test> { + pub(crate) fn run_coverage_map_test(&self) { + let Some(coverage_dump_path) = &self.config.coverage_dump_path else { + self.fatal("missing --coverage-dump"); + }; + + let (proc_res, llvm_ir_path) = self.compile_test_and_save_ir(); + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + drop(proc_res); + + let mut dump_command = Command::new(coverage_dump_path); + dump_command.arg(llvm_ir_path); + let proc_res = self.run_command_to_procres(&mut dump_command); + if !proc_res.status.success() { + self.fatal_proc_rec("coverage-dump failed!", &proc_res); + } + + let kind = UI_COVERAGE_MAP; + + let expected_coverage_dump = self.load_expected_output(kind); + let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]); + + let coverage_dump_errors = + self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump); + + if coverage_dump_errors > 0 { + self.fatal_proc_rec( + &format!("{coverage_dump_errors} errors occurred comparing coverage output."), + &proc_res, + ); + } + } + + pub(crate) fn run_coverage_run_test(&self) { + let should_run = self.run_if_enabled(); + let proc_res = self.compile_test(should_run, Emit::None); + + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + drop(proc_res); + + if let WillExecute::Disabled = should_run { + return; + } + + let profraw_path = self.output_base_dir().join("default.profraw"); + let profdata_path = self.output_base_dir().join("default.profdata"); + + // Delete any existing profraw/profdata files to rule out unintended + // interference between repeated test runs. + if profraw_path.exists() { + std::fs::remove_file(&profraw_path).unwrap(); + } + if profdata_path.exists() { + std::fs::remove_file(&profdata_path).unwrap(); + } + + let proc_res = self.exec_compiled_test_general( + &[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())], + false, + ); + if self.props.failure_status.is_some() { + self.check_correct_failure_status(&proc_res); + } else if !proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &proc_res); + } + drop(proc_res); + + let mut profraw_paths = vec![profraw_path]; + let mut bin_paths = vec![self.make_exe_name()]; + + if self.config.suite == "coverage-run-rustdoc" { + self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths); + } + + // Run `llvm-profdata merge` to index the raw coverage output. + let proc_res = self.run_llvm_tool("llvm-profdata", |cmd| { + cmd.args(["merge", "--sparse", "--output"]); + cmd.arg(&profdata_path); + cmd.args(&profraw_paths); + }); + if !proc_res.status.success() { + self.fatal_proc_rec("llvm-profdata merge failed!", &proc_res); + } + drop(proc_res); + + // Run `llvm-cov show` to produce a coverage report in text format. + let proc_res = self.run_llvm_tool("llvm-cov", |cmd| { + cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]); + + cmd.arg("--Xdemangler"); + cmd.arg(self.config.rust_demangler_path.as_ref().unwrap()); + + cmd.arg("--instr-profile"); + cmd.arg(&profdata_path); + + for bin in &bin_paths { + cmd.arg("--object"); + cmd.arg(bin); + } + + cmd.args(&self.props.llvm_cov_flags); + }); + if !proc_res.status.success() { + self.fatal_proc_rec("llvm-cov show failed!", &proc_res); + } + + let kind = UI_COVERAGE; + + let expected_coverage = self.load_expected_output(kind); + let normalized_actual_coverage = + self.normalize_coverage_output(&proc_res.stdout).unwrap_or_else(|err| { + self.fatal_proc_rec(&err, &proc_res); + }); + + let coverage_errors = + self.compare_output(kind, &normalized_actual_coverage, &expected_coverage); + + if coverage_errors > 0 { + self.fatal_proc_rec( + &format!("{} errors occurred comparing coverage output.", coverage_errors), + &proc_res, + ); + } + } + + /// Run any doctests embedded in this test file, and add any resulting + /// `.profraw` files and doctest executables to the given vectors. + fn run_doctests_for_coverage( + &self, + profraw_paths: &mut Vec, + bin_paths: &mut Vec, + ) { + // Put .profraw files and doctest executables in dedicated directories, + // to make it easier to glob them all later. + let profraws_dir = self.output_base_dir().join("doc_profraws"); + let bins_dir = self.output_base_dir().join("doc_bins"); + + // Remove existing directories to prevent cross-run interference. + if profraws_dir.try_exists().unwrap() { + std::fs::remove_dir_all(&profraws_dir).unwrap(); + } + if bins_dir.try_exists().unwrap() { + std::fs::remove_dir_all(&bins_dir).unwrap(); + } + + let mut rustdoc_cmd = + Command::new(self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed")); + + // In general there will be multiple doctest binaries running, so we + // tell the profiler runtime to write their coverage data into separate + // profraw files. + rustdoc_cmd.env("LLVM_PROFILE_FILE", profraws_dir.join("%p-%m.profraw")); + + rustdoc_cmd.args(["--test", "-Cinstrument-coverage"]); + + // Without this, the doctests complain about not being able to find + // their enclosing file's crate for some reason. + rustdoc_cmd.args(["--crate-name", "workaround_for_79771"]); + + // Persist the doctest binaries so that `llvm-cov show` can read their + // embedded coverage mappings later. + rustdoc_cmd.arg("-Zunstable-options"); + rustdoc_cmd.arg("--persist-doctests"); + rustdoc_cmd.arg(&bins_dir); + + rustdoc_cmd.arg("-L"); + rustdoc_cmd.arg(self.aux_output_dir_name()); + + rustdoc_cmd.arg(&self.testpaths.file); + + let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None); + if !proc_res.status.success() { + self.fatal_proc_rec("rustdoc --test failed!", &proc_res) + } + + fn glob_iter(path: impl AsRef) -> impl Iterator { + let path_str = path.as_ref().to_str().unwrap(); + let iter = glob(path_str).unwrap(); + iter.map(Result::unwrap) + } + + // Find all profraw files in the profraw directory. + for p in glob_iter(profraws_dir.join("*.profraw")) { + profraw_paths.push(p); + } + // Find all executables in the `--persist-doctests` directory, while + // avoiding other file types (e.g. `.pdb` on Windows). This doesn't + // need to be perfect, as long as it can handle the files actually + // produced by `rustdoc --test`. + for p in glob_iter(bins_dir.join("**/*")) { + let is_bin = p.is_file() + && match p.extension() { + None => true, + Some(ext) => ext == OsStr::new("exe"), + }; + if is_bin { + bin_paths.push(p); + } + } + } + + fn run_llvm_tool(&self, name: &str, configure_cmd_fn: impl FnOnce(&mut Command)) -> ProcRes { + let tool_path = self + .config + .llvm_bin_dir + .as_ref() + .expect("this test expects the LLVM bin dir to be available") + .join(name); + + let mut cmd = Command::new(tool_path); + configure_cmd_fn(&mut cmd); + + self.run_command_to_procres(&mut cmd) + } + + fn normalize_coverage_output(&self, coverage: &str) -> Result { + let normalized = self.normalize_output(coverage, &[]); + let normalized = Self::anonymize_coverage_line_numbers(&normalized); + + let mut lines = normalized.lines().collect::>(); + + Self::sort_coverage_file_sections(&mut lines)?; + Self::sort_coverage_subviews(&mut lines)?; + + let joined_lines = lines.iter().flat_map(|line| [line, "\n"]).collect::(); + Ok(joined_lines) + } + + /// Replace line numbers in coverage reports with the placeholder `LL`, + /// so that the tests are less sensitive to lines being added/removed. + fn anonymize_coverage_line_numbers(coverage: &str) -> String { + // The coverage reporter prints line numbers at the start of a line. + // They are truncated or left-padded to occupy exactly 5 columns. + // (`LineNumberColumnWidth` in `SourceCoverageViewText.cpp`.) + // A pipe character `|` appears immediately after the final digit. + // + // Line numbers that appear inside expansion/instantiation subviews + // have an additional prefix of ` |` for each nesting level. + // + // Branch views also include the relevant line number, so we want to + // redact those too. (These line numbers don't have padding.) + // + // Note: The pattern `(?m:^)` matches the start of a line. + + // ` 1|` => ` LL|` + // ` 10|` => ` LL|` + // ` 100|` => ` LL|` + // ` | 1000|` => ` | LL|` + // ` | | 1000|` => ` | | LL|` + let coverage = static_regex!(r"(?m:^)(?(?: \|)*) *[0-9]+\|") + .replace_all(&coverage, "${prefix} LL|"); + + // ` | Branch (1:` => ` | Branch (LL:` + // ` | | Branch (10:` => ` | | Branch (LL:` + let coverage = static_regex!(r"(?m:^)(?(?: \|)+ Branch \()[0-9]+:") + .replace_all(&coverage, "${prefix}LL:"); + + // ` |---> MC/DC Decision Region (1:30) to (2:` => ` |---> MC/DC Decision Region (LL:30) to (LL:` + let coverage = + static_regex!(r"(?m:^)(?(?: \|)+---> MC/DC Decision Region \()[0-9]+:(?[0-9]+\) to \()[0-9]+:") + .replace_all(&coverage, "${prefix}LL:${middle}LL:"); + + // ` | Condition C1 --> (1:` => ` | Condition C1 --> (LL:` + let coverage = + static_regex!(r"(?m:^)(?(?: \|)+ Condition C[0-9]+ --> \()[0-9]+:") + .replace_all(&coverage, "${prefix}LL:"); + + coverage.into_owned() + } + + /// Coverage reports can describe multiple source files, separated by + /// blank lines. The order of these files is unpredictable (since it + /// depends on implementation details), so we need to sort the file + /// sections into a consistent order before comparing against a snapshot. + fn sort_coverage_file_sections(coverage_lines: &mut Vec<&str>) -> Result<(), String> { + // Group the lines into file sections, separated by blank lines. + let mut sections = coverage_lines.split(|line| line.is_empty()).collect::>(); + + // The last section should be empty, representing an extra trailing blank line. + if !sections.last().is_some_and(|last| last.is_empty()) { + return Err("coverage report should end with an extra blank line".to_owned()); + } + + // Sort the file sections (not including the final empty "section"). + let except_last = sections.len() - 1; + (&mut sections[..except_last]).sort(); + + // Join the file sections back into a flat list of lines, with + // sections separated by blank lines. + let joined = sections.join(&[""] as &[_]); + assert_eq!(joined.len(), coverage_lines.len()); + *coverage_lines = joined; + + Ok(()) + } + + fn sort_coverage_subviews(coverage_lines: &mut Vec<&str>) -> Result<(), String> { + let mut output_lines = Vec::new(); + + // We accumulate a list of zero or more "subviews", where each + // subview is a list of one or more lines. + let mut subviews: Vec> = Vec::new(); + + fn flush<'a>(subviews: &mut Vec>, output_lines: &mut Vec<&'a str>) { + if subviews.is_empty() { + return; + } + + // Take and clear the list of accumulated subviews. + let mut subviews = std::mem::take(subviews); + + // The last "subview" should be just a boundary line on its own, + // so exclude it when sorting the other subviews. + let except_last = subviews.len() - 1; + (&mut subviews[..except_last]).sort(); + + for view in subviews { + for line in view { + output_lines.push(line); + } + } + } + + for (line, line_num) in coverage_lines.iter().zip(1..) { + if line.starts_with(" ------------------") { + // This is a subview boundary line, so start a new subview. + subviews.push(vec![line]); + } else if line.starts_with(" |") { + // Add this line to the current subview. + subviews + .last_mut() + .ok_or(format!( + "unexpected subview line outside of a subview on line {line_num}" + ))? + .push(line); + } else { + // This line is not part of a subview, so sort and print any + // accumulated subviews, and then print the line as-is. + flush(&mut subviews, &mut output_lines); + output_lines.push(line); + } + } + + flush(&mut subviews, &mut output_lines); + assert!(subviews.is_empty()); + + assert_eq!(output_lines.len(), coverage_lines.len()); + *coverage_lines = output_lines; + + Ok(()) + } +} diff --git a/src/tools/compiletest/src/runtest/tests.rs b/src/tools/compiletest/src/runtest/tests.rs index 817b56109a50..fb3dd326a4c8 100644 --- a/src/tools/compiletest/src/runtest/tests.rs +++ b/src/tools/compiletest/src/runtest/tests.rs @@ -48,71 +48,3 @@ fn normalize_platform_differences() { r#"println!("test\ntest")"#, ); } - -/// Test for anonymizing line numbers in coverage reports, especially for -/// MC/DC regions. -/// -/// FIXME(#123409): This test can be removed when we have examples of MC/DC -/// coverage in the actual coverage test suite. -#[test] -fn anonymize_coverage_line_numbers() { - let anon = |coverage| TestCx::anonymize_coverage_line_numbers(coverage); - - let input = r#" - 7| 2|fn mcdc_check_neither(a: bool, b: bool) { - 8| 2| if a && b { - ^0 - ------------------ - |---> MC/DC Decision Region (8:8) to (8:14) - | - | Number of Conditions: 2 - | Condition C1 --> (8:8) - | Condition C2 --> (8:13) - | - | Executed MC/DC Test Vectors: - | - | C1, C2 Result - | 1 { F, - = F } - | - | C1-Pair: not covered - | C2-Pair: not covered - | MC/DC Coverage for Decision: 0.00% - | - ------------------ - 9| 0| say("a and b"); - 10| 2| } else { - 11| 2| say("not both"); - 12| 2| } - 13| 2|} -"#; - - let expected = r#" - LL| 2|fn mcdc_check_neither(a: bool, b: bool) { - LL| 2| if a && b { - ^0 - ------------------ - |---> MC/DC Decision Region (LL:8) to (LL:14) - | - | Number of Conditions: 2 - | Condition C1 --> (LL:8) - | Condition C2 --> (LL:13) - | - | Executed MC/DC Test Vectors: - | - | C1, C2 Result - | 1 { F, - = F } - | - | C1-Pair: not covered - | C2-Pair: not covered - | MC/DC Coverage for Decision: 0.00% - | - ------------------ - LL| 0| say("a and b"); - LL| 2| } else { - LL| 2| say("not both"); - LL| 2| } - LL| 2|} -"#; - - assert_eq!(anon(input), expected); -} From 5b0e6cb6729df41d45d7b504d46aa29e2059779b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 28 May 2024 13:39:21 +0200 Subject: [PATCH 080/104] Migrate `run-make/const-prop-lint` to `rmake.rs` --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/const-prop-lint/Makefile | 9 --------- tests/run-make/const-prop-lint/rmake.rs | 18 ++++++++++++++++++ 3 files changed, 18 insertions(+), 10 deletions(-) delete mode 100644 tests/run-make/const-prop-lint/Makefile create mode 100644 tests/run-make/const-prop-lint/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 2329b8b44dea..b8a663820851 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -22,7 +22,6 @@ run-make/compiler-lookup-paths-2/Makefile run-make/compiler-lookup-paths/Makefile run-make/compiler-rt-works-on-mingw/Makefile run-make/compressed-debuginfo/Makefile -run-make/const-prop-lint/Makefile run-make/const_fn_mir/Makefile run-make/crate-data-smoke/Makefile run-make/crate-hash-rustc-version/Makefile diff --git a/tests/run-make/const-prop-lint/Makefile b/tests/run-make/const-prop-lint/Makefile deleted file mode 100644 index f29f282f7876..000000000000 --- a/tests/run-make/const-prop-lint/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../tools.mk - -# Test that emitting an error because of arithmetic -# overflow lint does not leave .o files around -# because of interrupted codegen. - -all: - $(RUSTC) input.rs; test $$? -eq 1 - ls *.o; test $$? -ne 0 diff --git a/tests/run-make/const-prop-lint/rmake.rs b/tests/run-make/const-prop-lint/rmake.rs new file mode 100644 index 000000000000..fa27a18a591a --- /dev/null +++ b/tests/run-make/const-prop-lint/rmake.rs @@ -0,0 +1,18 @@ +// Tests that const prop lints interrupting codegen don't leave `.o` files around. + +use std::fs; + +use run_make_support::{rustc, tmp_dir}; + +fn main() { + rustc().input("input.rs").run_fail_assert_exit_code(1); + + for entry in fs::read_dir(tmp_dir()).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + + if path.is_file() && path.extension().is_some_and(|ext| ext == "o") { + panic!("there should not be `.o` files!"); + } + } +} From 1e6544a20ec8ba822c8af93a953ec7ea70dddbd9 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 29 May 2024 13:04:28 +0000 Subject: [PATCH 081/104] Move run-make windows_subsystem tests to ui tests --- tests/run-make/windows-subsystem/Makefile | 6 ------ tests/{run-make => ui}/windows-subsystem/console.rs | 1 + .../ui/{ => windows-subsystem}/windows-subsystem-invalid.rs | 0 .../windows-subsystem-invalid.stderr | 0 tests/{run-make => ui}/windows-subsystem/windows.rs | 1 + 5 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 tests/run-make/windows-subsystem/Makefile rename tests/{run-make => ui}/windows-subsystem/console.rs (78%) rename tests/ui/{ => windows-subsystem}/windows-subsystem-invalid.rs (100%) rename tests/ui/{ => windows-subsystem}/windows-subsystem-invalid.stderr (100%) rename tests/{run-make => ui}/windows-subsystem/windows.rs (78%) diff --git a/tests/run-make/windows-subsystem/Makefile b/tests/run-make/windows-subsystem/Makefile deleted file mode 100644 index e3cf9181de41..000000000000 --- a/tests/run-make/windows-subsystem/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) windows.rs - $(RUSTC) console.rs diff --git a/tests/run-make/windows-subsystem/console.rs b/tests/ui/windows-subsystem/console.rs similarity index 78% rename from tests/run-make/windows-subsystem/console.rs rename to tests/ui/windows-subsystem/console.rs index 61a92eb6a9db..8f0ca2de370d 100644 --- a/tests/run-make/windows-subsystem/console.rs +++ b/tests/ui/windows-subsystem/console.rs @@ -1,3 +1,4 @@ +//@ run-pass #![windows_subsystem = "console"] fn main() {} diff --git a/tests/ui/windows-subsystem-invalid.rs b/tests/ui/windows-subsystem/windows-subsystem-invalid.rs similarity index 100% rename from tests/ui/windows-subsystem-invalid.rs rename to tests/ui/windows-subsystem/windows-subsystem-invalid.rs diff --git a/tests/ui/windows-subsystem-invalid.stderr b/tests/ui/windows-subsystem/windows-subsystem-invalid.stderr similarity index 100% rename from tests/ui/windows-subsystem-invalid.stderr rename to tests/ui/windows-subsystem/windows-subsystem-invalid.stderr diff --git a/tests/run-make/windows-subsystem/windows.rs b/tests/ui/windows-subsystem/windows.rs similarity index 78% rename from tests/run-make/windows-subsystem/windows.rs rename to tests/ui/windows-subsystem/windows.rs index 1138248f07da..65db0fec7a8b 100644 --- a/tests/run-make/windows-subsystem/windows.rs +++ b/tests/ui/windows-subsystem/windows.rs @@ -1,3 +1,4 @@ +//@ run-pass #![windows_subsystem = "windows"] fn main() {} From f08e00f3d56645c9bbd4d2ebfbabe257b56b837b Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 29 May 2024 13:11:48 +0000 Subject: [PATCH 082/104] Rename run-make/issue-85441 and convert to rmake --- tests/run-make/issue-85441/Makefile | 9 ------- .../{issue-85441 => windows-ws2_32}/empty.rs | 0 tests/run-make/windows-ws2_32/rmake.rs | 27 +++++++++++++++++++ tests/run-make/windows-ws2_32/tcp.rs | 5 ++++ 4 files changed, 32 insertions(+), 9 deletions(-) delete mode 100644 tests/run-make/issue-85441/Makefile rename tests/run-make/{issue-85441 => windows-ws2_32}/empty.rs (100%) create mode 100644 tests/run-make/windows-ws2_32/rmake.rs create mode 100644 tests/run-make/windows-ws2_32/tcp.rs diff --git a/tests/run-make/issue-85441/Makefile b/tests/run-make/issue-85441/Makefile deleted file mode 100644 index 987d7f7d4a76..000000000000 --- a/tests/run-make/issue-85441/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# only-windows-msvc - -include ../tools.mk - -# Tests that WS2_32.dll is not unnecessarily linked, see issue #85441 - -all: - $(RUSTC) empty.rs - objdump -p $(TMPDIR)/empty.exe | $(CGREP) -v -i "WS2_32.dll" diff --git a/tests/run-make/issue-85441/empty.rs b/tests/run-make/windows-ws2_32/empty.rs similarity index 100% rename from tests/run-make/issue-85441/empty.rs rename to tests/run-make/windows-ws2_32/empty.rs diff --git a/tests/run-make/windows-ws2_32/rmake.rs b/tests/run-make/windows-ws2_32/rmake.rs new file mode 100644 index 000000000000..543f8594478c --- /dev/null +++ b/tests/run-make/windows-ws2_32/rmake.rs @@ -0,0 +1,27 @@ +//@ only-msvc + +// Tests that WS2_32.dll is not unnecessarily linked, see issue #85441 + +use run_make_support::object::{self, read::Object}; +use run_make_support::{rustc, tmp_dir}; +use std::fs; + +fn main() { + rustc().input("empty.rs").run(); + rustc().input("tcp.rs").run(); + + assert!(!links_ws2_32("empty.exe")); + assert!(links_ws2_32("tcp.exe")); +} + +fn links_ws2_32(exe: &str) -> bool { + let path = tmp_dir().join(exe); + let binary_data = fs::read(path).unwrap(); + let file = object::File::parse(&*binary_data).unwrap(); + for import in file.imports().unwrap() { + if import.library().eq_ignore_ascii_case(b"WS2_32.dll") { + return true; + } + } + false +} diff --git a/tests/run-make/windows-ws2_32/tcp.rs b/tests/run-make/windows-ws2_32/tcp.rs new file mode 100644 index 000000000000..3d0248c76d78 --- /dev/null +++ b/tests/run-make/windows-ws2_32/tcp.rs @@ -0,0 +1,5 @@ +use std::net::TcpListener; + +fn main() { + TcpListener::bind("127.0.0.1:80").unwrap(); +} From e463f6fd0bbd7d22bb81cd1ab769eeeb21d9e91d Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 29 May 2024 13:12:45 +0000 Subject: [PATCH 083/104] Convert run-make/windows-spawn to rmake --- tests/run-make/windows-spawn/Makefile | 8 -------- tests/run-make/windows-spawn/rmake.rs | 17 +++++++++++++++++ tests/run-make/windows-spawn/spawn.rs | 10 ++++------ 3 files changed, 21 insertions(+), 14 deletions(-) delete mode 100644 tests/run-make/windows-spawn/Makefile create mode 100644 tests/run-make/windows-spawn/rmake.rs diff --git a/tests/run-make/windows-spawn/Makefile b/tests/run-make/windows-spawn/Makefile deleted file mode 100644 index b6cdb169bab4..000000000000 --- a/tests/run-make/windows-spawn/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -include ../tools.mk - -# only-windows - -all: - $(RUSTC) -o "$(TMPDIR)/hopefullydoesntexist bar.exe" hello.rs - $(RUSTC) spawn.rs - $(TMPDIR)/spawn.exe diff --git a/tests/run-make/windows-spawn/rmake.rs b/tests/run-make/windows-spawn/rmake.rs new file mode 100644 index 000000000000..fb9cf1e21490 --- /dev/null +++ b/tests/run-make/windows-spawn/rmake.rs @@ -0,0 +1,17 @@ +//@ only-windows + +use run_make_support::{run, rustc, tmp_dir}; + +// On Windows `Command` uses `CreateProcessW` to run a new process. +// However, in the past std used to not pass in the application name, leaving +// `CreateProcessW` to use heuristics to guess the intended name from the +// command line string. Sometimes this could go very wrong. +// E.g. in Rust 1.0 `Command::new("foo").arg("bar").spawn()` will try to launch +// `foo bar.exe` if foo.exe does not exist. Which is clearly not desired. + +fn main() { + let out_dir = tmp_dir(); + rustc().input("hello.rs").output(out_dir.join("hopefullydoesntexist bar.exe")).run(); + rustc().input("spawn.rs").run(); + run("spawn"); +} diff --git a/tests/run-make/windows-spawn/spawn.rs b/tests/run-make/windows-spawn/spawn.rs index c34da3d5fde4..a9e86d1577e5 100644 --- a/tests/run-make/windows-spawn/spawn.rs +++ b/tests/run-make/windows-spawn/spawn.rs @@ -3,10 +3,8 @@ use std::process::Command; fn main() { // Make sure it doesn't try to run "hopefullydoesntexist bar.exe". - assert_eq!(Command::new("hopefullydoesntexist") - .arg("bar") - .spawn() - .unwrap_err() - .kind(), - ErrorKind::NotFound); + assert_eq!( + Command::new("hopefullydoesntexist").arg("bar").spawn().unwrap_err().kind(), + ErrorKind::NotFound + ) } From e03f9cb52debfbbc3d995584b572f219b31dad7f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 29 May 2024 13:14:19 +0000 Subject: [PATCH 084/104] Convert run-make/windows-safeseh to rmake --- src/tools/run-make-support/src/rustc.rs | 6 ++++++ tests/run-make/windows-safeseh/Makefile | 19 ------------------- tests/run-make/windows-safeseh/rmake.rs | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 19 deletions(-) delete mode 100644 tests/run-make/windows-safeseh/Makefile create mode 100644 tests/run-make/windows-safeseh/rmake.rs diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index b424ae3f4210..5dde0f91feac 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -203,6 +203,12 @@ impl Rustc { self } + /// Specify the linker + pub fn linker(&mut self, linker: &str) -> &mut Self { + self.cmd.arg(format!("-Clinker={linker}")); + self + } + /// Get the [`Output`] of the finished process. #[track_caller] pub fn command_output(&mut self) -> ::std::process::Output { diff --git a/tests/run-make/windows-safeseh/Makefile b/tests/run-make/windows-safeseh/Makefile deleted file mode 100644 index d6a403961d79..000000000000 --- a/tests/run-make/windows-safeseh/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# only-windows -# needs-rust-lld - -include ../tools.mk - -all: foo bar - -# Ensure that LLD can link when an .rlib contains a synthetic object -# file referencing exported or used symbols. -foo: - $(RUSTC) -C linker=rust-lld foo.rs - -# Ensure that LLD can link when /WHOLEARCHIVE: is used with an .rlib. -# Previously, lib.rmeta was not marked as (trivially) SAFESEH-aware. -bar: baz - $(RUSTC) -C linker=rust-lld -C link-arg=/WHOLEARCHIVE:libbaz.rlib bar.rs - -baz: - $(RUSTC) baz.rs diff --git a/tests/run-make/windows-safeseh/rmake.rs b/tests/run-make/windows-safeseh/rmake.rs new file mode 100644 index 000000000000..10e6b38aa8df --- /dev/null +++ b/tests/run-make/windows-safeseh/rmake.rs @@ -0,0 +1,15 @@ +//@ only-windows +//@ needs-rust-lld + +use run_make_support::rustc; + +fn main() { + // Ensure that LLD can link when an .rlib contains a synthetic object + // file referencing exported or used symbols. + rustc().input("foo.rs").linker("rust-lld").run(); + + // Ensure that LLD can link when /WHOLEARCHIVE: is used with an .rlib. + // Previously, lib.rmeta was not marked as (trivially) SAFESEH-aware. + rustc().input("baz.rs").run(); + rustc().input("bar.rs").linker("rust-lld").link_arg("/WHOLEARCHIVE:libbaz.rlib").run(); +} From 5ec0c002edf05d7a5a3596c26f30ffa258b580bb Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 29 May 2024 13:15:10 +0000 Subject: [PATCH 085/104] Convert windows-binary-no-external-deps to rmake --- .../windows-binary-no-external-deps/Makefile | 9 -------- .../windows-binary-no-external-deps/rmake.rs | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) delete mode 100644 tests/run-make/windows-binary-no-external-deps/Makefile create mode 100644 tests/run-make/windows-binary-no-external-deps/rmake.rs diff --git a/tests/run-make/windows-binary-no-external-deps/Makefile b/tests/run-make/windows-binary-no-external-deps/Makefile deleted file mode 100644 index 8960020fed55..000000000000 --- a/tests/run-make/windows-binary-no-external-deps/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../tools.mk - -# only-windows - -PATH=$(SYSTEMROOT)/system32 - -all: - $(RUSTC) hello.rs - $(TMPDIR)/hello.exe diff --git a/tests/run-make/windows-binary-no-external-deps/rmake.rs b/tests/run-make/windows-binary-no-external-deps/rmake.rs new file mode 100644 index 000000000000..6704fe041483 --- /dev/null +++ b/tests/run-make/windows-binary-no-external-deps/rmake.rs @@ -0,0 +1,21 @@ +//! Ensure that we aren't relying on any non-system DLLs when running +//! a "hello world" application by setting `PATH` to `C:\Windows\System32`. +//@ only-windows + +use run_make_support::{rustc, tmp_dir}; +use std::env; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + rustc().input("hello.rs").run(); + + let windows_dir = env::var("SystemRoot").unwrap(); + let system32: PathBuf = [&windows_dir, "System32"].iter().collect(); + // Note: This does not use the support wrappers so that we can precisely control the PATH + let exe = tmp_dir().join("hello.exe"); + let status = Command::new(exe).env("PATH", &system32).spawn().unwrap().wait().unwrap(); + if !status.success() { + panic!("Command failed!\noutput status: `{status}`"); + } +} From f34bbdecc4cd8e39470cbe2cefe96d4aed351da9 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 29 May 2024 13:15:41 +0000 Subject: [PATCH 086/104] Remove Makefiles from allowed_run_make_makefiles --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 75cd2b4c7731..fac11cd1566d 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -116,7 +116,6 @@ run-make/issue-83112-incr-test-moved-file/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/issue-85019-moved-src-dir/Makefile run-make/issue-85401-static-mir/Makefile -run-make/issue-85441/Makefile run-make/issue-88756-default-output/Makefile run-make/issue-97463-abi-param-passing/Makefile run-make/jobserver-error/Makefile @@ -272,8 +271,4 @@ run-make/volatile-intrinsics/Makefile run-make/wasm-exceptions-nostd/Makefile run-make/wasm-override-linker/Makefile run-make/weird-output-filenames/Makefile -run-make/windows-binary-no-external-deps/Makefile -run-make/windows-safeseh/Makefile -run-make/windows-spawn/Makefile -run-make/windows-subsystem/Makefile run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile From de1d0e0da9a93d2881b0416b05423c63488c2343 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 May 2024 15:52:29 +0200 Subject: [PATCH 087/104] Migrate `run-make/crate-data-smoke` to `rmake.rs` --- src/tools/run-make-support/src/rustc.rs | 2 +- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/crate-data-smoke/Makefile | 10 ----- tests/run-make/crate-data-smoke/rmake.rs | 43 +++++++++++++++++++ 4 files changed, 44 insertions(+), 12 deletions(-) delete mode 100644 tests/run-make/crate-data-smoke/Makefile create mode 100644 tests/run-make/crate-data-smoke/rmake.rs diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index 1c83b630861c..0cd588a1eb3f 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -205,7 +205,7 @@ impl Rustc { /// Get the [`Output`][::std::process::Output] of the finished process. #[track_caller] - pub fn command_output(&mut self) -> ::std::process::Output { + pub fn command_output(&mut self) -> Output { // let's make sure we piped all the input and outputs self.cmd.stdin(Stdio::piped()); self.cmd.stdout(Stdio::piped()); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 2329b8b44dea..a51a6932ef22 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -24,7 +24,6 @@ run-make/compiler-rt-works-on-mingw/Makefile run-make/compressed-debuginfo/Makefile run-make/const-prop-lint/Makefile run-make/const_fn_mir/Makefile -run-make/crate-data-smoke/Makefile run-make/crate-hash-rustc-version/Makefile run-make/crate-name-priority/Makefile run-make/cross-lang-lto-clang/Makefile diff --git a/tests/run-make/crate-data-smoke/Makefile b/tests/run-make/crate-data-smoke/Makefile deleted file mode 100644 index a453f65ff3ea..000000000000 --- a/tests/run-make/crate-data-smoke/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -include ../tools.mk - -all: - [ `$(RUSTC) --print crate-name crate.rs` = "foo" ] - [ `$(RUSTC) --print file-names crate.rs` = "$(call BIN,foo)" ] - [ `$(RUSTC) --print file-names --crate-type=lib \ - --test crate.rs` = "$(call BIN,foo)" ] - [ `$(RUSTC) --print file-names --test lib.rs` = "$(call BIN,mylib)" ] - $(RUSTC) --print file-names lib.rs - $(RUSTC) --print file-names rlib.rs diff --git a/tests/run-make/crate-data-smoke/rmake.rs b/tests/run-make/crate-data-smoke/rmake.rs new file mode 100644 index 000000000000..9c9b1c334c0e --- /dev/null +++ b/tests/run-make/crate-data-smoke/rmake.rs @@ -0,0 +1,43 @@ +use std::process::Output; + +use run_make_support::{bin_name, rust_lib, rustc}; + +fn compare_stdout>(output: Output, expected: S) { + assert_eq!( + String::from_utf8(output.stdout).unwrap().trim(), + expected.as_ref() + ); +} + +fn main() { + compare_stdout(rustc().print("crate-name").input("crate.rs").run(), "foo"); + compare_stdout( + rustc().print("file-names").input("crate.rs").run(), + bin_name("foo"), + ); + compare_stdout( + rustc() + .print("file-names") + .crate_type("lib") + .arg("--test") + .input("crate.rs") + .run(), + bin_name("foo"), + ); + compare_stdout( + rustc() + .print("file-names") + .arg("--test") + .input("lib.rs") + .run(), + bin_name("mylib"), + ); + compare_stdout( + rustc().print("file-names").input("lib.rs").run(), + rust_lib("mylib").file_name().unwrap().to_string_lossy(), + ); + compare_stdout( + rustc().print("file-names").input("rlib.rs").run(), + rust_lib("mylib").file_name().unwrap().to_string_lossy(), + ); +} From 4aafecb1693c30625c3f8d75f428edf3dad22755 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Wed, 29 May 2024 16:58:46 +0200 Subject: [PATCH 088/104] Simplify check for unsupported architectures --- tests/ui/abi/fixed_x18.arm.stderr | 2 -- tests/ui/abi/fixed_x18.i686.stderr | 2 -- tests/ui/abi/fixed_x18.riscv32.stderr | 2 -- tests/ui/abi/fixed_x18.riscv64.stderr | 2 -- tests/ui/abi/fixed_x18.rs | 2 ++ tests/ui/abi/fixed_x18.x64.stderr | 2 -- 6 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 tests/ui/abi/fixed_x18.arm.stderr delete mode 100644 tests/ui/abi/fixed_x18.i686.stderr delete mode 100644 tests/ui/abi/fixed_x18.riscv32.stderr delete mode 100644 tests/ui/abi/fixed_x18.riscv64.stderr delete mode 100644 tests/ui/abi/fixed_x18.x64.stderr diff --git a/tests/ui/abi/fixed_x18.arm.stderr b/tests/ui/abi/fixed_x18.arm.stderr deleted file mode 100644 index 68728dd9307a..000000000000 --- a/tests/ui/abi/fixed_x18.arm.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Zfixed-x18` flag is not supported on the `arm` architecture - diff --git a/tests/ui/abi/fixed_x18.i686.stderr b/tests/ui/abi/fixed_x18.i686.stderr deleted file mode 100644 index 458c0679f843..000000000000 --- a/tests/ui/abi/fixed_x18.i686.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Zfixed-x18` flag is not supported on the `x86` architecture - diff --git a/tests/ui/abi/fixed_x18.riscv32.stderr b/tests/ui/abi/fixed_x18.riscv32.stderr deleted file mode 100644 index e872fb4455b7..000000000000 --- a/tests/ui/abi/fixed_x18.riscv32.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Zfixed-x18` flag is not supported on the `riscv32` architecture - diff --git a/tests/ui/abi/fixed_x18.riscv64.stderr b/tests/ui/abi/fixed_x18.riscv64.stderr deleted file mode 100644 index 7127e5d7056f..000000000000 --- a/tests/ui/abi/fixed_x18.riscv64.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Zfixed-x18` flag is not supported on the `riscv64` architecture - diff --git a/tests/ui/abi/fixed_x18.rs b/tests/ui/abi/fixed_x18.rs index 6d00cb2709da..f1ff3e1d5341 100644 --- a/tests/ui/abi/fixed_x18.rs +++ b/tests/ui/abi/fixed_x18.rs @@ -2,6 +2,8 @@ // Behavior on aarch64 is tested by tests/codegen/fixed-x18.rs. // //@ revisions: x64 i686 arm riscv32 riscv64 +//@ error-pattern: the `-Zfixed-x18` flag is not supported +//@ dont-check-compiler-stderr // //@ compile-flags: -Zfixed-x18 //@ [x64] needs-llvm-components: x86 diff --git a/tests/ui/abi/fixed_x18.x64.stderr b/tests/ui/abi/fixed_x18.x64.stderr deleted file mode 100644 index 6dc367f9edce..000000000000 --- a/tests/ui/abi/fixed_x18.x64.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Zfixed-x18` flag is not supported on the `x86_64` architecture - From 22953b3f52a06c5b4826d455fba526c36ef8cb58 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 28 May 2024 10:58:01 -0400 Subject: [PATCH 089/104] convert simple-dylib to ui test --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/simple-dylib/Makefile | 6 ------ tests/run-make/simple-dylib/bar.rs | 1 - tests/run-make/simple-dylib/foo.rs | 5 ----- tests/ui/imports/auxiliary/simple-dylib.rs | 4 ++++ tests/ui/imports/simple-dylib-import.rs | 12 ++++++++++++ 6 files changed, 16 insertions(+), 13 deletions(-) delete mode 100644 tests/run-make/simple-dylib/Makefile delete mode 100644 tests/run-make/simple-dylib/bar.rs delete mode 100644 tests/run-make/simple-dylib/foo.rs create mode 100644 tests/ui/imports/auxiliary/simple-dylib.rs create mode 100644 tests/ui/imports/simple-dylib-import.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 75cd2b4c7731..1639286e9021 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -235,7 +235,6 @@ run-make/share-generics-dylib/Makefile run-make/short-ice/Makefile run-make/silly-file-names/Makefile run-make/simd-ffi/Makefile -run-make/simple-dylib/Makefile run-make/split-debuginfo/Makefile run-make/stable-symbol-names/Makefile run-make/static-dylib-by-default/Makefile diff --git a/tests/run-make/simple-dylib/Makefile b/tests/run-make/simple-dylib/Makefile deleted file mode 100644 index f3e1c1da88ce..000000000000 --- a/tests/run-make/simple-dylib/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# ignore-cross-compile -include ../tools.mk -all: - $(RUSTC) bar.rs --crate-type=dylib -C prefer-dynamic - $(RUSTC) foo.rs - $(call RUN,foo) diff --git a/tests/run-make/simple-dylib/bar.rs b/tests/run-make/simple-dylib/bar.rs deleted file mode 100644 index c5c0bc606cd6..000000000000 --- a/tests/run-make/simple-dylib/bar.rs +++ /dev/null @@ -1 +0,0 @@ -pub fn bar() {} diff --git a/tests/run-make/simple-dylib/foo.rs b/tests/run-make/simple-dylib/foo.rs deleted file mode 100644 index 8d68535e3b64..000000000000 --- a/tests/run-make/simple-dylib/foo.rs +++ /dev/null @@ -1,5 +0,0 @@ -extern crate bar; - -fn main() { - bar::bar(); -} diff --git a/tests/ui/imports/auxiliary/simple-dylib.rs b/tests/ui/imports/auxiliary/simple-dylib.rs new file mode 100644 index 000000000000..1b5d85104ca1 --- /dev/null +++ b/tests/ui/imports/auxiliary/simple-dylib.rs @@ -0,0 +1,4 @@ +//@ compile-flags --crate-type=dylib -Cprefer-dynamic + +#![crate_type = "dylib"] +pub fn bar() {} diff --git a/tests/ui/imports/simple-dylib-import.rs b/tests/ui/imports/simple-dylib-import.rs new file mode 100644 index 000000000000..7c7f3afec93b --- /dev/null +++ b/tests/ui/imports/simple-dylib-import.rs @@ -0,0 +1,12 @@ +// A simple test, where foo.rs has a dependency +// on the dynamic library simple-dylib.rs. If the test passes, +// dylibs can be built and linked into another file successfully.. + +//@ aux-crate: simple-dylib.rs +//@ run-pass + +extern crate bar; + +fn main() { + bar::bar(); +} From 0697884ea970ebca67b2de41dc1d380e66fd9c2b Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 28 May 2024 11:17:17 -0400 Subject: [PATCH 090/104] convert fpic to ui test --- tests/run-make/fpic/Makefile | 11 ----------- tests/run-make/fpic/hello.rs | 1 - tests/ui/errors/pic-linker.rs | 12 ++++++++++++ 3 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 tests/run-make/fpic/Makefile delete mode 100644 tests/run-make/fpic/hello.rs create mode 100644 tests/ui/errors/pic-linker.rs diff --git a/tests/run-make/fpic/Makefile b/tests/run-make/fpic/Makefile deleted file mode 100644 index d3754d17372f..000000000000 --- a/tests/run-make/fpic/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# ignore-windows -# ignore-apple - -# Test for #39529. -# `-z text` causes ld to error if there are any non-PIC sections - -all: - $(RUSTC) hello.rs -C link-args=-Wl,-z,text diff --git a/tests/run-make/fpic/hello.rs b/tests/run-make/fpic/hello.rs deleted file mode 100644 index 45590d86ba6c..000000000000 --- a/tests/run-make/fpic/hello.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() { } diff --git a/tests/ui/errors/pic-linker.rs b/tests/ui/errors/pic-linker.rs new file mode 100644 index 000000000000..9fea42484ed8 --- /dev/null +++ b/tests/ui/errors/pic-linker.rs @@ -0,0 +1,12 @@ +// `-z text` caused the linker to error if there were any non-position-independent +// code (PIC) sections. This test checks that this no longer happens. +// See https://github.com/rust-lang/rust/pull/39803 + +//@ ignore-windows +//@ ignore-macos +//@ ignore-cross-compile + +//@ compile-flags -Clink-args=-Wl,-z,text +//@ run-pass + +fn main() {} From 8c8d0db02deccea377e179948b8b3bfdd4b92e44 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 28 May 2024 11:35:33 -0400 Subject: [PATCH 091/104] rewrite and rename issue-37893 to rmake --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 2 -- tests/run-make/issue-37893/Makefile | 5 ----- .../{issue-37893 => proc-macro-init-order}/a.rs | 0 .../{issue-37893 => proc-macro-init-order}/b.rs | 0 .../{issue-37893 => proc-macro-init-order}/c.rs | 0 tests/run-make/proc-macro-init-order/rmake.rs | 15 +++++++++++++++ tests/ui/errors/pic-linker.rs | 2 +- tests/ui/imports/auxiliary/simple-dylib.rs | 2 +- tests/ui/imports/simple-dylib-import.rs | 2 +- 9 files changed, 18 insertions(+), 10 deletions(-) delete mode 100644 tests/run-make/issue-37893/Makefile rename tests/run-make/{issue-37893 => proc-macro-init-order}/a.rs (100%) rename tests/run-make/{issue-37893 => proc-macro-init-order}/b.rs (100%) rename tests/run-make/{issue-37893 => proc-macro-init-order}/c.rs (100%) create mode 100644 tests/run-make/proc-macro-init-order/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 1639286e9021..c47361ebc059 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -72,7 +72,6 @@ run-make/forced-unwind-terminate-pof/Makefile run-make/foreign-double-unwind/Makefile run-make/foreign-exceptions/Makefile run-make/foreign-rust-exceptions/Makefile -run-make/fpic/Makefile run-make/glibc-staticlib-args/Makefile run-make/inaccessible-temp-dir/Makefile run-make/include_bytes_deps/Makefile @@ -103,7 +102,6 @@ run-make/issue-33329/Makefile run-make/issue-35164/Makefile run-make/issue-36710/Makefile run-make/issue-37839/Makefile -run-make/issue-37893/Makefile run-make/issue-40535/Makefile run-make/issue-47384/Makefile run-make/issue-47551/Makefile diff --git a/tests/run-make/issue-37893/Makefile b/tests/run-make/issue-37893/Makefile deleted file mode 100644 index 44e4a321a30a..000000000000 --- a/tests/run-make/issue-37893/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs diff --git a/tests/run-make/issue-37893/a.rs b/tests/run-make/proc-macro-init-order/a.rs similarity index 100% rename from tests/run-make/issue-37893/a.rs rename to tests/run-make/proc-macro-init-order/a.rs diff --git a/tests/run-make/issue-37893/b.rs b/tests/run-make/proc-macro-init-order/b.rs similarity index 100% rename from tests/run-make/issue-37893/b.rs rename to tests/run-make/proc-macro-init-order/b.rs diff --git a/tests/run-make/issue-37893/c.rs b/tests/run-make/proc-macro-init-order/c.rs similarity index 100% rename from tests/run-make/issue-37893/c.rs rename to tests/run-make/proc-macro-init-order/c.rs diff --git a/tests/run-make/proc-macro-init-order/rmake.rs b/tests/run-make/proc-macro-init-order/rmake.rs new file mode 100644 index 000000000000..3c3fc813381c --- /dev/null +++ b/tests/run-make/proc-macro-init-order/rmake.rs @@ -0,0 +1,15 @@ +// a.rs is a procedural macro crate, on which b.rs and c.rs depend. A now +// patched bug caused a compilation failure if the proc-macro crate was +// initialized with its dependents in this exact order. This test checks +// that compilation succeeds even when initialization is done in this order. +// See https://github.com/rust-lang/rust/issues/37893 + +//@ ignore-cross-compile + +use run_make_support::rustc; + +fn main() { + rustc().input("a.rs").run(); + rustc().input("b.rs").run(); + rustc().input("c.rs").run(); +} diff --git a/tests/ui/errors/pic-linker.rs b/tests/ui/errors/pic-linker.rs index 9fea42484ed8..d90989903048 100644 --- a/tests/ui/errors/pic-linker.rs +++ b/tests/ui/errors/pic-linker.rs @@ -6,7 +6,7 @@ //@ ignore-macos //@ ignore-cross-compile -//@ compile-flags -Clink-args=-Wl,-z,text +//@ compile-flags: -Clink-args=-Wl,-z,text //@ run-pass fn main() {} diff --git a/tests/ui/imports/auxiliary/simple-dylib.rs b/tests/ui/imports/auxiliary/simple-dylib.rs index 1b5d85104ca1..af64aa66f31b 100644 --- a/tests/ui/imports/auxiliary/simple-dylib.rs +++ b/tests/ui/imports/auxiliary/simple-dylib.rs @@ -1,4 +1,4 @@ -//@ compile-flags --crate-type=dylib -Cprefer-dynamic +//@ compile-flags: -Cprefer-dynamic #![crate_type = "dylib"] pub fn bar() {} diff --git a/tests/ui/imports/simple-dylib-import.rs b/tests/ui/imports/simple-dylib-import.rs index 7c7f3afec93b..d8ee3496b90d 100644 --- a/tests/ui/imports/simple-dylib-import.rs +++ b/tests/ui/imports/simple-dylib-import.rs @@ -2,7 +2,7 @@ // on the dynamic library simple-dylib.rs. If the test passes, // dylibs can be built and linked into another file successfully.. -//@ aux-crate: simple-dylib.rs +//@ aux-crate:bar=simple-dylib.rs //@ run-pass extern crate bar; From 301d7229f706cbb95e78cd2319148bcbf22d80a1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 May 2024 18:00:14 +0200 Subject: [PATCH 092/104] Add `run-make-support::rust_lib_name` --- src/tools/run-make-support/src/lib.rs | 8 +++++++- tests/run-make/crate-data-smoke/rmake.rs | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index d96c8b891278..c7f48ad3f19f 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -135,7 +135,13 @@ pub fn dynamic_lib_name(name: &str) -> String { /// Construct a path to a rust library (rlib) under `$TMPDIR` given the library name. This will return a /// path with `$TMPDIR` joined with the library name. pub fn rust_lib(name: &str) -> PathBuf { - tmp_dir().join(format!("lib{name}.rlib")) + tmp_dir().join(rust_lib_name(name)) +} + +/// Generate the name a rust library (rlib) would have. If you want the complete path, use +/// [`rust_lib`] instead. +pub fn rust_lib_name(name: &str) -> String { + format!("lib{name}.rlib") } /// Construct the binary name based on platform. diff --git a/tests/run-make/crate-data-smoke/rmake.rs b/tests/run-make/crate-data-smoke/rmake.rs index 9c9b1c334c0e..80d43903a532 100644 --- a/tests/run-make/crate-data-smoke/rmake.rs +++ b/tests/run-make/crate-data-smoke/rmake.rs @@ -1,6 +1,6 @@ use std::process::Output; -use run_make_support::{bin_name, rust_lib, rustc}; +use run_make_support::{bin_name, rust_lib_name, rustc}; fn compare_stdout>(output: Output, expected: S) { assert_eq!( @@ -34,10 +34,10 @@ fn main() { ); compare_stdout( rustc().print("file-names").input("lib.rs").run(), - rust_lib("mylib").file_name().unwrap().to_string_lossy(), + rust_lib_name("mylib"), ); compare_stdout( rustc().print("file-names").input("rlib.rs").run(), - rust_lib("mylib").file_name().unwrap().to_string_lossy(), + rust_lib_name("mylib"), ); } From 0d63e6b60843a9fb37b51e416b8cea6b146142d4 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 28 May 2024 19:00:37 -0700 Subject: [PATCH 093/104] [ACP 362] genericize `ptr::from_raw_parts` --- library/core/src/ptr/metadata.rs | 4 ++-- library/core/src/ptr/mod.rs | 8 ++++---- library/core/src/str/converts.rs | 4 ++-- library/core/tests/mem.rs | 4 ++-- library/core/tests/ptr.rs | 4 ++-- .../inline/inline_shims.drop.Inline.panic-abort.diff | 4 +++- ...set.demo_byte_add_fat.PreCodegen.after.panic-abort.mir | 2 +- ...et.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir | 2 +- ...et.demo_byte_add_thin.PreCodegen.after.panic-abort.mir | 2 +- ...t.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir | 2 +- ...ef.vec_deref_to_slice.PreCodegen.after.panic-abort.mir | 4 ++++ ...f.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir | 4 ++++ tests/ui/unsized/unsized3-rpass.rs | 2 +- 13 files changed, 28 insertions(+), 18 deletions(-) diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 8d75bd2e74c7..78fe0c5add50 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -120,7 +120,7 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] pub const fn from_raw_parts( - data_pointer: *const (), + data_pointer: *const impl Thin, metadata: ::Metadata, ) -> *const T { aggregate_raw_ptr(data_pointer, metadata) @@ -134,7 +134,7 @@ pub const fn from_raw_parts( #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] pub const fn from_raw_parts_mut( - data_pointer: *mut (), + data_pointer: *mut impl Thin, metadata: ::Metadata, ) -> *mut T { aggregate_raw_ptr(data_pointer, metadata) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index d2bbdc84d4dd..4213a9dedfe4 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -565,7 +565,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { #[rustc_allow_const_fn_unstable(ptr_metadata)] #[rustc_diagnostic_item = "ptr_null"] pub const fn null() -> *const T { - from_raw_parts(without_provenance(0), ()) + from_raw_parts(without_provenance::<()>(0), ()) } /// Creates a null mutable raw pointer. @@ -591,7 +591,7 @@ pub const fn null() -> *const T { #[rustc_allow_const_fn_unstable(ptr_metadata)] #[rustc_diagnostic_item = "ptr_null_mut"] pub const fn null_mut() -> *mut T { - from_raw_parts_mut(without_provenance_mut(0), ()) + from_raw_parts_mut(without_provenance_mut::<()>(0), ()) } /// Creates a pointer with the given address and no provenance. @@ -835,7 +835,7 @@ pub const fn from_mut(r: &mut T) -> *mut T { #[rustc_allow_const_fn_unstable(ptr_metadata)] #[rustc_diagnostic_item = "ptr_slice_from_raw_parts"] pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { - intrinsics::aggregate_raw_ptr(data, len) + from_raw_parts(data, len) } /// Forms a raw mutable slice from a pointer and a length. @@ -881,7 +881,7 @@ pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { #[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")] #[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"] pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { - intrinsics::aggregate_raw_ptr(data, len) + from_raw_parts_mut(data, len) } /// Swaps the values at two mutable locations of the same type, without diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index b6ffb0a608d0..397759bd5cae 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -222,7 +222,7 @@ pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { #[rustc_const_unstable(feature = "str_from_raw_parts", issue = "119206")] pub const unsafe fn from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str { // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. - unsafe { &*ptr::from_raw_parts(ptr.cast(), len) } + unsafe { &*ptr::from_raw_parts(ptr, len) } } /// Creates an `&mut str` from a pointer and a length. @@ -241,5 +241,5 @@ pub const unsafe fn from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str { #[rustc_const_unstable(feature = "const_str_from_raw_parts_mut", issue = "119206")] pub const unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut str { // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. - unsafe { &mut *ptr::from_raw_parts_mut(ptr.cast(), len) } + unsafe { &mut *ptr::from_raw_parts_mut(ptr, len) } } diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index e388800f400d..cc7339163076 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -83,12 +83,12 @@ fn align_of_val_raw_packed() { f: [u32], } let storage = [0u8; 4]; - let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1); + let b: *const B = ptr::from_raw_parts(storage.as_ptr(), 1); assert_eq!(unsafe { align_of_val_raw(b) }, 1); const ALIGN_OF_VAL_RAW: usize = { let storage = [0u8; 4]; - let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1); + let b: *const B = ptr::from_raw_parts(storage.as_ptr(), 1); unsafe { align_of_val_raw(b) } }; assert_eq!(ALIGN_OF_VAL_RAW, 1); diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index e8d05c2483de..e3830165eda6 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -965,7 +965,7 @@ fn thin_box() { fn value_ptr(&self) -> *const T { let (_, offset) = self.layout(); let data_ptr = unsafe { self.ptr.cast::().as_ptr().add(offset) }; - ptr::from_raw_parts(data_ptr.cast(), self.meta()) + ptr::from_raw_parts(data_ptr, self.meta()) } fn value_mut_ptr(&mut self) -> *mut T { @@ -973,7 +973,7 @@ fn thin_box() { // FIXME: can this line be shared with the same in `value_ptr()` // without upsetting Stacked Borrows? let data_ptr = unsafe { self.ptr.cast::().as_ptr().add(offset) }; - from_raw_parts_mut(data_ptr.cast(), self.meta()) + from_raw_parts_mut(data_ptr, self.meta()) } } diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff index df873600577a..45ce933a55ad 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff @@ -27,10 +27,12 @@ + } + } + scope 7 (inlined slice_from_raw_parts_mut::) { ++ scope 8 (inlined std::ptr::from_raw_parts_mut::<[A], A>) { ++ } + } + } + } -+ scope 8 (inlined std::ptr::drop_in_place::> - shim(Some(Option))) { ++ scope 9 (inlined std::ptr::drop_in_place::> - shim(Some(Option))) { + let mut _14: isize; + let mut _15: isize; + } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir index ea4ed2713056..2c6d93e10c11 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir @@ -16,7 +16,7 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { let mut _6: usize; scope 5 (inlined std::ptr::metadata::<[u32]>) { } - scope 6 (inlined std::ptr::from_raw_parts::<[u32]>) { + scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) { } } } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir index ea4ed2713056..2c6d93e10c11 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir @@ -16,7 +16,7 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { let mut _6: usize; scope 5 (inlined std::ptr::metadata::<[u32]>) { } - scope 6 (inlined std::ptr::from_raw_parts::<[u32]>) { + scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) { } } } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir index 766bd29ef41c..04fb6b838f02 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir @@ -14,7 +14,7 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 { scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::) { scope 5 (inlined std::ptr::metadata::) { } - scope 6 (inlined std::ptr::from_raw_parts::) { + scope 6 (inlined std::ptr::from_raw_parts::) { } } } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir index 766bd29ef41c..04fb6b838f02 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir @@ -14,7 +14,7 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 { scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::) { scope 5 (inlined std::ptr::metadata::) { } - scope 6 (inlined std::ptr::from_raw_parts::) { + scope 6 (inlined std::ptr::from_raw_parts::) { } } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index eabecaed0517..1c9ed25d7f2b 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -37,6 +37,10 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { scope 11 (inlined slice_from_raw_parts::) { debug data => _4; debug len => _5; + scope 12 (inlined std::ptr::from_raw_parts::<[u8], u8>) { + debug data_pointer => _4; + debug metadata => _5; + } } } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index eabecaed0517..1c9ed25d7f2b 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -37,6 +37,10 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { scope 11 (inlined slice_from_raw_parts::) { debug data => _4; debug len => _5; + scope 12 (inlined std::ptr::from_raw_parts::<[u8], u8>) { + debug data_pointer => _4; + debug metadata => _5; + } } } } diff --git a/tests/ui/unsized/unsized3-rpass.rs b/tests/ui/unsized/unsized3-rpass.rs index 1b3e932bfe6d..ff35051774bc 100644 --- a/tests/ui/unsized/unsized3-rpass.rs +++ b/tests/ui/unsized/unsized3-rpass.rs @@ -87,7 +87,7 @@ pub fn main() { let obj: Box = Box::new(St { f: 42 }); let obj: &Tr = &*obj; let data: Box<_> = Box::new(Qux_ { f: St { f: 234 } }); - let x: &Qux = &*ptr::from_raw_parts::((&*data as *const _).cast(), ptr::metadata(obj)); + let x: &Qux = &*ptr::from_raw_parts::(&*data as *const _, ptr::metadata(obj)); assert_eq!(x.f.foo(), 234); } } From a4b737643e1c46c859c1b216059b7ce392136de4 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 28 May 2024 23:26:20 -0700 Subject: [PATCH 094/104] give tidy the good news about C-SKY --- src/tools/tidy/src/target_specific_tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs index 5a402f3cc601..6fd2148ef678 100644 --- a/src/tools/tidy/src/target_specific_tests.rs +++ b/src/tools/tidy/src/target_specific_tests.rs @@ -15,6 +15,7 @@ const KNOWN_LLVM_COMPONENTS: &[&str] = &[ "arm", "avr", "bpf", + "csky", "hexagon", "loongarch", "m68k", From ce092d46e3d5538608b681cc7867d03a3551c6c9 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 29 May 2024 00:22:35 -0700 Subject: [PATCH 095/104] tests: reenable ABI compatibility test for csky --- tests/ui/abi/compatibility.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 784c6d488eaf..c27a107a639f 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -52,18 +52,16 @@ //@ revisions: m68k //@[m68k] compile-flags: --target m68k-unknown-linux-gnu //@[m68k] needs-llvm-components: m68k +//@ revisions: csky +//@[csky] compile-flags: --target csky-unknown-linux-gnuabiv2 +//@[csky] needs-llvm-components: csky + // FIXME: disabled on nvptx64 since the target ABI fails the sanity check // see https://github.com/rust-lang/rust/issues/117480 /* revisions: nvptx64 [nvptx64] compile-flags: --target nvptx64-nvidia-cuda [nvptx64] needs-llvm-components: nvptx */ -// FIXME: disabled since it fails on CI saying the csky component is missing -// see https://github.com/rust-lang/rust/issues/125697 -/* revisions: csky - [csky] compile-flags: --target csky-unknown-linux-gnuabiv2 - [csky] needs-llvm-components: csky -*/ #![feature(rustc_attrs, unsized_fn_params, transparent_unions)] #![cfg_attr(not(host), feature(no_core, lang_items), no_std, no_core)] #![allow(unused, improper_ctypes_definitions, internal_features)] @@ -75,8 +73,7 @@ #[cfg(host)] use std::{ - any::Any, marker::PhantomData, mem::ManuallyDrop, num::NonZero, ptr::NonNull, rc::Rc, - sync::Arc, + any::Any, marker::PhantomData, mem::ManuallyDrop, num::NonZero, ptr::NonNull, rc::Rc, sync::Arc, }; /// To work cross-target this test must be no_core. From 60c30f57c1c4937f73416bf06295295076aa0c15 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 29 May 2024 10:32:41 -0700 Subject: [PATCH 096/104] ci: Consolidate $IS_NOT_LATEST_LLVM into $EXTERNAL_LLVM We want to only demand that we check for all components we expect if we actually built the components we expect, which means we built the LLVM. Otherwise, it isn't worth checking. --- src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile | 4 ---- src/ci/run.sh | 8 ++------ 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile index 538962802c96..275acb47c33a 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile @@ -45,10 +45,6 @@ RUN sh /scripts/sccache.sh ENV NO_DOWNLOAD_CI_LLVM 1 ENV EXTERNAL_LLVM 1 -# This is not the latest LLVM version, so some components required by tests may -# be missing. -ENV IS_NOT_LATEST_LLVM 1 - # Using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/ci/run.sh b/src/ci/run.sh index 3ad04c73d3da..2e36b7e5962e 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -89,6 +89,8 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --dist-compression-formats=xz" # (to avoid spending a lot of time cloning llvm) if [ "$EXTERNAL_LLVM" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.optimized-compiler-builtins" + # Likewise, only demand we test all LLVM components if we know we built LLVM with them + export COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS=1 elif [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then echo "error: dist builds should always use optimized compiler-rt!" >&2 exit 1 @@ -169,12 +171,6 @@ else fi fi -# Unless we're using an older version of LLVM, check that all LLVM components -# used by tests are available. -if [ "$IS_NOT_LATEST_LLVM" = "" ]; then - export COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS=1 -fi - if [ "$ENABLE_GCC_CODEGEN" = "1" ]; then # If `ENABLE_GCC_CODEGEN` is set and not empty, we add the `--enable-new-symbol-mangling` # argument to `RUST_CONFIGURE_ARGS` and set the `GCC_EXEC_PREFIX` environment variable. From 7f11d6f4bf8c4574b29d683ff72e596e7bcfbb50 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 29 May 2024 14:06:39 -0400 Subject: [PATCH 097/104] Add lang items for AsyncFn's associated types --- compiler/rustc_hir/src/lang_items.rs | 3 +++ compiler/rustc_span/src/symbol.rs | 3 +++ .../src/solve/normalizes_to/mod.rs | 22 ++++++++++++------- library/core/src/ops/async_function.rs | 3 +++ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index c4be67cdd887..410c2ed8703b 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -228,6 +228,9 @@ language_item_table! { AsyncFn, sym::async_fn, async_fn_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1); + AsyncFnOnceOutput, sym::async_fn_once_output,async_fn_once_output, Target::AssocTy, GenericRequirement::Exact(1); + CallOnceFuture, sym::call_once_future, call_once_future, Target::AssocTy, GenericRequirement::Exact(1); + CallRefFuture, sym::call_ref_future, call_ref_future, Target::AssocTy, GenericRequirement::Exact(2); AsyncFnKindHelper, sym::async_fn_kind_helper,async_fn_kind_helper, Target::Trait, GenericRequirement::Exact(1); FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 90da220b3f54..cabd462cc8a6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -441,6 +441,7 @@ symbols! { async_fn_kind_helper, async_fn_mut, async_fn_once, + async_fn_once_output, async_fn_track_caller, async_fn_traits, async_for_loop, @@ -498,6 +499,8 @@ symbols! { call, call_mut, call_once, + call_once_future, + call_ref_future, caller_location, capture_disjoint_fields, catch_unwind, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 7fd2a3801cc4..f9e164e1f3f9 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -407,16 +407,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { output_coroutine_ty, coroutine_return_ty, }| { - let (projection_term, term) = match tcx.item_name(goal.predicate.def_id()) { - sym::CallOnceFuture => ( + let lang_items = tcx.lang_items(); + let (projection_term, term) = if Some(goal.predicate.def_id()) + == lang_items.call_once_future() + { + ( ty::AliasTerm::new( tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), tupled_inputs_ty], ), output_coroutine_ty.into(), - ), - sym::CallRefFuture => ( + ) + } else if Some(goal.predicate.def_id()) == lang_items.call_ref_future() { + ( ty::AliasTerm::new( tcx, goal.predicate.def_id(), @@ -427,8 +431,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ], ), output_coroutine_ty.into(), - ), - sym::Output => ( + ) + } else if Some(goal.predicate.def_id()) == lang_items.async_fn_once_output() { + ( ty::AliasTerm::new( tcx, goal.predicate.def_id(), @@ -438,8 +443,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ], ), coroutine_return_ty.into(), - ), - name => bug!("no such associated type: {name}"), + ) + } else { + bug!("no such associated type in `AsyncFn*`: {:?}", goal.predicate.def_id()) }; ty::ProjectionPredicate { projection_term, term } }, diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs index 18bcee5a1c7e..fc21ffd5246e 100644 --- a/library/core/src/ops/async_function.rs +++ b/library/core/src/ops/async_function.rs @@ -26,6 +26,7 @@ pub trait AsyncFn: AsyncFnMut { pub trait AsyncFnMut: AsyncFnOnce { /// Future returned by [`AsyncFnMut::async_call_mut`] and [`AsyncFn::async_call`]. #[unstable(feature = "async_fn_traits", issue = "none")] + #[cfg_attr(not(bootstrap), lang = "call_ref_future")] type CallRefFuture<'a>: Future where Self: 'a; @@ -46,10 +47,12 @@ pub trait AsyncFnMut: AsyncFnOnce { pub trait AsyncFnOnce { /// Future returned by [`AsyncFnOnce::async_call_once`]. #[unstable(feature = "async_fn_traits", issue = "none")] + #[cfg_attr(not(bootstrap), lang = "call_once_future")] type CallOnceFuture: Future; /// Output type of the called closure's future. #[unstable(feature = "async_fn_traits", issue = "none")] + #[cfg_attr(not(bootstrap), lang = "async_fn_once_output")] type Output; /// Call the [`AsyncFnOnce`], returning a future which may move out of the called closure. From 3c4066d1126b7c0ed13da96639ca86ffc42ceea6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 29 May 2024 20:56:36 +0300 Subject: [PATCH 098/104] Add a test for resolving `macro_rules` calls inside attributes --- .../attributes/key-value-expansion-scope.rs | 64 ++++++++ .../key-value-expansion-scope.stderr | 138 ++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 tests/ui/attributes/key-value-expansion-scope.rs create mode 100644 tests/ui/attributes/key-value-expansion-scope.stderr diff --git a/tests/ui/attributes/key-value-expansion-scope.rs b/tests/ui/attributes/key-value-expansion-scope.rs new file mode 100644 index 000000000000..f435e36ce638 --- /dev/null +++ b/tests/ui/attributes/key-value-expansion-scope.rs @@ -0,0 +1,64 @@ +#![doc = in_root!()] // FIXME, this is a bug +#![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope +#![doc = in_mod_escape!()] // FIXME, this is a bug +#![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope + +#[doc = in_root!()] //~ ERROR cannot find macro `in_root` in this scope +#[doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope +#[doc = in_mod_escape!()] //~ ERROR cannot find macro `in_mod_escape` in this scope +#[doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope +fn before() { + #![doc = in_root!()] //~ ERROR cannot find macro `in_root` in this scope + #![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope + #![doc = in_mod_escape!()] //~ ERROR cannot find macro `in_mod_escape` in this scope + #![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope +} + +macro_rules! in_root { () => { "" } } + +mod macros_stay { + #![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope + + macro_rules! in_mod { () => { "" } } + + #[doc = in_mod!()] // OK + fn f() { + #![doc = in_mod!()] // OK + } +} + +#[macro_use] +mod macros_escape { + #![doc = in_mod_escape!()] //~ ERROR cannot find macro `in_mod_escape` in this scope + + macro_rules! in_mod_escape { () => { "" } } + + #[doc = in_mod_escape!()] // OK + fn f() { + #![doc = in_mod_escape!()] // OK + } +} + +fn block() { + #![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope + + macro_rules! in_block { () => { "" } } + + #[doc = in_block!()] // OK + fn f() { + #![doc = in_block!()] // OK + } +} + +#[doc = in_root!()] // OK +#[doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope +#[doc = in_mod_escape!()] // OK +#[doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope +fn after() { + #![doc = in_root!()] // OK + #![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope + #![doc = in_mod_escape!()] // OK + #![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope +} + +fn main() {} diff --git a/tests/ui/attributes/key-value-expansion-scope.stderr b/tests/ui/attributes/key-value-expansion-scope.stderr new file mode 100644 index 000000000000..2fa2ed0fa3a4 --- /dev/null +++ b/tests/ui/attributes/key-value-expansion-scope.stderr @@ -0,0 +1,138 @@ +error: cannot find macro `in_mod` in this scope + --> $DIR/key-value-expansion-scope.rs:2:10 + | +LL | #![doc = in_mod!()] + | ^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_block` in this scope + --> $DIR/key-value-expansion-scope.rs:4:10 + | +LL | #![doc = in_block!()] + | ^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_root` in this scope + --> $DIR/key-value-expansion-scope.rs:6:9 + | +LL | #[doc = in_root!()] + | ^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_mod` in this scope + --> $DIR/key-value-expansion-scope.rs:7:9 + | +LL | #[doc = in_mod!()] + | ^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_mod_escape` in this scope + --> $DIR/key-value-expansion-scope.rs:8:9 + | +LL | #[doc = in_mod_escape!()] + | ^^^^^^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_block` in this scope + --> $DIR/key-value-expansion-scope.rs:9:9 + | +LL | #[doc = in_block!()] + | ^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_root` in this scope + --> $DIR/key-value-expansion-scope.rs:11:14 + | +LL | #![doc = in_root!()] + | ^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_mod` in this scope + --> $DIR/key-value-expansion-scope.rs:12:14 + | +LL | #![doc = in_mod!()] + | ^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_mod_escape` in this scope + --> $DIR/key-value-expansion-scope.rs:13:14 + | +LL | #![doc = in_mod_escape!()] + | ^^^^^^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_block` in this scope + --> $DIR/key-value-expansion-scope.rs:14:14 + | +LL | #![doc = in_block!()] + | ^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_mod` in this scope + --> $DIR/key-value-expansion-scope.rs:20:14 + | +LL | #![doc = in_mod!()] + | ^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_mod_escape` in this scope + --> $DIR/key-value-expansion-scope.rs:32:14 + | +LL | #![doc = in_mod_escape!()] + | ^^^^^^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_block` in this scope + --> $DIR/key-value-expansion-scope.rs:43:14 + | +LL | #![doc = in_block!()] + | ^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_mod` in this scope + --> $DIR/key-value-expansion-scope.rs:54:9 + | +LL | #[doc = in_mod!()] + | ^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_block` in this scope + --> $DIR/key-value-expansion-scope.rs:56:9 + | +LL | #[doc = in_block!()] + | ^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_mod` in this scope + --> $DIR/key-value-expansion-scope.rs:59:14 + | +LL | #![doc = in_mod!()] + | ^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_block` in this scope + --> $DIR/key-value-expansion-scope.rs:61:14 + | +LL | #![doc = in_block!()] + | ^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: aborting due to 17 previous errors + From a9c7e024c08ce4c7172cf3a46d0d16222eb4991f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 29 May 2024 14:22:56 -0400 Subject: [PATCH 099/104] Add lang item for Future::Output --- compiler/rustc_hir/src/lang_items.rs | 1 + compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- .../src/solve/assembly/structural_traits.rs | 14 ++------------ .../rustc_trait_selection/src/traits/project.rs | 16 ++-------------- library/core/src/future/future.rs | 2 +- 6 files changed, 8 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 410c2ed8703b..67114a6212c4 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -238,6 +238,7 @@ language_item_table! { Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0); FusedIterator, sym::fused_iterator, fused_iterator_trait, Target::Trait, GenericRequirement::Exact(0); Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0); + FutureOutput, sym::future_output, future_output, Target::AssocTy, GenericRequirement::Exact(0); AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0); CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 75e35e7bf50c..7e7460061484 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1478,7 +1478,7 @@ pub fn suggest_impl_trait<'tcx>( ), ( infcx.tcx.lang_items().future_trait(), - infcx.tcx.get_diagnostic_item(sym::FutureOutput), + infcx.tcx.lang_items().future_output(), format_as_assoc, ), ( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index cabd462cc8a6..fa4ef923cc01 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -210,7 +210,6 @@ symbols! { FsPermissions, FusedIterator, Future, - FutureOutput, GlobalAlloc, Hash, HashMap, @@ -914,6 +913,7 @@ symbols! { fundamental, fused_iterator, future, + future_output, future_trait, gdb_script_file, ge, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 64d5f725a1f4..67cf0c3b2fde 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -454,12 +454,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc .rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()])) .upcast(tcx), ]; - let future_output_def_id = tcx - .associated_items(future_trait_def_id) - .filter_by_name_unhygienic(sym::Output) - .next() - .unwrap() - .def_id; + let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None); let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]); Ok(( bound_sig.rebind(AsyncCallableRelevantTypes { @@ -510,12 +505,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc ); } - let future_output_def_id = tcx - .associated_items(future_trait_def_id) - .filter_by_name_unhygienic(sym::Output) - .next() - .unwrap() - .def_id; + let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None); let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]); Ok(( bound_sig.rebind(AsyncCallableRelevantTypes { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 87c8b1cda504..c92c8369fede 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1880,13 +1880,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( let term = match item_name { sym::CallOnceFuture | sym::CallRefFuture => sig.output(), sym::Output => { - let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None); - let future_output_def_id = tcx - .associated_items(future_trait_def_id) - .filter_by_name_unhygienic(sym::Output) - .next() - .unwrap() - .def_id; + let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None); Ty::new_projection(tcx, future_output_def_id, [sig.output()]) } name => bug!("no such associated type: {name}"), @@ -1919,13 +1913,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( let term = match item_name { sym::CallOnceFuture | sym::CallRefFuture => sig.output(), sym::Output => { - let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None); - let future_output_def_id = tcx - .associated_items(future_trait_def_id) - .filter_by_name_unhygienic(sym::Output) - .next() - .unwrap() - .def_id; + let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None); Ty::new_projection(tcx, future_output_def_id, [sig.output()]) } name => bug!("no such associated type: {name}"), diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index f965afc8a593..86963b548b9c 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -35,7 +35,7 @@ use crate::task::{Context, Poll}; pub trait Future { /// The type of value produced on completion. #[stable(feature = "futures_api", since = "1.36.0")] - #[rustc_diagnostic_item = "FutureOutput"] + #[cfg_attr(not(bootstrap), lang = "future_output")] type Output; /// Attempt to resolve the future to a final value, registering From a03ba7fd2d0a94bd29f1ed7618c6e7ceecd3222c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 29 May 2024 14:28:53 -0400 Subject: [PATCH 100/104] Add lang item for AsyncFnKindHelper::Upvars --- compiler/rustc_hir/src/lang_items.rs | 5 +++-- compiler/rustc_span/src/symbol.rs | 1 + .../src/solve/assembly/structural_traits.rs | 9 +-------- .../src/traits/project.rs | 20 ++++--------------- library/core/src/ops/async_function.rs | 1 + 5 files changed, 10 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 67114a6212c4..f5f7bae11b20 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -228,10 +228,11 @@ language_item_table! { AsyncFn, sym::async_fn, async_fn_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1); - AsyncFnOnceOutput, sym::async_fn_once_output,async_fn_once_output, Target::AssocTy, GenericRequirement::Exact(1); + AsyncFnOnceOutput, sym::async_fn_once_output, async_fn_once_output, Target::AssocTy, GenericRequirement::Exact(1); CallOnceFuture, sym::call_once_future, call_once_future, Target::AssocTy, GenericRequirement::Exact(1); CallRefFuture, sym::call_ref_future, call_ref_future, Target::AssocTy, GenericRequirement::Exact(2); - AsyncFnKindHelper, sym::async_fn_kind_helper,async_fn_kind_helper, Target::Trait, GenericRequirement::Exact(1); + AsyncFnKindHelper, sym::async_fn_kind_helper, async_fn_kind_helper, Target::Trait, GenericRequirement::Exact(1); + AsyncFnKindUpvars, sym::async_fn_kind_upvars, async_fn_kind_upvars, Target::AssocTy, GenericRequirement::Exact(5); FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index fa4ef923cc01..25ecb9a31c6a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -438,6 +438,7 @@ symbols! { async_fn, async_fn_in_trait, async_fn_kind_helper, + async_fn_kind_upvars, async_fn_mut, async_fn_once, async_fn_once_output, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 67cf0c3b2fde..08796ef3109e 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -9,7 +9,6 @@ use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::bug; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, Upcast}; -use rustc_span::sym; use crate::solve::EvalCtxt; @@ -582,13 +581,7 @@ fn coroutine_closure_to_ambiguous_coroutine<'tcx>( args: ty::CoroutineClosureArgs<'tcx>, sig: ty::CoroutineClosureSignature<'tcx>, ) -> Ty<'tcx> { - let async_fn_kind_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); - let upvars_projection_def_id = tcx - .associated_items(async_fn_kind_trait_def_id) - .filter_by_name_unhygienic(sym::Upvars) - .next() - .unwrap() - .def_id; + let upvars_projection_def_id = tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None); let tupled_upvars_ty = Ty::new_projection( tcx, upvars_projection_def_id, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c92c8369fede..b6557e6c4eb3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1680,14 +1680,8 @@ fn confirm_closure_candidate<'cx, 'tcx>( args.coroutine_captures_by_ref_ty(), ) } else { - let async_fn_kind_trait_def_id = - tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); - let upvars_projection_def_id = tcx - .associated_items(async_fn_kind_trait_def_id) - .filter_by_name_unhygienic(sym::Upvars) - .next() - .unwrap() - .def_id; + let upvars_projection_def_id = + tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None); let tupled_upvars_ty = Ty::new_projection( tcx, upvars_projection_def_id, @@ -1816,14 +1810,8 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( args.coroutine_captures_by_ref_ty(), ) } else { - let async_fn_kind_trait_def_id = - tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); - let upvars_projection_def_id = tcx - .associated_items(async_fn_kind_trait_def_id) - .filter_by_name_unhygienic(sym::Upvars) - .next() - .unwrap() - .def_id; + let upvars_projection_def_id = + tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None); // When we don't know the closure kind (and therefore also the closure's upvars, // which are computed at the same time), we must delay the computation of the // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs index fc21ffd5246e..f4e9d1a63ac6 100644 --- a/library/core/src/ops/async_function.rs +++ b/library/core/src/ops/async_function.rs @@ -146,6 +146,7 @@ mod internal_implementation_detail { // `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder // of the closure's self-capture, and these upvar types will be instantiated with // the `'closure_env` region provided to the associated type. + #[cfg_attr(not(bootstrap), lang = "async_fn_kind_upvars")] type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>; } } From 6e67eaa311c8e2992ccc64cf6a9e8f311a02a5d4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 29 May 2024 21:30:21 +0300 Subject: [PATCH 101/104] ast: Revert a breaking attribute visiting order change --- compiler/rustc_ast/src/visit.rs | 2 +- .../tests/ui/tabs_in_doc_comments.stderr | 54 +++++++++---------- .../attributes/key-value-expansion-scope.rs | 4 +- .../key-value-expansion-scope.stderr | 18 +------ .../feature-gate-optimize_attribute.stderr | 20 +++---- .../issue-43106-gating-of-stable.stderr | 12 ++--- .../issue-43106-gating-of-unstable.stderr | 12 ++--- 7 files changed, 53 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 182aa6ed085c..6382eb6861c7 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -852,10 +852,10 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>( ctxt: AssocCtxt, ) -> V::Result { let &Item { id: _, span: _, ident, ref vis, ref attrs, ref kind, tokens: _ } = item; - walk_list!(visitor, visit_attribute, attrs); try_visit!(visitor.visit_vis(vis)); try_visit!(visitor.visit_ident(ident)); try_visit!(kind.walk(item, ctxt, visitor)); + walk_list!(visitor, visit_attribute, attrs); V::Result::output() } diff --git a/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr b/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr index aef6c3914526..23d5dcd3a8da 100644 --- a/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr +++ b/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr @@ -1,35 +1,11 @@ -error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:6:5 - | -LL | /// - first one - | ^^^^ help: consider using four spaces per tab - | - = note: `-D clippy::tabs-in-doc-comments` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::tabs_in_doc_comments)]` - -error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:6:13 - | -LL | /// - first one - | ^^^^^^^^ help: consider using four spaces per tab - -error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:7:5 - | -LL | /// - second one - | ^^^^ help: consider using four spaces per tab - -error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:7:14 - | -LL | /// - second one - | ^^^^ help: consider using four spaces per tab - error: using tabs in doc comments is not recommended --> tests/ui/tabs_in_doc_comments.rs:10:9 | LL | /// - First String: | ^^^^ help: consider using four spaces per tab + | + = note: `-D clippy::tabs-in-doc-comments` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::tabs_in_doc_comments)]` error: using tabs in doc comments is not recommended --> tests/ui/tabs_in_doc_comments.rs:11:9 @@ -49,5 +25,29 @@ error: using tabs in doc comments is not recommended LL | /// - needs to be inside here | ^^^^^^^^ help: consider using four spaces per tab +error: using tabs in doc comments is not recommended + --> tests/ui/tabs_in_doc_comments.rs:6:5 + | +LL | /// - first one + | ^^^^ help: consider using four spaces per tab + +error: using tabs in doc comments is not recommended + --> tests/ui/tabs_in_doc_comments.rs:6:13 + | +LL | /// - first one + | ^^^^^^^^ help: consider using four spaces per tab + +error: using tabs in doc comments is not recommended + --> tests/ui/tabs_in_doc_comments.rs:7:5 + | +LL | /// - second one + | ^^^^ help: consider using four spaces per tab + +error: using tabs in doc comments is not recommended + --> tests/ui/tabs_in_doc_comments.rs:7:14 + | +LL | /// - second one + | ^^^^ help: consider using four spaces per tab + error: aborting due to 8 previous errors diff --git a/tests/ui/attributes/key-value-expansion-scope.rs b/tests/ui/attributes/key-value-expansion-scope.rs index f435e36ce638..b84fe4873c37 100644 --- a/tests/ui/attributes/key-value-expansion-scope.rs +++ b/tests/ui/attributes/key-value-expansion-scope.rs @@ -17,7 +17,7 @@ fn before() { macro_rules! in_root { () => { "" } } mod macros_stay { - #![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope + #![doc = in_mod!()] // FIXME, this is a bug macro_rules! in_mod { () => { "" } } @@ -29,7 +29,7 @@ mod macros_stay { #[macro_use] mod macros_escape { - #![doc = in_mod_escape!()] //~ ERROR cannot find macro `in_mod_escape` in this scope + #![doc = in_mod_escape!()] // FIXME, this is a bug macro_rules! in_mod_escape { () => { "" } } diff --git a/tests/ui/attributes/key-value-expansion-scope.stderr b/tests/ui/attributes/key-value-expansion-scope.stderr index 2fa2ed0fa3a4..a66ee9b17fb9 100644 --- a/tests/ui/attributes/key-value-expansion-scope.stderr +++ b/tests/ui/attributes/key-value-expansion-scope.stderr @@ -78,22 +78,6 @@ LL | #![doc = in_block!()] | = help: have you added the `#[macro_use]` on the module/import? -error: cannot find macro `in_mod` in this scope - --> $DIR/key-value-expansion-scope.rs:20:14 - | -LL | #![doc = in_mod!()] - | ^^^^^^ - | - = help: have you added the `#[macro_use]` on the module/import? - -error: cannot find macro `in_mod_escape` in this scope - --> $DIR/key-value-expansion-scope.rs:32:14 - | -LL | #![doc = in_mod_escape!()] - | ^^^^^^^^^^^^^ - | - = help: have you added the `#[macro_use]` on the module/import? - error: cannot find macro `in_block` in this scope --> $DIR/key-value-expansion-scope.rs:43:14 | @@ -134,5 +118,5 @@ LL | #![doc = in_block!()] | = help: have you added the `#[macro_use]` on the module/import? -error: aborting due to 17 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr index 9bab366f7fef..815013733a98 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -1,13 +1,3 @@ -error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:4:1 - | -LL | #[optimize(size)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #54882 for more information - = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:7:1 | @@ -38,6 +28,16 @@ LL | #[optimize(banana)] = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: the `#[optimize]` attribute is an experimental feature + --> $DIR/feature-gate-optimize_attribute.rs:4:1 + | +LL | #[optimize(size)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:2:1 | diff --git a/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr b/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr index e4cc088e2cd3..677fef3a926b 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr @@ -1,9 +1,3 @@ -error[E0734]: stability attributes may not be used outside of the standard library - --> $DIR/issue-43106-gating-of-stable.rs:10:1 - | -LL | #[stable()] - | ^^^^^^^^^^^ - error[E0734]: stability attributes may not be used outside of the standard library --> $DIR/issue-43106-gating-of-stable.rs:14:9 | @@ -34,6 +28,12 @@ error[E0734]: stability attributes may not be used outside of the standard libra LL | #[stable()] | ^^^^^^^^^^^ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:10:1 + | +LL | #[stable()] + | ^^^^^^^^^^^ + error[E0734]: stability attributes may not be used outside of the standard library --> $DIR/issue-43106-gating-of-stable.rs:7:1 | diff --git a/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr b/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr index f7c6e631cd17..a2f361878c6d 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr @@ -1,9 +1,3 @@ -error[E0734]: stability attributes may not be used outside of the standard library - --> $DIR/issue-43106-gating-of-unstable.rs:10:1 - | -LL | #[unstable()] - | ^^^^^^^^^^^^^ - error[E0734]: stability attributes may not be used outside of the standard library --> $DIR/issue-43106-gating-of-unstable.rs:14:9 | @@ -34,6 +28,12 @@ error[E0734]: stability attributes may not be used outside of the standard libra LL | #[unstable()] | ^^^^^^^^^^^^^ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:10:1 + | +LL | #[unstable()] + | ^^^^^^^^^^^^^ + error[E0734]: stability attributes may not be used outside of the standard library --> $DIR/issue-43106-gating-of-unstable.rs:7:1 | From fa563c138433583ebbd64c963666f6c9ddb53739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 26 Apr 2024 13:01:06 +0000 Subject: [PATCH 102/104] coverage: Add CLI support for `-Zcoverage-options=condition` --- compiler/rustc_session/src/config.rs | 18 +++++++++++++++++- compiler/rustc_session/src/options.rs | 3 ++- compiler/rustc_session/src/session.rs | 5 +++++ .../src/compiler-flags/coverage-options.md | 7 +++++-- .../coverage-options.bad.stderr | 2 +- .../ui/instrument-coverage/coverage-options.rs | 5 ++++- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 0287085ad60e..a622f1b577df 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -159,7 +159,23 @@ pub enum CoverageLevel { Block, /// Also instrument branch points (includes block coverage). Branch, - /// Instrument for MC/DC. Mostly a superset of branch coverage, but might + /// Same as branch coverage, but also adds branch instrumentation for + /// certain boolean expressions that are not directly used for branching. + /// + /// For example, in the following code, `b` does not directly participate + /// in a branch, but condition coverage will instrument it as its own + /// artificial branch: + /// ``` + /// # let (a, b) = (false, true); + /// let x = a && b; + /// // ^ last operand + /// ``` + /// + /// This level is mainly intended to be a stepping-stone towards full MC/DC + /// instrumentation, so it might be removed in the future when MC/DC is + /// sufficiently complete, or if it is making MC/DC changes difficult. + Condition, + /// Instrument for MC/DC. Mostly a superset of condition coverage, but might /// differ in some corner cases. Mcdc, } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index cca9f1eb9978..fd4a3a9e6ceb 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -395,7 +395,7 @@ mod desc { pub const parse_optimization_fuel: &str = "crate=integer"; pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; pub const parse_instrument_coverage: &str = parse_bool; - pub const parse_coverage_options: &str = "`block` | `branch` | `mcdc`"; + pub const parse_coverage_options: &str = "`block` | `branch` | `condition` | `mcdc`"; pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; @@ -961,6 +961,7 @@ mod parse { match option { "block" => slot.level = CoverageLevel::Block, "branch" => slot.level = CoverageLevel::Branch, + "condition" => slot.level = CoverageLevel::Condition, "mcdc" => slot.level = CoverageLevel::Mcdc, _ => return false, } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a5cf136db6a6..87bbfcf07c84 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -353,6 +353,11 @@ impl Session { && self.opts.unstable_opts.coverage_options.level >= CoverageLevel::Branch } + pub fn instrument_coverage_condition(&self) -> bool { + self.instrument_coverage() + && self.opts.unstable_opts.coverage_options.level >= CoverageLevel::Condition + } + pub fn instrument_coverage_mcdc(&self) -> bool { self.instrument_coverage() && self.opts.unstable_opts.coverage_options.level >= CoverageLevel::Mcdc diff --git a/src/doc/unstable-book/src/compiler-flags/coverage-options.md b/src/doc/unstable-book/src/compiler-flags/coverage-options.md index 212788335502..87a9a00b3c0f 100644 --- a/src/doc/unstable-book/src/compiler-flags/coverage-options.md +++ b/src/doc/unstable-book/src/compiler-flags/coverage-options.md @@ -5,13 +5,16 @@ This option controls details of the coverage instrumentation performed by Multiple options can be passed, separated by commas. Valid options are: -- `block`, `branch`, `mcdc`: +- `block`, `branch`, `condition`, `mcdc`: Sets the level of coverage instrumentation. Setting the level will override any previously-specified level. - `block` (default): Blocks in the control-flow graph will be instrumented for coverage. - `branch`: In addition to block coverage, also enables branch coverage instrumentation. + - `condition`: + In addition to branch coverage, also instruments some boolean expressions + as branches, even if they are not directly used as branch conditions. - `mcdc`: - In addition to block and branch coverage, also enables MC/DC instrumentation. + In addition to condition coverage, also enables MC/DC instrumentation. (Branch coverage instrumentation may differ in some cases.) diff --git a/tests/ui/instrument-coverage/coverage-options.bad.stderr b/tests/ui/instrument-coverage/coverage-options.bad.stderr index 9e2c19e90d59..4a272cf97fb0 100644 --- a/tests/ui/instrument-coverage/coverage-options.bad.stderr +++ b/tests/ui/instrument-coverage/coverage-options.bad.stderr @@ -1,2 +1,2 @@ -error: incorrect value `bad` for unstable option `coverage-options` - `block` | `branch` | `mcdc` was expected +error: incorrect value `bad` for unstable option `coverage-options` - `block` | `branch` | `condition` | `mcdc` was expected diff --git a/tests/ui/instrument-coverage/coverage-options.rs b/tests/ui/instrument-coverage/coverage-options.rs index 2a80ce4ab2e9..8f523a5fd11a 100644 --- a/tests/ui/instrument-coverage/coverage-options.rs +++ b/tests/ui/instrument-coverage/coverage-options.rs @@ -1,5 +1,5 @@ //@ needs-profiler-support -//@ revisions: block branch mcdc bad +//@ revisions: block branch condition mcdc bad //@ compile-flags -Cinstrument-coverage //@ [block] check-pass @@ -8,6 +8,9 @@ //@ [branch] check-pass //@ [branch] compile-flags: -Zcoverage-options=branch +//@ [condition] check-pass +//@ [condition] compile-flags: -Zcoverage-options=condition + //@ [mcdc] check-pass //@ [mcdc] compile-flags: -Zcoverage-options=mcdc From 20174e6638eb0d5ac0195706ce6cc7185949a407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 29 Apr 2024 15:58:14 +0000 Subject: [PATCH 103/104] coverage: Add a test for `-Zcoverage-options=condition` --- tests/coverage/condition/conditions.cov-map | 117 +++++++++++++++++++ tests/coverage/condition/conditions.coverage | 90 ++++++++++++++ tests/coverage/condition/conditions.rs | 67 +++++++++++ 3 files changed, 274 insertions(+) create mode 100644 tests/coverage/condition/conditions.cov-map create mode 100644 tests/coverage/condition/conditions.coverage create mode 100644 tests/coverage/condition/conditions.rs diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map new file mode 100644 index 000000000000..6c81f7bda985 --- /dev/null +++ b/tests/coverage/condition/conditions.cov-map @@ -0,0 +1,117 @@ +Function name: conditions::assign_3_and_or +Raw bytes (60): 0x[01, 01, 06, 0d, 13, 09, 16, 01, 05, 01, 05, 09, 16, 01, 05, 08, 01, 1c, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 16, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 0d, 09, 00, 12, 00, 13, 13, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 6 +- expression 0 operands: lhs = Counter(3), rhs = Expression(4, Add) +- expression 1 operands: lhs = Counter(2), rhs = Expression(5, Sub) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +- expression 4 operands: lhs = Counter(2), rhs = Expression(5, Sub) +- expression 5 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 47) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = (c3 + (c2 + (c0 - c1))) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(5, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- Branch { true: Counter(3), false: Counter(2) } at (prev + 0, 18) to (start + 0, 19) + true = c3 + false = c2 +- Code(Expression(4, Add)) at (prev + 0, 23) to (start + 0, 24) + = (c2 + (c0 - c1)) +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c3 + (c2 + (c0 - c1))) + +Function name: conditions::assign_3_or_and +Raw bytes (56): 0x[01, 01, 04, 05, 07, 09, 0d, 01, 05, 01, 05, 08, 01, 17, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 09, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 47) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = (c1 + (c2 + c3)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Expression(3, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = c3 +- Code(Counter(2)) at (prev + 0, 23) to (start + 0, 24) +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + (c2 + c3)) + +Function name: conditions::assign_and +Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 0d, 01, 00, 21, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 33) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) + +Function name: conditions::assign_or +Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 12, 01, 00, 20, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 18, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) + +Function name: conditions::foo +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) + +Function name: conditions::func_call +Raw bytes (28): 0x[01, 01, 01, 01, 05, 04, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 10) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) + +Function name: conditions::simple_assign +Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) + diff --git a/tests/coverage/condition/conditions.coverage b/tests/coverage/condition/conditions.coverage new file mode 100644 index 000000000000..a71ab8e5d894 --- /dev/null +++ b/tests/coverage/condition/conditions.coverage @@ -0,0 +1,90 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| |//@ compile-flags: -Zcoverage-options=condition + LL| |//@ llvm-cov-flags: --show-branches=count + LL| | + LL| |use core::hint::black_box; + LL| | + LL| 2|fn simple_assign(a: bool) { + LL| 2| let x = a; + LL| 2| black_box(x); + LL| 2|} + LL| | + LL| 3|fn assign_and(a: bool, b: bool) { + LL| 3| let x = a && b; + ^2 + ------------------ + | Branch (LL:13): [True: 2, False: 1] + ------------------ + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 3|fn assign_or(a: bool, b: bool) { + LL| 3| let x = a || b; + ^1 + ------------------ + | Branch (LL:13): [True: 2, False: 1] + ------------------ + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 4|fn assign_3_or_and(a: bool, b: bool, c: bool) { + LL| 4| let x = a || b && c; + ^2 ^1 + ------------------ + | Branch (LL:13): [True: 2, False: 2] + | Branch (LL:18): [True: 1, False: 1] + ------------------ + LL| 4| black_box(x); + LL| 4|} + LL| | + LL| 4|fn assign_3_and_or(a: bool, b: bool, c: bool) { + LL| 4| let x = a && b || c; + ^2 ^3 + ------------------ + | Branch (LL:13): [True: 2, False: 2] + | Branch (LL:18): [True: 1, False: 1] + ------------------ + LL| 4| black_box(x); + LL| 4|} + LL| | + LL| 3|fn foo(a: bool) -> bool { + LL| 3| black_box(a) + LL| 3|} + LL| | + LL| 3|fn func_call(a: bool, b: bool) { + LL| 3| foo(a && b); + ^2 + ------------------ + | Branch (LL:9): [True: 2, False: 1] + ------------------ + LL| 3|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | simple_assign(true); + LL| | simple_assign(false); + LL| | + LL| | assign_and(true, false); + LL| | assign_and(true, true); + LL| | assign_and(false, false); + LL| | + LL| | assign_or(true, false); + LL| | assign_or(true, true); + LL| | assign_or(false, false); + LL| | + LL| | assign_3_or_and(true, false, false); + LL| | assign_3_or_and(true, true, false); + LL| | assign_3_or_and(false, false, true); + LL| | assign_3_or_and(false, true, true); + LL| | + LL| | assign_3_and_or(true, false, false); + LL| | assign_3_and_or(true, true, false); + LL| | assign_3_and_or(false, false, true); + LL| | assign_3_and_or(false, true, true); + LL| | + LL| | func_call(true, false); + LL| | func_call(true, true); + LL| | func_call(false, false); + LL| |} + diff --git a/tests/coverage/condition/conditions.rs b/tests/coverage/condition/conditions.rs new file mode 100644 index 000000000000..3d658dc93e0c --- /dev/null +++ b/tests/coverage/condition/conditions.rs @@ -0,0 +1,67 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 +//@ compile-flags: -Zcoverage-options=condition +//@ llvm-cov-flags: --show-branches=count + +use core::hint::black_box; + +fn simple_assign(a: bool) { + let x = a; + black_box(x); +} + +fn assign_and(a: bool, b: bool) { + let x = a && b; + black_box(x); +} + +fn assign_or(a: bool, b: bool) { + let x = a || b; + black_box(x); +} + +fn assign_3_or_and(a: bool, b: bool, c: bool) { + let x = a || b && c; + black_box(x); +} + +fn assign_3_and_or(a: bool, b: bool, c: bool) { + let x = a && b || c; + black_box(x); +} + +fn foo(a: bool) -> bool { + black_box(a) +} + +fn func_call(a: bool, b: bool) { + foo(a && b); +} + +#[coverage(off)] +fn main() { + simple_assign(true); + simple_assign(false); + + assign_and(true, false); + assign_and(true, true); + assign_and(false, false); + + assign_or(true, false); + assign_or(true, true); + assign_or(false, false); + + assign_3_or_and(true, false, false); + assign_3_or_and(true, true, false); + assign_3_or_and(false, false, true); + assign_3_or_and(false, true, true); + + assign_3_and_or(true, false, false); + assign_3_and_or(true, true, false); + assign_3_and_or(false, false, true); + assign_3_and_or(false, true, true); + + func_call(true, false); + func_call(true, true); + func_call(false, false); +} From 35a8746832a4d9103f317c5cac56cfa1e0316d8c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 1 May 2024 17:33:33 +1000 Subject: [PATCH 104/104] coverage: Instrument the RHS value of lazy logical operators When a lazy logical operator (`&&` or `||`) occurs outside of an `if` condition, it normally doesn't have any associated control-flow branch, so we don't have an existing way to track whether it was true or false. This patch adds special code to handle this case, by inserting extra MIR blocks in a diamond shape after evaluating the RHS. This gives us a place to insert the appropriate marker statements, which can then be given their own counters. --- .../rustc_mir_build/src/build/coverageinfo.rs | 57 +++++++ .../rustc_mir_build/src/build/expr/into.rs | 8 +- tests/coverage/condition/conditions.cov-map | 153 +++++++++++------- tests/coverage/condition/conditions.coverage | 5 + 4 files changed, 162 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index ee9eeb62990d..855dcbbcb346 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -157,6 +157,63 @@ impl BranchInfoBuilder { } impl<'tcx> Builder<'_, 'tcx> { + /// If condition coverage is enabled, inject extra blocks and marker statements + /// that will let us track the value of the condition in `place`. + pub(crate) fn visit_coverage_standalone_condition( + &mut self, + mut expr_id: ExprId, // Expression giving the span of the condition + place: mir::Place<'tcx>, // Already holds the boolean condition value + block: &mut BasicBlock, + ) { + // Bail out if condition coverage is not enabled for this function. + let Some(branch_info) = self.coverage_branch_info.as_mut() else { return }; + if !self.tcx.sess.instrument_coverage_condition() { + return; + }; + + // Remove any wrappers, so that we can inspect the real underlying expression. + while let ExprKind::Use { source: inner } | ExprKind::Scope { value: inner, .. } = + self.thir[expr_id].kind + { + expr_id = inner; + } + // If the expression is a lazy logical op, it will naturally get branch + // coverage as part of its normal lowering, so we can disregard it here. + if let ExprKind::LogicalOp { .. } = self.thir[expr_id].kind { + return; + } + + let source_info = SourceInfo { span: self.thir[expr_id].span, scope: self.source_scope }; + + // Using the boolean value that has already been stored in `place`, set up + // control flow in the shape of a diamond, so that we can place separate + // marker statements in the true and false blocks. The coverage MIR pass + // will use those markers to inject coverage counters as appropriate. + // + // block + // / \ + // true_block false_block + // (marker) (marker) + // \ / + // join_block + + let true_block = self.cfg.start_new_block(); + let false_block = self.cfg.start_new_block(); + self.cfg.terminate( + *block, + source_info, + mir::TerminatorKind::if_(mir::Operand::Copy(place), true_block, false_block), + ); + + branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block); + + let join_block = self.cfg.start_new_block(); + self.cfg.goto(true_block, source_info, join_block); + self.cfg.goto(false_block, source_info, join_block); + // Any subsequent codegen in the caller should use the new join block. + *block = join_block; + } + /// If branch coverage is enabled, inject marker statements into `then_block` /// and `else_block`, and record their IDs in the table of branch spans. pub(crate) fn visit_coverage_branch_condition( diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 9349133d2dbc..c08a3b6691af 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -183,9 +183,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { const_: Const::from_bool(this.tcx, constant), }, ); - let rhs = unpack!(this.expr_into_dest(destination, continuation, rhs)); + let mut rhs_block = unpack!(this.expr_into_dest(destination, continuation, rhs)); + // Instrument the lowered RHS's value for condition coverage. + // (Does nothing if condition coverage is not enabled.) + this.visit_coverage_standalone_condition(rhs, destination, &mut rhs_block); + let target = this.cfg.start_new_block(); - this.cfg.goto(rhs, source_info, target); + this.cfg.goto(rhs_block, source_info, target); this.cfg.goto(short_circuit, source_info, target); target.unit() } diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map index 6c81f7bda985..74726e269fc6 100644 --- a/tests/coverage/condition/conditions.cov-map +++ b/tests/coverage/condition/conditions.cov-map @@ -1,44 +1,107 @@ Function name: conditions::assign_3_and_or -Raw bytes (60): 0x[01, 01, 06, 0d, 13, 09, 16, 01, 05, 01, 05, 09, 16, 01, 05, 08, 01, 1c, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 16, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 0d, 09, 00, 12, 00, 13, 13, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (69): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 09, 01, 1c, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 1a, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 16, 00, 12, 00, 13, 13, 00, 17, 00, 18, 20, 0d, 11, 00, 17, 00, 18, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 6 -- expression 0 operands: lhs = Counter(3), rhs = Expression(4, Add) -- expression 1 operands: lhs = Counter(2), rhs = Expression(5, Sub) +Number of expressions: 7 +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(4) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) -- expression 3 operands: lhs = Counter(0), rhs = Counter(1) -- expression 4 operands: lhs = Counter(2), rhs = Expression(5, Sub) -- expression 5 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 8 +- expression 3 operands: lhs = Counter(1), rhs = Counter(2) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Expression(6, Sub) +- expression 5 operands: lhs = Counter(1), rhs = Counter(2) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 28, 1) to (start + 0, 47) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) - = (c3 + (c2 + (c0 - c1))) + = ((c2 + c3) + c4) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(5, Sub) } at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(6, Sub) } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) -- Branch { true: Counter(3), false: Counter(2) } at (prev + 0, 18) to (start + 0, 19) - true = c3 - false = c2 +- Branch { true: Counter(2), false: Expression(5, Sub) } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = (c1 - c2) - Code(Expression(4, Add)) at (prev + 0, 23) to (start + 0, 24) - = (c2 + (c0 - c1)) + = ((c1 - c2) + (c0 - c1)) +- Branch { true: Counter(3), false: Counter(4) } at (prev + 0, 23) to (start + 0, 24) + true = c3 + false = c4 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) - = (c3 + (c2 + (c0 - c1))) + = ((c2 + c3) + c4) Function name: conditions::assign_3_or_and -Raw bytes (56): 0x[01, 01, 04, 05, 07, 09, 0d, 01, 05, 01, 05, 08, 01, 17, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 09, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (73): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 09, 01, 17, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 22, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 20, 1e, 11, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 20, 09, 0d, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 9 +- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add) +- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +- expression 4 operands: lhs = Counter(0), rhs = Counter(1) +- expression 5 operands: lhs = Expression(8, Sub), rhs = Counter(4) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4) +- expression 8 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 47) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = (c1 + ((c2 + c3) + c4)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(8, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Expression(8, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- Branch { true: Expression(7, Sub), false: Counter(4) } at (prev + 0, 18) to (start + 0, 19) + true = ((c0 - c1) - c4) + false = c4 +- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 24) + = ((c0 - c1) - c4) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 23) to (start + 0, 24) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + ((c2 + c3) + c4)) + +Function name: conditions::assign_and +Raw bytes (51): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 07, 01, 0d, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 -- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add) +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(3, Sub) - expression 1 operands: lhs = Counter(2), rhs = Counter(3) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) - expression 3 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 47) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 33) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) - = (c1 + (c2 + c3)) + = ((c2 + c3) + (c0 - c1)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c2 + c3) + (c0 - c1)) + +Function name: conditions::assign_or +Raw bytes (51): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 07, 01, 12, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 18, 1) to (start + 0, 32) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c1 + c2) + c3) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) true = c1 @@ -48,42 +111,8 @@ Number of file 0 mappings: 8 - Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) true = c2 false = c3 -- Code(Counter(2)) at (prev + 0, 23) to (start + 0, 24) - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) - = (c1 + (c2 + c3)) - -Function name: conditions::assign_and -Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 0d, 01, 00, 21, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 33) -- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) -- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) - true = c1 - false = (c0 - c1) -- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) - -Function name: conditions::assign_or -Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 12, 01, 00, 20, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 18, 1) to (start + 0, 32) -- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) -- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) - true = c1 - false = (c0 - c1) -- Code(Expression(0, Sub)) at (prev + 0, 18) to (start + 0, 19) - = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) + = ((c1 + c2) + c3) Function name: conditions::foo Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] @@ -94,18 +123,24 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) Function name: conditions::func_call -Raw bytes (28): 0x[01, 01, 01, 01, 05, 04, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] +Raw bytes (39): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 05, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 0d, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 +Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 +- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 37, 1) to (start + 1, 10) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15) -- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 14) to (start + 0, 15) + true = c2 + false = c3 +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = ((c2 + c3) + (c0 - c1)) Function name: conditions::simple_assign Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02] diff --git a/tests/coverage/condition/conditions.coverage b/tests/coverage/condition/conditions.coverage index a71ab8e5d894..3215b391d622 100644 --- a/tests/coverage/condition/conditions.coverage +++ b/tests/coverage/condition/conditions.coverage @@ -15,6 +15,7 @@ ^2 ------------------ | Branch (LL:13): [True: 2, False: 1] + | Branch (LL:18): [True: 1, False: 1] ------------------ LL| 3| black_box(x); LL| 3|} @@ -24,6 +25,7 @@ ^1 ------------------ | Branch (LL:13): [True: 2, False: 1] + | Branch (LL:18): [True: 0, False: 1] ------------------ LL| 3| black_box(x); LL| 3|} @@ -34,6 +36,7 @@ ------------------ | Branch (LL:13): [True: 2, False: 2] | Branch (LL:18): [True: 1, False: 1] + | Branch (LL:23): [True: 1, False: 0] ------------------ LL| 4| black_box(x); LL| 4|} @@ -44,6 +47,7 @@ ------------------ | Branch (LL:13): [True: 2, False: 2] | Branch (LL:18): [True: 1, False: 1] + | Branch (LL:23): [True: 2, False: 1] ------------------ LL| 4| black_box(x); LL| 4|} @@ -57,6 +61,7 @@ ^2 ------------------ | Branch (LL:9): [True: 2, False: 1] + | Branch (LL:14): [True: 1, False: 1] ------------------ LL| 3|} LL| |