From 4dabbcb23b0dc605cdb4aa6f3499d0f053f7b600 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Tue, 27 Feb 2024 00:09:12 -0500 Subject: [PATCH 01/99] allow using scalarpair with a common prim of ptr/ptr-sized-int --- compiler/rustc_abi/src/layout.rs | 41 ++++++- tests/codegen/common_prim_int_ptr.rs | 43 ++++++++ tests/codegen/try_question_mark_nop.rs | 104 ++++++++++++++++-- tests/ui/layout/enum-scalar-pair-int-ptr.rs | 24 ++++ .../ui/layout/enum-scalar-pair-int-ptr.stderr | 14 +++ tests/ui/layout/enum.rs | 6 + tests/ui/layout/enum.stderr | 8 +- 7 files changed, 221 insertions(+), 19 deletions(-) create mode 100644 tests/codegen/common_prim_int_ptr.rs create mode 100644 tests/ui/layout/enum-scalar-pair-int-ptr.rs create mode 100644 tests/ui/layout/enum-scalar-pair-int-ptr.stderr diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 28e148bddb22..d023c869e8b6 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -813,15 +813,44 @@ where break; } }; - if let Some(pair) = common_prim { - // This is pretty conservative. We could go fancier - // by conflating things like i32 and u32, or even - // realising that (u8, u8) could just cohabit with - // u16 or even u32. - if pair != (prim, offset) { + if let Some((old_common_prim, common_offset)) = common_prim { + // All variants must be at the same offset + if offset != common_offset { common_prim = None; break; } + // This is pretty conservative. We could go fancier + // by realising that (u8, u8) could just cohabit with + // u16 or even u32. + let new_common_prim = match (old_common_prim, prim) { + // Allow all identical primitives. + (x, y) if x == y => Some(x), + // Allow integers of the same size with differing signedness. + // We arbitrarily choose the signedness of the first variant. + (p @ Primitive::Int(x, _), Primitive::Int(y, _)) if x == y => Some(p), + // Allow integers mixed with pointers of the same layout. + // We must represent this using a pointer, to avoid + // roundtripping pointers through ptrtoint/inttoptr. + (p @ Primitive::Pointer(_), i @ Primitive::Int(..)) + | (i @ Primitive::Int(..), p @ Primitive::Pointer(_)) + if p.size(dl) == i.size(dl) && p.align(dl) == i.align(dl) => + { + Some(p) + } + _ => None, + }; + match new_common_prim { + Some(new_prim) => { + // Primitives are compatible. + // We may be updating the primitive here, for example from int->ptr. + common_prim = Some((new_prim, common_offset)); + } + None => { + // Primitives are incompatible. + common_prim = None; + break; + } + } } else { common_prim = Some((prim, offset)); } diff --git a/tests/codegen/common_prim_int_ptr.rs b/tests/codegen/common_prim_int_ptr.rs new file mode 100644 index 000000000000..9b798d495d4f --- /dev/null +++ b/tests/codegen/common_prim_int_ptr.rs @@ -0,0 +1,43 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] + +// Tests that codegen works properly when enums like `Result>` +// are represented as `{ u64, ptr }`, i.e., for `Ok(123)`, `123` is stored +// as a pointer. + +// CHECK-LABEL: @insert_int +#[no_mangle] +pub fn insert_int(x: usize) -> Result> { + // CHECK: start: + // CHECK-NEXT: inttoptr i{{[0-9]+}} %x to ptr + // CHECK-NEXT: insertvalue + // CHECK-NEXT: ret { i{{[0-9]+}}, ptr } + Ok(x) +} + +// CHECK-LABEL: @insert_box +#[no_mangle] +pub fn insert_box(x: Box<()>) -> Result> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: ret + Err(x) +} + +// CHECK-LABEL: @extract_int +#[no_mangle] +pub unsafe fn extract_int(x: Result>) -> usize { + // CHECK: start: + // CHECK-NEXT: ptrtoint + // CHECK-NEXT: ret + x.unwrap_unchecked() +} + +// CHECK-LABEL: @extract_box +#[no_mangle] +pub unsafe fn extract_box(x: Result>) -> Box<()> { + // CHECK: start: + // CHECK-NEXT: ret ptr + x.unwrap_err_unchecked() +} diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 58cd6ff233a1..f6cdf9552097 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -4,17 +4,41 @@ #![crate_type = "lib"] #![feature(try_blocks)] -// These are now NOPs in LLVM 15, presumably thanks to nikic's change mentioned in -// . -// Unfortunately, as of 2022-08-17 they're not yet nops for `u64`s nor `Option`. - use std::ops::ControlFlow::{self, Continue, Break}; +use std::ptr::NonNull; + +// CHECK-LABEL: @option_nop_match_32 +#[no_mangle] +pub fn option_nop_match_32(x: Option) -> Option { + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } + match x { + Some(x) => Some(x), + None => None, + } +} + +// CHECK-LABEL: @option_nop_traits_32 +#[no_mangle] +pub fn option_nop_traits_32(x: Option) -> Option { + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } + try { + x? + } +} // CHECK-LABEL: @result_nop_match_32 #[no_mangle] pub fn result_nop_match_32(x: Result) -> Result { - // CHECK: start - // CHECK-NEXT: ret i64 %0 + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } match x { Ok(x) => Ok(x), Err(x) => Err(x), @@ -24,8 +48,60 @@ pub fn result_nop_match_32(x: Result) -> Result { // CHECK-LABEL: @result_nop_traits_32 #[no_mangle] pub fn result_nop_traits_32(x: Result) -> Result { - // CHECK: start - // CHECK-NEXT: ret i64 %0 + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } + try { + x? + } +} + +// CHECK-LABEL: @result_nop_match_64 +#[no_mangle] +pub fn result_nop_match_64(x: Result) -> Result { + // CHECK: start: + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: ret { i64, i64 } + match x { + Ok(x) => Ok(x), + Err(x) => Err(x), + } +} + +// CHECK-LABEL: @result_nop_traits_64 +#[no_mangle] +pub fn result_nop_traits_64(x: Result) -> Result { + // CHECK: start: + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: ret { i64, i64 } + try { + x? + } +} + +// CHECK-LABEL: @result_nop_match_ptr +#[no_mangle] +pub fn result_nop_match_ptr(x: Result>) -> Result> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: ret + match x { + Ok(x) => Ok(x), + Err(x) => Err(x), + } +} + +// CHECK-LABEL: @result_nop_traits_ptr +#[no_mangle] +pub fn result_nop_traits_ptr(x: Result>) -> Result> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: ret try { x? } @@ -34,8 +110,10 @@ pub fn result_nop_traits_32(x: Result) -> Result { // CHECK-LABEL: @control_flow_nop_match_32 #[no_mangle] pub fn control_flow_nop_match_32(x: ControlFlow) -> ControlFlow { - // CHECK: start - // CHECK-NEXT: ret i64 %0 + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } match x { Continue(x) => Continue(x), Break(x) => Break(x), @@ -45,8 +123,10 @@ pub fn control_flow_nop_match_32(x: ControlFlow) -> ControlFlow) -> ControlFlow { - // CHECK: start - // CHECK-NEXT: ret i64 %0 + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } try { x? } diff --git a/tests/ui/layout/enum-scalar-pair-int-ptr.rs b/tests/ui/layout/enum-scalar-pair-int-ptr.rs new file mode 100644 index 000000000000..a1aec094d802 --- /dev/null +++ b/tests/ui/layout/enum-scalar-pair-int-ptr.rs @@ -0,0 +1,24 @@ +//@ normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" +//@ normalize-stderr-test "Int\(I[0-9]+," -> "Int(I?," +//@ normalize-stderr-test "valid_range: 0..=[0-9]+" -> "valid_range: $$VALID_RANGE" + +//! Enum layout tests related to scalar pairs with an int/ptr common primitive. + +#![feature(rustc_attrs)] +#![feature(never_type)] +#![crate_type = "lib"] + +#[rustc_layout(abi)] +enum ScalarPairPointerWithInt { //~ERROR: abi: ScalarPair + A(usize), + B(Box<()>), +} + +// Negative test--ensure that pointers are not commoned with integers +// of a different size. (Assumes that no target has 8 bit pointers, which +// feels pretty safe.) +#[rustc_layout(abi)] +enum NotScalarPairPointerWithSmallerInt { //~ERROR: abi: Aggregate + A(u8), + B(Box<()>), +} diff --git a/tests/ui/layout/enum-scalar-pair-int-ptr.stderr b/tests/ui/layout/enum-scalar-pair-int-ptr.stderr new file mode 100644 index 000000000000..b25eda628cd6 --- /dev/null +++ b/tests/ui/layout/enum-scalar-pair-int-ptr.stderr @@ -0,0 +1,14 @@ +error: abi: ScalarPair(Initialized { value: Int(I?, false), valid_range: $VALID_RANGE }, Initialized { value: Pointer(AddressSpace(0)), valid_range: $VALID_RANGE }) + --> $DIR/enum-scalar-pair-int-ptr.rs:12:1 + | +LL | enum ScalarPairPointerWithInt { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: abi: Aggregate { sized: true } + --> $DIR/enum-scalar-pair-int-ptr.rs:21:1 + | +LL | enum NotScalarPairPointerWithSmallerInt { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/layout/enum.rs b/tests/ui/layout/enum.rs index bde8450b9d56..5710634cf6b1 100644 --- a/tests/ui/layout/enum.rs +++ b/tests/ui/layout/enum.rs @@ -16,3 +16,9 @@ enum UninhabitedVariantSpace { //~ERROR: size: Size(16 bytes) A, B([u8; 15], !), // make sure there is space being reserved for this field. } + +#[rustc_layout(abi)] +enum ScalarPairDifferingSign { //~ERROR: abi: ScalarPair + A(u64), + B(i64), +} diff --git a/tests/ui/layout/enum.stderr b/tests/ui/layout/enum.stderr index d6bc7780ce20..189c4225ec54 100644 --- a/tests/ui/layout/enum.stderr +++ b/tests/ui/layout/enum.stderr @@ -10,5 +10,11 @@ error: size: Size(16 bytes) LL | enum UninhabitedVariantSpace { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: abi: ScalarPair(Initialized { value: Int(I64, false), valid_range: 0..=1 }, Initialized { value: Int(I64, false), valid_range: 0..=18446744073709551615 }) + --> $DIR/enum.rs:21:1 + | +LL | enum ScalarPairDifferingSign { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors From f574c651476a43dd7ca92ef859fb501d18a8c3ff Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Wed, 28 Feb 2024 17:55:04 -0500 Subject: [PATCH 02/99] simplify common prim computation --- compiler/rustc_abi/src/layout.rs | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index d023c869e8b6..a476d83d4c7f 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -813,7 +813,7 @@ where break; } }; - if let Some((old_common_prim, common_offset)) = common_prim { + if let Some((old_prim, common_offset)) = common_prim { // All variants must be at the same offset if offset != common_offset { common_prim = None; @@ -822,12 +822,12 @@ where // This is pretty conservative. We could go fancier // by realising that (u8, u8) could just cohabit with // u16 or even u32. - let new_common_prim = match (old_common_prim, prim) { + let new_prim = match (old_prim, prim) { // Allow all identical primitives. - (x, y) if x == y => Some(x), + (x, y) if x == y => x, // Allow integers of the same size with differing signedness. // We arbitrarily choose the signedness of the first variant. - (p @ Primitive::Int(x, _), Primitive::Int(y, _)) if x == y => Some(p), + (p @ Primitive::Int(x, _), Primitive::Int(y, _)) if x == y => p, // Allow integers mixed with pointers of the same layout. // We must represent this using a pointer, to avoid // roundtripping pointers through ptrtoint/inttoptr. @@ -835,22 +835,15 @@ where | (i @ Primitive::Int(..), p @ Primitive::Pointer(_)) if p.size(dl) == i.size(dl) && p.align(dl) == i.align(dl) => { - Some(p) + p } - _ => None, - }; - match new_common_prim { - Some(new_prim) => { - // Primitives are compatible. - // We may be updating the primitive here, for example from int->ptr. - common_prim = Some((new_prim, common_offset)); - } - None => { - // Primitives are incompatible. + _ => { common_prim = None; break; } - } + }; + // We may be updating the primitive here, for example from int->ptr. + common_prim = Some((new_prim, common_offset)); } else { common_prim = Some((prim, offset)); } From 8e40b17b6bc57e9a905b263b79e254895252ea49 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Wed, 28 Feb 2024 18:48:14 -0500 Subject: [PATCH 03/99] fix test failure due to differing u64 alignment on different targets --- tests/ui/layout/enum.rs | 4 ++-- tests/ui/layout/enum.stderr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/layout/enum.rs b/tests/ui/layout/enum.rs index 5710634cf6b1..e0a7fc328df3 100644 --- a/tests/ui/layout/enum.rs +++ b/tests/ui/layout/enum.rs @@ -19,6 +19,6 @@ enum UninhabitedVariantSpace { //~ERROR: size: Size(16 bytes) #[rustc_layout(abi)] enum ScalarPairDifferingSign { //~ERROR: abi: ScalarPair - A(u64), - B(i64), + A(u8), + B(i8), } diff --git a/tests/ui/layout/enum.stderr b/tests/ui/layout/enum.stderr index 189c4225ec54..7f0b38d0a07c 100644 --- a/tests/ui/layout/enum.stderr +++ b/tests/ui/layout/enum.stderr @@ -10,7 +10,7 @@ error: size: Size(16 bytes) LL | enum UninhabitedVariantSpace { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: abi: ScalarPair(Initialized { value: Int(I64, false), valid_range: 0..=1 }, Initialized { value: Int(I64, false), valid_range: 0..=18446744073709551615 }) +error: abi: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=1 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }) --> $DIR/enum.rs:21:1 | LL | enum ScalarPairDifferingSign { From 3ab693689ae878aca6c0c6f188370de973d246e1 Mon Sep 17 00:00:00 2001 From: kirandevraj Date: Fri, 1 Mar 2024 23:33:24 +0530 Subject: [PATCH 04/99] mir-opt unnamed-fields filecheck annotations --- tests/mir-opt/unnamed-fields/field_access.rs | 21 +++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/unnamed-fields/field_access.rs b/tests/mir-opt/unnamed-fields/field_access.rs index 3d33ca26875b..8024fd5015d4 100644 --- a/tests/mir-opt/unnamed-fields/field_access.rs +++ b/tests/mir-opt/unnamed-fields/field_access.rs @@ -1,4 +1,5 @@ -// skip-filecheck +//@ unit-test: UnnamedFields + // EMIT_MIR field_access.foo.SimplifyCfg-initial.after.mir // EMIT_MIR field_access.bar.SimplifyCfg-initial.after.mir @@ -36,18 +37,36 @@ union Bar { fn access(_: T) {} +// CHECK-LABEL: fn foo( fn foo(foo: Foo) { + // CHECK _3 = (_1.0: u8); + // CHECK _2 = access::(move _3) -> [return: bb1, unwind: bb5]; access(foo.a); + // CHECK _5 = ((_1.1: Foo::{anon_adt#0}).0: i8); + // CHECK _4 = access::(move _5) -> [return: bb2, unwind: bb5]; access(foo.b); + // CHECK _7 = ((_1.1: Foo::{anon_adt#0}).1: bool); + // CHECK _6 = access::(move _7) -> [return: bb3, unwind: bb5]; access(foo.c); + // CHECK _9 = (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); + // CHECK _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; access(foo.d); } +// CHECK-LABEL: fn bar( fn bar(bar: Bar) { unsafe { + // CHECK _3 = (_1.0: u8); + // CHECK _2 = access::(move _3) -> [return: bb1, unwind: bb5]; access(bar.a); + // CHECK _5 = ((_1.1: Bar::{anon_adt#0}).0: i8); + // CHECK _4 = access::(move _5) -> [return: bb2, unwind: bb5]; access(bar.b); + // CHECK _7 = ((_1.1: Bar::{anon_adt#0}).1: bool); + // CHECK _6 = access::(move _7) -> [return: bb3, unwind: bb5]; access(bar.c); + // CHECK _9 = (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); + // CHECK _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; access(bar.d); } } From 832b23ffcfae702c333915bf2c25493f9f62ebb5 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 1 Mar 2024 19:07:08 +0100 Subject: [PATCH 05/99] Tiny missed simplification --- compiler/rustc_mir_build/src/build/matches/test.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 8ce7461747b4..d811141f50ff 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -603,17 +603,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) } - (&TestKind::If, TestCase::Constant { value }) => { + (TestKind::If, TestCase::Constant { value }) => { fully_matched = true; let value = value.try_eval_bool(self.tcx, self.param_env).unwrap_or_else(|| { span_bug!(test.span, "expected boolean value but got {value:?}") }); Some(value as usize) } - (&TestKind::If, _) => { - fully_matched = false; - None - } ( &TestKind::Len { len: test_len, op: BinOp::Eq }, @@ -714,6 +710,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ( TestKind::Switch { .. } | TestKind::SwitchInt { .. } + | TestKind::If | TestKind::Len { .. } | TestKind::Range { .. } | TestKind::Eq { .. }, From 3d3b321c60f6ce1ac59edf0706c083aa7fbd1e83 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 29 Feb 2024 00:52:03 +0100 Subject: [PATCH 06/99] Use an enum instead of manually tracking indices for `target_blocks` --- .../rustc_mir_build/src/build/matches/mod.rs | 34 +++-- .../rustc_mir_build/src/build/matches/test.rs | 117 ++++++++++-------- .../building/issue_49232.main.built.after.mir | 8 +- ...fg-initial.after-ElaborateDrops.after.diff | 15 +-- ...fg-initial.after-ElaborateDrops.after.diff | 15 +-- 5 files changed, 112 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index daa0349789ed..aea52fc497f0 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1160,6 +1160,19 @@ pub(crate) struct Test<'tcx> { kind: TestKind<'tcx>, } +/// The branch to be taken after a test. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum TestBranch<'tcx> { + /// Success branch, used for tests with two possible outcomes. + Success, + /// Branch corresponding to this constant. + Constant(Const<'tcx>, u128), + /// Branch corresponding to this variant. + Variant(VariantIdx), + /// Failure branch for tests with two possible outcomes, and "otherwise" branch for other tests. + Failure, +} + /// `ArmHasGuard` is a wrapper around a boolean flag. It indicates whether /// a match arm has a guard expression attached to it. #[derive(Copy, Clone, Debug)] @@ -1636,11 +1649,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_place: &PlaceBuilder<'tcx>, test: &Test<'tcx>, mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], - ) -> (&'b mut [&'c mut Candidate<'pat, 'tcx>], Vec>>) { + ) -> ( + &'b mut [&'c mut Candidate<'pat, 'tcx>], + FxIndexMap, Vec<&'b mut Candidate<'pat, 'tcx>>>, + ) { // For each of the N possible outcomes, create a (initially empty) vector of candidates. // Those are the candidates that apply if the test has that particular outcome. - let mut target_candidates: Vec>> = vec![]; - target_candidates.resize_with(test.targets(), Default::default); + let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'pat, 'tcx>>> = + test.targets().into_iter().map(|branch| (branch, Vec::new())).collect(); let total_candidate_count = candidates.len(); @@ -1648,11 +1664,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // point we may encounter a candidate where the test is not relevant; at that point, we stop // sorting. while let Some(candidate) = candidates.first_mut() { - let Some(idx) = self.sort_candidate(&match_place, &test, candidate) else { + let Some(branch) = self.sort_candidate(&match_place, &test, candidate) else { break; }; let (candidate, rest) = candidates.split_first_mut().unwrap(); - target_candidates[idx].push(candidate); + target_candidates[&branch].push(candidate); candidates = rest; } @@ -1797,9 +1813,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // apply. Collect a list of blocks where control flow will // branch if one of the `target_candidate` sets is not // exhaustive. - let target_blocks: Vec<_> = target_candidates + let target_blocks: FxIndexMap<_, _> = target_candidates .into_iter() - .map(|mut candidates| { + .map(|(branch, mut candidates)| { if !candidates.is_empty() { let candidate_start = self.cfg.start_new_block(); self.match_candidates( @@ -1809,9 +1825,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { remainder_start, &mut *candidates, ); - candidate_start + (branch, candidate_start) } else { - remainder_start + (branch, remainder_start) } }) .collect(); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index d811141f50ff..d003ae8d803c 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -6,7 +6,7 @@ // the candidates based on the result. use crate::build::expr::as_place::PlaceBuilder; -use crate::build::matches::{Candidate, MatchPair, Test, TestCase, TestKind}; +use crate::build::matches::{Candidate, MatchPair, Test, TestBranch, TestCase, TestKind}; use crate::build::Builder; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::{LangItem, RangeEnd}; @@ -129,11 +129,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block: BasicBlock, place_builder: &PlaceBuilder<'tcx>, test: &Test<'tcx>, - target_blocks: Vec, + target_blocks: FxIndexMap, BasicBlock>, ) { let place = place_builder.to_place(self); let place_ty = place.ty(&self.local_decls, self.tcx); - debug!(?place, ?place_ty,); + debug!(?place, ?place_ty); + let target_block = |branch| target_blocks[&branch]; let source_info = self.source_info(test.span); match test.kind { @@ -141,20 +142,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Variants is a BitVec of indexes into adt_def.variants. let num_enum_variants = adt_def.variants().len(); debug_assert_eq!(target_blocks.len(), num_enum_variants + 1); - let otherwise_block = *target_blocks.last().unwrap(); + let otherwise_block = target_block(TestBranch::Failure); let tcx = self.tcx; let switch_targets = SwitchTargets::new( adt_def.discriminants(tcx).filter_map(|(idx, discr)| { if variants.contains(idx) { debug_assert_ne!( - target_blocks[idx.index()], + target_block(TestBranch::Variant(idx)), otherwise_block, "no candidates for tested discriminant: {discr:?}", ); - Some((discr.val, target_blocks[idx.index()])) + Some((discr.val, target_block(TestBranch::Variant(idx)))) } else { debug_assert_eq!( - target_blocks[idx.index()], + target_block(TestBranch::Variant(idx)), otherwise_block, "found candidates for untested discriminant: {discr:?}", ); @@ -185,9 +186,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TestKind::SwitchInt { ref options } => { // The switch may be inexhaustive so we have a catch-all block debug_assert_eq!(options.len() + 1, target_blocks.len()); - let otherwise_block = *target_blocks.last().unwrap(); + let otherwise_block = target_block(TestBranch::Failure); let switch_targets = SwitchTargets::new( - options.values().copied().zip(target_blocks), + options + .iter() + .map(|(&val, &bits)| (bits, target_block(TestBranch::Constant(val, bits)))), otherwise_block, ); let terminator = TerminatorKind::SwitchInt { @@ -198,18 +201,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } TestKind::If => { - let [false_bb, true_bb] = *target_blocks else { - bug!("`TestKind::If` should have two targets") - }; - let terminator = TerminatorKind::if_(Operand::Copy(place), true_bb, false_bb); + debug_assert_eq!(target_blocks.len(), 2); + let success_block = target_block(TestBranch::Success); + let fail_block = target_block(TestBranch::Failure); + let terminator = + TerminatorKind::if_(Operand::Copy(place), success_block, fail_block); self.cfg.terminate(block, self.source_info(match_start_span), terminator); } TestKind::Eq { value, ty } => { let tcx = self.tcx; - let [success_block, fail_block] = *target_blocks else { - bug!("`TestKind::Eq` should have two target blocks") - }; + debug_assert_eq!(target_blocks.len(), 2); + let success_block = target_block(TestBranch::Success); + let fail_block = target_block(TestBranch::Failure); if let ty::Adt(def, _) = ty.kind() && Some(def.did()) == tcx.lang_items().string() { @@ -286,9 +290,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } TestKind::Range(ref range) => { - let [success, fail] = *target_blocks else { - bug!("`TestKind::Range` should have two target blocks"); - }; + debug_assert_eq!(target_blocks.len(), 2); + let success = target_block(TestBranch::Success); + let fail = target_block(TestBranch::Failure); // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. let val = Operand::Copy(place); @@ -333,15 +337,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // expected = let expected = self.push_usize(block, source_info, len); - let [true_bb, false_bb] = *target_blocks else { - bug!("`TestKind::Len` should have two target blocks"); - }; + debug_assert_eq!(target_blocks.len(), 2); + let success_block = target_block(TestBranch::Success); + let fail_block = target_block(TestBranch::Failure); // result = actual == expected OR result = actual < expected // branch based on result self.compare( block, - true_bb, - false_bb, + success_block, + fail_block, source_info, op, Operand::Move(actual), @@ -526,10 +530,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Given that we are performing `test` against `test_place`, this job /// sorts out what the status of `candidate` will be after the test. See - /// `test_candidates` for the usage of this function. The returned index is - /// the index that this candidate should be placed in the - /// `target_candidates` vec. The candidate may be modified to update its - /// `match_pairs`. + /// `test_candidates` for the usage of this function. The candidate may + /// be modified to update its `match_pairs`. /// /// So, for example, if this candidate is `x @ Some(P0)` and the `Test` is /// a variant test, then we would modify the candidate to be `(x as @@ -556,7 +558,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { test_place: &PlaceBuilder<'tcx>, test: &Test<'tcx>, candidate: &mut Candidate<'pat, 'tcx>, - ) -> Option { + ) -> Option> { // Find the match_pair for this place (if any). At present, // afaik, there can be at most one. (In the future, if we // adopted a more general `@` operator, there might be more @@ -576,7 +578,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) => { assert_eq!(adt_def, tested_adt_def); fully_matched = true; - Some(variant_index.as_usize()) + Some(TestBranch::Variant(variant_index)) } // If we are performing a switch over integers, then this informs integer @@ -584,12 +586,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // // FIXME(#29623) we could use PatKind::Range to rule // things out here, in some cases. - (TestKind::SwitchInt { options }, TestCase::Constant { value }) + (TestKind::SwitchInt { options }, &TestCase::Constant { value }) if is_switch_ty(match_pair.pattern.ty) => { fully_matched = true; - let index = options.get_index_of(value).unwrap(); - Some(index) + let bits = options.get(&value).unwrap(); + Some(TestBranch::Constant(value, *bits)) } (TestKind::SwitchInt { options }, TestCase::Range(range)) => { fully_matched = false; @@ -599,7 +601,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { not_contained.then(|| { // No switch values are contained in the pattern range, // so the pattern can be matched only if this test fails. - options.len() + TestBranch::Failure }) } @@ -608,7 +610,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let value = value.try_eval_bool(self.tcx, self.param_env).unwrap_or_else(|| { span_bug!(test.span, "expected boolean value but got {value:?}") }); - Some(value as usize) + Some(if value { TestBranch::Success } else { TestBranch::Failure }) } ( @@ -620,14 +622,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // on true, min_len = len = $actual_length, // on false, len != $actual_length fully_matched = true; - Some(0) + Some(TestBranch::Success) } (Ordering::Less, _) => { // test_len < pat_len. If $actual_len = test_len, // then $actual_len < pat_len and we don't have // enough elements. fully_matched = false; - Some(1) + Some(TestBranch::Failure) } (Ordering::Equal | Ordering::Greater, true) => { // This can match both if $actual_len = test_len >= pat_len, @@ -639,7 +641,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // test_len != pat_len, so if $actual_len = test_len, then // $actual_len != pat_len. fully_matched = false; - Some(1) + Some(TestBranch::Failure) } } } @@ -653,20 +655,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // $actual_len >= test_len = pat_len, // so we can match. fully_matched = true; - Some(0) + Some(TestBranch::Success) } (Ordering::Less, _) | (Ordering::Equal, false) => { // test_len <= pat_len. If $actual_len < test_len, // then it is also < pat_len, so the test passing is // necessary (but insufficient). fully_matched = false; - Some(0) + Some(TestBranch::Success) } (Ordering::Greater, false) => { // test_len > pat_len. If $actual_len >= test_len > pat_len, // then we know we won't have a match. fully_matched = false; - Some(1) + Some(TestBranch::Failure) } (Ordering::Greater, true) => { // test_len < pat_len, and is therefore less @@ -680,12 +682,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { (TestKind::Range(test), &TestCase::Range(pat)) => { if test.as_ref() == pat { fully_matched = true; - Some(0) + Some(TestBranch::Success) } else { fully_matched = false; // If the testing range does not overlap with pattern range, // the pattern can be matched only if this test fails. - if !test.overlaps(pat, self.tcx, self.param_env)? { Some(1) } else { None } + if !test.overlaps(pat, self.tcx, self.param_env)? { + Some(TestBranch::Failure) + } else { + None + } } } (TestKind::Range(range), &TestCase::Constant { value }) => { @@ -693,7 +699,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if !range.contains(value, self.tcx, self.param_env)? { // `value` is not contained in the testing range, // so `value` can be matched only if this test fails. - Some(1) + Some(TestBranch::Failure) } else { None } @@ -704,7 +710,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if test_val == case_val => { fully_matched = true; - Some(0) + Some(TestBranch::Success) } ( @@ -747,18 +753,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } -impl Test<'_> { - pub(super) fn targets(&self) -> usize { +impl<'tcx> Test<'tcx> { + pub(super) fn targets(&self) -> Vec> { match self.kind { - TestKind::Eq { .. } | TestKind::Range(_) | TestKind::Len { .. } | TestKind::If => 2, + TestKind::Eq { .. } | TestKind::Range(_) | TestKind::Len { .. } | TestKind::If => { + vec![TestBranch::Success, TestBranch::Failure] + } TestKind::Switch { adt_def, .. } => { // While the switch that we generate doesn't test for all // variants, we have a target for each variant and the // otherwise case, and we make sure that all of the cases not // specified have the same block. - adt_def.variants().len() + 1 + adt_def + .variants() + .indices() + .map(|idx| TestBranch::Variant(idx)) + .chain([TestBranch::Failure]) + .collect() } - TestKind::SwitchInt { ref options } => options.len() + 1, + TestKind::SwitchInt { ref options } => options + .iter() + .map(|(val, bits)| TestBranch::Constant(*val, *bits)) + .chain([TestBranch::Failure]) + .collect(), } } } diff --git a/tests/mir-opt/building/issue_49232.main.built.after.mir b/tests/mir-opt/building/issue_49232.main.built.after.mir index d09a1748a8b3..166e28ce51d4 100644 --- a/tests/mir-opt/building/issue_49232.main.built.after.mir +++ b/tests/mir-opt/building/issue_49232.main.built.after.mir @@ -25,7 +25,7 @@ fn main() -> () { StorageLive(_3); _3 = const true; PlaceMention(_3); - switchInt(_3) -> [0: bb4, otherwise: bb6]; + switchInt(_3) -> [0: bb6, otherwise: bb4]; } bb3: { @@ -34,7 +34,8 @@ fn main() -> () { } bb4: { - falseEdge -> [real: bb8, imaginary: bb6]; + _0 = const (); + goto -> bb13; } bb5: { @@ -42,8 +43,7 @@ fn main() -> () { } bb6: { - _0 = const (); - goto -> bb13; + falseEdge -> [real: bb8, imaginary: bb4]; } bb7: { diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 619fda339a6a..307f7105dd2f 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -42,11 +42,15 @@ } bb2: { -- switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4]; +- switchInt((_2.0: bool)) -> [0: bb4, otherwise: bb3]; + switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17]; } bb3: { +- falseEdge -> [real: bb20, imaginary: bb4]; +- } +- +- bb4: { StorageLive(_15); _15 = (_2.1: bool); StorageLive(_16); @@ -55,12 +59,8 @@ + goto -> bb16; } - bb4: { -- falseEdge -> [real: bb20, imaginary: bb3]; -- } -- - bb5: { -- falseEdge -> [real: bb13, imaginary: bb4]; +- falseEdge -> [real: bb13, imaginary: bb3]; - } - - bb6: { @@ -68,6 +68,7 @@ - } - - bb7: { ++ bb4: { _0 = const 1_i32; - drop(_7) -> [return: bb18, unwind: bb25]; + drop(_7) -> [return: bb15, unwind: bb22]; @@ -183,7 +184,7 @@ StorageDead(_12); StorageDead(_8); StorageDead(_6); -- falseEdge -> [real: bb2, imaginary: bb4]; +- falseEdge -> [real: bb2, imaginary: bb3]; + goto -> bb2; } diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 619fda339a6a..307f7105dd2f 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -42,11 +42,15 @@ } bb2: { -- switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4]; +- switchInt((_2.0: bool)) -> [0: bb4, otherwise: bb3]; + switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17]; } bb3: { +- falseEdge -> [real: bb20, imaginary: bb4]; +- } +- +- bb4: { StorageLive(_15); _15 = (_2.1: bool); StorageLive(_16); @@ -55,12 +59,8 @@ + goto -> bb16; } - bb4: { -- falseEdge -> [real: bb20, imaginary: bb3]; -- } -- - bb5: { -- falseEdge -> [real: bb13, imaginary: bb4]; +- falseEdge -> [real: bb13, imaginary: bb3]; - } - - bb6: { @@ -68,6 +68,7 @@ - } - - bb7: { ++ bb4: { _0 = const 1_i32; - drop(_7) -> [return: bb18, unwind: bb25]; + drop(_7) -> [return: bb15, unwind: bb22]; @@ -183,7 +184,7 @@ StorageDead(_12); StorageDead(_8); StorageDead(_6); -- falseEdge -> [real: bb2, imaginary: bb4]; +- falseEdge -> [real: bb2, imaginary: bb3]; + goto -> bb2; } From 8c3688cbb56b8fcb087261215a9215c001d4ea9d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 2 Mar 2024 02:14:13 +0100 Subject: [PATCH 07/99] Allocate candidate vectors as we sort them --- .../rustc_mir_build/src/build/matches/mod.rs | 46 +++++++++---------- .../rustc_mir_build/src/build/matches/test.rs | 36 +-------------- .../building/issue_49232.main.built.after.mir | 8 ++-- ...se_edges.full_tested_match.built.after.mir | 14 +++--- ...e_edges.full_tested_match2.built.after.mir | 22 ++++----- ...wise_branch.opt2.EarlyOtherwiseBranch.diff | 6 +-- ...nch_noopt.noopt1.EarlyOtherwiseBranch.diff | 12 ++--- 7 files changed, 56 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index aea52fc497f0..a1f620e7bafc 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1653,10 +1653,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &'b mut [&'c mut Candidate<'pat, 'tcx>], FxIndexMap, Vec<&'b mut Candidate<'pat, 'tcx>>>, ) { - // For each of the N possible outcomes, create a (initially empty) vector of candidates. - // Those are the candidates that apply if the test has that particular outcome. - let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'pat, 'tcx>>> = - test.targets().into_iter().map(|branch| (branch, Vec::new())).collect(); + // For each of the possible outcomes, collect vector of candidates that apply if the test + // has that particular outcome. + let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_, '_>>> = Default::default(); let total_candidate_count = candidates.len(); @@ -1668,7 +1667,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { break; }; let (candidate, rest) = candidates.split_first_mut().unwrap(); - target_candidates[&branch].push(candidate); + target_candidates.entry(branch).or_insert_with(Vec::new).push(candidate); candidates = rest; } @@ -1809,31 +1808,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { otherwise_block }; - // For each outcome of test, process the candidates that still - // apply. Collect a list of blocks where control flow will - // branch if one of the `target_candidate` sets is not - // exhaustive. + // For each outcome of test, process the candidates that still apply. let target_blocks: FxIndexMap<_, _> = target_candidates .into_iter() .map(|(branch, mut candidates)| { - if !candidates.is_empty() { - let candidate_start = self.cfg.start_new_block(); - self.match_candidates( - span, - scrutinee_span, - candidate_start, - remainder_start, - &mut *candidates, - ); - (branch, candidate_start) - } else { - (branch, remainder_start) - } + let candidate_start = self.cfg.start_new_block(); + self.match_candidates( + span, + scrutinee_span, + candidate_start, + remainder_start, + &mut *candidates, + ); + (branch, candidate_start) }) .collect(); // Perform the test, branching to one of N blocks. - self.perform_test(span, scrutinee_span, start_block, &match_place, &test, target_blocks); + self.perform_test( + span, + scrutinee_span, + start_block, + remainder_start, + &match_place, + &test, + target_blocks, + ); } /// Determine the fake borrows that are needed from a set of places that diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index d003ae8d803c..4244eb45045e 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -127,6 +127,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_start_span: Span, scrutinee_span: Span, block: BasicBlock, + otherwise_block: BasicBlock, place_builder: &PlaceBuilder<'tcx>, test: &Test<'tcx>, target_blocks: FxIndexMap, BasicBlock>, @@ -134,14 +135,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let place = place_builder.to_place(self); let place_ty = place.ty(&self.local_decls, self.tcx); debug!(?place, ?place_ty); - let target_block = |branch| target_blocks[&branch]; + let target_block = |branch| target_blocks.get(&branch).copied().unwrap_or(otherwise_block); let source_info = self.source_info(test.span); match test.kind { TestKind::Switch { adt_def, ref variants } => { // Variants is a BitVec of indexes into adt_def.variants. let num_enum_variants = adt_def.variants().len(); - debug_assert_eq!(target_blocks.len(), num_enum_variants + 1); let otherwise_block = target_block(TestBranch::Failure); let tcx = self.tcx; let switch_targets = SwitchTargets::new( @@ -185,7 +185,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TestKind::SwitchInt { ref options } => { // The switch may be inexhaustive so we have a catch-all block - debug_assert_eq!(options.len() + 1, target_blocks.len()); let otherwise_block = target_block(TestBranch::Failure); let switch_targets = SwitchTargets::new( options @@ -201,7 +200,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } TestKind::If => { - debug_assert_eq!(target_blocks.len(), 2); let success_block = target_block(TestBranch::Success); let fail_block = target_block(TestBranch::Failure); let terminator = @@ -211,7 +209,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TestKind::Eq { value, ty } => { let tcx = self.tcx; - debug_assert_eq!(target_blocks.len(), 2); let success_block = target_block(TestBranch::Success); let fail_block = target_block(TestBranch::Failure); if let ty::Adt(def, _) = ty.kind() @@ -290,7 +287,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } TestKind::Range(ref range) => { - debug_assert_eq!(target_blocks.len(), 2); let success = target_block(TestBranch::Success); let fail = target_block(TestBranch::Failure); // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. @@ -337,7 +333,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // expected = let expected = self.push_usize(block, source_info, len); - debug_assert_eq!(target_blocks.len(), 2); let success_block = target_block(TestBranch::Success); let fail_block = target_block(TestBranch::Failure); // result = actual == expected OR result = actual < expected @@ -753,33 +748,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } -impl<'tcx> Test<'tcx> { - pub(super) fn targets(&self) -> Vec> { - match self.kind { - TestKind::Eq { .. } | TestKind::Range(_) | TestKind::Len { .. } | TestKind::If => { - vec![TestBranch::Success, TestBranch::Failure] - } - TestKind::Switch { adt_def, .. } => { - // While the switch that we generate doesn't test for all - // variants, we have a target for each variant and the - // otherwise case, and we make sure that all of the cases not - // specified have the same block. - adt_def - .variants() - .indices() - .map(|idx| TestBranch::Variant(idx)) - .chain([TestBranch::Failure]) - .collect() - } - TestKind::SwitchInt { ref options } => options - .iter() - .map(|(val, bits)| TestBranch::Constant(*val, *bits)) - .chain([TestBranch::Failure]) - .collect(), - } - } -} - fn is_switch_ty(ty: Ty<'_>) -> bool { ty.is_integral() || ty.is_char() } diff --git a/tests/mir-opt/building/issue_49232.main.built.after.mir b/tests/mir-opt/building/issue_49232.main.built.after.mir index 166e28ce51d4..d09a1748a8b3 100644 --- a/tests/mir-opt/building/issue_49232.main.built.after.mir +++ b/tests/mir-opt/building/issue_49232.main.built.after.mir @@ -25,7 +25,7 @@ fn main() -> () { StorageLive(_3); _3 = const true; PlaceMention(_3); - switchInt(_3) -> [0: bb6, otherwise: bb4]; + switchInt(_3) -> [0: bb4, otherwise: bb6]; } bb3: { @@ -34,8 +34,7 @@ fn main() -> () { } bb4: { - _0 = const (); - goto -> bb13; + falseEdge -> [real: bb8, imaginary: bb6]; } bb5: { @@ -43,7 +42,8 @@ fn main() -> () { } bb6: { - falseEdge -> [real: bb8, imaginary: bb4]; + _0 = const (); + goto -> bb13; } bb7: { diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir index 4e91eb6f76fc..194afdf7dd8a 100644 --- a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir @@ -28,7 +28,7 @@ fn full_tested_match() -> () { _2 = Option::::Some(const 42_i32); PlaceMention(_2); _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1]; + switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1]; } bb1: { @@ -37,20 +37,20 @@ fn full_tested_match() -> () { } bb2: { - _1 = (const 3_i32, const 3_i32); - goto -> bb13; + falseEdge -> [real: bb7, imaginary: bb3]; } bb3: { - goto -> bb1; + falseEdge -> [real: bb12, imaginary: bb5]; } bb4: { - falseEdge -> [real: bb7, imaginary: bb5]; + goto -> bb1; } bb5: { - falseEdge -> [real: bb12, imaginary: bb2]; + _1 = (const 3_i32, const 3_i32); + goto -> bb13; } bb6: { @@ -91,7 +91,7 @@ fn full_tested_match() -> () { bb11: { StorageDead(_7); StorageDead(_6); - goto -> bb5; + goto -> bb3; } bb12: { diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir index 0c67cc9f71e5..ae83075434f7 100644 --- a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir @@ -28,7 +28,7 @@ fn full_tested_match2() -> () { _2 = Option::::Some(const 42_i32); PlaceMention(_2); _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1]; + switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1]; } bb1: { @@ -37,18 +37,10 @@ fn full_tested_match2() -> () { } bb2: { - falseEdge -> [real: bb12, imaginary: bb5]; + falseEdge -> [real: bb7, imaginary: bb5]; } bb3: { - goto -> bb1; - } - - bb4: { - falseEdge -> [real: bb7, imaginary: bb2]; - } - - bb5: { StorageLive(_9); _9 = ((_2 as Some).0: i32); StorageLive(_10); @@ -59,6 +51,14 @@ fn full_tested_match2() -> () { goto -> bb13; } + bb4: { + goto -> bb1; + } + + bb5: { + falseEdge -> [real: bb12, imaginary: bb3]; + } + bb6: { goto -> bb1; } @@ -97,7 +97,7 @@ fn full_tested_match2() -> () { bb11: { StorageDead(_7); StorageDead(_6); - falseEdge -> [real: bb5, imaginary: bb2]; + falseEdge -> [real: bb3, imaginary: bb5]; } bb12: { diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff index 32a8dd8b8b4f..0aed59be7944 100644 --- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff @@ -30,7 +30,7 @@ StorageDead(_5); StorageDead(_4); _8 = discriminant((_3.0: std::option::Option)); -- switchInt(move _8) -> [0: bb2, 1: bb3, otherwise: bb1]; +- switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1]; + StorageLive(_11); + _11 = discriminant((_3.1: std::option::Option)); + StorageLive(_12); @@ -48,12 +48,12 @@ bb2: { - _6 = discriminant((_3.1: std::option::Option)); -- switchInt(move _6) -> [0: bb5, otherwise: bb1]; +- switchInt(move _6) -> [1: bb4, otherwise: bb1]; - } - - bb3: { - _7 = discriminant((_3.1: std::option::Option)); -- switchInt(move _7) -> [1: bb4, otherwise: bb1]; +- switchInt(move _7) -> [0: bb5, otherwise: bb1]; - } - - bb4: { diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff index d7908ab3cd2a..d446a5003a39 100644 --- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff @@ -36,7 +36,7 @@ StorageDead(_5); StorageDead(_4); _8 = discriminant((_3.0: std::option::Option)); - switchInt(move _8) -> [0: bb2, 1: bb4, otherwise: bb1]; + switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1]; } bb1: { @@ -45,17 +45,17 @@ bb2: { _6 = discriminant((_3.1: std::option::Option)); - switchInt(move _6) -> [0: bb3, 1: bb7, otherwise: bb1]; + switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1]; } bb3: { - _0 = const 3_u32; - goto -> bb8; + _7 = discriminant((_3.1: std::option::Option)); + switchInt(move _7) -> [0: bb4, 1: bb7, otherwise: bb1]; } bb4: { - _7 = discriminant((_3.1: std::option::Option)); - switchInt(move _7) -> [0: bb6, 1: bb5, otherwise: bb1]; + _0 = const 3_u32; + goto -> bb8; } bb5: { From edea739292f6ca2c69ad0d70d250806b579a1172 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 1 Mar 2024 01:59:04 +0100 Subject: [PATCH 08/99] No need to collect test variants ahead of time --- .../rustc_mir_build/src/build/matches/mod.rs | 45 ++---- .../rustc_mir_build/src/build/matches/test.rs | 140 ++++-------------- 2 files changed, 38 insertions(+), 147 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index a1f620e7bafc..fdd41eeabecc 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -14,7 +14,6 @@ use rustc_data_structures::{ fx::{FxHashSet, FxIndexMap, FxIndexSet}, stack::ensure_sufficient_stack, }; -use rustc_index::bit_set::BitSet; use rustc_middle::middle::region; use rustc_middle::mir::{self, *}; use rustc_middle::thir::{self, *}; @@ -1116,19 +1115,10 @@ enum TestKind<'tcx> { Switch { /// The enum type being tested. adt_def: ty::AdtDef<'tcx>, - /// The set of variants that we should create a branch for. We also - /// create an additional "otherwise" case. - variants: BitSet, }, /// Test what value an integer or `char` has. - SwitchInt { - /// The (ordered) set of values that we test for. - /// - /// We create a branch to each of the values in `options`, as well as an "otherwise" branch - /// for all other values, even in the (rare) case that `options` is exhaustive. - options: FxIndexMap, u128>, - }, + SwitchInt, /// Test what value a `bool` has. If, @@ -1173,6 +1163,12 @@ enum TestBranch<'tcx> { Failure, } +impl<'tcx> TestBranch<'tcx> { + fn as_constant(&self) -> Option<&Const<'tcx>> { + if let Self::Constant(v, _) = self { Some(v) } else { None } + } +} + /// `ArmHasGuard` is a wrapper around a boolean flag. It indicates whether /// a match arm has a guard expression attached to it. #[derive(Copy, Clone, Debug)] @@ -1583,30 +1579,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> (PlaceBuilder<'tcx>, Test<'tcx>) { // Extract the match-pair from the highest priority candidate let match_pair = &candidates.first().unwrap().match_pairs[0]; - let mut test = self.test(match_pair); + let test = self.test(match_pair); let match_place = match_pair.place.clone(); - debug!(?test, ?match_pair); - // Most of the time, the test to perform is simply a function of the main candidate; but for - // a test like SwitchInt, we may want to add cases based on the candidates that are - // available - match test.kind { - TestKind::SwitchInt { ref mut options } => { - for candidate in candidates.iter() { - if !self.add_cases_to_switch(&match_place, candidate, options) { - break; - } - } - } - TestKind::Switch { adt_def: _, ref mut variants } => { - for candidate in candidates.iter() { - if !self.add_variants_to_switch(&match_place, candidate, variants) { - break; - } - } - } - _ => {} - } (match_place, test) } @@ -1663,7 +1638,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // point we may encounter a candidate where the test is not relevant; at that point, we stop // sorting. while let Some(candidate) = candidates.first_mut() { - let Some(branch) = self.sort_candidate(&match_place, &test, candidate) else { + let Some(branch) = + self.sort_candidate(&match_place, test, candidate, &target_candidates) + else { break; }; let (candidate, rest) = candidates.split_first_mut().unwrap(); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 4244eb45045e..0598ffccea7b 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -10,9 +10,7 @@ use crate::build::matches::{Candidate, MatchPair, Test, TestBranch, TestCase, Te use crate::build::Builder; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::{LangItem, RangeEnd}; -use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; -use rustc_middle::thir::*; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::GenericArg; use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt}; @@ -20,7 +18,6 @@ use rustc_span::def_id::DefId; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::VariantIdx; use std::cmp::Ordering; @@ -30,22 +27,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// It is a bug to call this with a not-fully-simplified pattern. pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> { let kind = match match_pair.test_case { - TestCase::Variant { adt_def, variant_index: _ } => { - TestKind::Switch { adt_def, variants: BitSet::new_empty(adt_def.variants().len()) } - } + TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def }, TestCase::Constant { .. } if match_pair.pattern.ty.is_bool() => TestKind::If, - - TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => { - // For integers, we use a `SwitchInt` match, which allows - // us to handle more cases. - TestKind::SwitchInt { - // these maps are empty to start; cases are - // added below in add_cases_to_switch - options: Default::default(), - } - } - + TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => TestKind::SwitchInt, TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty }, TestCase::Range(range) => { @@ -70,57 +55,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Test { span: match_pair.pattern.span, kind } } - pub(super) fn add_cases_to_switch<'pat>( - &mut self, - test_place: &PlaceBuilder<'tcx>, - candidate: &Candidate<'pat, 'tcx>, - options: &mut FxIndexMap, u128>, - ) -> bool { - let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) - else { - return false; - }; - - match match_pair.test_case { - TestCase::Constant { value } => { - options.entry(value).or_insert_with(|| value.eval_bits(self.tcx, self.param_env)); - true - } - TestCase::Variant { .. } => { - panic!("you should have called add_variants_to_switch instead!"); - } - TestCase::Range(ref range) => { - // Check that none of the switch values are in the range. - self.values_not_contained_in_range(&*range, options).unwrap_or(false) - } - // don't know how to add these patterns to a switch - _ => false, - } - } - - pub(super) fn add_variants_to_switch<'pat>( - &mut self, - test_place: &PlaceBuilder<'tcx>, - candidate: &Candidate<'pat, 'tcx>, - variants: &mut BitSet, - ) -> bool { - let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) - else { - return false; - }; - - match match_pair.test_case { - TestCase::Variant { variant_index, .. } => { - // We have a pattern testing for variant `variant_index` - // set the corresponding index to true - variants.insert(variant_index); - true - } - // don't know how to add these patterns to a switch - _ => false, - } - } - #[instrument(skip(self, target_blocks, place_builder), level = "debug")] pub(super) fn perform_test( &mut self, @@ -139,33 +73,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = self.source_info(test.span); match test.kind { - TestKind::Switch { adt_def, ref variants } => { - // Variants is a BitVec of indexes into adt_def.variants. - let num_enum_variants = adt_def.variants().len(); + TestKind::Switch { adt_def } => { let otherwise_block = target_block(TestBranch::Failure); - let tcx = self.tcx; let switch_targets = SwitchTargets::new( - adt_def.discriminants(tcx).filter_map(|(idx, discr)| { - if variants.contains(idx) { - debug_assert_ne!( - target_block(TestBranch::Variant(idx)), - otherwise_block, - "no candidates for tested discriminant: {discr:?}", - ); - Some((discr.val, target_block(TestBranch::Variant(idx)))) + adt_def.discriminants(self.tcx).filter_map(|(idx, discr)| { + if let Some(&block) = target_blocks.get(&TestBranch::Variant(idx)) { + Some((discr.val, block)) } else { - debug_assert_eq!( - target_block(TestBranch::Variant(idx)), - otherwise_block, - "found candidates for untested discriminant: {discr:?}", - ); None } }), otherwise_block, ); - debug!("num_enum_variants: {}, variants: {:?}", num_enum_variants, variants); - let discr_ty = adt_def.repr().discr_type().to_ty(tcx); + debug!("num_enum_variants: {}", adt_def.variants().len()); + let discr_ty = adt_def.repr().discr_type().to_ty(self.tcx); let discr = self.temp(discr_ty, test.span); self.cfg.push_assign( block, @@ -183,13 +104,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); } - TestKind::SwitchInt { ref options } => { + TestKind::SwitchInt => { // The switch may be inexhaustive so we have a catch-all block let otherwise_block = target_block(TestBranch::Failure); let switch_targets = SwitchTargets::new( - options - .iter() - .map(|(&val, &bits)| (bits, target_block(TestBranch::Constant(val, bits)))), + target_blocks.iter().filter_map(|(&branch, &block)| { + if let TestBranch::Constant(_, bits) = branch { + Some((bits, block)) + } else { + None + } + }), otherwise_block, ); let terminator = TerminatorKind::SwitchInt { @@ -548,11 +473,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// that it *doesn't* apply. For now, we return false, indicate that the /// test does not apply to this candidate, but it might be we can get /// tighter match code if we do something a bit different. - pub(super) fn sort_candidate<'pat>( + pub(super) fn sort_candidate( &mut self, test_place: &PlaceBuilder<'tcx>, test: &Test<'tcx>, - candidate: &mut Candidate<'pat, 'tcx>, + candidate: &mut Candidate<'_, 'tcx>, + sorted_candidates: &FxIndexMap, Vec<&mut Candidate<'_, 'tcx>>>, ) -> Option> { // Find the match_pair for this place (if any). At present, // afaik, there can be at most one. (In the future, if we @@ -568,7 +494,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // If we are performing a variant switch, then this // informs variant patterns, but nothing else. ( - &TestKind::Switch { adt_def: tested_adt_def, .. }, + &TestKind::Switch { adt_def: tested_adt_def }, &TestCase::Variant { adt_def, variant_index }, ) => { assert_eq!(adt_def, tested_adt_def); @@ -581,17 +507,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // // FIXME(#29623) we could use PatKind::Range to rule // things out here, in some cases. - (TestKind::SwitchInt { options }, &TestCase::Constant { value }) + (TestKind::SwitchInt, &TestCase::Constant { value }) if is_switch_ty(match_pair.pattern.ty) => { fully_matched = true; - let bits = options.get(&value).unwrap(); - Some(TestBranch::Constant(value, *bits)) + let bits = value.eval_bits(self.tcx, self.param_env); + Some(TestBranch::Constant(value, bits)) } - (TestKind::SwitchInt { options }, TestCase::Range(range)) => { + (TestKind::SwitchInt, TestCase::Range(range)) => { fully_matched = false; let not_contained = - self.values_not_contained_in_range(&*range, options).unwrap_or(false); + sorted_candidates.keys().filter_map(|br| br.as_constant()).copied().all( + |val| matches!(range.contains(val, self.tcx, self.param_env), Some(false)), + ); not_contained.then(|| { // No switch values are contained in the pattern range, @@ -732,20 +660,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ret } - - fn values_not_contained_in_range( - &self, - range: &PatRange<'tcx>, - options: &FxIndexMap, u128>, - ) -> Option { - for &val in options.keys() { - if range.contains(val, self.tcx, self.param_env)? { - return Some(false); - } - } - - Some(true) - } } fn is_switch_ty(ty: Ty<'_>) -> bool { From d46ff6415c033ccfebac3d2a757908611a67d324 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 2 Mar 2024 02:49:33 +0100 Subject: [PATCH 09/99] Fix a subtle regression Before, the SwitchInt cases were computed in two passes: if the first pass accepted e.g. 0..=5 and then 1, the second pass would not accept 0..=5 anymore because 1 would be listed in the SwitchInt options. Now there's a single pass, so if we sort 0..=5 we must take care to not sort a subsequent 1. --- .../rustc_mir_build/src/build/matches/mod.rs | 6 +++++ .../rustc_mir_build/src/build/matches/test.rs | 27 ++++++++++++++++--- ...egression-switchint-sorting-with-ranges.rs | 14 ++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 tests/ui/pattern/usefulness/integer-ranges/regression-switchint-sorting-with-ranges.rs diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index fdd41eeabecc..cfd12cec0e46 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1091,6 +1091,12 @@ enum TestCase<'pat, 'tcx> { Or { pats: Box<[FlatPat<'pat, 'tcx>]> }, } +impl<'pat, 'tcx> TestCase<'pat, 'tcx> { + fn as_range(&self) -> Option<&'pat PatRange<'tcx>> { + if let Self::Range(v) = self { Some(*v) } else { None } + } +} + #[derive(Debug, Clone)] pub(crate) struct MatchPair<'pat, 'tcx> { /// This place... diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 0598ffccea7b..9d77bd063e11 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -510,9 +510,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { (TestKind::SwitchInt, &TestCase::Constant { value }) if is_switch_ty(match_pair.pattern.ty) => { - fully_matched = true; - let bits = value.eval_bits(self.tcx, self.param_env); - Some(TestBranch::Constant(value, bits)) + // Beware: there might be some ranges sorted into the failure case; we must not add + // a success case that could be matched by one of these ranges. + let is_covering_range = |test_case: &TestCase<'_, 'tcx>| { + test_case.as_range().is_some_and(|range| { + matches!(range.contains(value, self.tcx, self.param_env), None | Some(true)) + }) + }; + let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| { + candidate + .match_pairs + .iter() + .any(|mp| mp.place == *test_place && is_covering_range(&mp.test_case)) + }; + if sorted_candidates + .get(&TestBranch::Failure) + .is_some_and(|candidates| candidates.iter().any(is_conflicting_candidate)) + { + fully_matched = false; + None + } else { + fully_matched = true; + let bits = value.eval_bits(self.tcx, self.param_env); + Some(TestBranch::Constant(value, bits)) + } } (TestKind::SwitchInt, TestCase::Range(range)) => { fully_matched = false; diff --git a/tests/ui/pattern/usefulness/integer-ranges/regression-switchint-sorting-with-ranges.rs b/tests/ui/pattern/usefulness/integer-ranges/regression-switchint-sorting-with-ranges.rs new file mode 100644 index 000000000000..bacb60a108bf --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/regression-switchint-sorting-with-ranges.rs @@ -0,0 +1,14 @@ +//@ run-pass +// +// Regression test for match lowering to MIR: when gathering candidates, by the time we get to the +// range we know the range will only match on the failure case of the switchint. Hence we mustn't +// add the `1` to the switchint or the range would be incorrectly sorted. +#![allow(unreachable_patterns)] +fn main() { + match 1 { + 10 => unreachable!(), + 0..=5 => {} + 1 => unreachable!(), + _ => unreachable!(), + } +} From d413ad8f64498fa5933fe5fd8e190b16415354a7 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 6 Mar 2024 15:36:52 +0300 Subject: [PATCH 10/99] update remap path of `rust-analyzer-proc-macro-srv` alias Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 8223a80c9310..71283783f9e3 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -291,7 +291,7 @@ impl PathSet { const PATH_REMAP: &[(&str, &[&str])] = &[ // config.toml uses `rust-analyzer-proc-macro-srv`, but the // actual path is `proc-macro-srv-cli` - ("rust-analyzer-proc-macro-srv", &["proc-macro-srv-cli"]), + ("rust-analyzer-proc-macro-srv", &["src/tools/rust-analyzer/crates/proc-macro-srv-cli"]), // Make `x test tests` function the same as `x t tests/*` ( "tests", From ea22e7851f2d97b63379685258b482deb2409b8f Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 6 Mar 2024 15:37:21 +0300 Subject: [PATCH 11/99] validate `builder::PATH_REMAP` in bootstrap tests Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 2cbebbcf4e2a..e402a0ba8bc7 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -115,6 +115,19 @@ fn test_intersection() { assert_eq!(command_paths, vec![Path::new("library/stdarch")]); } +#[test] +fn validate_path_remap() { + let build = Build::new(configure("test", &["A"], &["A"])); + + PATH_REMAP + .iter() + .flat_map(|(_, paths)| paths.iter()) + .map(|path| build.src.join(path)) + .for_each(|path| { + assert!(path.exists(), "{} should exist.", path.display()); + }); +} + #[test] fn test_exclude() { let mut config = configure("test", &["A"], &["A"]); From 5ccada66a21e2fff8691b97189f127ecfd42ea26 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Wed, 6 Mar 2024 19:36:09 -0500 Subject: [PATCH 12/99] make check lines for int/ptr common prim test more permissive It seems that LLVM 17 doesn't fully optimize out unwrap_unchecked. We can just loosen the check lines to account for this, since we don't really care about the exact instructions, we just want to make sure that inttoptr/ptrtoint aren't used for Box. --- tests/codegen/common_prim_int_ptr.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/codegen/common_prim_int_ptr.rs b/tests/codegen/common_prim_int_ptr.rs index 9b798d495d4f..666ccc5a2cff 100644 --- a/tests/codegen/common_prim_int_ptr.rs +++ b/tests/codegen/common_prim_int_ptr.rs @@ -28,16 +28,16 @@ pub fn insert_box(x: Box<()>) -> Result> { // CHECK-LABEL: @extract_int #[no_mangle] pub unsafe fn extract_int(x: Result>) -> usize { - // CHECK: start: - // CHECK-NEXT: ptrtoint - // CHECK-NEXT: ret + // CHECK: ptrtoint x.unwrap_unchecked() } // CHECK-LABEL: @extract_box #[no_mangle] pub unsafe fn extract_box(x: Result>) -> Box<()> { - // CHECK: start: - // CHECK-NEXT: ret ptr + // CHECK-NOT: ptrtoint + // CHECK-NOT: inttoptr + // CHECK-NOT: load + // CHECK-NOT: store x.unwrap_err_unchecked() } From 288380d4578e6e0be913fea6852226227a6c4170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 9 Mar 2024 01:26:59 +0100 Subject: [PATCH 13/99] Lock stderr in panic handler --- compiler/rustc_driver_impl/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index e06d1d245b23..b74819071877 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1317,6 +1317,9 @@ pub fn install_ice_hook( panic::update_hook(Box::new( move |default_hook: &(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static), info: &PanicInfo<'_>| { + // Lock stderr to prevent interleaving of concurrent panics. + let _guard = io::stderr().lock(); + // If the error was caused by a broken pipe then this is not a bug. // Write the error and return immediately. See #98700. #[cfg(windows)] From 16e869a678312b16c2e97461f144ce63ef5309bc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Mar 2024 13:50:39 +0100 Subject: [PATCH 14/99] interpret: pass Size and Align to before_memory_deallocation --- compiler/rustc_const_eval/src/interpret/machine.rs | 3 ++- compiler/rustc_const_eval/src/interpret/memory.rs | 3 ++- src/tools/miri/src/borrow_tracker/mod.rs | 6 +++--- src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs | 6 +++--- src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs | 4 ++-- src/tools/miri/src/concurrency/data_race.rs | 4 ++-- src/tools/miri/src/machine.rs | 7 ++++--- 7 files changed, 18 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index ee5de44a6514..1b9a96ec3219 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -433,7 +433,8 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, _prov: (AllocId, Self::ProvenanceExtra), - _range: AllocRange, + _size: Size, + _align: Align, ) -> InterpResult<'tcx> { Ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 3b2208b8caa8..0df724f29c40 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -345,7 +345,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self.machine, &mut alloc.extra, (alloc_id, prov), - alloc_range(Size::ZERO, size), + size, + alloc.align, )?; // Don't forget to remember size and align of this now-dead allocation diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 262f7c449d27..8d76a488269f 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -472,14 +472,14 @@ impl AllocState { &mut self, alloc_id: AllocId, prov_extra: ProvenanceExtra, - range: AllocRange, + size: Size, machine: &MiriMachine<'_, 'tcx>, ) -> InterpResult<'tcx> { match self { AllocState::StackedBorrows(sb) => - sb.get_mut().before_memory_deallocation(alloc_id, prov_extra, range, machine), + sb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine), AllocState::TreeBorrows(tb) => - tb.get_mut().before_memory_deallocation(alloc_id, prov_extra, range, machine), + tb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine), } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 86d22229714d..7ca2bc76f1e8 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -574,13 +574,13 @@ impl Stacks { &mut self, alloc_id: AllocId, tag: ProvenanceExtra, - range: AllocRange, + size: Size, machine: &MiriMachine<'_, 'tcx>, ) -> InterpResult<'tcx> { - trace!("deallocation with tag {:?}: {:?}, size {}", tag, alloc_id, range.size.bytes()); + trace!("deallocation with tag {:?}: {:?}, size {}", tag, alloc_id, size.bytes()); let dcx = DiagnosticCxBuilder::dealloc(machine, tag); let state = machine.borrow_tracker.as_ref().unwrap().borrow(); - self.for_each(range, dcx, |stack, dcx, exposed_tags| { + self.for_each(alloc_range(Size::ZERO, size), dcx, |stack, dcx, exposed_tags| { stack.dealloc(tag, &state, dcx, exposed_tags) })?; Ok(()) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 4b944ea88f50..9dd147af4244 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -80,7 +80,7 @@ impl<'tcx> Tree { &mut self, alloc_id: AllocId, prov: ProvenanceExtra, - range: AllocRange, + size: Size, machine: &MiriMachine<'_, 'tcx>, ) -> InterpResult<'tcx> { // TODO: for now we bail out on wildcard pointers. Eventually we should @@ -91,7 +91,7 @@ impl<'tcx> Tree { }; let global = machine.borrow_tracker.as_ref().unwrap(); let span = machine.current_span(); - self.dealloc(tag, range, global, alloc_id, span) + self.dealloc(tag, alloc_range(Size::ZERO, size), global, alloc_id, span) } pub fn expose_tag(&mut self, _tag: BorTag) { diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index e30448840838..4a1c3ac868e1 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -1071,10 +1071,10 @@ impl VClockAlloc { pub fn deallocate<'tcx>( &mut self, alloc_id: AllocId, - range: AllocRange, + size: Size, machine: &mut MiriMachine<'_, '_>, ) -> InterpResult<'tcx> { - self.unique_access(alloc_id, range, NaWriteType::Deallocate, machine) + self.unique_access(alloc_id, alloc_range(Size::ZERO, size), NaWriteType::Deallocate, machine) } } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index c3c3a8158561..fda7e6f4449a 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1288,16 +1288,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { machine: &mut Self, alloc_extra: &mut AllocExtra<'tcx>, (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra), - range: AllocRange, + size: Size, + _align: Align, ) -> InterpResult<'tcx> { if machine.tracked_alloc_ids.contains(&alloc_id) { machine.emit_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id)); } if let Some(data_race) = &mut alloc_extra.data_race { - data_race.deallocate(alloc_id, range, machine)?; + data_race.deallocate(alloc_id, size, machine)?; } if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker { - borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, range, machine)?; + borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, size, machine)?; } if let Some((_, deallocated_at)) = machine.allocation_spans.borrow_mut().get_mut(&alloc_id) { From 092bd53c1ef96ede03bb50ecefc15c6a365531f4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Mar 2024 13:20:51 +0100 Subject: [PATCH 15/99] rename intptrcast -> alloc_addresses, and make a folder for it --- .../src/{intptrcast.rs => alloc_addresses/mod.rs} | 13 ++++++++----- src/tools/miri/src/lib.rs | 4 ++-- src/tools/miri/src/machine.rs | 10 +++++----- src/tools/miri/src/provenance_gc.rs | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) rename src/tools/miri/src/{intptrcast.rs => alloc_addresses/mod.rs} (96%) diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/alloc_addresses/mod.rs similarity index 96% rename from src/tools/miri/src/intptrcast.rs rename to src/tools/miri/src/alloc_addresses/mod.rs index 3fe127f97326..3177a1297c82 100644 --- a/src/tools/miri/src/intptrcast.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -1,3 +1,6 @@ +//! This module is responsible for managing the absolute addresses that allocations are located at, +//! and for casting between pointers and integers based on those addresses. + use std::cell::RefCell; use std::cmp::max; use std::collections::hash_map::Entry; @@ -96,7 +99,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // or `None` if the addr is out of bounds fn alloc_id_from_addr(&self, addr: u64) -> Option { let ecx = self.eval_context_ref(); - let global_state = ecx.machine.intptrcast.borrow(); + let global_state = ecx.machine.alloc_addresses.borrow(); assert!(global_state.provenance_mode != ProvenanceMode::Strict); let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr); @@ -133,7 +136,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn addr_from_alloc_id(&self, alloc_id: AllocId) -> InterpResult<'tcx, u64> { let ecx = self.eval_context_ref(); - let mut global_state = ecx.machine.intptrcast.borrow_mut(); + let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); let global_state = &mut *global_state; Ok(match global_state.base_addr.entry(alloc_id) { @@ -196,7 +199,7 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn expose_ptr(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { let ecx = self.eval_context_mut(); - let global_state = ecx.machine.intptrcast.get_mut(); + let global_state = ecx.machine.alloc_addresses.get_mut(); // In strict mode, we don't need this, so we can save some cycles by not tracking it. if global_state.provenance_mode == ProvenanceMode::Strict { return Ok(()); @@ -207,7 +210,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(()); } trace!("Exposing allocation id {alloc_id:?}"); - let global_state = ecx.machine.intptrcast.get_mut(); + let global_state = ecx.machine.alloc_addresses.get_mut(); global_state.exposed.insert(alloc_id); if ecx.machine.borrow_tracker.is_some() { ecx.expose_tag(alloc_id, tag)?; @@ -219,7 +222,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { trace!("Casting {:#x} to a pointer", addr); let ecx = self.eval_context_ref(); - let global_state = ecx.machine.intptrcast.borrow(); + let global_state = ecx.machine.alloc_addresses.borrow(); // Potentially emit a warning. match global_state.provenance_mode { diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index e1d0bc1c1838..819952d09e17 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -71,13 +71,13 @@ extern crate tracing; #[allow(unused_extern_crates)] extern crate rustc_driver; +mod alloc_addresses; mod borrow_tracker; mod clock; mod concurrency; mod diagnostics; mod eval; mod helpers; -mod intptrcast; mod machine; mod mono_hash_map; mod operator; @@ -100,6 +100,7 @@ pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _}; pub use crate::shims::time::EvalContextExt as _; pub use crate::shims::tls::TlsData; +pub use crate::alloc_addresses::{EvalContextExt as _, ProvenanceMode}; pub use crate::borrow_tracker::stacked_borrows::{ EvalContextExt as _, Item, Permission, Stack, Stacks, }; @@ -121,7 +122,6 @@ pub use crate::eval::{ create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith, }; pub use crate::helpers::{AccessKind, EvalContextExt as _}; -pub use crate::intptrcast::{EvalContextExt as _, ProvenanceMode}; pub use crate::machine::{ AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind, PrimitiveLayouts, Provenance, ProvenanceExtra, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index fda7e6f4449a..3a54629222d5 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -436,7 +436,7 @@ pub struct MiriMachine<'mir, 'tcx> { pub data_race: Option, /// Ptr-int-cast module global data. - pub intptrcast: intptrcast::GlobalState, + pub alloc_addresses: alloc_addresses::GlobalState, /// Environment variables set by `setenv`. /// Miri does not expose env vars from the host to the emulated program. @@ -634,7 +634,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { tcx, borrow_tracker, data_race, - intptrcast: RefCell::new(intptrcast::GlobalStateInner::new(config, stack_addr)), + alloc_addresses: RefCell::new(alloc_addresses::GlobalStateInner::new(config, stack_addr)), // `env_vars` depends on a full interpreter so we cannot properly initialize it yet. env_vars: EnvVars::default(), main_fn_ret_place: None, @@ -782,7 +782,7 @@ impl VisitProvenance for MiriMachine<'_, '_> { dir_handler, borrow_tracker, data_race, - intptrcast, + alloc_addresses, file_handler, tcx: _, isolated_op: _, @@ -827,7 +827,7 @@ impl VisitProvenance for MiriMachine<'_, '_> { file_handler.visit_provenance(visit); data_race.visit_provenance(visit); borrow_tracker.visit_provenance(visit); - intptrcast.visit_provenance(visit); + alloc_addresses.visit_provenance(visit); main_fn_ret_place.visit_provenance(visit); argc.visit_provenance(visit); argv.visit_provenance(visit); @@ -1304,7 +1304,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { { *deallocated_at = Some(machine.current_span()); } - machine.intptrcast.get_mut().free_alloc_id(alloc_id); + machine.alloc_addresses.get_mut().free_alloc_id(alloc_id); Ok(()) } diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs index 347951ce3727..f23d7dfd52d5 100644 --- a/src/tools/miri/src/provenance_gc.rs +++ b/src/tools/miri/src/provenance_gc.rs @@ -197,7 +197,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let allocs = LiveAllocs { ecx: this, collected: allocs }; this.machine.allocation_spans.borrow_mut().retain(|id, _| allocs.is_live(*id)); this.machine.symbolic_alignment.borrow_mut().retain(|id, _| allocs.is_live(*id)); - this.machine.intptrcast.borrow_mut().remove_unreachable_allocs(&allocs); + this.machine.alloc_addresses.borrow_mut().remove_unreachable_allocs(&allocs); if let Some(borrow_tracker) = &this.machine.borrow_tracker { borrow_tracker.borrow_mut().remove_unreachable_allocs(&allocs); } From aa6cfb2669e51b3211017bde2faa6eddba22ecbe Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 8 Mar 2024 21:50:23 -0500 Subject: [PATCH 16/99] Sink ptrtoint for RMW ops on pointers to cg_llvm --- compiler/rustc_codegen_llvm/src/builder.rs | 8 ++- compiler/rustc_codegen_ssa/src/common.rs | 2 +- .../rustc_codegen_ssa/src/mir/intrinsic.rs | 50 ++++--------------- 3 files changed, 18 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index ca2e2b575805..63e59ea13fc3 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1132,9 +1132,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { &mut self, op: rustc_codegen_ssa::common::AtomicRmwBinOp, dst: &'ll Value, - src: &'ll Value, + mut src: &'ll Value, order: rustc_codegen_ssa::common::AtomicOrdering, ) -> &'ll Value { + // The only RMW operation that LLVM supports on pointers is compare-exchange. + if self.val_ty(src) == self.type_ptr() + && op != rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicXchg + { + src = self.ptrtoint(src, self.type_isize()); + } unsafe { llvm::LLVMBuildAtomicRMW( self.llbuilder, diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 641ac3eb8087..44a2434238da 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -42,7 +42,7 @@ pub enum RealPredicate { RealPredicateTrue, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq)] pub enum AtomicRmwBinOp { AtomicXchg, AtomicAdd, diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 82488829b6e1..1d1826d98447 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -350,14 +350,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { let weak = instruction == "cxchgweak"; let dst = args[0].immediate(); - let mut cmp = args[1].immediate(); - let mut src = args[2].immediate(); - if ty.is_unsafe_ptr() { - // Some platforms do not support atomic operations on pointers, - // so we cast to integer first. - cmp = bx.ptrtoint(cmp, bx.type_isize()); - src = bx.ptrtoint(src, bx.type_isize()); - } + let cmp = args[1].immediate(); + let src = args[2].immediate(); let (val, success) = bx.atomic_cmpxchg( dst, cmp, @@ -385,26 +379,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let layout = bx.layout_of(ty); let size = layout.size; let source = args[0].immediate(); - if ty.is_unsafe_ptr() { - // Some platforms do not support atomic operations on pointers, - // so we cast to integer first... - let llty = bx.type_isize(); - let result = bx.atomic_load( - llty, - source, - parse_ordering(bx, ordering), - size, - ); - // ... and then cast the result back to a pointer - bx.inttoptr(result, bx.backend_type(layout)) - } else { - bx.atomic_load( - bx.backend_type(layout), - source, - parse_ordering(bx, ordering), - size, - ) - } + bx.atomic_load( + bx.backend_type(layout), + source, + parse_ordering(bx, ordering), + size, + ) } else { invalid_monomorphization(ty); return Ok(()); @@ -415,13 +395,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let ty = fn_args.type_at(0); if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { let size = bx.layout_of(ty).size; - let mut val = args[1].immediate(); + let val = args[1].immediate(); let ptr = args[0].immediate(); - if ty.is_unsafe_ptr() { - // Some platforms do not support atomic operations on pointers, - // so we cast to integer first. - val = bx.ptrtoint(val, bx.type_isize()); - } bx.atomic_store(val, ptr, parse_ordering(bx, ordering), size); } else { invalid_monomorphization(ty); @@ -465,12 +440,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let ty = fn_args.type_at(0); if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { let ptr = args[0].immediate(); - let mut val = args[1].immediate(); - if ty.is_unsafe_ptr() { - // Some platforms do not support atomic operations on pointers, - // so we cast to integer first. - val = bx.ptrtoint(val, bx.type_isize()); - } + let val = args[1].immediate(); bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering)) } else { invalid_monomorphization(ty); From c01676835125747b5fff3143ca2a71d2bf7b94c4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Mar 2024 16:05:37 +0100 Subject: [PATCH 17/99] miri: add some chance to reuse addresses of previously freed allocations --- src/tools/miri/src/alloc_addresses/mod.rs | 101 ++++++++++++------ .../miri/src/alloc_addresses/reuse_pool.rs | 87 +++++++++++++++ src/tools/miri/src/helpers.rs | 4 +- src/tools/miri/src/machine.rs | 9 +- src/tools/miri/tests/pass/address-reuse.rs | 16 +++ src/tools/miri/tests/pass/intptrcast.rs | 4 +- 6 files changed, 182 insertions(+), 39 deletions(-) create mode 100644 src/tools/miri/src/alloc_addresses/reuse_pool.rs create mode 100644 src/tools/miri/tests/pass/address-reuse.rs diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 3177a1297c82..e1714aa9e46b 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -1,6 +1,8 @@ //! This module is responsible for managing the absolute addresses that allocations are located at, //! and for casting between pointers and integers based on those addresses. +mod reuse_pool; + use std::cell::RefCell; use std::cmp::max; use std::collections::hash_map::Entry; @@ -9,9 +11,10 @@ use rand::Rng; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_span::Span; -use rustc_target::abi::{HasDataLayout, Size}; +use rustc_target::abi::{Align, HasDataLayout, Size}; use crate::*; +use reuse_pool::ReusePool; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ProvenanceMode { @@ -26,7 +29,7 @@ pub enum ProvenanceMode { pub type GlobalState = RefCell; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct GlobalStateInner { /// This is used as a map between the address of each allocation and its `AllocId`. It is always /// sorted by address. We cannot use a `HashMap` since we can be given an address that is offset @@ -38,6 +41,8 @@ pub struct GlobalStateInner { /// they do not have an `AllocExtra`. /// This is the inverse of `int_to_ptr_map`. base_addr: FxHashMap, + /// A pool of addresses we can reuse for future allocations. + reuse: ReusePool, /// Whether an allocation has been exposed or not. This cannot be put /// into `AllocExtra` for the same reason as `base_addr`. exposed: FxHashSet, @@ -53,6 +58,7 @@ impl VisitProvenance for GlobalStateInner { let GlobalStateInner { int_to_ptr_map: _, base_addr: _, + reuse: _, exposed: _, next_base_addr: _, provenance_mode: _, @@ -71,6 +77,7 @@ impl GlobalStateInner { GlobalStateInner { int_to_ptr_map: Vec::default(), base_addr: FxHashMap::default(), + reuse: ReusePool::new(), exposed: FxHashSet::default(), next_base_addr: stack_addr, provenance_mode: config.provenance_mode, @@ -142,6 +149,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(match global_state.base_addr.entry(alloc_id) { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { + let mut rng = ecx.machine.rng.borrow_mut(); let (size, align, kind) = ecx.get_alloc_info(alloc_id); // This is either called immediately after allocation (and then cached), or when // adjusting `tcx` pointers (which never get freed). So assert that we are looking @@ -150,44 +158,63 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // information was removed. assert!(!matches!(kind, AllocKind::Dead)); - // This allocation does not have a base address yet, pick one. - // Leave some space to the previous allocation, to give it some chance to be less aligned. - let slack = { - let mut rng = ecx.machine.rng.borrow_mut(); - // This means that `(global_state.next_base_addr + slack) % 16` is uniformly distributed. - rng.gen_range(0..16) + // This allocation does not have a base address yet, pick or reuse one. + let base_addr = if let Some(reuse_addr) = + global_state.reuse.take_addr(&mut *rng, size, align) + { + reuse_addr + } else { + // We have to pick a fresh address. + // Leave some space to the previous allocation, to give it some chance to be less aligned. + // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed. + let slack = rng.gen_range(0..16); + // From next_base_addr + slack, round up to adjust for alignment. + let base_addr = global_state + .next_base_addr + .checked_add(slack) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; + let base_addr = align_addr(base_addr, align.bytes()); + + // Remember next base address. If this allocation is zero-sized, leave a gap + // of at least 1 to avoid two allocations having the same base address. + // (The logic in `alloc_id_from_addr` assumes unique addresses, and different + // function/vtable pointers need to be distinguishable!) + global_state.next_base_addr = base_addr + .checked_add(max(size.bytes(), 1)) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; + // Even if `Size` didn't overflow, we might still have filled up the address space. + if global_state.next_base_addr > ecx.target_usize_max() { + throw_exhaust!(AddressSpaceFull); + } + + base_addr }; - // From next_base_addr + slack, round up to adjust for alignment. - let base_addr = global_state - .next_base_addr - .checked_add(slack) - .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; - let base_addr = align_addr(base_addr, align.bytes()); - entry.insert(base_addr); trace!( - "Assigning base address {:#x} to allocation {:?} (size: {}, align: {}, slack: {})", + "Assigning base address {:#x} to allocation {:?} (size: {}, align: {})", base_addr, alloc_id, size.bytes(), align.bytes(), - slack, ); - // Remember next base address. If this allocation is zero-sized, leave a gap - // of at least 1 to avoid two allocations having the same base address. - // (The logic in `alloc_id_from_addr` assumes unique addresses, and different - // function/vtable pointers need to be distinguishable!) - global_state.next_base_addr = base_addr - .checked_add(max(size.bytes(), 1)) - .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; - // Even if `Size` didn't overflow, we might still have filled up the address space. - if global_state.next_base_addr > ecx.target_usize_max() { - throw_exhaust!(AddressSpaceFull); - } - // Also maintain the opposite mapping in `int_to_ptr_map`. - // Given that `next_base_addr` increases in each allocation, pushing the - // corresponding tuple keeps `int_to_ptr_map` sorted - global_state.int_to_ptr_map.push((base_addr, alloc_id)); + // Store address in cache. + entry.insert(base_addr); + + // Also maintain the opposite mapping in `int_to_ptr_map`, ensuring we keep it sorted. + // We have a fast-path for the common case that this address is bigger than all previous ones. + let pos = if global_state + .int_to_ptr_map + .last() + .is_some_and(|(last_addr, _)| *last_addr < base_addr) + { + global_state.int_to_ptr_map.len() + } else { + global_state + .int_to_ptr_map + .binary_search_by_key(&base_addr, |(addr, _)| *addr) + .unwrap_err() + }; + global_state.int_to_ptr_map.insert(pos, (base_addr, alloc_id)); base_addr } @@ -302,7 +329,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } impl GlobalStateInner { - pub fn free_alloc_id(&mut self, dead_id: AllocId) { + pub fn free_alloc_id( + &mut self, + rng: &mut impl Rng, + dead_id: AllocId, + size: Size, + align: Align, + ) { // We can *not* remove this from `base_addr`, since the interpreter design requires that we // be able to retrieve an AllocId + offset for any memory access *before* we check if the // access is valid. Specifically, `ptr_get_alloc` is called on each attempt at a memory @@ -322,6 +355,8 @@ impl GlobalStateInner { // We can also remove it from `exposed`, since this allocation can anyway not be returned by // `alloc_id_from_addr` any more. self.exposed.remove(&dead_id); + // Also remember this address for future reuse. + self.reuse.add_addr(rng, addr, size, align) } } diff --git a/src/tools/miri/src/alloc_addresses/reuse_pool.rs b/src/tools/miri/src/alloc_addresses/reuse_pool.rs new file mode 100644 index 000000000000..8374d0ec605a --- /dev/null +++ b/src/tools/miri/src/alloc_addresses/reuse_pool.rs @@ -0,0 +1,87 @@ +//! Manages a pool of addresses that can be reused. + +use rand::Rng; + +use rustc_target::abi::{Align, Size}; + +const MAX_POOL_SIZE: usize = 64; + +// Just use fair coins, until we have evidence that other numbers are better. +const ADDR_REMEMBER_CHANCE: f64 = 0.5; +const ADDR_TAKE_CHANCE: f64 = 0.5; + +/// The pool strikes a balance between exploring more possible executions and making it more likely +/// to find bugs. The hypothesis is that bugs are more likely to occur when reuse happens for +/// allocations with the same layout, since that can trigger e.g. ABA issues in a concurrent data +/// structure. Therefore we only reuse allocations when size and alignment match exactly. +#[derive(Debug)] +pub struct ReusePool { + /// The i-th element in `pool` stores allocations of alignment `2^i`. We store these reusable + /// allocations as address-size pairs, the list must be sorted by the size. + /// + /// Each of these maps has at most MAX_POOL_SIZE elements, and since alignment is limited to + /// less than 64 different possible value, that bounds the overall size of the pool. + pool: Vec>, +} + +impl ReusePool { + pub fn new() -> Self { + ReusePool { pool: vec![] } + } + + fn subpool(&mut self, align: Align) -> &mut Vec<(u64, Size)> { + let pool_idx: usize = align.bytes().trailing_zeros().try_into().unwrap(); + if self.pool.len() <= pool_idx { + self.pool.resize(pool_idx + 1, Vec::new()); + } + &mut self.pool[pool_idx] + } + + pub fn add_addr(&mut self, rng: &mut impl Rng, addr: u64, size: Size, align: Align) { + // Let's see if we even want to remember this address. + if !rng.gen_bool(ADDR_REMEMBER_CHANCE) { + return; + } + // Determine the pool to add this to, and where in the pool to put it. + let subpool = self.subpool(align); + let pos = subpool.partition_point(|(_addr, other_size)| *other_size < size); + // Make sure the pool does not grow too big. + if subpool.len() >= MAX_POOL_SIZE { + // Pool full. Replace existing element, or last one if this would be even bigger. + let clamped_pos = pos.min(subpool.len() - 1); + subpool[clamped_pos] = (addr, size); + return; + } + // Add address to pool, at the right position. + subpool.insert(pos, (addr, size)); + } + + pub fn take_addr(&mut self, rng: &mut impl Rng, size: Size, align: Align) -> Option { + // Determine whether we'll even attempt a reuse. + if !rng.gen_bool(ADDR_TAKE_CHANCE) { + return None; + } + // Determine the pool to take this from. + let subpool = self.subpool(align); + // Let's see if we can find something of the right size. We want to find the full range of + // such items, beginning with the first, so we can't use `binary_search_by_key`. + let begin = subpool.partition_point(|(_addr, other_size)| *other_size < size); + let mut end = begin; + while let Some((_addr, other_size)) = subpool.get(end) { + if *other_size != size { + break; + } + end += 1; + } + if end == begin { + // Could not find any item of the right size. + return None; + } + // Pick a random element with the desired size. + let idx = rng.gen_range(begin..end); + // Remove it from the pool and return. + let (chosen_addr, chosen_size) = subpool.remove(idx); + debug_assert!(chosen_size >= size && chosen_addr % align.bytes() == 0); + Some(chosen_addr) + } +} diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 9e4b5fe8ad78..371dc6edda31 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -3,6 +3,8 @@ use std::iter; use std::num::NonZero; use std::time::Duration; +use rand::RngCore; + use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_hir::def::{DefKind, Namespace}; @@ -18,8 +20,6 @@ use rustc_span::{def_id::CrateNum, sym, Span, Symbol}; use rustc_target::abi::{Align, FieldIdx, FieldsShape, Size, Variants}; use rustc_target::spec::abi::Abi; -use rand::RngCore; - use crate::*; /// Indicates which kind of access is being performed. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 3a54629222d5..53f30ec2ba44 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1289,7 +1289,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { alloc_extra: &mut AllocExtra<'tcx>, (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra), size: Size, - _align: Align, + align: Align, ) -> InterpResult<'tcx> { if machine.tracked_alloc_ids.contains(&alloc_id) { machine.emit_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id)); @@ -1304,7 +1304,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { { *deallocated_at = Some(machine.current_span()); } - machine.alloc_addresses.get_mut().free_alloc_id(alloc_id); + machine.alloc_addresses.get_mut().free_alloc_id( + machine.rng.get_mut(), + alloc_id, + size, + align, + ); Ok(()) } diff --git a/src/tools/miri/tests/pass/address-reuse.rs b/src/tools/miri/tests/pass/address-reuse.rs new file mode 100644 index 000000000000..9b5c8c38b8fb --- /dev/null +++ b/src/tools/miri/tests/pass/address-reuse.rs @@ -0,0 +1,16 @@ +//! Check that we do sometimes reuse addresses. +use std::collections::HashSet; + +fn main() { + let count = 100; + let mut addrs = HashSet::::new(); + for _ in 0..count { + // We make a `Box` with a layout that's hopefully not used by tons of things inside the + // allocator itself, so that we are more likely to get reuse. (With `i32` or `usize`, on + // Windows the reuse chances are very low.) + let b = Box::new([42usize; 4]); + addrs.insert(&*b as *const [usize; 4] as usize); + } + // dbg!(addrs.len()); + assert!(addrs.len() > 1 && addrs.len() < count); +} diff --git a/src/tools/miri/tests/pass/intptrcast.rs b/src/tools/miri/tests/pass/intptrcast.rs index 42b6f433420b..370b09f512cb 100644 --- a/src/tools/miri/tests/pass/intptrcast.rs +++ b/src/tools/miri/tests/pass/intptrcast.rs @@ -67,8 +67,8 @@ fn ptr_eq_dangling() { drop(b); let b = Box::new(0); let y = &*b as *const i32; // different allocation - // They *could* be equal if memory was reused, but probably are not. - assert!(x != y); + // They *could* be equal if memory is reused... + assert!(x != y || x == y); } fn ptr_eq_out_of_bounds() { From 6f1156a9ff75305b88ce2cb43e21ee04e7a8b556 Mon Sep 17 00:00:00 2001 From: kirandevraj Date: Sun, 10 Mar 2024 01:24:35 +0530 Subject: [PATCH 18/99] fixing mir pass name to text comment --- tests/mir-opt/unnamed-fields/field_access.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mir-opt/unnamed-fields/field_access.rs b/tests/mir-opt/unnamed-fields/field_access.rs index 8024fd5015d4..70ce7c222ffb 100644 --- a/tests/mir-opt/unnamed-fields/field_access.rs +++ b/tests/mir-opt/unnamed-fields/field_access.rs @@ -1,4 +1,4 @@ -//@ unit-test: UnnamedFields +// Tests the correct handling of unnamed fields within structs and unions marked with #[repr(C)]. // EMIT_MIR field_access.foo.SimplifyCfg-initial.after.mir // EMIT_MIR field_access.bar.SimplifyCfg-initial.after.mir From 11f8866ca811628275a9e17c788462804444226f Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 11 Feb 2024 23:12:34 -0500 Subject: [PATCH 19/99] Detect truncated incr comp files --- .../rustc_query_system/src/dep_graph/serialized.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 3272a0ed1673..e7c210e86ffb 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -179,13 +179,15 @@ impl SerializedDepGraph { pub fn decode(d: &mut MemDecoder<'_>) -> SerializedDepGraph { // The last 16 bytes are the node count and edge count. debug!("position: {:?}", d.position()); - let (node_count, edge_count) = - d.with_position(d.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { + let (node_count, edge_count, graph_size) = + d.with_position(d.len() - 3 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { debug!("position: {:?}", d.position()); let node_count = IntEncodedWithFixedSize::decode(d).0 as usize; let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize; - (node_count, edge_count) + let graph_size = IntEncodedWithFixedSize::decode(d).0 as usize; + (node_count, edge_count, graph_size) }); + assert_eq!(d.len(), graph_size); debug!("position: {:?}", d.position()); debug!(?node_count, ?edge_count); @@ -491,6 +493,8 @@ impl EncoderState { debug!("position: {:?}", encoder.position()); IntEncodedWithFixedSize(node_count).encode(&mut encoder); IntEncodedWithFixedSize(edge_count).encode(&mut encoder); + let graph_size = encoder.position() + IntEncodedWithFixedSize::ENCODED_SIZE; + IntEncodedWithFixedSize(graph_size as u64).encode(&mut encoder); debug!("position: {:?}", encoder.position()); // Drop the encoder so that nothing is written after the counts. let result = encoder.finish(); From 3af28f0b7094046a190acc7e823b170694f085b9 Mon Sep 17 00:00:00 2001 From: erer1243 Date: Mon, 4 Mar 2024 16:17:23 -0500 Subject: [PATCH 20/99] Fix 32-bit overflows in LLVM composite constants --- compiler/rustc_codegen_llvm/src/common.rs | 17 ++++---- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 21 ++++------ compiler/rustc_codegen_llvm/src/type_.rs | 2 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 42 +++++++++++++++---- 4 files changed, 52 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 8173e41aff45..25cbd90460f2 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -95,11 +95,13 @@ impl<'ll> BackendTypes for CodegenCx<'ll, '_> { impl<'ll> CodegenCx<'ll, '_> { pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { - unsafe { llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint) } + let len = u64::try_from(elts.len()).expect("LLVMConstArray2 elements len overflow"); + unsafe { llvm::LLVMConstArray2(ty, elts.as_ptr(), len) } } pub fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value { - unsafe { llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint) } + let len = c_uint::try_from(elts.len()).expect("LLVMConstVector elements len overflow"); + unsafe { llvm::LLVMConstVector(elts.as_ptr(), len) } } pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value { @@ -108,8 +110,8 @@ impl<'ll> CodegenCx<'ll, '_> { pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value { unsafe { - assert_eq!(idx as c_uint as u64, idx); - let r = llvm::LLVMGetAggregateElement(v, idx as c_uint).unwrap(); + let idx = c_uint::try_from(idx).expect("LLVMGetAggregateElement index overflow"); + let r = llvm::LLVMGetAggregateElement(v, idx).unwrap(); debug!("const_get_elt(v={:?}, idx={}, r={:?})", v, idx, r); @@ -329,7 +331,7 @@ pub fn val_ty(v: &Value) -> &Type { pub fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { unsafe { let ptr = bytes.as_ptr() as *const c_char; - llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True) + llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), True) } } @@ -338,9 +340,8 @@ pub fn struct_in_context<'ll>( elts: &[&'ll Value], packed: bool, ) -> &'ll Value { - unsafe { - llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), elts.len() as c_uint, packed as Bool) - } + let len = c_uint::try_from(elts.len()).expect("LLVMConstStructInContext elements len overflow"); + unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), len, packed as Bool) } } #[inline] diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 58e980370673..d34c289887e1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -936,10 +936,16 @@ extern "C" { pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value; // Operations on composite constants - pub fn LLVMConstStringInContext( + pub fn LLVMConstArray2<'a>( + ElementTy: &'a Type, + ConstantVals: *const &'a Value, + Length: u64, + ) -> &'a Value; + pub fn LLVMArrayType2(ElementType: &Type, ElementCount: u64) -> &Type; + pub fn LLVMConstStringInContext2( C: &Context, Str: *const c_char, - Length: c_uint, + Length: size_t, DontNullTerminate: Bool, ) -> &Value; pub fn LLVMConstStructInContext<'a>( @@ -948,14 +954,6 @@ extern "C" { Count: c_uint, Packed: Bool, ) -> &'a Value; - - // FIXME: replace with LLVMConstArray2 when bumped minimal version to llvm-17 - // https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc - pub fn LLVMConstArray<'a>( - ElementTy: &'a Type, - ConstantVals: *const &'a Value, - Length: c_uint, - ) -> &'a Value; pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value; // Constant expressions @@ -1530,9 +1528,6 @@ extern "C" { /// See llvm::LLVMTypeKind::getTypeID. pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind; - // Operations on array, pointer, and vector types (sequence types) - pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type; - // Operations on all values pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); pub fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool; diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 07a4861ed738..af1bbda4d08a 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -233,7 +233,7 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type { - unsafe { llvm::LLVMRustArrayType(ty, len) } + unsafe { llvm::LLVMArrayType2(ty, len) } } } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 3e998d428ee9..d76dea6f86cc 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -10,6 +10,7 @@ #include "llvm/IR/IntrinsicsARM.h" #include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/Mangler.h" +#include "llvm/IR/Value.h" #include "llvm/Remarks/RemarkStreamer.h" #include "llvm/Remarks/RemarkSerializer.h" #include "llvm/Remarks/RemarkFormat.h" @@ -1223,14 +1224,6 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, } } -// LLVMArrayType function does not support 64-bit ElementCount -// FIXME: replace with LLVMArrayType2 when bumped minimal version to llvm-17 -// https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc -extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, - uint64_t ElementCount) { - return wrap(ArrayType::get(unwrap(ElementTy), ElementCount)); -} - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef) extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) { @@ -2114,3 +2107,36 @@ extern "C" bool LLVMRustLLVMHasZlibCompressionForDebugSymbols() { extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() { return llvm::compression::zstd::isAvailable(); } + +// Operations on composite constants. +// These are clones of LLVM api functions that will become available in future releases. +// They can be removed once Rust's minimum supported LLVM version supports them. +// See https://github.com/rust-lang/rust/issues/121868 +// See https://llvm.org/doxygen/group__LLVMCCoreValueConstantComposite.html + +// FIXME: Remove when Rust's minimum supported LLVM version reaches 19. +// https://github.com/llvm/llvm-project/commit/e1405e4f71c899420ebf8262d5e9745598419df8 +#if LLVM_VERSION_LT(19, 0) +extern "C" LLVMValueRef LLVMConstStringInContext2(LLVMContextRef C, + const char *Str, + size_t Length, + bool DontNullTerminate) { + return wrap(ConstantDataArray::getString(*unwrap(C), StringRef(Str, Length), !DontNullTerminate)); +} +#endif + +// FIXME: Remove when Rust's minimum supported LLVM version reaches 17. +// https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc +#if LLVM_VERSION_LT(17, 0) +extern "C" LLVMValueRef LLVMConstArray2(LLVMTypeRef ElementTy, + LLVMValueRef *ConstantVals, + uint64_t Length) { + ArrayRef V(unwrap(ConstantVals, Length), Length); + return wrap(ConstantArray::get(ArrayType::get(unwrap(ElementTy), Length), V)); +} + +extern "C" LLVMTypeRef LLVMArrayType2(LLVMTypeRef ElementTy, + uint64_t ElementCount) { + return wrap(ArrayType::get(unwrap(ElementTy), ElementCount)); +} +#endif From c1e68860d0a66ddf261f7e512eaaa4ba4144b28a Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 29 Feb 2024 23:34:52 +0100 Subject: [PATCH 21/99] Store pattern arity in `DeconstructedPat` Right now this is just `self.fields.len()` but that'll change in the next commit. `arity` will be useful for the `Debug` impl. --- .../rustc_pattern_analysis/src/constructor.rs | 4 ++-- compiler/rustc_pattern_analysis/src/pat.rs | 16 +++++++++++-- compiler/rustc_pattern_analysis/src/rustc.rs | 23 ++++++++++++++++--- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 69e294e47a56..2d55785cd069 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -423,7 +423,7 @@ pub enum SliceKind { } impl SliceKind { - fn arity(self) -> usize { + pub fn arity(self) -> usize { match self { FixedLen(length) => length, VarLen(prefix, suffix) => prefix + suffix, @@ -462,7 +462,7 @@ impl Slice { Slice { array_len, kind } } - pub(crate) fn arity(self) -> usize { + pub fn arity(self) -> usize { self.kind.arity() } diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index decbfa5c0cf4..cd4f057c84c2 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -26,6 +26,10 @@ impl PatId { pub struct DeconstructedPat { ctor: Constructor, fields: Vec>, + /// The number of fields in this pattern. E.g. if the pattern is `SomeStruct { field12: true, .. + /// }` this would be the total number of fields of the struct. + /// This is also the same as `self.ctor.arity(self.ty)`. + arity: usize, ty: Cx::Ty, /// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not /// correspond to a user-supplied pattern. @@ -36,16 +40,24 @@ pub struct DeconstructedPat { impl DeconstructedPat { pub fn wildcard(ty: Cx::Ty) -> Self { - DeconstructedPat { ctor: Wildcard, fields: Vec::new(), ty, data: None, uid: PatId::new() } + DeconstructedPat { + ctor: Wildcard, + fields: Vec::new(), + arity: 0, + ty, + data: None, + uid: PatId::new(), + } } pub fn new( ctor: Constructor, fields: Vec>, + arity: usize, ty: Cx::Ty, data: Cx::PatData, ) -> Self { - DeconstructedPat { ctor, fields, ty, data: Some(data), uid: PatId::new() } + DeconstructedPat { ctor, fields, arity, ty, data: Some(data), uid: PatId::new() } } pub(crate) fn is_or_pat(&self) -> bool { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 0085f0ab6566..4e9e17dc24ec 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -445,6 +445,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { let cx = self; let ty = cx.reveal_opaque_ty(pat.ty); let ctor; + let arity; let mut fields: Vec<_>; match &pat.kind { PatKind::AscribeUserType { subpattern, .. } @@ -453,9 +454,11 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; fields = vec![]; + arity = 0; } PatKind::Deref { subpattern } => { fields = vec![self.lower_pat(subpattern)]; + arity = 1; ctor = match ty.kind() { // This is a box pattern. ty::Adt(adt, ..) if adt.is_box() => Struct, @@ -467,6 +470,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { match ty.kind() { ty::Tuple(fs) => { ctor = Struct; + arity = fs.len(); fields = fs .iter() .map(|ty| cx.reveal_opaque_ty(ty)) @@ -497,6 +501,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { }; ctor = Struct; fields = vec![pat]; + arity = 1; } ty::Adt(adt, _) => { ctor = match pat.kind { @@ -507,6 +512,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { }; let variant = &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt)); + arity = variant.fields.len(); fields = cx .variant_sub_tys(ty, variant) .map(|(_, ty)| DeconstructedPat::wildcard(ty)) @@ -526,6 +532,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => Opaque(OpaqueId::new()), }; fields = vec![]; + arity = 0; } ty::Char | ty::Int(_) | ty::Uint(_) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -542,6 +549,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => Opaque(OpaqueId::new()), }; fields = vec![]; + arity = 0; } ty::Float(ty::FloatTy::F32) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -553,6 +561,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => Opaque(OpaqueId::new()), }; fields = vec![]; + arity = 0; } ty::Float(ty::FloatTy::F64) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -564,6 +573,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => Opaque(OpaqueId::new()), }; fields = vec![]; + arity = 0; } ty::Ref(_, t, _) if t.is_str() => { // We want a `&str` constant to behave like a `Deref` pattern, to be compatible @@ -574,9 +584,10 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { // subfields. // Note: `t` is `str`, not `&str`. let ty = self.reveal_opaque_ty(*t); - let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), ty, pat); + let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), 0, ty, pat); ctor = Ref; - fields = vec![subpattern] + fields = vec![subpattern]; + arity = 1; } // All constants that can be structurally matched have already been expanded // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are @@ -584,6 +595,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { _ => { ctor = Opaque(OpaqueId::new()); fields = vec![]; + arity = 0; } } } @@ -623,6 +635,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { _ => bug!("invalid type for range pattern: {}", ty.inner()), }; fields = vec![]; + arity = 0; } PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => { let array_len = match ty.kind() { @@ -639,11 +652,13 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { }; ctor = Slice(Slice::new(array_len, kind)); fields = prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)).collect(); + arity = kind.arity(); } PatKind::Or { .. } => { ctor = Or; let pats = expand_or_pat(pat); fields = pats.into_iter().map(|p| self.lower_pat(p)).collect(); + arity = fields.len(); } PatKind::Never => { // A never pattern matches all the values of its type (namely none). Moreover it @@ -651,13 +666,15 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { // `Result` which has other constructors. Hence we lower it as a wildcard. ctor = Wildcard; fields = vec![]; + arity = 0; } PatKind::Error(_) => { ctor = Opaque(OpaqueId::new()); fields = vec![]; + arity = 0; } } - DeconstructedPat::new(ctor, fields, ty, pat) + DeconstructedPat::new(ctor, fields, arity, ty, pat) } /// Convert back to a `thir::PatRangeBoundary` for diagnostic purposes. From 6ae9fa31f0588fd456cb0937c452a27006ed2810 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 29 Feb 2024 23:34:57 +0100 Subject: [PATCH 22/99] Store field indices in `DeconstructedPat` to avoid virtual wildcards --- .../src/thir/pattern/check_match.rs | 4 +- compiler/rustc_pattern_analysis/src/pat.rs | 116 ++++++++++-------- compiler/rustc_pattern_analysis/src/rustc.rs | 49 ++++---- .../rustc_pattern_analysis/src/usefulness.rs | 17 +-- 4 files changed, 102 insertions(+), 84 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 2685bae4d09c..1fe571962ed9 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -917,7 +917,9 @@ fn report_arm_reachability<'p, 'tcx>( fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { match pat.ctor() { Constructor::Wildcard => true, - Constructor::Struct | Constructor::Ref => pat.iter_fields().all(|pat| pat_is_catchall(pat)), + Constructor::Struct | Constructor::Ref => { + pat.iter_fields().all(|ipat| pat_is_catchall(&ipat.pat)) + } _ => false, } } diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index cd4f057c84c2..4cb14dd4ae1d 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -20,12 +20,18 @@ impl PatId { } } +/// A pattern with an index denoting which field it corresponds to. +pub struct IndexedPat { + pub idx: usize, + pub pat: DeconstructedPat, +} + /// Values and patterns can be represented as a constructor applied to some fields. This represents /// a pattern in this form. A `DeconstructedPat` will almost always come from user input; the only /// exception are some `Wildcard`s introduced during pattern lowering. pub struct DeconstructedPat { ctor: Constructor, - fields: Vec>, + fields: Vec>, /// The number of fields in this pattern. E.g. if the pattern is `SomeStruct { field12: true, .. /// }` this would be the total number of fields of the struct. /// This is also the same as `self.ctor.arity(self.ty)`. @@ -39,20 +45,9 @@ pub struct DeconstructedPat { } impl DeconstructedPat { - pub fn wildcard(ty: Cx::Ty) -> Self { - DeconstructedPat { - ctor: Wildcard, - fields: Vec::new(), - arity: 0, - ty, - data: None, - uid: PatId::new(), - } - } - pub fn new( ctor: Constructor, - fields: Vec>, + fields: Vec>, arity: usize, ty: Cx::Ty, data: Cx::PatData, @@ -60,6 +55,10 @@ impl DeconstructedPat { DeconstructedPat { ctor, fields, arity, ty, data: Some(data), uid: PatId::new() } } + pub fn at_index(self, idx: usize) -> IndexedPat { + IndexedPat { idx, pat: self } + } + pub(crate) fn is_or_pat(&self) -> bool { matches!(self.ctor, Or) } @@ -75,8 +74,11 @@ impl DeconstructedPat { pub fn data(&self) -> Option<&Cx::PatData> { self.data.as_ref() } + pub fn arity(&self) -> usize { + self.arity + } - pub fn iter_fields<'a>(&'a self) -> impl Iterator> { + pub fn iter_fields<'a>(&'a self) -> impl Iterator> { self.fields.iter() } @@ -85,36 +87,40 @@ impl DeconstructedPat { pub(crate) fn specialize<'a>( &'a self, other_ctor: &Constructor, - ctor_arity: usize, + other_ctor_arity: usize, ) -> SmallVec<[PatOrWild<'a, Cx>; 2]> { - let wildcard_sub_tys = || (0..ctor_arity).map(|_| PatOrWild::Wild).collect(); - match (&self.ctor, other_ctor) { - // Return a wildcard for each field of `other_ctor`. - (Wildcard, _) => wildcard_sub_tys(), + if matches!(other_ctor, PrivateUninhabited) { // Skip this column. - (_, PrivateUninhabited) => smallvec![], - // The only non-trivial case: two slices of different arity. `other_slice` is - // guaranteed to have a larger arity, so we fill the middle part with enough - // wildcards to reach the length of the new, larger slice. - ( - &Slice(self_slice @ Slice { kind: SliceKind::VarLen(prefix, suffix), .. }), - &Slice(other_slice), - ) if self_slice.arity() != other_slice.arity() => { - // Start with a slice of wildcards of the appropriate length. - let mut fields: SmallVec<[_; 2]> = wildcard_sub_tys(); - // Fill in the fields from both ends. - let new_arity = fields.len(); - for i in 0..prefix { - fields[i] = PatOrWild::Pat(&self.fields[i]); - } - for i in 0..suffix { - fields[new_arity - 1 - i] = - PatOrWild::Pat(&self.fields[self.fields.len() - 1 - i]); - } - fields - } - _ => self.fields.iter().map(PatOrWild::Pat).collect(), + return smallvec![]; } + + // Start with a slice of wildcards of the appropriate length. + let mut fields: SmallVec<[_; 2]> = (0..other_ctor_arity).map(|_| PatOrWild::Wild).collect(); + // Fill `fields` with our fields. The arities are known to be compatible. + match self.ctor { + // The only non-trivial case: two slices of different arity. `other_ctor` is guaranteed + // to have a larger arity, so we adjust the indices of the patterns in the suffix so + // that they are correctly positioned in the larger slice. + Slice(Slice { kind: SliceKind::VarLen(prefix, _), .. }) + if self.arity != other_ctor_arity => + { + for ipat in &self.fields { + let new_idx = if ipat.idx < prefix { + ipat.idx + } else { + // Adjust the indices in the suffix. + ipat.idx + other_ctor_arity - self.arity + }; + fields[new_idx] = PatOrWild::Pat(&ipat.pat); + } + } + _ => { + for ipat in &self.fields { + fields[ipat.idx] = PatOrWild::Pat(&ipat.pat); + } + } + } + fields } /// Walk top-down and call `it` in each place where a pattern occurs @@ -126,7 +132,7 @@ impl DeconstructedPat { } for p in self.iter_fields() { - p.walk(it) + p.pat.walk(it) } } } @@ -146,6 +152,11 @@ impl fmt::Debug for DeconstructedPat { }; let mut start_or_comma = || start_or_continue(", "); + let mut fields: Vec<_> = (0..self.arity).map(|_| PatOrWild::Wild).collect(); + for ipat in self.iter_fields() { + fields[ipat.idx] = PatOrWild::Pat(&ipat.pat); + } + match pat.ctor() { Struct | Variant(_) | UnionField => { Cx::write_variant_name(f, pat)?; @@ -153,7 +164,7 @@ impl fmt::Debug for DeconstructedPat { // get the names of the fields. Instead we just display everything as a tuple // struct, which should be good enough. write!(f, "(")?; - for p in pat.iter_fields() { + for p in fields { write!(f, "{}", start_or_comma())?; write!(f, "{p:?}")?; } @@ -163,25 +174,23 @@ impl fmt::Debug for DeconstructedPat { // be careful to detect strings here. However a string literal pattern will never // be reported as a non-exhaustiveness witness, so we can ignore this issue. Ref => { - let subpattern = pat.iter_fields().next().unwrap(); - write!(f, "&{:?}", subpattern) + write!(f, "&{:?}", &fields[0]) } Slice(slice) => { - let mut subpatterns = pat.iter_fields(); write!(f, "[")?; match slice.kind { SliceKind::FixedLen(_) => { - for p in subpatterns { + for p in fields { write!(f, "{}{:?}", start_or_comma(), p)?; } } SliceKind::VarLen(prefix_len, _) => { - for p in subpatterns.by_ref().take(prefix_len) { + for p in &fields[..prefix_len] { write!(f, "{}{:?}", start_or_comma(), p)?; } write!(f, "{}", start_or_comma())?; write!(f, "..")?; - for p in subpatterns { + for p in &fields[prefix_len..] { write!(f, "{}{:?}", start_or_comma(), p)?; } } @@ -196,7 +205,7 @@ impl fmt::Debug for DeconstructedPat { Str(value) => write!(f, "{value:?}"), Opaque(..) => write!(f, ""), Or => { - for pat in pat.iter_fields() { + for pat in fields { write!(f, "{}{:?}", start_or_continue(" | "), pat)?; } Ok(()) @@ -254,9 +263,10 @@ impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { /// Expand this (possibly-nested) or-pattern into its alternatives. pub(crate) fn flatten_or_pat(self) -> SmallVec<[Self; 1]> { match self { - PatOrWild::Pat(pat) if pat.is_or_pat() => { - pat.iter_fields().flat_map(|p| PatOrWild::Pat(p).flatten_or_pat()).collect() - } + PatOrWild::Pat(pat) if pat.is_or_pat() => pat + .iter_fields() + .flat_map(|ipat| PatOrWild::Pat(&ipat.pat).flatten_or_pat()) + .collect(), _ => smallvec![self], } } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 4e9e17dc24ec..b780ee66b692 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -446,7 +446,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { let ty = cx.reveal_opaque_ty(pat.ty); let ctor; let arity; - let mut fields: Vec<_>; + let fields: Vec<_>; match &pat.kind { PatKind::AscribeUserType { subpattern, .. } | PatKind::InlineConstant { subpattern, .. } => return self.lower_pat(subpattern), @@ -457,7 +457,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { arity = 0; } PatKind::Deref { subpattern } => { - fields = vec![self.lower_pat(subpattern)]; + fields = vec![self.lower_pat(subpattern).at_index(0)]; arity = 1; ctor = match ty.kind() { // This is a box pattern. @@ -471,16 +471,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { ty::Tuple(fs) => { ctor = Struct; arity = fs.len(); - fields = fs + fields = subpatterns .iter() - .map(|ty| cx.reveal_opaque_ty(ty)) - .map(|ty| DeconstructedPat::wildcard(ty)) + .map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index())) .collect(); - for pat in subpatterns { - fields[pat.field.index()] = self.lower_pat(&pat.pattern); - } } - ty::Adt(adt, args) if adt.is_box() => { + ty::Adt(adt, _) if adt.is_box() => { // The only legal patterns of type `Box` (outside `std`) are `_` and box // patterns. If we're here we can assume this is a box pattern. // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_, @@ -494,13 +490,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { // solution when we introduce generalized deref patterns. Also need to // prevent mixing of those two options. let pattern = subpatterns.into_iter().find(|pat| pat.field.index() == 0); - let pat = if let Some(pat) = pattern { - self.lower_pat(&pat.pattern) + if let Some(pat) = pattern { + fields = vec![self.lower_pat(&pat.pattern).at_index(0)]; } else { - DeconstructedPat::wildcard(self.reveal_opaque_ty(args.type_at(0))) - }; + fields = vec![]; + } ctor = Struct; - fields = vec![pat]; arity = 1; } ty::Adt(adt, _) => { @@ -513,13 +508,10 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { let variant = &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt)); arity = variant.fields.len(); - fields = cx - .variant_sub_tys(ty, variant) - .map(|(_, ty)| DeconstructedPat::wildcard(ty)) + fields = subpatterns + .iter() + .map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index())) .collect(); - for pat in subpatterns { - fields[pat.field.index()] = self.lower_pat(&pat.pattern); - } } _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty), } @@ -586,7 +578,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { let ty = self.reveal_opaque_ty(*t); let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), 0, ty, pat); ctor = Ref; - fields = vec![subpattern]; + fields = vec![subpattern.at_index(0)]; arity = 1; } // All constants that can be structurally matched have already been expanded @@ -651,13 +643,24 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { SliceKind::FixedLen(prefix.len() + suffix.len()) }; ctor = Slice(Slice::new(array_len, kind)); - fields = prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)).collect(); + fields = prefix + .iter() + .chain(suffix.iter()) + .map(|p| self.lower_pat(&*p)) + .enumerate() + .map(|(i, p)| p.at_index(i)) + .collect(); arity = kind.arity(); } PatKind::Or { .. } => { ctor = Or; let pats = expand_or_pat(pat); - fields = pats.into_iter().map(|p| self.lower_pat(p)).collect(); + fields = pats + .into_iter() + .map(|p| self.lower_pat(p)) + .enumerate() + .map(|(i, p)| p.at_index(i)) + .collect(); arity = fields.len(); } PatKind::Never => { diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index a067bf1f0c23..0834d08106f3 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1006,15 +1006,17 @@ impl<'p, Cx: TypeCx> PatStack<'p, Cx> { ctor_arity: usize, ctor_is_relevant: bool, ) -> Result, Cx::Error> { - // We pop the head pattern and push the new fields extracted from the arguments of - // `self.head()`. - let mut new_pats = self.head().specialize(ctor, ctor_arity); - if new_pats.len() != ctor_arity { + let head_pat = self.head(); + if head_pat.as_pat().is_some_and(|pat| pat.arity() > ctor_arity) { + // Arity can be smaller in case of variable-length slices, but mustn't be larger. return Err(cx.bug(format_args!( - "uncaught type error: pattern {:?} has inconsistent arity (expected arity {ctor_arity})", - self.head().as_pat().unwrap() + "uncaught type error: pattern {:?} has inconsistent arity (expected arity <= {ctor_arity})", + head_pat.as_pat().unwrap() ))); } + // We pop the head pattern and push the new fields extracted from the arguments of + // `self.head()`. + let mut new_pats = head_pat.specialize(ctor, ctor_arity); new_pats.extend_from_slice(&self.pats[1..]); // `ctor` is relevant for this row if it is the actual constructor of this row, or if the // row has a wildcard and `ctor` is relevant for wildcards. @@ -1706,7 +1708,8 @@ fn collect_pattern_usefulness<'p, Cx: TypeCx>( ) -> bool { if useful_subpatterns.contains(&pat.uid) { true - } else if pat.is_or_pat() && pat.iter_fields().any(|f| pat_is_useful(useful_subpatterns, f)) + } else if pat.is_or_pat() + && pat.iter_fields().any(|f| pat_is_useful(useful_subpatterns, &f.pat)) { // We always expand or patterns in the matrix, so we will never see the actual // or-pattern (the one with constructor `Or`) in the column. As such, it will not be From d339bdaa071ae50e20b9dbf1084df30a92c9576f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 6 Feb 2024 03:37:03 +0100 Subject: [PATCH 23/99] `DeconstructedPat.data` is always present now --- .../src/thir/pattern/check_match.rs | 8 ++++---- compiler/rustc_pattern_analysis/src/lints.rs | 2 +- compiler/rustc_pattern_analysis/src/pat.rs | 14 ++++++-------- compiler/rustc_pattern_analysis/src/rustc.rs | 8 ++++---- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 1fe571962ed9..f395bb44f574 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -420,9 +420,9 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { { let mut redundant_subpats = redundant_subpats.clone(); // Emit lints in the order in which they occur in the file. - redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span); + redundant_subpats.sort_unstable_by_key(|pat| pat.data().span); for pat in redundant_subpats { - report_unreachable_pattern(cx, arm.arm_data, pat.data().unwrap().span, None) + report_unreachable_pattern(cx, arm.arm_data, pat.data().span, None) } } } @@ -905,10 +905,10 @@ fn report_arm_reachability<'p, 'tcx>( let mut catchall = None; for (arm, is_useful) in report.arm_usefulness.iter() { if matches!(is_useful, Usefulness::Redundant) { - report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().unwrap().span, catchall) + report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().span, catchall) } if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) { - catchall = Some(arm.pat.data().unwrap().span); + catchall = Some(arm.pat.data().span); } } } diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 16530960656f..072a8e4bfe5a 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -98,7 +98,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( }; use rustc_errors::LintDiagnostic; - let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().unwrap().span, ""); + let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().span, ""); err.primary_message(decorator.msg()); decorator.decorate_lint(&mut err); err.emit(); diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 4cb14dd4ae1d..cefc1d8e3b3a 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -37,9 +37,8 @@ pub struct DeconstructedPat { /// This is also the same as `self.ctor.arity(self.ty)`. arity: usize, ty: Cx::Ty, - /// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not - /// correspond to a user-supplied pattern. - data: Option, + /// Extra data to store in a pattern. + data: Cx::PatData, /// Globally-unique id used to track usefulness at the level of subpatterns. pub(crate) uid: PatId, } @@ -52,7 +51,7 @@ impl DeconstructedPat { ty: Cx::Ty, data: Cx::PatData, ) -> Self { - DeconstructedPat { ctor, fields, arity, ty, data: Some(data), uid: PatId::new() } + DeconstructedPat { ctor, fields, arity, ty, data, uid: PatId::new() } } pub fn at_index(self, idx: usize) -> IndexedPat { @@ -69,10 +68,9 @@ impl DeconstructedPat { pub fn ty(&self) -> &Cx::Ty { &self.ty } - /// Returns the extra data stored in a pattern. Returns `None` if the pattern is a wildcard that - /// does not correspond to a user-supplied pattern. - pub fn data(&self) -> Option<&Cx::PatData> { - self.data.as_ref() + /// Returns the extra data stored in a pattern. + pub fn data(&self) -> &Cx::PatData { + &self.data } pub fn arity(&self) -> usize { self.arity diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index b780ee66b692..53a32d3237e6 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -904,10 +904,10 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty()); let overlaps: Vec<_> = overlaps_with .iter() - .map(|pat| pat.data().unwrap().span) + .map(|pat| pat.data().span) .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span }) .collect(); - let pat_span = pat.data().unwrap().span; + let pat_span = pat.data().span; self.tcx.emit_node_span_lint( lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, self.match_lint_level, @@ -927,7 +927,7 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { gap: IntRange, gapped_with: &[&crate::pat::DeconstructedPat], ) { - let Some(&thir_pat) = pat.data() else { return }; + let &thir_pat = pat.data(); let thir::PatKind::Range(range) = &thir_pat.kind else { return }; // Only lint when the left range is an exclusive range. if range.end != rustc_hir::RangeEnd::Excluded { @@ -975,7 +975,7 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { gap_with: gapped_with .iter() .map(|pat| errors::GappedRange { - span: pat.data().unwrap().span, + span: pat.data().span, gap: gap_as_pat.clone(), first_range: thir_pat.clone(), }) From cfbc1b96d5ea70b8f6dea8fa86450d40c72c7036 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 8 Mar 2024 13:19:35 +0000 Subject: [PATCH 24/99] Enable creating backtraces via -Ztreat-err-as-bug when stashing errors --- compiler/rustc_errors/src/lib.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 76b44f73f47b..be1caa0aa1ba 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -768,13 +768,10 @@ impl DiagCtxt { format!("invalid level in `stash_diagnostic`: {:?}", diag.level), ); } - Error => { - // This `unchecked_error_guaranteed` is valid. It is where the - // `ErrorGuaranteed` for stashed errors originates. See - // `DiagCtxtInner::drop`. - #[allow(deprecated)] - Some(ErrorGuaranteed::unchecked_error_guaranteed()) - } + // We delay a bug here so that `-Ztreat-err-as-bug -Zeagerly-emit-delayed-bugs` + // can be used to create a backtrace at the stashing site insted of whenever the + // diagnostic context is dropped and thus delayed bugs are emitted. + Error => Some(self.span_delayed_bug(span, "stashing {key:?}")), DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag), ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow | Expect(_) => None, From e1e9d38f5851694d9901cc5e71d84d5e7404b555 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 7 Mar 2024 18:01:45 -0800 Subject: [PATCH 25/99] Rename `wasm32-wasi-preview1-threads` to `wasm32-wasip1-threads` This commit renames the current `wasm32-wasi-preview1-threads` target to `wasm32-wasip1-threads`. The need for this rename is a bit unfortunate as the previous name was chosen in an attempt to be future-compatible with other WASI targets. Originally this target was proposed to be `wasm32-wasi-threads`, and that's what was originally implemented in wasi-sdk as well. After discussion though and with the plans for the upcoming component-model target (now named `wasm32-wasip2`) the "preview1" naming was chosen for the threads-based target. The WASI subgroup later decided that it was time to drop the "preview" terminology and recommends "pX" instead, hence previous PRs to add `wasm32-wasip2` and rename `wasm32-wasi` to `wasm32-wasip1`. So, with all that history, the "proper name" for this target is different than its current name, so one way or another a rename is required. This PR proposes renaming this target cold-turkey, unlike `wasm32-wasi` which is having a long transition period to change its name. The threads-based target is predicted to see only a fraction of the traffic of `wasm32-wasi` due to the unstable nature of the WASI threads proposal itself. While I was here I updated the in-tree documentation in the target spec file itself as most of the documentation was copied from the original WASI target and wasn't as applicable to this target. Also, as an aside, I can at least try to apologize for all the naming confusion here, but this is hopefully the last WASI-related rename. --- compiler/rustc_target/src/spec/mod.rs | 2 +- .../targets/wasm32_wasi_preview1_threads.rs | 139 ------------------ .../src/spec/targets/wasm32_wasip1_threads.rs | 74 ++++++++++ .../host-x86_64/dist-various-2/Dockerfile | 4 +- .../build-wasi-threads-toolchain.sh | 2 +- src/doc/rustc/src/SUMMARY.md | 2 +- src/doc/rustc/src/platform-support.md | 2 +- ...w1-threads.md => wasm32-wasip1-threads.md} | 38 ++--- .../src/platform-support/wasm32-wasip1.md | 2 +- src/tools/build-manifest/src/main.rs | 2 +- .../stack-protector-target-support.rs | 3 +- tests/assembly/targets/targets-elf.rs | 6 +- 12 files changed, 107 insertions(+), 169 deletions(-) delete mode 100644 compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs create mode 100644 compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs rename src/doc/rustc/src/platform-support/{wasm32-wasi-preview1-threads.md => wasm32-wasip1-threads.md} (83%) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 6552810d1134..373246588c90 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1581,7 +1581,7 @@ supported_targets! { ("wasm32-wasi", wasm32_wasi), ("wasm32-wasip1", wasm32_wasip1), ("wasm32-wasip2", wasm32_wasip2), - ("wasm32-wasi-preview1-threads", wasm32_wasi_preview1_threads), + ("wasm32-wasip1-threads", wasm32_wasip1_threads), ("wasm64-unknown-unknown", wasm64_unknown_unknown), ("thumbv6m-none-eabi", thumbv6m_none_eabi), diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs deleted file mode 100644 index 26bdb1cbebef..000000000000 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs +++ /dev/null @@ -1,139 +0,0 @@ -//! The `wasm32-wasi-preview1-threads` target is a new and still (as of July 2023) an -//! experimental target. The definition in this file is likely to be tweaked -//! over time and shouldn't be relied on too much. -//! -//! The `wasi-threads` target is a proposal to define a standardized set of syscalls -//! that WebAssembly files can interoperate with. This set of syscalls is -//! intended to empower WebAssembly binaries with native capabilities such as -//! threads, filesystem access, network access, etc. -//! -//! You can see more about the proposal at . -//! -//! The Rust target definition here is interesting in a few ways. We want to -//! serve two use cases here with this target: -//! -//! * First, we want Rust usage of the target to be as hassle-free as possible, -//! ideally avoiding the need to configure and install a local wasm32-wasi-preview1-threads -//! toolchain. -//! -//! * Second, one of the primary use cases of LLVM's new wasm backend and the -//! wasm support in LLD is that any compiled language can interoperate with -//! any other. To that the `wasm32-wasi-preview1-threads` target is the first with a viable C -//! standard library and sysroot common definition, so we want Rust and C/C++ -//! code to interoperate when compiled to `wasm32-unknown-unknown`. -//! -//! You'll note, however, that the two goals above are somewhat at odds with one -//! another. To attempt to solve both use cases in one go we define a target -//! that (ab)uses the `crt-static` target feature to indicate which one you're -//! in. -//! -//! ## No interop with C required -//! -//! By default the `crt-static` target feature is enabled, and when enabled -//! this means that the bundled version of `libc.a` found in `liblibc.rlib` -//! is used. This isn't intended really for interoperation with a C because it -//! may be the case that Rust's bundled C library is incompatible with a -//! foreign-compiled C library. In this use case, though, we use `rust-lld` and -//! some copied crt startup object files to ensure that you can download the -//! wasi target for Rust and you're off to the races, no further configuration -//! necessary. -//! -//! All in all, by default, no external dependencies are required. You can -//! compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, -//! reliably interoperate with C code in this mode (yet). -//! -//! ## Interop with C required -//! -//! For the second goal we repurpose the `target-feature` flag, meaning that -//! you'll need to do a few things to have C/Rust code interoperate. -//! -//! 1. All Rust code needs to be compiled with `-C target-feature=-crt-static`, -//! indicating that the bundled C standard library in the Rust sysroot will -//! not be used. -//! -//! 2. If you're using rustc to build a linked artifact then you'll need to -//! specify `-C linker` to a `clang` binary that supports -//! `wasm32-wasi-preview1-threads` and is configured with the `wasm32-wasi-preview1-threads` sysroot. This -//! will cause Rust code to be linked against the libc.a that the specified -//! `clang` provides. -//! -//! 3. If you're building a staticlib and integrating Rust code elsewhere, then -//! compiling with `-C target-feature=-crt-static` is all you need to do. -//! -//! You can configure the linker via Cargo using the -//! `CARGO_TARGET_WASM32_WASI_LINKER` env var. Be sure to also set -//! `CC_wasm32-wasi-preview1-threads` if any crates in the dependency graph are using the `cc` -//! crate. -//! -//! ## Remember, this is all in flux -//! -//! The wasi target is **very** new in its specification. It's likely going to -//! be a long effort to get it standardized and stable. We'll be following it as -//! best we can with this target. Don't start relying on too much here unless -//! you know what you're getting in to! - -use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; - -pub fn target() -> Target { - let mut options = base::wasm::options(); - - options.os = "wasi".into(); - - options.add_pre_link_args( - LinkerFlavor::WasmLld(Cc::No), - &["--import-memory", "--export-memory", "--shared-memory"], - ); - options.add_pre_link_args( - LinkerFlavor::WasmLld(Cc::Yes), - &[ - "--target=wasm32-wasi-threads", - "-Wl,--import-memory", - "-Wl,--export-memory,", - "-Wl,--shared-memory", - ], - ); - - options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); - options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); - - // FIXME: Figure out cases in which WASM needs to link with a native toolchain. - options.link_self_contained = LinkSelfContainedDefault::True; - - // Right now this is a bit of a workaround but we're currently saying that - // the target by default has a static crt which we're taking as a signal - // for "use the bundled crt". If that's turned off then the system's crt - // will be used, but this means that default usage of this target doesn't - // need an external compiler but it's still interoperable with an external - // compiler if configured correctly. - options.crt_static_default = true; - options.crt_static_respected = true; - - // Allow `+crt-static` to create a "cdylib" output which is just a wasm file - // without a main function. - options.crt_static_allows_dylibs = true; - - // WASI's `sys::args::init` function ignores its arguments; instead, - // `args::args()` makes the WASI API calls itself. - options.main_needs_argc_argv = false; - - // And, WASI mangles the name of "main" to distinguish between different - // signatures. - options.entry_name = "__main_void".into(); - - options.singlethread = false; - options.features = "+atomics,+bulk-memory,+mutable-globals".into(); - - Target { - llvm_target: "wasm32-wasi".into(), - metadata: crate::spec::TargetMetadata { - description: None, - tier: None, - host_tools: None, - std: None, - }, - pointer_width: 32, - data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(), - arch: "wasm32".into(), - options, - } -} diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs new file mode 100644 index 000000000000..c592b944d44a --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs @@ -0,0 +1,74 @@ +//! The `wasm32-wasip1-threads` target is an extension of the `wasm32-wasip1` +//! target where threads are enabled by default for all crates. This target +//! should be considered "in flux" as WASI itself has moved on from "p1" to "p2" +//! now and threads in "p2" are still under heavy design. +//! +//! This target inherits most of the other aspects of `wasm32-wasip1`. +//! +//! Historically this target was known as `wasm32-wasi-preview1-threads`. + +use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; + +pub fn target() -> Target { + let mut options = base::wasm::options(); + + options.os = "wasi".into(); + + options.add_pre_link_args( + LinkerFlavor::WasmLld(Cc::No), + &["--import-memory", "--export-memory", "--shared-memory"], + ); + options.add_pre_link_args( + LinkerFlavor::WasmLld(Cc::Yes), + &[ + "--target=wasm32-wasip1-threads", + "-Wl,--import-memory", + "-Wl,--export-memory,", + "-Wl,--shared-memory", + ], + ); + + options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); + options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); + + // FIXME: Figure out cases in which WASM needs to link with a native toolchain. + options.link_self_contained = LinkSelfContainedDefault::True; + + // Right now this is a bit of a workaround but we're currently saying that + // the target by default has a static crt which we're taking as a signal + // for "use the bundled crt". If that's turned off then the system's crt + // will be used, but this means that default usage of this target doesn't + // need an external compiler but it's still interoperable with an external + // compiler if configured correctly. + options.crt_static_default = true; + options.crt_static_respected = true; + + // Allow `+crt-static` to create a "cdylib" output which is just a wasm file + // without a main function. + options.crt_static_allows_dylibs = true; + + // WASI's `sys::args::init` function ignores its arguments; instead, + // `args::args()` makes the WASI API calls itself. + options.main_needs_argc_argv = false; + + // And, WASI mangles the name of "main" to distinguish between different + // signatures. + options.entry_name = "__main_void".into(); + + options.singlethread = false; + options.features = "+atomics,+bulk-memory,+mutable-globals".into(); + + Target { + llvm_target: "wasm32-wasi".into(), + metadata: crate::spec::TargetMetadata { + description: None, + tier: None, + host_tools: None, + std: None, + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(), + arch: "wasm32".into(), + options, + } +} diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index e90141bb9a96..d7571d7e3df3 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -113,7 +113,7 @@ ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,wasm32-wasi ENV TARGETS=$TARGETS,wasm32-wasip1 -ENV TARGETS=$TARGETS,wasm32-wasi-preview1-threads +ENV TARGETS=$TARGETS,wasm32-wasip1-threads ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,x86_64-pc-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 @@ -138,7 +138,7 @@ RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \ --set target.wasm32-wasi.wasi-root=/wasm32-wasip1 \ --set target.wasm32-wasip1.wasi-root=/wasm32-wasip1 \ - --set target.wasm32-wasi-preview1-threads.wasi-root=/wasm32-wasi-preview1-threads \ + --set target.wasm32-wasip1-threads.wasi-root=/wasm32-wasip1-threads \ --musl-root-armv7=/musl-armv7 ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh index 689fe52863e0..8f802eeaa8c0 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh @@ -16,7 +16,7 @@ make -j$(nproc) \ NM="$bin/llvm-nm" \ AR="$bin/llvm-ar" \ THREAD_MODEL=posix \ - INSTALL_DIR=/wasm32-wasi-preview1-threads \ + INSTALL_DIR=/wasm32-wasip1-threads \ install cd .. diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 5a0168e30cbb..12a421f3c454 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -62,7 +62,7 @@ - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) - [wasm32-wasip1](platform-support/wasm32-wasip1.md) - - [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md) + - [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md) - [wasm32-wasip2](platform-support/wasm32-wasip2.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 537a724579eb..44f0aa2ccf06 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -190,7 +190,7 @@ target | std | notes `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename]) [`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI -[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads +[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads `x86_64-apple-ios` | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` diff --git a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md similarity index 83% rename from src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md rename to src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md index b719cb53aba4..519e9cc7cc49 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md @@ -1,12 +1,16 @@ -# `wasm32-wasi-preview1-threads` +# `wasm32-wasip1-threads` **Tier: 2** -The `wasm32-wasi-preview1-threads` target is a new and still (as of July 2023) an -experimental target. This target is an extension to `wasm32-wasi-preview1` target, +The `wasm32-wasip1-threads` target is a new and still (as of July 2023) an +experimental target. This target is an extension to `wasm32-wasip1` target, originally known as `wasm32-wasi`. It extends the original target with a -standardized set of syscalls that are intended to empower WebAssembly binaries with -native multi threading capabilities. +standardized set of syscalls that are intended to empower WebAssembly binaries +with native multi threading capabilities. + +> **Note**: Prior to March 2024 this target was known as +> `wasm32-wasi-preview1-threads`, and even longer before that it was known as +> `wasm32-wasi-threads`. [wasi-threads]: https://github.com/WebAssembly/wasi-threads [threads]: https://github.com/WebAssembly/threads @@ -26,11 +30,11 @@ This target is cross-compiled. The target supports `std` fully. The Rust target definition here is interesting in a few ways. We want to serve two use cases here with this target: * First, we want Rust usage of the target to be as hassle-free as possible, - ideally avoiding the need to configure and install a local wasm32-wasi-preview1-threads + ideally avoiding the need to configure and install a local wasm32-wasip1-threads toolchain. * Second, one of the primary use cases of LLVM's new wasm backend and the wasm support in LLD is that any compiled language can interoperate with - any other. The `wasm32-wasi-preview1-threads` target is the first with a viable C + any other. The `wasm32-wasip1-threads` target is the first with a viable C standard library and sysroot common definition, so we want Rust and C/C++ code to interoperate when compiled to `wasm32-unknown-unknown`. @@ -49,7 +53,7 @@ some copied crt startup object files to ensure that you can download the wasi target for Rust and you're off to the races, no further configuration necessary. All in all, by default, no external dependencies are required. You can -compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, +compile `wasm32-wasip1-threads` binaries straight out of the box. You can't, however, reliably interoperate with C code in this mode (yet). ### Interop with C required For the second goal we repurpose the `target-feature` flag, meaning that @@ -59,18 +63,18 @@ you'll need to do a few things to have C/Rust code interoperate. not be used. 2. If you're using rustc to build a linked artifact then you'll need to specify `-C linker` to a `clang` binary that supports - `wasm32-wasi-preview1-threads` and is configured with the `wasm32-wasi-preview1-threads` sysroot. This + `wasm32-wasip1-threads` and is configured with the `wasm32-wasip1-threads` sysroot. This will cause Rust code to be linked against the libc.a that the specified `clang` provides. 3. If you're building a staticlib and integrating Rust code elsewhere, then compiling with `-C target-feature=-crt-static` is all you need to do. All in all, by default, no external dependencies are required. You can -compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, +compile `wasm32-wasip1-threads` binaries straight out of the box. You can't, however, reliably interoperate with C code in this mode (yet). -Also note that at this time the `wasm32-wasi-preview1-threads` target assumes the +Also note that at this time the `wasm32-wasip1-threads` target assumes the presence of other merged wasm proposals such as (with their LLVM feature flags): * [Bulk memory] - `+bulk-memory` @@ -106,7 +110,7 @@ https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-20 and specify path to *wasi-root* `.cargo/config.toml` ```toml -[target.wasm32-wasi-preview1-threads] +[target.wasm32-wasip1-threads] wasi-root = ".../wasi-libc/sysroot" ``` @@ -118,13 +122,13 @@ After that users can build this by adding it to the `target` list in From Rust Nightly 1.71.1 (2023-08-03) on the artifacts are shipped pre-compiled: ```text -rustup target add wasm32-wasi-preview1-threads --toolchain nightly +rustup target add wasm32-wasip1-threads --toolchain nightly ``` Rust programs can be built for that target: ```text -rustc --target wasm32-wasi-preview1-threads your-code.rs +rustc --target wasm32-wasip1-threads your-code.rs ``` ## Cross-compilation @@ -133,7 +137,7 @@ This target can be cross-compiled from any hosts. ## Testing -Currently testing is not well supported for `wasm32-wasi-preview1-threads` and the +Currently testing is not well supported for `wasm32-wasip1-threads` and the Rust project doesn't run any tests for this target. However the UI testsuite can be run manually following this instructions: @@ -141,8 +145,8 @@ manually following this instructions: or another engine that supports `wasi-threads` is installed and can be found in the `$PATH` env variable. 1. Clone master branch. 2. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1. -3. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests. +3. Run `./x.py test --target wasm32-wasip1-threads tests/ui` and save the list of failed tests. 4. Checkout branch with your changes. 5. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1. -6. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests. +6. Run `./x.py test --target wasm32-wasip1-threads tests/ui` and save the list of failed tests. 7. For both lists of failed tests run `cat list | sort > sorted_list` and compare it with `diff sorted_list1 sorted_list2`. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index 71f8d281bc88..a1ca81d1fecb 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -49,7 +49,7 @@ this target are: This target is cross-compiled. The target includes support for `std` itself, but not all of the standard library works. For example spawning a thread will -always return an error (see the `wasm32-wasi-preview1-threads` target for +always return an error (see the `wasm32-wasip1-threads` target for example). Another example is that spawning a process will always return an error. Operations such as opening a file, however, will be implemented by calling WASI-defined APIs. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 067bf4054da0..eab9138b8fed 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -149,7 +149,7 @@ static TARGETS: &[&str] = &[ "wasm32-unknown-unknown", "wasm32-wasi", "wasm32-wasip1", - "wasm32-wasi-preview1-threads", + "wasm32-wasip1-threads", "x86_64-apple-darwin", "x86_64-apple-ios", "x86_64-fortanix-unknown-sgx", diff --git a/tests/assembly/stack-protector/stack-protector-target-support.rs b/tests/assembly/stack-protector/stack-protector-target-support.rs index df8a0dce40b2..74a609dcdcc1 100644 --- a/tests/assembly/stack-protector/stack-protector-target-support.rs +++ b/tests/assembly/stack-protector/stack-protector-target-support.rs @@ -151,7 +151,7 @@ //@ [r72] needs-llvm-components: webassembly //@ [r73] compile-flags:--target wasm32-wasip1 //@ [r73] needs-llvm-components: webassembly -//@ [r74] compile-flags:--target wasm32-wasi-preview1-threads +//@ [r74] compile-flags:--target wasm32-wasip1-threads //@ [r74] needs-llvm-components: webassembly //@ [r75] compile-flags:--target x86_64-apple-ios //@ [r75] needs-llvm-components: x86 @@ -179,7 +179,6 @@ //@ compile-flags: -C opt-level=2 #![crate_type = "lib"] - #![feature(no_core, lang_items)] #![crate_type = "lib"] #![no_core] diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index b0f8ebd5920b..bda77b5f09b8 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -492,9 +492,9 @@ //@ revisions: wasm32_wasip1 //@ [wasm32_wasip1] compile-flags: --target wasm32-wasip1 //@ [wasm32_wasip1] needs-llvm-components: webassembly -//@ revisions: wasm32_wasi_preview1_threads -//@ [wasm32_wasi_preview1_threads] compile-flags: --target wasm32-wasi-preview1-threads -//@ [wasm32_wasi_preview1_threads] needs-llvm-components: webassembly +//@ revisions: wasm32_wasip1_threads +//@ [wasm32_wasip1_threads] compile-flags: --target wasm32-wasip1-threads +//@ [wasm32_wasip1_threads] needs-llvm-components: webassembly //@ revisions: wasm32_wasip2 //@ [wasm32_wasip2] compile-flags: --target wasm32-wasip2 //@ [wasm32_wasip2] needs-llvm-components: webassembly From b66d7f58277db90f6dd7d5a7229ab1903343dfaa Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:00:45 -0400 Subject: [PATCH 26/99] Update books --- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/reference b/src/doc/reference index 3417f866932c..5afb503a4c1e 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 3417f866932cb1c09c6be0f31d2a02ee01b4b95d +Subproject commit 5afb503a4c1ea3c84370f8f4c08a1cddd1cdf6ad diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 57f1e708f5d5..e09309970945 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 57f1e708f5d5850562bc385aaf610e6af14d6ec8 +Subproject commit e093099709456e6fd74fecd2505fdf49a2471c10 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 7b0ef5b0bea5..8a5d647f19b0 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 7b0ef5b0bea5e3ce3b9764aa5754a60e2cc05c52 +Subproject commit 8a5d647f19b08998612146b1cb2ca47083db63e0 From 779ac6951f8bd03e1fa5214d1637de9e5e5e8a7f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 10 Mar 2024 15:35:35 +0000 Subject: [PATCH 27/99] Update Windows platform support --- .../src/spec/targets/i686_pc_windows_msvc.rs | 2 +- .../src/spec/targets/x86_64_pc_windows_msvc.rs | 2 +- src/doc/rustc/src/platform-support.md | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs index eb44520ad9bf..becd2fd7afb2 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs @@ -24,7 +24,7 @@ pub fn target() -> Target { Target { llvm_target: "i686-pc-windows-msvc".into(), metadata: crate::spec::TargetMetadata { - description: Some("32-bit MSVC (Windows 7+)".into()), + description: Some("32-bit MSVC (Windows 10+)".into()), tier: Some(1), host_tools: Some(true), std: Some(true), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs index da4dc9bf9499..3ef3e5114e68 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-msvc".into(), metadata: crate::spec::TargetMetadata { - description: Some("64-bit MSVC (Windows 7+)".into()), + description: Some("64-bit MSVC (Windows 10+)".into()), tier: Some(1), host_tools: Some(true), std: Some(true), diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 537a724579eb..a155bb423af7 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -33,12 +33,12 @@ All tier 1 targets with host tools support the full standard library. target | notes -------|------- `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) -`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI] -`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI] +`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+) [^windows-support] [^x86_32-floats-return-ABI] +`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+) [^windows-support] [^x86_32-floats-return-ABI] `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI] `x86_64-apple-darwin` | 64-bit macOS (10.12+, Sierra+) -`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 7+) [^windows-support] -`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 7+) [^windows-support] +`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 10+) [^windows-support] +`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 10+) [^windows-support] `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+) [^windows-support]: Only Windows 10 currently undergoes automated testing. Earlier versions of Windows rely on testing and support from the community. @@ -292,7 +292,6 @@ target | std | host | notes [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI] [`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86, restricted to Pentium `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) [^x86_32-floats-return-ABI] -`i686-pc-windows-msvc` | * | | 32-bit Windows XP support [^x86_32-floats-return-ABI] [`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [^x86_32-floats-return-ABI] `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku [^x86_32-floats-return-ABI] [`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [^x86_32-floats-return-ABI] @@ -369,7 +368,6 @@ target | std | host | notes [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS | [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | -`x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl 1.2.3 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku From aeec0d1269eebb5319d798d403bd3c78f2303a23 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 11 Mar 2024 18:12:51 +0000 Subject: [PATCH 28/99] Update /NODEFAUTLIB comment for msvc --- .../src/spec/base/windows_msvc.rs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/windows_msvc.rs b/compiler/rustc_target/src/spec/base/windows_msvc.rs index e3cf9757219e..bd0318f31832 100644 --- a/compiler/rustc_target/src/spec/base/windows_msvc.rs +++ b/compiler/rustc_target/src/spec/base/windows_msvc.rs @@ -17,15 +17,19 @@ pub fn opts() -> TargetOptions { crt_static_allows_dylibs: true, crt_static_respected: true, requires_uwtable: true, - // Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC - // as there's been trouble in the past of linking the C++ standard - // library required by LLVM. This likely needs to happen one day, but - // in general Windows is also a more controlled environment than - // Unix, so it's not necessarily as critical that this be implemented. + // We don't pass the /NODEFAULTLIB flag to the linker on MSVC + // as that prevents linker directives embedded in object files from + // including other necessary libraries. // - // Note that there are also some licensing worries about statically - // linking some libraries which require a specific agreement, so it may - // not ever be possible for us to pass this flag. + // For example, msvcrt.lib embeds a linker directive like: + // /DEFAULTLIB:vcruntime.lib /DEFAULTLIB:ucrt.lib + // So that vcruntime.lib and ucrt.lib are included when the entry point + // in msvcrt.lib is used. Using /NODEFAULTLIB would mean having to + // manually add those two libraries and potentially further dependencies + // they bring in. + // + // See also https://learn.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-170#lib + // for documention on including library dependencies in C/C++ code. no_default_libraries: false, has_thread_local: true, From 2a1d4dd6e3204e24467143d228107058032b2962 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 10 Mar 2024 22:32:55 -0400 Subject: [PATCH 29/99] Don't ICE when non-self part of trait goal is constrained in new solver --- .../src/solve/assembly/mod.rs | 4 +++- ...rmalize-self-type-constrains-trait-args.rs | 24 +++++++++++++++++++ ...ize-self-type-constrains-trait-args.stderr | 11 +++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.rs create mode 100644 tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.stderr diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 3be53a6591dc..9c7fa5216d76 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -274,7 +274,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let goal = goal.with(self.tcx(), goal.predicate.with_self_ty(self.tcx(), normalized_self_ty)); - debug_assert_eq!(goal, self.resolve_vars_if_possible(goal)); + // 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); let mut candidates = vec![]; diff --git a/tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.rs b/tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.rs new file mode 100644 index 000000000000..0ece8f8321ce --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.rs @@ -0,0 +1,24 @@ +//@ check-pass + +// This goal is also possible w/ a GAT, but lazy_type_alias +// makes the behavior a bit more readable. +#![feature(lazy_type_alias)] +//~^ WARN the feature `lazy_type_alias` is incomplete + +struct Wr(T); +trait Foo {} +impl Foo for Wr {} + +type Alias = (T,) + where Wr: Foo; + +fn hello() where Alias: Into<(T,)>, Wr: Foo {} + +fn main() { + // When calling `hello`, proving `Alias: Into<(?0,)>` will require + // normalizing the self type of the goal. This will emit the where + // clause `Wr: Foo`, which constrains `?0` in both the self type + // *and* the non-self part of the goal. That used to trigger a debug + // assertion. + hello::<_>(); +} diff --git a/tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.stderr b/tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.stderr new file mode 100644 index 000000000000..5554f0ccc0aa --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.stderr @@ -0,0 +1,11 @@ +warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/normalize-self-type-constrains-trait-args.rs:5:12 + | +LL | #![feature(lazy_type_alias)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #112792 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + From 0b6b3307fcd9faef6d32d09c5674795600e95a35 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 11 Mar 2024 19:09:25 +0000 Subject: [PATCH 30/99] Move project -> normalize, move normalize tests --- .../{ => normalize}/normalize-async-closure-in-trait.rs | 0 .../traits/next-solver/{ => normalize}/normalize-param-env-1.rs | 0 .../traits/next-solver/{ => normalize}/normalize-param-env-2.rs | 0 .../next-solver/{ => normalize}/normalize-param-env-2.stderr | 0 .../traits/next-solver/{ => normalize}/normalize-param-env-3.rs | 0 .../next-solver/{ => normalize}/normalize-param-env-4.next.stderr | 0 .../traits/next-solver/{ => normalize}/normalize-param-env-4.rs | 0 .../next-solver/{ => normalize}/normalize-path-for-method.rs | 0 .../next-solver/{ => normalize}/normalize-rcvr-for-inherent.rs | 0 .../next-solver/{ => normalize}/normalize-region-obligations.rs | 0 .../{ => normalize}/normalize-self-type-constrains-trait-args.rs | 0 .../normalize-self-type-constrains-trait-args.stderr | 0 .../{ => normalize}/normalize-type-outlives-in-param-env.rs | 0 .../traits/next-solver/{ => normalize}/normalize-type-outlives.rs | 0 .../ui/traits/next-solver/{ => normalize}/normalize-unsize-rhs.rs | 0 .../next-solver/{ => normalize}/normalized-const-built-in-op.rs | 0 .../{projection => normalize}/param-env-trait-candidate-1.rs | 0 .../{projection => normalize}/param-env-trait-candidate-2.rs | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/traits/next-solver/{ => normalize}/normalize-async-closure-in-trait.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-param-env-1.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-param-env-2.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-param-env-2.stderr (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-param-env-3.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-param-env-4.next.stderr (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-param-env-4.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-path-for-method.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-rcvr-for-inherent.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-region-obligations.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-self-type-constrains-trait-args.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-self-type-constrains-trait-args.stderr (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-type-outlives-in-param-env.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-type-outlives.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalize-unsize-rhs.rs (100%) rename tests/ui/traits/next-solver/{ => normalize}/normalized-const-built-in-op.rs (100%) rename tests/ui/traits/next-solver/{projection => normalize}/param-env-trait-candidate-1.rs (100%) rename tests/ui/traits/next-solver/{projection => normalize}/param-env-trait-candidate-2.rs (100%) diff --git a/tests/ui/traits/next-solver/normalize-async-closure-in-trait.rs b/tests/ui/traits/next-solver/normalize/normalize-async-closure-in-trait.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-async-closure-in-trait.rs rename to tests/ui/traits/next-solver/normalize/normalize-async-closure-in-trait.rs diff --git a/tests/ui/traits/next-solver/normalize-param-env-1.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-1.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-1.rs rename to tests/ui/traits/next-solver/normalize/normalize-param-env-1.rs diff --git a/tests/ui/traits/next-solver/normalize-param-env-2.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-2.rs rename to tests/ui/traits/next-solver/normalize/normalize-param-env-2.rs diff --git a/tests/ui/traits/next-solver/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-2.stderr rename to tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr diff --git a/tests/ui/traits/next-solver/normalize-param-env-3.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-3.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-3.rs rename to tests/ui/traits/next-solver/normalize/normalize-param-env-3.rs diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-4.next.stderr rename to tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-4.rs rename to tests/ui/traits/next-solver/normalize/normalize-param-env-4.rs diff --git a/tests/ui/traits/next-solver/normalize-path-for-method.rs b/tests/ui/traits/next-solver/normalize/normalize-path-for-method.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-path-for-method.rs rename to tests/ui/traits/next-solver/normalize/normalize-path-for-method.rs diff --git a/tests/ui/traits/next-solver/normalize-rcvr-for-inherent.rs b/tests/ui/traits/next-solver/normalize/normalize-rcvr-for-inherent.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-rcvr-for-inherent.rs rename to tests/ui/traits/next-solver/normalize/normalize-rcvr-for-inherent.rs diff --git a/tests/ui/traits/next-solver/normalize-region-obligations.rs b/tests/ui/traits/next-solver/normalize/normalize-region-obligations.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-region-obligations.rs rename to tests/ui/traits/next-solver/normalize/normalize-region-obligations.rs diff --git a/tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.rs b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.rs rename to tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs diff --git a/tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.stderr b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr similarity index 100% rename from tests/ui/traits/next-solver/normalize-self-type-constrains-trait-args.stderr rename to tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr diff --git a/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs b/tests/ui/traits/next-solver/normalize/normalize-type-outlives-in-param-env.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs rename to tests/ui/traits/next-solver/normalize/normalize-type-outlives-in-param-env.rs diff --git a/tests/ui/traits/next-solver/normalize-type-outlives.rs b/tests/ui/traits/next-solver/normalize/normalize-type-outlives.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-type-outlives.rs rename to tests/ui/traits/next-solver/normalize/normalize-type-outlives.rs diff --git a/tests/ui/traits/next-solver/normalize-unsize-rhs.rs b/tests/ui/traits/next-solver/normalize/normalize-unsize-rhs.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-unsize-rhs.rs rename to tests/ui/traits/next-solver/normalize/normalize-unsize-rhs.rs diff --git a/tests/ui/traits/next-solver/normalized-const-built-in-op.rs b/tests/ui/traits/next-solver/normalize/normalized-const-built-in-op.rs similarity index 100% rename from tests/ui/traits/next-solver/normalized-const-built-in-op.rs rename to tests/ui/traits/next-solver/normalize/normalized-const-built-in-op.rs diff --git a/tests/ui/traits/next-solver/projection/param-env-trait-candidate-1.rs b/tests/ui/traits/next-solver/normalize/param-env-trait-candidate-1.rs similarity index 100% rename from tests/ui/traits/next-solver/projection/param-env-trait-candidate-1.rs rename to tests/ui/traits/next-solver/normalize/param-env-trait-candidate-1.rs diff --git a/tests/ui/traits/next-solver/projection/param-env-trait-candidate-2.rs b/tests/ui/traits/next-solver/normalize/param-env-trait-candidate-2.rs similarity index 100% rename from tests/ui/traits/next-solver/projection/param-env-trait-candidate-2.rs rename to tests/ui/traits/next-solver/normalize/param-env-trait-candidate-2.rs From 0e354c98a82df53df04e49c5d0f7107c03482d42 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Wed, 28 Feb 2024 20:13:43 +0100 Subject: [PATCH 31/99] [bootstrap] Move the split-debuginfo setting to the per-target section --- config.example.toml | 40 +++++++++++++-------- src/bootstrap/src/core/builder.rs | 7 ++-- src/bootstrap/src/core/config/config.rs | 42 ++++++++++++++++++----- src/bootstrap/src/utils/change_tracker.rs | 5 +++ 4 files changed, 69 insertions(+), 25 deletions(-) diff --git a/config.example.toml b/config.example.toml index ddcd0ec02e0d..f94553dd63f7 100644 --- a/config.example.toml +++ b/config.example.toml @@ -543,23 +543,15 @@ # FIXME(#61117): Some tests fail when this option is enabled. #debuginfo-level-tests = 0 -# Should rustc be build with split debuginfo? Default is platform dependent. -# Valid values are the same as those accepted by `-C split-debuginfo` -# (`off`/`unpacked`/`packed`). +# Should rustc and the standard library be built with split debuginfo? Default +# is platform dependent. # -# On Linux, split debuginfo is disabled by default. +# This field is deprecated, use `target..split-debuginfo` instead. # -# On Apple platforms, unpacked split debuginfo is used by default. Unpacked -# debuginfo does not run `dsymutil`, which packages debuginfo from disparate -# object files into a single `.dSYM` file. `dsymutil` adds time to builds for -# no clear benefit, and also makes it more difficult for debuggers to find -# debug info. The compiler currently defaults to running `dsymutil` to preserve -# its historical default, but when compiling the compiler itself, we skip it by -# default since we know it's safe to do so in that case. +# The value specified here is only used when targeting the `build.build` triple, +# and is overridden by `target..split-debuginfo` if specified. # -# On Windows platforms, packed debuginfo is the only supported option, -# producing a `.pdb` file. -#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked } +#split-debuginfo = see target..split-debuginfo # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) #backtrace = true @@ -773,6 +765,26 @@ # Setting this will override the `use-lld` option for Rust code when targeting MSVC. #linker = "cc" (path) +# Should rustc and the standard library be built with split debuginfo? Default +# is platform dependent. +# +# Valid values are the same as those accepted by `-C split-debuginfo` +# (`off`/`unpacked`/`packed`). +# +# On Linux, split debuginfo is disabled by default. +# +# On Apple platforms, unpacked split debuginfo is used by default. Unpacked +# debuginfo does not run `dsymutil`, which packages debuginfo from disparate +# object files into a single `.dSYM` file. `dsymutil` adds time to builds for +# no clear benefit, and also makes it more difficult for debuggers to find +# debug info. The compiler currently defaults to running `dsymutil` to preserve +# its historical default, but when compiling the compiler itself, we skip it by +# default since we know it's safe to do so in that case. +# +# On Windows platforms, packed debuginfo is the only supported option, +# producing a `.pdb` file. +#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked } + # Path to the `llvm-config` binary of the installation of a custom LLVM to link # against. Note that if this is specified we don't compile LLVM at all for this # target. diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 5e5d6d024ee8..d35880a31d8e 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1731,15 +1731,16 @@ impl<'a> Builder<'a> { }, ); + let split_debuginfo = self.config.split_debuginfo(target); let split_debuginfo_is_stable = target.contains("linux") || target.contains("apple") - || (target.is_msvc() && self.config.rust_split_debuginfo == SplitDebuginfo::Packed) - || (target.is_windows() && self.config.rust_split_debuginfo == SplitDebuginfo::Off); + || (target.is_msvc() && split_debuginfo == SplitDebuginfo::Packed) + || (target.is_windows() && split_debuginfo == SplitDebuginfo::Off); if !split_debuginfo_is_stable { rustflags.arg("-Zunstable-options"); } - match self.config.rust_split_debuginfo { + match split_debuginfo { SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"), SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"), SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"), diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index ae5169e93839..1504866ef747 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -256,7 +256,7 @@ pub struct Config { pub rust_debuginfo_level_std: DebuginfoLevel, pub rust_debuginfo_level_tools: DebuginfoLevel, pub rust_debuginfo_level_tests: DebuginfoLevel, - pub rust_split_debuginfo: SplitDebuginfo, + pub rust_split_debuginfo_for_build_triple: Option, // FIXME: Deprecated field. Remove in Q3'24. pub rust_rpath: bool, pub rust_strip: bool, pub rust_frame_pointers: bool, @@ -574,6 +574,7 @@ pub struct Target { pub ranlib: Option, pub default_linker: Option, pub linker: Option, + pub split_debuginfo: Option, pub sanitizers: Option, pub profiler: Option, pub rpath: Option, @@ -1133,6 +1134,7 @@ define_config! { ranlib: Option = "ranlib", default_linker: Option = "default-linker", linker: Option = "linker", + split_debuginfo: Option = "split-debuginfo", llvm_config: Option = "llvm-config", llvm_has_rust_patches: Option = "llvm-has-rust-patches", llvm_filecheck: Option = "llvm-filecheck", @@ -1627,11 +1629,18 @@ impl Config { debuginfo_level_tools = debuginfo_level_tools_toml; debuginfo_level_tests = debuginfo_level_tests_toml; - config.rust_split_debuginfo = split_debuginfo + config.rust_split_debuginfo_for_build_triple = split_debuginfo .as_deref() .map(SplitDebuginfo::from_str) - .map(|v| v.expect("invalid value for rust.split_debuginfo")) - .unwrap_or(SplitDebuginfo::default_for_platform(config.build)); + .map(|v| v.expect("invalid value for rust.split-debuginfo")); + + if config.rust_split_debuginfo_for_build_triple.is_some() { + println!( + "WARNING: specifying `rust.split-debuginfo` is deprecated, use `target.{}.split-debuginfo` instead", + config.build + ); + } + optimize = optimize_toml; omit_git_hash = omit_git_hash_toml; config.rust_new_symbol_mangling = new_symbol_mangling; @@ -1853,10 +1862,11 @@ impl Config { if let Some(ref s) = cfg.llvm_filecheck { target.llvm_filecheck = Some(config.src.join(s)); } - target.llvm_libunwind = cfg - .llvm_libunwind - .as_ref() - .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")); + target.llvm_libunwind = cfg.llvm_libunwind.as_ref().map(|v| { + v.parse().unwrap_or_else(|_| { + panic!("failed to parse target.{triple}.llvm-libunwind") + }) + }); if let Some(s) = cfg.no_std { target.no_std = s; } @@ -1893,6 +1903,12 @@ impl Config { }).collect()); } + target.split_debuginfo = cfg.split_debuginfo.as_ref().map(|v| { + v.parse().unwrap_or_else(|_| { + panic!("invalid value for target.{triple}.split-debuginfo") + }) + }); + config.target_config.insert(TargetSelection::from_user(&triple), target); } } @@ -2291,6 +2307,16 @@ impl Config { }) } + pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo { + self.target_config + .get(&target) + .and_then(|t| t.split_debuginfo) + .or_else(|| { + if self.build == target { self.rust_split_debuginfo_for_build_triple } else { None } + }) + .unwrap_or_else(|| SplitDebuginfo::default_for_platform(target)) + } + pub fn submodules(&self, rust_info: &GitInfo) -> bool { self.submodules.unwrap_or(rust_info.is_managed_git_subrepository()) } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 85dfe45111fa..14c1dc073069 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -151,4 +151,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "New option `rust.llvm-bitcode-linker` that will build the llvm-bitcode-linker.", }, + ChangeInfo { + change_id: 121754, + severity: ChangeSeverity::Warning, + summary: "`rust.split-debuginfo` has been moved to `target..split-debuginfo` and its default value is determined for each target individually.", + }, ]; From f614eaea2c4b626c19d7e82ec9d9bcf85b14a58b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 11 Mar 2024 19:41:40 +0000 Subject: [PATCH 32/99] Remove some unnecessary allow(incomplete_features) --- .../ui/async-await/in-trait/early-bound-2.rs | 2 - .../async-await/in-trait/fn-not-async-err.rs | 2 - .../in-trait/fn-not-async-err.stderr | 4 +- .../async-await/in-trait/fn-not-async-err2.rs | 2 - .../async-await/in-trait/generics-mismatch.rs | 2 - .../in-trait/generics-mismatch.stderr | 2 +- .../ui/async-await/in-trait/implied-bounds.rs | 2 - tests/ui/async-await/in-trait/issue-102138.rs | 2 - tests/ui/async-await/in-trait/issue-102219.rs | 2 - tests/ui/async-await/in-trait/issue-102310.rs | 2 - tests/ui/async-await/in-trait/issue-104678.rs | 2 - tests/ui/async-await/in-trait/nested-rpit.rs | 2 - .../auxiliary/generics_of_parent.rs | 1 - .../generics_of_parent_impl_trait.rs | 1 - .../auxiliary/anon_const_non_local.rs | 1 - .../auxiliary/const_evaluatable_lib.rs | 1 - .../cross_crate_predicate.stderr | 8 +- .../auxiliary/const_generic_issues_lib.rs | 1 - ...ent_generics_of_encoding_impl_trait.stderr | 2 +- .../auxiliary/closure-in-foreign-crate.rs | 1 - .../ui/dyn-star/auxiliary/dyn-star-foreign.rs | 1 - tests/ui/dyn-star/no-implicit-dyn-star.stderr | 2 +- .../issue-90014-tait2.rs | 1 - .../issue-90014-tait2.stderr | 2 +- .../impl-trait/in-trait/deep-match-works.rs | 1 - .../in-trait/default-body-type-err-2.rs | 2 - .../in-trait/default-body-type-err-2.stderr | 2 +- .../in-trait/default-body-with-rpit.rs | 2 - tests/ui/impl-trait/in-trait/default-body.rs | 2 - tests/ui/impl-trait/in-trait/early.rs | 2 - tests/ui/impl-trait/in-trait/encode.rs | 2 - tests/ui/impl-trait/in-trait/issue-102301.rs | 2 - .../method-signature-matches.lt.stderr | 4 +- .../method-signature-matches.mismatch.stderr | 4 +- ...od-signature-matches.mismatch_async.stderr | 4 +- .../in-trait/method-signature-matches.rs | 2 - .../method-signature-matches.too_few.stderr | 2 +- .../method-signature-matches.too_many.stderr | 2 +- tests/ui/impl-trait/in-trait/nested-rpitit.rs | 1 - .../ui/impl-trait/in-trait/opaque-in-impl.rs | 2 - tests/ui/impl-trait/in-trait/reveal.rs | 1 - tests/ui/impl-trait/in-trait/success.rs | 1 - tests/ui/impl-trait/in-trait/wf-bounds.rs | 2 - tests/ui/impl-trait/in-trait/wf-bounds.stderr | 12 +- tests/ui/impl-trait/in-trait/where-clause.rs | 2 - tests/ui/lazy-type-alias/auxiliary/lazy.rs | 1 - ...has-lazy-type-aliases.locally_eager.stderr | 2 +- ...-has-lazy-type-aliases.locally_lazy.stderr | 2 +- .../issue-103052-2.rs | 2 - .../issue-103052-2.stderr | 4 +- .../coerce-in-base-expr.rs | 1 - .../issue-96878.rs | 1 - .../lifetime-update.rs | 1 - .../lifetime-update.stderr | 2 +- .../type-generic-update.rs | 1 - .../type-generic-update.stderr | 4 +- .../primitives/numbers.current.stderr | 228 +++++++++--------- .../primitives/numbers.next.stderr | 228 +++++++++--------- .../ui/transmutability/primitives/numbers.rs | 1 - tests/ui/transmutability/unions/boolish.rs | 1 - tests/ui/type-alias-impl-trait/issue-65384.rs | 1 - .../type-alias-impl-trait/issue-65384.stderr | 2 +- 62 files changed, 261 insertions(+), 323 deletions(-) diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs index c25835c68dd5..33da7d828c79 100644 --- a/tests/ui/async-await/in-trait/early-bound-2.rs +++ b/tests/ui/async-await/in-trait/early-bound-2.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - pub trait Foo { #[allow(async_fn_in_trait)] async fn foo(&mut self); diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs index dab100b2e22d..a67f7fd182c5 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs @@ -1,7 +1,5 @@ //@ edition: 2021 -#![allow(incomplete_features)] - trait MyTrait { async fn foo(&self) -> i32; } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr index 8260cd5271ee..d8a5ff8b1684 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.stderr +++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr @@ -1,11 +1,11 @@ error: method should be `async` or return a future, but it is synchronous - --> $DIR/fn-not-async-err.rs:10:5 + --> $DIR/fn-not-async-err.rs:8:5 | LL | fn foo(&self) -> i32 { | ^^^^^^^^^^^^^^^^^^^^ | note: this method is `async` so it expects a future to be returned - --> $DIR/fn-not-async-err.rs:6:5 + --> $DIR/fn-not-async-err.rs:4:5 | LL | async fn foo(&self) -> i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs index 983d650764e9..0af1e8a66b31 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err2.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs @@ -1,8 +1,6 @@ //@ edition: 2021 //@ check-pass -#![allow(incomplete_features)] - use std::future::Future; trait MyTrait { diff --git a/tests/ui/async-await/in-trait/generics-mismatch.rs b/tests/ui/async-await/in-trait/generics-mismatch.rs index 1f7095ae72b5..d3d1284982a9 100644 --- a/tests/ui/async-await/in-trait/generics-mismatch.rs +++ b/tests/ui/async-await/in-trait/generics-mismatch.rs @@ -1,7 +1,5 @@ //@ edition: 2021 -#![allow(incomplete_features)] - trait Foo { async fn foo(); } diff --git a/tests/ui/async-await/in-trait/generics-mismatch.stderr b/tests/ui/async-await/in-trait/generics-mismatch.stderr index 5f7aeb17117b..c0357dc7f3e6 100644 --- a/tests/ui/async-await/in-trait/generics-mismatch.stderr +++ b/tests/ui/async-await/in-trait/generics-mismatch.stderr @@ -1,5 +1,5 @@ error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo` - --> $DIR/generics-mismatch.rs:10:18 + --> $DIR/generics-mismatch.rs:8:18 | LL | trait Foo { | --- diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs index eda4cf5647f9..72ae0ce68a2f 100644 --- a/tests/ui/async-await/in-trait/implied-bounds.rs +++ b/tests/ui/async-await/in-trait/implied-bounds.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition: 2021 -#![allow(incomplete_features)] - trait TcpStack { type Connection<'a>: Sized where Self: 'a; fn connect<'a>(&'a self) -> Self::Connection<'a>; diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs index fde5f36f39c0..ffb23fcc0da9 100644 --- a/tests/ui/async-await/in-trait/issue-102138.rs +++ b/tests/ui/async-await/in-trait/issue-102138.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - use std::future::Future; async fn yield_now() {} diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs index 954e9e8bc5d9..e373b17db4f4 100644 --- a/tests/ui/async-await/in-trait/issue-102219.rs +++ b/tests/ui/async-await/in-trait/issue-102219.rs @@ -2,8 +2,6 @@ //@ edition:2021 //@ check-pass -#![allow(incomplete_features)] - trait T { #[allow(async_fn_in_trait)] async fn foo(); diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs index ea0646edd17c..daaafba56bf7 100644 --- a/tests/ui/async-await/in-trait/issue-102310.rs +++ b/tests/ui/async-await/in-trait/issue-102310.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - pub trait SpiDevice { #[allow(async_fn_in_trait)] async fn transaction(&mut self); diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs index 5265c4486a17..e64315157b2d 100644 --- a/tests/ui/async-await/in-trait/issue-104678.rs +++ b/tests/ui/async-await/in-trait/issue-104678.rs @@ -1,8 +1,6 @@ //@ edition:2021 //@ check-pass -#![allow(incomplete_features)] - use std::future::Future; pub trait Pool { type Conn; diff --git a/tests/ui/async-await/in-trait/nested-rpit.rs b/tests/ui/async-await/in-trait/nested-rpit.rs index 3a6b9f3760c8..789b751fcc90 100644 --- a/tests/ui/async-await/in-trait/nested-rpit.rs +++ b/tests/ui/async-await/in-trait/nested-rpit.rs @@ -1,8 +1,6 @@ //@ edition: 2021 //@ check-pass -#![allow(incomplete_features)] - use std::future::Future; use std::marker::PhantomData; diff --git a/tests/ui/const-generics/auxiliary/generics_of_parent.rs b/tests/ui/const-generics/auxiliary/generics_of_parent.rs index 5c2b1f4bddf8..5009fe469853 100644 --- a/tests/ui/const-generics/auxiliary/generics_of_parent.rs +++ b/tests/ui/const-generics/auxiliary/generics_of_parent.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] // library portion of regression test for #87674 pub struct Foo([(); N + 1]) diff --git a/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs b/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs index cd5b8161d08b..a66ce817be5e 100644 --- a/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs +++ b/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] // library portion of testing that `impl Trait<{ expr }>` doesnt // ice because of a `DefKind::TyParam` parent diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs index 97be074933d9..8779e20a2af6 100644 --- a/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] pub struct Foo; diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs index 15d618caef4b..9890e46e4453 100644 --- a/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] pub fn test1() -> [u8; std::mem::size_of::() - 1] where diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr index 3a7f3cd0ba00..921314f0c504 100644 --- a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr @@ -6,7 +6,7 @@ LL | let _ = const_evaluatable_lib::test1::(); | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + --> $DIR/auxiliary/const_evaluatable_lib.rs:5:10 | LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] | ----- required by a bound in this function @@ -22,7 +22,7 @@ LL | let _ = const_evaluatable_lib::test1::(); | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + --> $DIR/auxiliary/const_evaluatable_lib.rs:3:27 | LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` @@ -35,7 +35,7 @@ LL | let _ = const_evaluatable_lib::test1::(); | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + --> $DIR/auxiliary/const_evaluatable_lib.rs:5:10 | LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] | ----- required by a bound in this function @@ -51,7 +51,7 @@ LL | let _ = const_evaluatable_lib::test1::(); | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + --> $DIR/auxiliary/const_evaluatable_lib.rs:3:27 | LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` diff --git a/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs b/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs index 6a10ee267df9..21e6b344586f 100644 --- a/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs +++ b/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] // All of these three items must be in `lib2` to reproduce the error diff --git a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr index 989be74d1b0d..5bef6f3c795e 100644 --- a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr +++ b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr @@ -5,7 +5,7 @@ LL | generics_of_parent_impl_trait::foo([()]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `foo` | note: required by a bound in `foo` - --> $DIR/auxiliary/generics_of_parent_impl_trait.rs:6:48 + --> $DIR/auxiliary/generics_of_parent_impl_trait.rs:5:48 | LL | pub fn foo(foo: impl Into<[(); N + 1]>) { | ^^^^^ required by this bound in `foo` diff --git a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs index 411707133a88..8adf3ba433d9 100644 --- a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs +++ b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs @@ -1,6 +1,5 @@ #![crate_type = "lib"] #![feature(const_closures, const_trait_impl, effects)] -#![allow(incomplete_features)] pub const fn test() { let cl = const || {}; diff --git a/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs b/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs index 7673c7936783..ce892088f500 100644 --- a/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs +++ b/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs @@ -1,5 +1,4 @@ #![feature(dyn_star)] -#![allow(incomplete_features)] use std::fmt::Display; diff --git a/tests/ui/dyn-star/no-implicit-dyn-star.stderr b/tests/ui/dyn-star/no-implicit-dyn-star.stderr index bea334a8a69a..d1d3da9ca702 100644 --- a/tests/ui/dyn-star/no-implicit-dyn-star.stderr +++ b/tests/ui/dyn-star/no-implicit-dyn-star.stderr @@ -10,7 +10,7 @@ LL | dyn_star_foreign::require_dyn_star_display(1usize); found type `usize` = help: `usize` implements `Display`, `#[feature(dyn_star)]` is likely not enabled; that feature it is currently incomplete note: function defined here - --> $DIR/auxiliary/dyn-star-foreign.rs:6:8 + --> $DIR/auxiliary/dyn-star-foreign.rs:5:8 | LL | pub fn require_dyn_star_display(_: dyn* Display) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.rs b/tests/ui/generic-associated-types/issue-90014-tait2.rs index 4ba32011c0d6..ef54a89aaae5 100644 --- a/tests/ui/generic-associated-types/issue-90014-tait2.rs +++ b/tests/ui/generic-associated-types/issue-90014-tait2.rs @@ -6,7 +6,6 @@ //@ error-pattern: expected generic lifetime parameter, found `'a` #![feature(type_alias_impl_trait)] -#![allow(incomplete_features)] use std::future::Future; diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.stderr index 58390032d92d..be6f4272ce18 100644 --- a/tests/ui/generic-associated-types/issue-90014-tait2.stderr +++ b/tests/ui/generic-associated-types/issue-90014-tait2.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'a` - --> $DIR/issue-90014-tait2.rs:27:9 + --> $DIR/issue-90014-tait2.rs:26:9 | LL | type Fut<'a> = impl Future; | -- this generic parameter must be used with a generic lifetime parameter diff --git a/tests/ui/impl-trait/in-trait/deep-match-works.rs b/tests/ui/impl-trait/in-trait/deep-match-works.rs index 3978b909ed53..02fe5b0e19bf 100644 --- a/tests/ui/impl-trait/in-trait/deep-match-works.rs +++ b/tests/ui/impl-trait/in-trait/deep-match-works.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(lint_reasons)] -#![allow(incomplete_features)] pub struct Wrapper(T); diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs index 9cfac8954305..5deafe5c65ff 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs @@ -1,7 +1,5 @@ //@ edition:2021 -#![allow(incomplete_features)] - pub trait Foo { async fn woopsie_async(&self) -> String { 42 diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr index 9fa73d817ca9..856c92217b92 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/default-body-type-err-2.rs:7:9 + --> $DIR/default-body-type-err-2.rs:5:9 | LL | async fn woopsie_async(&self) -> String { | ------ expected `String` because of return type diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs index 508826e2f77a..c1a78bc23885 100644 --- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs @@ -1,8 +1,6 @@ //@ edition:2021 //@ check-pass -#![allow(incomplete_features)] - use std::fmt::Debug; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs index 631ee2b08434..5674507ad12c 100644 --- a/tests/ui/impl-trait/in-trait/default-body.rs +++ b/tests/ui/impl-trait/in-trait/default-body.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - use std::fmt::Debug; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/early.rs b/tests/ui/impl-trait/in-trait/early.rs index 21d629b3ca7f..294be02ad8d7 100644 --- a/tests/ui/impl-trait/in-trait/early.rs +++ b/tests/ui/impl-trait/in-trait/early.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - pub trait Foo { #[allow(async_fn_in_trait)] async fn bar<'a: 'a>(&'a mut self); diff --git a/tests/ui/impl-trait/in-trait/encode.rs b/tests/ui/impl-trait/in-trait/encode.rs index 8c6a0fdb813f..84dc617cba06 100644 --- a/tests/ui/impl-trait/in-trait/encode.rs +++ b/tests/ui/impl-trait/in-trait/encode.rs @@ -1,8 +1,6 @@ //@ build-pass //@ compile-flags: --crate-type=lib -#![allow(incomplete_features)] - trait Foo { fn bar() -> impl Sized; } diff --git a/tests/ui/impl-trait/in-trait/issue-102301.rs b/tests/ui/impl-trait/in-trait/issue-102301.rs index 2e2a38a29b2b..afd7bf6b1ae7 100644 --- a/tests/ui/impl-trait/in-trait/issue-102301.rs +++ b/tests/ui/impl-trait/in-trait/issue-102301.rs @@ -1,7 +1,5 @@ //@ check-pass -#![allow(incomplete_features)] - trait Foo { fn foo>(self) -> impl Foo; } diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr index 59ffea6fb9f0..2231205327cb 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr @@ -1,5 +1,5 @@ error[E0053]: method `early` has an incompatible type for trait - --> $DIR/method-signature-matches.rs:57:27 + --> $DIR/method-signature-matches.rs:55:27 | LL | fn early<'late, T>(_: &'late ()) {} | - ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | fn early<'late, T>(_: &'late ()) {} | expected this type parameter | note: type in trait - --> $DIR/method-signature-matches.rs:52:28 + --> $DIR/method-signature-matches.rs:50:28 | LL | fn early<'early, T>(x: &'early T) -> impl Sized; | ^^^^^^^^^ diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr index f8980828b89e..ec2a126865d5 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr @@ -1,5 +1,5 @@ error[E0053]: method `owo` has an incompatible type for trait - --> $DIR/method-signature-matches.rs:13:15 + --> $DIR/method-signature-matches.rs:11:15 | LL | fn owo(_: u8) {} | ^^ @@ -8,7 +8,7 @@ LL | fn owo(_: u8) {} | help: change the parameter type to match the trait: `()` | note: type in trait - --> $DIR/method-signature-matches.rs:8:15 + --> $DIR/method-signature-matches.rs:6:15 | LL | fn owo(x: ()) -> impl Sized; | ^^ diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr index a6fb1a200e69..4d3e64e8050f 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr @@ -1,5 +1,5 @@ error[E0053]: method `owo` has an incompatible type for trait - --> $DIR/method-signature-matches.rs:24:21 + --> $DIR/method-signature-matches.rs:22:21 | LL | async fn owo(_: u8) {} | ^^ @@ -8,7 +8,7 @@ LL | async fn owo(_: u8) {} | help: change the parameter type to match the trait: `()` | note: type in trait - --> $DIR/method-signature-matches.rs:19:21 + --> $DIR/method-signature-matches.rs:17:21 | LL | async fn owo(x: ()) {} | ^^ diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.rs b/tests/ui/impl-trait/in-trait/method-signature-matches.rs index e6ab932e18e8..e44425d72283 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.rs +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.rs @@ -1,8 +1,6 @@ //@ edition: 2021 //@ revisions: mismatch mismatch_async too_many too_few lt -#![allow(incomplete_features)] - #[cfg(mismatch)] trait Uwu { fn owo(x: ()) -> impl Sized; diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr index 0b26e039e6b2..799d476ab23a 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr @@ -1,5 +1,5 @@ error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 - --> $DIR/method-signature-matches.rs:46:5 + --> $DIR/method-signature-matches.rs:44:5 | LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; | ---------------- trait requires 3 parameters diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr index 9226e1f8b983..e8eac9468a8d 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr @@ -1,5 +1,5 @@ error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 - --> $DIR/method-signature-matches.rs:35:28 + --> $DIR/method-signature-matches.rs:33:28 | LL | fn calm_down_please() -> impl Sized; | ------------------------------------ trait requires 0 parameters diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit.rs b/tests/ui/impl-trait/in-trait/nested-rpitit.rs index b19f378cdc16..91fb5331f769 100644 --- a/tests/ui/impl-trait/in-trait/nested-rpitit.rs +++ b/tests/ui/impl-trait/in-trait/nested-rpitit.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(lint_reasons)] -#![allow(incomplete_features)] use std::fmt::Display; use std::ops::Deref; diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl.rs b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs index b0279168fde7..f69f93b92197 100644 --- a/tests/ui/impl-trait/in-trait/opaque-in-impl.rs +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs @@ -1,7 +1,5 @@ //@ check-pass -#![allow(incomplete_features)] - use std::fmt::Debug; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/reveal.rs b/tests/ui/impl-trait/in-trait/reveal.rs index a63e7c457d4b..f949077a1317 100644 --- a/tests/ui/impl-trait/in-trait/reveal.rs +++ b/tests/ui/impl-trait/in-trait/reveal.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(lint_reasons)] -#![allow(incomplete_features)] pub trait Foo { fn f() -> Box; diff --git a/tests/ui/impl-trait/in-trait/success.rs b/tests/ui/impl-trait/in-trait/success.rs index 750804f79206..c99291def034 100644 --- a/tests/ui/impl-trait/in-trait/success.rs +++ b/tests/ui/impl-trait/in-trait/success.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(lint_reasons)] -#![allow(incomplete_features)] use std::fmt::Display; diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.rs b/tests/ui/impl-trait/in-trait/wf-bounds.rs index f1e372b196ae..5c34cd037b5c 100644 --- a/tests/ui/impl-trait/in-trait/wf-bounds.rs +++ b/tests/ui/impl-trait/in-trait/wf-bounds.rs @@ -1,7 +1,5 @@ // issue #101663 -#![allow(incomplete_features)] - use std::fmt::Display; trait Wf { diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.stderr index 7d42659d81ed..634557094ced 100644 --- a/tests/ui/impl-trait/in-trait/wf-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/wf-bounds.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/wf-bounds.rs:14:22 + --> $DIR/wf-bounds.rs:12:22 | LL | fn nya() -> impl Wf>; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -9,14 +9,14 @@ note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/wf-bounds.rs:17:23 + --> $DIR/wf-bounds.rs:15:23 | LL | fn nya2() -> impl Wf<[u8]>; | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` note: required by an implicit `Sized` bound in `Wf` - --> $DIR/wf-bounds.rs:7:10 + --> $DIR/wf-bounds.rs:5:10 | LL | trait Wf { | ^ required by the implicit `Sized` requirement on this type parameter in `Wf` @@ -26,7 +26,7 @@ LL | trait Wf { | ++++++++ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/wf-bounds.rs:20:44 + --> $DIR/wf-bounds.rs:18:44 | LL | fn nya3() -> impl Wf<(), Output = impl Wf>>; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -36,14 +36,14 @@ note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/wf-bounds.rs:23:26 + --> $DIR/wf-bounds.rs:21:26 | LL | fn nya4() -> impl Wf>; | ^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `NeedsDisplay` - --> $DIR/wf-bounds.rs:11:24 + --> $DIR/wf-bounds.rs:9:24 | LL | struct NeedsDisplay(T); | ^^^^^^^ required by this bound in `NeedsDisplay` diff --git a/tests/ui/impl-trait/in-trait/where-clause.rs b/tests/ui/impl-trait/in-trait/where-clause.rs index e502f67c2b7e..3ab3d1496944 100644 --- a/tests/ui/impl-trait/in-trait/where-clause.rs +++ b/tests/ui/impl-trait/in-trait/where-clause.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition: 2021 -#![allow(incomplete_features)] - use std::fmt::Debug; trait Foo { diff --git a/tests/ui/lazy-type-alias/auxiliary/lazy.rs b/tests/ui/lazy-type-alias/auxiliary/lazy.rs index caa7999b4f71..2b678226a8ac 100644 --- a/tests/ui/lazy-type-alias/auxiliary/lazy.rs +++ b/tests/ui/lazy-type-alias/auxiliary/lazy.rs @@ -1,4 +1,3 @@ #![feature(lazy_type_alias)] -#![allow(incomplete_features)] pub type Alias = Option; diff --git a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr index fdc5bae15379..887b9e36008e 100644 --- a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr +++ b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr @@ -5,7 +5,7 @@ LL | let _: lazy::Alias; | ^^^^^^ the trait `Copy` is not implemented for `String` | note: required by a bound in `lazy::Alias` - --> $DIR/auxiliary/lazy.rs:4:19 + --> $DIR/auxiliary/lazy.rs:3:19 | LL | pub type Alias = Option; | ^^^^ required by this bound in `Alias` diff --git a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr index fdc5bae15379..887b9e36008e 100644 --- a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr +++ b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr @@ -5,7 +5,7 @@ LL | let _: lazy::Alias; | ^^^^^^ the trait `Copy` is not implemented for `String` | note: required by a bound in `lazy::Alias` - --> $DIR/auxiliary/lazy.rs:4:19 + --> $DIR/auxiliary/lazy.rs:3:19 | LL | pub type Alias = Option; | ^^^^ required by this bound in `Alias` diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs index 1933a68c2216..37bd0ce06f0b 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - mod child { trait Main { fn main() -> impl std::process::Termination; diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr index b17700ec6325..f1f53e300abf 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `Something: Termination` is not satisfied - --> $DIR/issue-103052-2.rs:11:22 + --> $DIR/issue-103052-2.rs:9:22 | LL | fn main() -> Something { | ^^^^^^^^^ the trait `Termination` is not implemented for `Something` | note: required by a bound in `Main::{synthetic#0}` - --> $DIR/issue-103052-2.rs:5:27 + --> $DIR/issue-103052-2.rs:3:27 | LL | fn main() -> impl std::process::Termination; | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{synthetic#0}` diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs index 02915a5dc372..2ff571a66155 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(type_changing_struct_update)] -#![allow(incomplete_features)] use std::any::Any; diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs index 15907bc2ddbf..a15312f1119b 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(type_changing_struct_update)] -#![allow(incomplete_features)] use std::borrow::Cow; use std::marker::PhantomData; diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs index df2fef55dd2d..cc0795ff49a7 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs @@ -1,5 +1,4 @@ #![feature(type_changing_struct_update)] -#![allow(incomplete_features)] #[derive(Clone)] struct Machine<'a, S> { diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr index 8ae7691a4848..5aae82769ab8 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr @@ -1,5 +1,5 @@ error[E0597]: `s` does not live long enough - --> $DIR/lifetime-update.rs:20:17 + --> $DIR/lifetime-update.rs:19:17 | LL | let s = String::from("hello"); | - binding `s` declared here diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs index dae1241d35a5..7e8a0e50fdf3 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs @@ -1,5 +1,4 @@ #![feature(type_changing_struct_update)] -#![allow(incomplete_features)] struct Machine<'a, S, M> { state: S, diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr index f31b311c732d..88779c8005c2 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/type-generic-update.rs:46:11 + --> $DIR/type-generic-update.rs:45:11 | LL | ..m1 | ^^ expected `Machine<'_, i32, f64>`, found `Machine<'_, f64, f64>` @@ -8,7 +8,7 @@ LL | ..m1 found struct `Machine<'_, f64, _>` error[E0308]: mismatched types - --> $DIR/type-generic-update.rs:51:11 + --> $DIR/type-generic-update.rs:50:11 | LL | ..m1 | ^^ expected `Machine<'_, i32, i32>`, found `Machine<'_, f64, f64>` diff --git a/tests/ui/transmutability/primitives/numbers.current.stderr b/tests/ui/transmutability/primitives/numbers.current.stderr index 009e377af99a..7a80e444149d 100644 --- a/tests/ui/transmutability/primitives/numbers.current.stderr +++ b/tests/ui/transmutability/primitives/numbers.current.stderr @@ -1,11 +1,11 @@ error[E0277]: `i8` cannot be safely transmuted into `i16` - --> $DIR/numbers.rs:65:40 + --> $DIR/numbers.rs:64:40 | LL | assert::is_transmutable::< i8, i16>(); | ^^^ The size of `i8` is smaller than the size of `i16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -14,13 +14,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` - --> $DIR/numbers.rs:66:40 + --> $DIR/numbers.rs:65:40 | LL | assert::is_transmutable::< i8, u16>(); | ^^^ The size of `i8` is smaller than the size of `u16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -29,13 +29,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:67:40 + --> $DIR/numbers.rs:66:40 | LL | assert::is_transmutable::< i8, i32>(); | ^^^ The size of `i8` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -44,13 +44,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:68:40 + --> $DIR/numbers.rs:67:40 | LL | assert::is_transmutable::< i8, f32>(); | ^^^ The size of `i8` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -59,13 +59,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:69:40 + --> $DIR/numbers.rs:68:40 | LL | assert::is_transmutable::< i8, u32>(); | ^^^ The size of `i8` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -74,13 +74,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:70:40 + --> $DIR/numbers.rs:69:40 | LL | assert::is_transmutable::< i8, u64>(); | ^^^ The size of `i8` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -89,13 +89,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:71:40 + --> $DIR/numbers.rs:70:40 | LL | assert::is_transmutable::< i8, i64>(); | ^^^ The size of `i8` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -104,13 +104,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:72:40 + --> $DIR/numbers.rs:71:40 | LL | assert::is_transmutable::< i8, f64>(); | ^^^ The size of `i8` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -119,13 +119,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:73:39 + --> $DIR/numbers.rs:72:39 | LL | assert::is_transmutable::< i8, u128>(); | ^^^^ The size of `i8` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -134,13 +134,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:74:39 + --> $DIR/numbers.rs:73:39 | LL | assert::is_transmutable::< i8, i128>(); | ^^^^ The size of `i8` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -149,13 +149,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` - --> $DIR/numbers.rs:76:40 + --> $DIR/numbers.rs:75:40 | LL | assert::is_transmutable::< u8, i16>(); | ^^^ The size of `u8` is smaller than the size of `i16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -164,13 +164,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` - --> $DIR/numbers.rs:77:40 + --> $DIR/numbers.rs:76:40 | LL | assert::is_transmutable::< u8, u16>(); | ^^^ The size of `u8` is smaller than the size of `u16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -179,13 +179,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:78:40 + --> $DIR/numbers.rs:77:40 | LL | assert::is_transmutable::< u8, i32>(); | ^^^ The size of `u8` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -194,13 +194,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:79:40 + --> $DIR/numbers.rs:78:40 | LL | assert::is_transmutable::< u8, f32>(); | ^^^ The size of `u8` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -209,13 +209,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:80:40 + --> $DIR/numbers.rs:79:40 | LL | assert::is_transmutable::< u8, u32>(); | ^^^ The size of `u8` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -224,13 +224,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:81:40 + --> $DIR/numbers.rs:80:40 | LL | assert::is_transmutable::< u8, u64>(); | ^^^ The size of `u8` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -239,13 +239,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:82:40 + --> $DIR/numbers.rs:81:40 | LL | assert::is_transmutable::< u8, i64>(); | ^^^ The size of `u8` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -254,13 +254,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:83:40 + --> $DIR/numbers.rs:82:40 | LL | assert::is_transmutable::< u8, f64>(); | ^^^ The size of `u8` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -269,13 +269,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:84:39 + --> $DIR/numbers.rs:83:39 | LL | assert::is_transmutable::< u8, u128>(); | ^^^^ The size of `u8` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -284,13 +284,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:85:39 + --> $DIR/numbers.rs:84:39 | LL | assert::is_transmutable::< u8, i128>(); | ^^^^ The size of `u8` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -299,13 +299,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:87:40 + --> $DIR/numbers.rs:86:40 | LL | assert::is_transmutable::< i16, i32>(); | ^^^ The size of `i16` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -314,13 +314,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:88:40 + --> $DIR/numbers.rs:87:40 | LL | assert::is_transmutable::< i16, f32>(); | ^^^ The size of `i16` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -329,13 +329,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:89:40 + --> $DIR/numbers.rs:88:40 | LL | assert::is_transmutable::< i16, u32>(); | ^^^ The size of `i16` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -344,13 +344,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:90:40 + --> $DIR/numbers.rs:89:40 | LL | assert::is_transmutable::< i16, u64>(); | ^^^ The size of `i16` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -359,13 +359,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:91:40 + --> $DIR/numbers.rs:90:40 | LL | assert::is_transmutable::< i16, i64>(); | ^^^ The size of `i16` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -374,13 +374,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:92:40 + --> $DIR/numbers.rs:91:40 | LL | assert::is_transmutable::< i16, f64>(); | ^^^ The size of `i16` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -389,13 +389,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:93:39 + --> $DIR/numbers.rs:92:39 | LL | assert::is_transmutable::< i16, u128>(); | ^^^^ The size of `i16` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -404,13 +404,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:94:39 + --> $DIR/numbers.rs:93:39 | LL | assert::is_transmutable::< i16, i128>(); | ^^^^ The size of `i16` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -419,13 +419,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:96:40 + --> $DIR/numbers.rs:95:40 | LL | assert::is_transmutable::< u16, i32>(); | ^^^ The size of `u16` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -434,13 +434,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:97:40 + --> $DIR/numbers.rs:96:40 | LL | assert::is_transmutable::< u16, f32>(); | ^^^ The size of `u16` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -449,13 +449,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:98:40 + --> $DIR/numbers.rs:97:40 | LL | assert::is_transmutable::< u16, u32>(); | ^^^ The size of `u16` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -464,13 +464,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:99:40 + --> $DIR/numbers.rs:98:40 | LL | assert::is_transmutable::< u16, u64>(); | ^^^ The size of `u16` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -479,13 +479,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:100:40 + --> $DIR/numbers.rs:99:40 | LL | assert::is_transmutable::< u16, i64>(); | ^^^ The size of `u16` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -494,13 +494,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:101:40 + --> $DIR/numbers.rs:100:40 | LL | assert::is_transmutable::< u16, f64>(); | ^^^ The size of `u16` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -509,13 +509,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:102:39 + --> $DIR/numbers.rs:101:39 | LL | assert::is_transmutable::< u16, u128>(); | ^^^^ The size of `u16` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -524,13 +524,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:103:39 + --> $DIR/numbers.rs:102:39 | LL | assert::is_transmutable::< u16, i128>(); | ^^^^ The size of `u16` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -539,13 +539,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:105:40 + --> $DIR/numbers.rs:104:40 | LL | assert::is_transmutable::< i32, u64>(); | ^^^ The size of `i32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -554,13 +554,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:106:40 + --> $DIR/numbers.rs:105:40 | LL | assert::is_transmutable::< i32, i64>(); | ^^^ The size of `i32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -569,13 +569,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:107:40 + --> $DIR/numbers.rs:106:40 | LL | assert::is_transmutable::< i32, f64>(); | ^^^ The size of `i32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -584,13 +584,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:108:39 + --> $DIR/numbers.rs:107:39 | LL | assert::is_transmutable::< i32, u128>(); | ^^^^ The size of `i32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -599,13 +599,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:109:39 + --> $DIR/numbers.rs:108:39 | LL | assert::is_transmutable::< i32, i128>(); | ^^^^ The size of `i32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -614,13 +614,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:111:40 + --> $DIR/numbers.rs:110:40 | LL | assert::is_transmutable::< f32, u64>(); | ^^^ The size of `f32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -629,13 +629,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:112:40 + --> $DIR/numbers.rs:111:40 | LL | assert::is_transmutable::< f32, i64>(); | ^^^ The size of `f32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -644,13 +644,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:113:40 + --> $DIR/numbers.rs:112:40 | LL | assert::is_transmutable::< f32, f64>(); | ^^^ The size of `f32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -659,13 +659,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:114:39 + --> $DIR/numbers.rs:113:39 | LL | assert::is_transmutable::< f32, u128>(); | ^^^^ The size of `f32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -674,13 +674,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:115:39 + --> $DIR/numbers.rs:114:39 | LL | assert::is_transmutable::< f32, i128>(); | ^^^^ The size of `f32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -689,13 +689,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:117:40 + --> $DIR/numbers.rs:116:40 | LL | assert::is_transmutable::< u32, u64>(); | ^^^ The size of `u32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -704,13 +704,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:118:40 + --> $DIR/numbers.rs:117:40 | LL | assert::is_transmutable::< u32, i64>(); | ^^^ The size of `u32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -719,13 +719,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:119:40 + --> $DIR/numbers.rs:118:40 | LL | assert::is_transmutable::< u32, f64>(); | ^^^ The size of `u32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -734,13 +734,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:120:39 + --> $DIR/numbers.rs:119:39 | LL | assert::is_transmutable::< u32, u128>(); | ^^^^ The size of `u32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -749,13 +749,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:121:39 + --> $DIR/numbers.rs:120:39 | LL | assert::is_transmutable::< u32, i128>(); | ^^^^ The size of `u32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -764,13 +764,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:123:39 + --> $DIR/numbers.rs:122:39 | LL | assert::is_transmutable::< u64, u128>(); | ^^^^ The size of `u64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -779,13 +779,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:124:39 + --> $DIR/numbers.rs:123:39 | LL | assert::is_transmutable::< u64, i128>(); | ^^^^ The size of `u64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -794,13 +794,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:126:39 + --> $DIR/numbers.rs:125:39 | LL | assert::is_transmutable::< i64, u128>(); | ^^^^ The size of `i64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -809,13 +809,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:127:39 + --> $DIR/numbers.rs:126:39 | LL | assert::is_transmutable::< i64, i128>(); | ^^^^ The size of `i64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -824,13 +824,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:129:39 + --> $DIR/numbers.rs:128:39 | LL | assert::is_transmutable::< f64, u128>(); | ^^^^ The size of `f64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -839,13 +839,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:130:39 + --> $DIR/numbers.rs:129:39 | LL | assert::is_transmutable::< f64, i128>(); | ^^^^ The size of `f64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function diff --git a/tests/ui/transmutability/primitives/numbers.next.stderr b/tests/ui/transmutability/primitives/numbers.next.stderr index 009e377af99a..7a80e444149d 100644 --- a/tests/ui/transmutability/primitives/numbers.next.stderr +++ b/tests/ui/transmutability/primitives/numbers.next.stderr @@ -1,11 +1,11 @@ error[E0277]: `i8` cannot be safely transmuted into `i16` - --> $DIR/numbers.rs:65:40 + --> $DIR/numbers.rs:64:40 | LL | assert::is_transmutable::< i8, i16>(); | ^^^ The size of `i8` is smaller than the size of `i16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -14,13 +14,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` - --> $DIR/numbers.rs:66:40 + --> $DIR/numbers.rs:65:40 | LL | assert::is_transmutable::< i8, u16>(); | ^^^ The size of `i8` is smaller than the size of `u16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -29,13 +29,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:67:40 + --> $DIR/numbers.rs:66:40 | LL | assert::is_transmutable::< i8, i32>(); | ^^^ The size of `i8` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -44,13 +44,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:68:40 + --> $DIR/numbers.rs:67:40 | LL | assert::is_transmutable::< i8, f32>(); | ^^^ The size of `i8` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -59,13 +59,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:69:40 + --> $DIR/numbers.rs:68:40 | LL | assert::is_transmutable::< i8, u32>(); | ^^^ The size of `i8` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -74,13 +74,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:70:40 + --> $DIR/numbers.rs:69:40 | LL | assert::is_transmutable::< i8, u64>(); | ^^^ The size of `i8` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -89,13 +89,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:71:40 + --> $DIR/numbers.rs:70:40 | LL | assert::is_transmutable::< i8, i64>(); | ^^^ The size of `i8` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -104,13 +104,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:72:40 + --> $DIR/numbers.rs:71:40 | LL | assert::is_transmutable::< i8, f64>(); | ^^^ The size of `i8` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -119,13 +119,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:73:39 + --> $DIR/numbers.rs:72:39 | LL | assert::is_transmutable::< i8, u128>(); | ^^^^ The size of `i8` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -134,13 +134,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:74:39 + --> $DIR/numbers.rs:73:39 | LL | assert::is_transmutable::< i8, i128>(); | ^^^^ The size of `i8` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -149,13 +149,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` - --> $DIR/numbers.rs:76:40 + --> $DIR/numbers.rs:75:40 | LL | assert::is_transmutable::< u8, i16>(); | ^^^ The size of `u8` is smaller than the size of `i16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -164,13 +164,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` - --> $DIR/numbers.rs:77:40 + --> $DIR/numbers.rs:76:40 | LL | assert::is_transmutable::< u8, u16>(); | ^^^ The size of `u8` is smaller than the size of `u16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -179,13 +179,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:78:40 + --> $DIR/numbers.rs:77:40 | LL | assert::is_transmutable::< u8, i32>(); | ^^^ The size of `u8` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -194,13 +194,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:79:40 + --> $DIR/numbers.rs:78:40 | LL | assert::is_transmutable::< u8, f32>(); | ^^^ The size of `u8` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -209,13 +209,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:80:40 + --> $DIR/numbers.rs:79:40 | LL | assert::is_transmutable::< u8, u32>(); | ^^^ The size of `u8` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -224,13 +224,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:81:40 + --> $DIR/numbers.rs:80:40 | LL | assert::is_transmutable::< u8, u64>(); | ^^^ The size of `u8` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -239,13 +239,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:82:40 + --> $DIR/numbers.rs:81:40 | LL | assert::is_transmutable::< u8, i64>(); | ^^^ The size of `u8` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -254,13 +254,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:83:40 + --> $DIR/numbers.rs:82:40 | LL | assert::is_transmutable::< u8, f64>(); | ^^^ The size of `u8` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -269,13 +269,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:84:39 + --> $DIR/numbers.rs:83:39 | LL | assert::is_transmutable::< u8, u128>(); | ^^^^ The size of `u8` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -284,13 +284,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:85:39 + --> $DIR/numbers.rs:84:39 | LL | assert::is_transmutable::< u8, i128>(); | ^^^^ The size of `u8` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -299,13 +299,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:87:40 + --> $DIR/numbers.rs:86:40 | LL | assert::is_transmutable::< i16, i32>(); | ^^^ The size of `i16` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -314,13 +314,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:88:40 + --> $DIR/numbers.rs:87:40 | LL | assert::is_transmutable::< i16, f32>(); | ^^^ The size of `i16` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -329,13 +329,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:89:40 + --> $DIR/numbers.rs:88:40 | LL | assert::is_transmutable::< i16, u32>(); | ^^^ The size of `i16` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -344,13 +344,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:90:40 + --> $DIR/numbers.rs:89:40 | LL | assert::is_transmutable::< i16, u64>(); | ^^^ The size of `i16` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -359,13 +359,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:91:40 + --> $DIR/numbers.rs:90:40 | LL | assert::is_transmutable::< i16, i64>(); | ^^^ The size of `i16` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -374,13 +374,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:92:40 + --> $DIR/numbers.rs:91:40 | LL | assert::is_transmutable::< i16, f64>(); | ^^^ The size of `i16` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -389,13 +389,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:93:39 + --> $DIR/numbers.rs:92:39 | LL | assert::is_transmutable::< i16, u128>(); | ^^^^ The size of `i16` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -404,13 +404,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:94:39 + --> $DIR/numbers.rs:93:39 | LL | assert::is_transmutable::< i16, i128>(); | ^^^^ The size of `i16` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -419,13 +419,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:96:40 + --> $DIR/numbers.rs:95:40 | LL | assert::is_transmutable::< u16, i32>(); | ^^^ The size of `u16` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -434,13 +434,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:97:40 + --> $DIR/numbers.rs:96:40 | LL | assert::is_transmutable::< u16, f32>(); | ^^^ The size of `u16` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -449,13 +449,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:98:40 + --> $DIR/numbers.rs:97:40 | LL | assert::is_transmutable::< u16, u32>(); | ^^^ The size of `u16` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -464,13 +464,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:99:40 + --> $DIR/numbers.rs:98:40 | LL | assert::is_transmutable::< u16, u64>(); | ^^^ The size of `u16` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -479,13 +479,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:100:40 + --> $DIR/numbers.rs:99:40 | LL | assert::is_transmutable::< u16, i64>(); | ^^^ The size of `u16` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -494,13 +494,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:101:40 + --> $DIR/numbers.rs:100:40 | LL | assert::is_transmutable::< u16, f64>(); | ^^^ The size of `u16` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -509,13 +509,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:102:39 + --> $DIR/numbers.rs:101:39 | LL | assert::is_transmutable::< u16, u128>(); | ^^^^ The size of `u16` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -524,13 +524,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:103:39 + --> $DIR/numbers.rs:102:39 | LL | assert::is_transmutable::< u16, i128>(); | ^^^^ The size of `u16` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -539,13 +539,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:105:40 + --> $DIR/numbers.rs:104:40 | LL | assert::is_transmutable::< i32, u64>(); | ^^^ The size of `i32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -554,13 +554,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:106:40 + --> $DIR/numbers.rs:105:40 | LL | assert::is_transmutable::< i32, i64>(); | ^^^ The size of `i32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -569,13 +569,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:107:40 + --> $DIR/numbers.rs:106:40 | LL | assert::is_transmutable::< i32, f64>(); | ^^^ The size of `i32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -584,13 +584,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:108:39 + --> $DIR/numbers.rs:107:39 | LL | assert::is_transmutable::< i32, u128>(); | ^^^^ The size of `i32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -599,13 +599,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:109:39 + --> $DIR/numbers.rs:108:39 | LL | assert::is_transmutable::< i32, i128>(); | ^^^^ The size of `i32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -614,13 +614,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:111:40 + --> $DIR/numbers.rs:110:40 | LL | assert::is_transmutable::< f32, u64>(); | ^^^ The size of `f32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -629,13 +629,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:112:40 + --> $DIR/numbers.rs:111:40 | LL | assert::is_transmutable::< f32, i64>(); | ^^^ The size of `f32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -644,13 +644,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:113:40 + --> $DIR/numbers.rs:112:40 | LL | assert::is_transmutable::< f32, f64>(); | ^^^ The size of `f32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -659,13 +659,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:114:39 + --> $DIR/numbers.rs:113:39 | LL | assert::is_transmutable::< f32, u128>(); | ^^^^ The size of `f32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -674,13 +674,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:115:39 + --> $DIR/numbers.rs:114:39 | LL | assert::is_transmutable::< f32, i128>(); | ^^^^ The size of `f32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -689,13 +689,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:117:40 + --> $DIR/numbers.rs:116:40 | LL | assert::is_transmutable::< u32, u64>(); | ^^^ The size of `u32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -704,13 +704,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:118:40 + --> $DIR/numbers.rs:117:40 | LL | assert::is_transmutable::< u32, i64>(); | ^^^ The size of `u32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -719,13 +719,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:119:40 + --> $DIR/numbers.rs:118:40 | LL | assert::is_transmutable::< u32, f64>(); | ^^^ The size of `u32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -734,13 +734,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:120:39 + --> $DIR/numbers.rs:119:39 | LL | assert::is_transmutable::< u32, u128>(); | ^^^^ The size of `u32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -749,13 +749,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:121:39 + --> $DIR/numbers.rs:120:39 | LL | assert::is_transmutable::< u32, i128>(); | ^^^^ The size of `u32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -764,13 +764,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:123:39 + --> $DIR/numbers.rs:122:39 | LL | assert::is_transmutable::< u64, u128>(); | ^^^^ The size of `u64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -779,13 +779,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:124:39 + --> $DIR/numbers.rs:123:39 | LL | assert::is_transmutable::< u64, i128>(); | ^^^^ The size of `u64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -794,13 +794,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:126:39 + --> $DIR/numbers.rs:125:39 | LL | assert::is_transmutable::< i64, u128>(); | ^^^^ The size of `i64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -809,13 +809,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:127:39 + --> $DIR/numbers.rs:126:39 | LL | assert::is_transmutable::< i64, i128>(); | ^^^^ The size of `i64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -824,13 +824,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:129:39 + --> $DIR/numbers.rs:128:39 | LL | assert::is_transmutable::< f64, u128>(); | ^^^^ The size of `f64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -839,13 +839,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:130:39 + --> $DIR/numbers.rs:129:39 | LL | assert::is_transmutable::< f64, i128>(); | ^^^^ The size of `f64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function diff --git a/tests/ui/transmutability/primitives/numbers.rs b/tests/ui/transmutability/primitives/numbers.rs index 896f5f49f67f..401502474cfb 100644 --- a/tests/ui/transmutability/primitives/numbers.rs +++ b/tests/ui/transmutability/primitives/numbers.rs @@ -5,7 +5,6 @@ #![crate_type = "lib"] #![feature(transmutability)] #![allow(dead_code)] -#![allow(incomplete_features)] mod assert { use std::mem::BikeshedIntrinsicFrom; diff --git a/tests/ui/transmutability/unions/boolish.rs b/tests/ui/transmutability/unions/boolish.rs index 0ba59bcaa9f2..c829f83149e3 100644 --- a/tests/ui/transmutability/unions/boolish.rs +++ b/tests/ui/transmutability/unions/boolish.rs @@ -4,7 +4,6 @@ #![feature(transmutability)] #![feature(marker_trait_attr)] #![allow(dead_code)] -#![allow(incomplete_features)] mod assert { use std::mem::{Assume, BikeshedIntrinsicFrom}; diff --git a/tests/ui/type-alias-impl-trait/issue-65384.rs b/tests/ui/type-alias-impl-trait/issue-65384.rs index 9a9b2269f802..44ca5cb94b0f 100644 --- a/tests/ui/type-alias-impl-trait/issue-65384.rs +++ b/tests/ui/type-alias-impl-trait/issue-65384.rs @@ -1,5 +1,4 @@ #![feature(type_alias_impl_trait)] -#![allow(incomplete_features)] trait MyTrait {} diff --git a/tests/ui/type-alias-impl-trait/issue-65384.stderr b/tests/ui/type-alias-impl-trait/issue-65384.stderr index 6accd45bad65..5653ee324be1 100644 --- a/tests/ui/type-alias-impl-trait/issue-65384.stderr +++ b/tests/ui/type-alias-impl-trait/issue-65384.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `MyTrait` for type `()` - --> $DIR/issue-65384.rs:10:1 + --> $DIR/issue-65384.rs:9:1 | LL | impl MyTrait for () {} | ------------------- first implementation here From ba70528fd8cfbc1bf3d0b08c60dd753d6865d8a6 Mon Sep 17 00:00:00 2001 From: kirandevraj Date: Tue, 12 Mar 2024 01:51:52 +0530 Subject: [PATCH 33/99] updating variable names in CHECK --- tests/mir-opt/unnamed-fields/field_access.rs | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/mir-opt/unnamed-fields/field_access.rs b/tests/mir-opt/unnamed-fields/field_access.rs index 70ce7c222ffb..5badfa1646bc 100644 --- a/tests/mir-opt/unnamed-fields/field_access.rs +++ b/tests/mir-opt/unnamed-fields/field_access.rs @@ -39,34 +39,34 @@ fn access(_: T) {} // CHECK-LABEL: fn foo( fn foo(foo: Foo) { - // CHECK _3 = (_1.0: u8); - // CHECK _2 = access::(move _3) -> [return: bb1, unwind: bb5]; + // CHECK [[a:_.*]] = (_1.0: u8); + // CHECK _.* = access::(move [[a]]) -> [return: bb1, unwind: bb5]; access(foo.a); - // CHECK _5 = ((_1.1: Foo::{anon_adt#0}).0: i8); - // CHECK _4 = access::(move _5) -> [return: bb2, unwind: bb5]; + // CHECK [[b:_.*]] = ((_1.1: Foo::{anon_adt#0}).0: i8); + // CHECK _.* = access::(move [[b]]) -> [return: bb2, unwind: bb5]; access(foo.b); - // CHECK _7 = ((_1.1: Foo::{anon_adt#0}).1: bool); - // CHECK _6 = access::(move _7) -> [return: bb3, unwind: bb5]; + // CHECK [[c:_.*]] = ((_1.1: Foo::{anon_adt#0}).1: bool); + // CHECK _.* = access::(move [[c]]) -> [return: bb3, unwind: bb5]; access(foo.c); - // CHECK _9 = (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); - // CHECK _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; + // CHECK [[d:_.*]] = (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); + // CHECK _.* = access::<[u8; 1]>(move [[d]]) -> [return: bb4, unwind: bb5]; access(foo.d); } // CHECK-LABEL: fn bar( fn bar(bar: Bar) { unsafe { - // CHECK _3 = (_1.0: u8); - // CHECK _2 = access::(move _3) -> [return: bb1, unwind: bb5]; + // CHECK [[a:_.*]] = (_1.0: u8); + // CHECK _.* = access::(move [[a]]) -> [return: bb1, unwind: bb5]; access(bar.a); - // CHECK _5 = ((_1.1: Bar::{anon_adt#0}).0: i8); - // CHECK _4 = access::(move _5) -> [return: bb2, unwind: bb5]; + // CHECK [[b:_.*]] = ((_1.1: Bar::{anon_adt#0}).0: i8); + // CHECK _.* = access::(move [[b]]) -> [return: bb2, unwind: bb5]; access(bar.b); - // CHECK _7 = ((_1.1: Bar::{anon_adt#0}).1: bool); - // CHECK _6 = access::(move _7) -> [return: bb3, unwind: bb5]; + // CHECK [[c:_.*]] = ((_1.1: Bar::{anon_adt#0}).1: bool); + // CHECK _.* = access::(move [[c]]) -> [return: bb3, unwind: bb5]; access(bar.c); - // CHECK _9 = (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); - // CHECK _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; + // CHECK [[d:_.*]] = (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); + // CHECK _.* = access::<[u8; 1]>(move [[d]]) -> [return: bb4, unwind: bb5]; access(bar.d); } } From 96d24f2dd13e8e9d0c6f9912781ffe1fc79864d3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 11 Mar 2024 21:28:16 +0000 Subject: [PATCH 34/99] Revert "Auto merge of #122140 - oli-obk:track_errors13, r=davidtwco" This reverts commit 65cd843ae06ad00123c131a431ed5304e4cd577a, reversing changes made to d255c6a57c393db6221b1ff700daea478436f1cd. --- compiler/rustc_driver_impl/src/pretty.rs | 6 +- .../src/collect/type_of/opaque.rs | 8 +- compiler/rustc_hir_analysis/src/lib.rs | 30 +++- .../rustc_hir_analysis/src/outlives/test.rs | 8 +- .../rustc_hir_analysis/src/variance/test.rs | 13 +- compiler/rustc_interface/src/passes.rs | 33 ++--- tests/ui/binop/issue-77910-1.stderr | 26 ++-- tests/ui/binop/issue-77910-2.stderr | 26 ++-- ...5492-borrowck-migrate-scans-parents.stderr | 46 +++--- .../generic_const_exprs/type_mismatch.stderr | 12 +- .../unify-op-with-fn-call.stderr | 16 +-- tests/ui/const-generics/transmute-fail.stderr | 24 ++-- tests/ui/const-generics/type_mismatch.stderr | 12 +- .../return-mismatches.stderr | 12 +- tests/ui/expr/if/if-no-match-bindings.stderr | 18 +-- .../issue-74684-2.stderr | 32 ++--- .../hrtb-higher-ranker-supertraits.stderr | 26 ++-- tests/ui/issues/issue-11374.stderr | 18 +-- .../ui/kindck/kindck-impl-type-params.stderr | 18 +-- tests/ui/kindck/kindck-send-object1.stderr | 16 +-- tests/ui/lifetimes/issue-17728.stderr | 32 ++--- tests/ui/liveness/liveness-consts.stderr | 12 +- tests/ui/liveness/liveness-forgot-ret.stderr | 22 +-- tests/ui/liveness/liveness-unused.stderr | 30 ++-- ...lifetime-bounds-on-fns-where-clause.stderr | 22 +-- ...lifetime-bounds-on-fns-where-clause.stderr | 22 +-- .../regions-lifetime-bounds-on-fns.stderr | 22 +-- tests/ui/suggestions/issue-102892.stderr | 32 ++--- .../ui/type-alias-impl-trait/variance.stderr | 132 +++++++++--------- .../variance-associated-consts.stderr | 12 +- .../variance/variance-regions-direct.stderr | 16 +-- .../variance/variance-regions-indirect.stderr | 60 ++++---- .../ui/variance/variance-trait-bounds.stderr | 48 +++---- 33 files changed, 443 insertions(+), 419 deletions(-) diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index c0c6201f73d4..c9bbe45b2127 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -336,8 +336,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { ThirTree => { let tcx = ex.tcx(); let mut out = String::new(); - rustc_hir_analysis::check_crate(tcx); - if tcx.dcx().has_errors().is_some() { + if rustc_hir_analysis::check_crate(tcx).is_err() { FatalError.raise(); } debug!("pretty printing THIR tree"); @@ -349,8 +348,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { ThirFlat => { let tcx = ex.tcx(); let mut out = String::new(); - rustc_hir_analysis::check_crate(tcx); - if tcx.dcx().has_errors().is_some() { + if rustc_hir_analysis::check_crate(tcx).is_err() { FatalError.raise(); } debug!("pretty printing THIR flat"); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index d370efc9d0ef..dcb01a117b04 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -5,20 +5,22 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP}; use crate::errors::{TaitForwardCompat, TypeOf, UnconstrainedOpaqueType}; -pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) { +pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); if tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { let type_of = tcx.type_of(id.owner_id).instantiate_identity(); - tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of }); + res = Err(tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of })); } } } + res } /// Checks "defining uses" of opaque `impl Trait` in associated types. diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 696c47710c23..e056c0e84cf4 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -98,6 +98,7 @@ mod outlives; pub mod structured_errors; mod variance; +use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_middle::middle; use rustc_middle::query::Providers; @@ -155,13 +156,11 @@ pub fn provide(providers: &mut Providers) { hir_wf_check::provide(providers); } -pub fn check_crate(tcx: TyCtxt<'_>) { +pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { let _prof_timer = tcx.sess.timer("type_check_crate"); if tcx.features().rustc_attrs { - tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx)); - tcx.sess.time("variance_testing", || variance::test::test_variance(tcx)); - collect::test_opaque_hidden_types(tcx); + tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?; } tcx.sess.time("coherence_checking", || { @@ -177,6 +176,14 @@ pub fn check_crate(tcx: TyCtxt<'_>) { let _ = tcx.ensure().crate_inherent_impls_overlap_check(()); }); + if tcx.features().rustc_attrs { + tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?; + } + + if tcx.features().rustc_attrs { + collect::test_opaque_hidden_types(tcx)?; + } + // Make sure we evaluate all static and (non-associated) const items, even if unused. // If any of these fail to evaluate, we do not want this crate to pass compilation. tcx.hir().par_body_owners(|item_def_id| { @@ -191,6 +198,21 @@ 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 + // cycle errors because it may typeck on anon constants directly. + tcx.hir().par_body_owners(|item_def_id| { + let def_kind = tcx.def_kind(item_def_id); + if !matches!(def_kind, DefKind::AnonConst) { + tcx.ensure().typeck(item_def_id); + } + }); + + tcx.ensure().check_unused_traits(()); + + Ok(()) } /// A quasi-deprecated helper used in rustdoc and clippy to get diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs index dea3f1a99308..60cd8c39fa02 100644 --- a/compiler/rustc_hir_analysis/src/outlives/test.rs +++ b/compiler/rustc_hir_analysis/src/outlives/test.rs @@ -1,7 +1,8 @@ use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::symbol::sym; +use rustc_span::{symbol::sym, ErrorGuaranteed}; -pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { +pub fn test_inferred_outlives(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); for id in tcx.hir().items() { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. @@ -22,7 +23,8 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { for p in pred { err.note(p); } - err.emit(); + res = Err(err.emit()); } } + res } diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs index 5264d5aa26f2..c211e1af046a 100644 --- a/compiler/rustc_hir_analysis/src/variance/test.rs +++ b/compiler/rustc_hir_analysis/src/variance/test.rs @@ -2,19 +2,21 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; +use rustc_span::ErrorGuaranteed; use crate::errors; -pub fn test_variance(tcx: TyCtxt<'_>) { +pub fn test_variance(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { let variances_of = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(errors::VariancesOf { + res = Err(tcx.dcx().emit_err(errors::VariancesOf { span: tcx.def_span(id.owner_id), variances_of: format!("{variances_of:?}"), - }); + })); } } } @@ -25,10 +27,11 @@ pub fn test_variance(tcx: TyCtxt<'_>) { if tcx.has_attr(id.owner_id, sym::rustc_variance) { let variances_of = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(errors::VariancesOf { + res = Err(tcx.dcx().emit_err(errors::VariancesOf { span: tcx.def_span(id.owner_id), variances_of: format!("{variances_of:?}"), - }); + })); } } + res } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 4cc9ffdbb2fa..4b4c1d6cf672 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -734,22 +734,19 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); // passes are timed inside typeck - rustc_hir_analysis::check_crate(tcx); + rustc_hir_analysis::check_crate(tcx)?; - sess.time("typeck_and_mir_analyses", || { + sess.time("MIR_borrow_checking", || { tcx.hir().par_body_owners(|def_id| { - let def_kind = tcx.def_kind(def_id); - // 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 - // cycle errors because it may typeck on anon constants directly. - if !matches!(def_kind, rustc_hir::def::DefKind::AnonConst) { - tcx.ensure().typeck(def_id); - } // Run unsafety check because it's responsible for stealing and // deallocating THIR. tcx.ensure().check_unsafety(def_id); - tcx.ensure().mir_borrowck(def_id); + tcx.ensure().mir_borrowck(def_id) + }); + }); + + sess.time("MIR_effect_checking", || { + for def_id in tcx.hir().body_owners() { if !tcx.sess.opts.unstable_opts.thir_unsafeck { rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id); } @@ -764,15 +761,15 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { tcx.ensure().mir_drops_elaborated_and_const_checked(def_id); tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id())); } - - if tcx.is_coroutine(def_id.to_def_id()) { - tcx.ensure().mir_coroutine_witnesses(def_id); - tcx.ensure().check_coroutine_obligations(def_id); - } - }) + } }); - tcx.ensure().check_unused_traits(()); + tcx.hir().par_body_owners(|def_id| { + if tcx.is_coroutine(def_id.to_def_id()) { + tcx.ensure().mir_coroutine_witnesses(def_id); + tcx.ensure().check_coroutine_obligations(def_id); + } + }); sess.time("layout_testing", || layout_test::test_layout(tcx)); sess.time("abi_testing", || abi_test::test_abi(tcx)); diff --git a/tests/ui/binop/issue-77910-1.stderr b/tests/ui/binop/issue-77910-1.stderr index 71d03b38cd61..6402e5681884 100644 --- a/tests/ui/binop/issue-77910-1.stderr +++ b/tests/ui/binop/issue-77910-1.stderr @@ -1,16 +1,3 @@ -error[E0381]: used binding `xs` isn't initialized - --> $DIR/issue-77910-1.rs:3:5 - | -LL | let xs; - | -- binding declared here but left uninitialized -LL | xs - | ^^ `xs` used here but it isn't initialized - | -help: consider assigning a value - | -LL | let xs = todo!(); - | +++++++++ - error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}` --> $DIR/issue-77910-1.rs:8:5 | @@ -35,6 +22,19 @@ LL | assert_eq!(foo, y); = help: use parentheses to call this function: `foo(/* &i32 */)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-1.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0369, E0381. diff --git a/tests/ui/binop/issue-77910-2.stderr b/tests/ui/binop/issue-77910-2.stderr index 87f074ff3136..a14560ff188e 100644 --- a/tests/ui/binop/issue-77910-2.stderr +++ b/tests/ui/binop/issue-77910-2.stderr @@ -1,16 +1,3 @@ -error[E0381]: used binding `xs` isn't initialized - --> $DIR/issue-77910-2.rs:3:5 - | -LL | let xs; - | -- binding declared here but left uninitialized -LL | xs - | ^^ `xs` used here but it isn't initialized - | -help: consider assigning a value - | -LL | let xs = todo!(); - | +++++++++ - error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}` --> $DIR/issue-77910-2.rs:7:12 | @@ -24,6 +11,19 @@ help: use parentheses to call this function LL | if foo(/* &i32 */) == y {} | ++++++++++++ +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-2.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + error: aborting due to 2 previous errors Some errors have detailed explanations: E0369, E0381. diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr index c5903b3ab561..098a2964e9fc 100644 --- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr +++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr @@ -13,15 +13,6 @@ help: use `addr_of_mut!` instead to create a raw pointer LL | c1(addr_of_mut!(Y)); | ~~~~~~~~~~~~~~~ -error[E0594]: cannot assign to `x`, as it is not declared as mutable - --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46 - | -LL | pub fn e(x: &'static mut isize) { - | - help: consider changing this to be mutable: `mut x` -LL | static mut Y: isize = 3; -LL | let mut c1 = |y: &'static mut isize| x = y; - | ^^^^^ cannot assign - warning: creating a mutable reference to mutable static is discouraged --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:27:16 | @@ -36,6 +27,29 @@ help: use `addr_of_mut!` instead to create a raw pointer LL | c1(addr_of_mut!(Z)); | ~~~~~~~~~~~~~~~ +warning: creating a mutable reference to mutable static is discouraged + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37 + | +LL | borrowck_closures_unique::e(&mut X); + | ^^^^^^ mutable reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer + | +LL | borrowck_closures_unique::e(addr_of_mut!(X)); + | ~~~~~~~~~~~~~~~ + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46 + | +LL | pub fn e(x: &'static mut isize) { + | - help: consider changing this to be mutable: `mut x` +LL | static mut Y: isize = 3; +LL | let mut c1 = |y: &'static mut isize| x = y; + | ^^^^^ cannot assign + error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:22:50 | @@ -81,20 +95,6 @@ LL | || { LL | &mut x.0; | ^^^^^^^^ cannot borrow as mutable -warning: creating a mutable reference to mutable static is discouraged - --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37 - | -LL | borrowck_closures_unique::e(&mut X); - | ^^^^^^ mutable reference to mutable static - | - = note: for more information, see issue #114447 - = note: this will be a hard error in the 2024 edition - = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior -help: use `addr_of_mut!` instead to create a raw pointer - | -LL | borrowck_closures_unique::e(addr_of_mut!(X)); - | ~~~~~~~~~~~~~~~ - error: aborting due to 6 previous errors; 3 warnings emitted Some errors have detailed explanations: E0594, E0596. diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr index bfb40c7e54f6..bb6d650b7ab2 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr @@ -21,12 +21,6 @@ LL | impl Q for [u8; N] {} | | | unsatisfied trait bound introduced here -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:8:31 - | -LL | impl Q for [u8; N] {} - | ^ expected `usize`, found `u64` - error[E0308]: mismatched types --> $DIR/type_mismatch.rs:12:20 | @@ -35,6 +29,12 @@ LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} | | | implicitly returns `()` as its body has no tail or `return` expression +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:8:31 + | +LL | impl Q for [u8; N] {} + | ^ expected `usize`, found `u64` + error: aborting due to 4 previous errors Some errors have detailed explanations: E0046, E0308. diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr index 557530ebe3d4..77a7da17c131 100644 --- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -34,6 +34,14 @@ LL + #[derive(ConstParamTy)] LL | struct Foo(u8); | +error: unconstrained generic constant + --> $DIR/unify-op-with-fn-call.rs:30:12 + | +LL | bar2::<{ std::ops::Add::add(N, N) }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:` + error[E0015]: cannot call non-const operator in constants --> $DIR/unify-op-with-fn-call.rs:20:39 | @@ -57,14 +65,6 @@ LL | bar::<{ std::ops::Add::add(N, N) }>(); = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(effects)]` to the crate attributes to enable -error: unconstrained generic constant - --> $DIR/unify-op-with-fn-call.rs:30:12 - | -LL | bar2::<{ std::ops::Add::add(N, N) }>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:` - error[E0015]: cannot call non-const fn `::add` in constants --> $DIR/unify-op-with-fn-call.rs:30:14 | diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index 9e308620a9c2..12644b9f36d0 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -16,18 +16,6 @@ LL | std::mem::transmute(v) = note: source type: `[[u32; H]; W]` (this type does not have a fixed size) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) -error[E0308]: mismatched types - --> $DIR/transmute-fail.rs:12:53 - | -LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - | ^ expected `usize`, found `bool` - -error[E0308]: mismatched types - --> $DIR/transmute-fail.rs:12:67 - | -LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - | ^ expected `usize`, found `bool` - error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fail.rs:23:5 | @@ -46,6 +34,18 @@ LL | std::mem::transmute(v) = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:53 + | +LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:67 + | +LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + error: aborting due to 6 previous errors Some errors have detailed explanations: E0308, E0512. diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr index 394dd44d40d3..07476ae76c65 100644 --- a/tests/ui/const-generics/type_mismatch.stderr +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -10,12 +10,6 @@ note: required by a bound in `bar` LL | fn bar() -> [u8; N] {} | ^^^^^^^^^^^ required by this bound in `bar` -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:2:11 - | -LL | bar::() - | ^ expected `u8`, found `usize` - error[E0308]: mismatched types --> $DIR/type_mismatch.rs:6:26 | @@ -24,6 +18,12 @@ LL | fn bar() -> [u8; N] {} | | | implicitly returns `()` as its body has no tail or `return` expression +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:2:11 + | +LL | bar::() + | ^ expected `u8`, found `usize` + error[E0308]: mismatched types --> $DIR/type_mismatch.rs:6:31 | diff --git a/tests/ui/explicit-tail-calls/return-mismatches.stderr b/tests/ui/explicit-tail-calls/return-mismatches.stderr index 147cec499e8b..31c7a46ded91 100644 --- a/tests/ui/explicit-tail-calls/return-mismatches.stderr +++ b/tests/ui/explicit-tail-calls/return-mismatches.stderr @@ -16,6 +16,12 @@ LL | become _g1(); = note: expected unit type `()` found type `!` +error[E0308]: mismatched types + --> $DIR/return-mismatches.rs:21:5 + | +LL | become _g2(); + | ^^^^^^^^^^^^ expected `u32`, found `u16` + warning: function cannot return without recursing --> $DIR/return-mismatches.rs:16:1 | @@ -27,12 +33,6 @@ LL | become _g1(); = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -error[E0308]: mismatched types - --> $DIR/return-mismatches.rs:21:5 - | -LL | become _g2(); - | ^^^^^^^^^^^^ expected `u32`, found `u16` - error: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-no-match-bindings.stderr b/tests/ui/expr/if/if-no-match-bindings.stderr index 34ba126d9a77..18f3b6b168ec 100644 --- a/tests/ui/expr/if/if-no-match-bindings.stderr +++ b/tests/ui/expr/if/if-no-match-bindings.stderr @@ -1,12 +1,3 @@ -error[E0515]: cannot return reference to temporary value - --> $DIR/if-no-match-bindings.rs:8:38 - | -LL | fn b_mut_ref<'a>() -> &'a mut bool { &mut true } - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:19:8 | @@ -99,6 +90,15 @@ LL - while &mut true {} LL + while true {} | +error[E0515]: cannot return reference to temporary value + --> $DIR/if-no-match-bindings.rs:8:38 + | +LL | fn b_mut_ref<'a>() -> &'a mut bool { &mut true } + | ^^^^^---- + | | | + | | temporary value created here + | returns a reference to data owned by the current function + error: aborting due to 9 previous errors Some errors have detailed explanations: E0308, E0515. diff --git a/tests/ui/generic-associated-types/issue-74684-2.stderr b/tests/ui/generic-associated-types/issue-74684-2.stderr index 7b295c7bd456..d39513ec523a 100644 --- a/tests/ui/generic-associated-types/issue-74684-2.stderr +++ b/tests/ui/generic-associated-types/issue-74684-2.stderr @@ -1,19 +1,3 @@ -error[E0597]: `a` does not live long enough - --> $DIR/issue-74684-2.rs:13:25 - | -LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { - | -- lifetime `'a` defined here -LL | let a = [0; 1]; - | - binding `a` declared here -LL | let x = T::identity(&a); - | ------------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `a` is borrowed for `'a` -LL | todo!() -LL | } - | - `a` dropped here while still borrowed - error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` --> $DIR/issue-74684-2.rs:21:9 | @@ -33,6 +17,22 @@ note: required by a bound in `bug` LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { | ^^^^^^^^^^^^ required by this bound in `bug` +error[E0597]: `a` does not live long enough + --> $DIR/issue-74684-2.rs:13:25 + | +LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { + | -- lifetime `'a` defined here +LL | let a = [0; 1]; + | - binding `a` declared here +LL | let x = T::identity(&a); + | ------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +LL | todo!() +LL | } + | - `a` dropped here while still borrowed + error: aborting due to 2 previous errors Some errors have detailed explanations: E0271, E0597. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr index 23dfc77d92ec..f220ba6f3389 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr @@ -18,19 +18,6 @@ help: consider further restricting this bound LL | where F : Foo<'x> + for<'tcx> Foo<'tcx> | +++++++++++++++++++++ -warning: function cannot return without recursing - --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 - | -LL | / fn want_foo_for_any_tcx(f: &F) -LL | | where F : for<'tcx> Foo<'tcx> - | |_________________________________^ cannot return without recursing -... -LL | want_foo_for_any_tcx(f); - | ----------------------- recursive call site - | - = help: a `loop` may express intention better if this is on purpose - = note: `#[warn(unconditional_recursion)]` on by default - error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26 | @@ -51,6 +38,19 @@ help: consider further restricting this bound LL | where B : Bar<'x> + for<'ccx> Bar<'ccx> | +++++++++++++++++++++ +warning: function cannot return without recursing + --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 + | +LL | / fn want_foo_for_any_tcx(f: &F) +LL | | where F : for<'tcx> Foo<'tcx> + | |_________________________________^ cannot return without recursing +... +LL | want_foo_for_any_tcx(f); + | ----------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + warning: function cannot return without recursing --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 | diff --git a/tests/ui/issues/issue-11374.stderr b/tests/ui/issues/issue-11374.stderr index c5dca7a9313d..3ae5cfc79f87 100644 --- a/tests/ui/issues/issue-11374.stderr +++ b/tests/ui/issues/issue-11374.stderr @@ -1,12 +1,3 @@ -error[E0515]: cannot return value referencing local variable `r` - --> $DIR/issue-11374.rs:20:5 - | -LL | Container::wrap(&mut r as &mut dyn io::Read) - | ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | `r` is borrowed here - | returns a value referencing data owned by the current function - error[E0308]: mismatched types --> $DIR/issue-11374.rs:27:15 | @@ -27,6 +18,15 @@ help: consider mutably borrowing here LL | c.read_to(&mut v); | ++++ +error[E0515]: cannot return value referencing local variable `r` + --> $DIR/issue-11374.rs:20:5 + | +LL | Container::wrap(&mut r as &mut dyn io::Read) + | ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `r` is borrowed here + | returns a value referencing data owned by the current function + error: aborting due to 2 previous errors Some errors have detailed explanations: E0308, E0515. diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr index ca3a90f46a72..aad020e4ec97 100644 --- a/tests/ui/kindck/kindck-impl-type-params.stderr +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -74,15 +74,6 @@ help: consider restricting type parameter `T` LL | fn g(val: T) { | +++++++++++++++++++ -error: lifetime may not live long enough - --> $DIR/kindck-impl-type-params.rs:30:13 - | -LL | fn foo<'a>() { - | -- lifetime `'a` defined here -LL | let t: S<&'a isize> = S(marker::PhantomData); -LL | let a = &t as &dyn Gettable<&'a isize>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:36:13 | @@ -120,6 +111,15 @@ LL + #[derive(Copy)] LL | struct Foo; // does not impl Copy | +error: lifetime may not live long enough + --> $DIR/kindck-impl-type-params.rs:30:13 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let t: S<&'a isize> = S(marker::PhantomData); +LL | let a = &t as &dyn Gettable<&'a isize>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr index 5d06a2ab4daf..f2aa814676fc 100644 --- a/tests/ui/kindck/kindck-send-object1.stderr +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -12,14 +12,6 @@ note: required by a bound in `assert_send` LL | fn assert_send() { } | ^^^^ required by this bound in `assert_send` -error: lifetime may not live long enough - --> $DIR/kindck-send-object1.rs:14:5 - | -LL | fn test52<'a>() { - | -- lifetime `'a` defined here -LL | assert_send::<&'a (dyn Dummy + Sync)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely --> $DIR/kindck-send-object1.rs:29:19 | @@ -36,6 +28,14 @@ note: required by a bound in `assert_send` LL | fn assert_send() { } | ^^^^ required by this bound in `assert_send` +error: lifetime may not live long enough + --> $DIR/kindck-send-object1.rs:14:5 + | +LL | fn test52<'a>() { + | -- lifetime `'a` defined here +LL | assert_send::<&'a (dyn Dummy + Sync)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lifetimes/issue-17728.stderr b/tests/ui/lifetimes/issue-17728.stderr index 811d8c899910..23547f722a11 100644 --- a/tests/ui/lifetimes/issue-17728.stderr +++ b/tests/ui/lifetimes/issue-17728.stderr @@ -1,19 +1,3 @@ -error: lifetime may not live long enough - --> $DIR/issue-17728.rs:15:28 - | -LL | fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> { - | - - let's call the lifetime of this reference `'1` - | | - | let's call the lifetime of this reference `'2` -... -LL | Some(entry) => Ok(entry), - | ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` - | -help: consider introducing a named lifetime parameter - | -LL | fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> { - | ++++ ++ ++ - error[E0308]: `match` arms have incompatible types --> $DIR/issue-17728.rs:108:14 | @@ -32,6 +16,22 @@ LL | | } = note: expected enum `RoomDirection` found enum `Option<_>` +error: lifetime may not live long enough + --> $DIR/issue-17728.rs:15:28 + | +LL | fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +... +LL | Some(entry) => Ok(entry), + | ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter + | +LL | fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> { + | ++++ ++ ++ + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-consts.stderr b/tests/ui/liveness/liveness-consts.stderr index ceff62de5d29..34ce39473379 100644 --- a/tests/ui/liveness/liveness-consts.stderr +++ b/tests/ui/liveness/liveness-consts.stderr @@ -40,6 +40,12 @@ LL | b += 1; = help: maybe it is overwritten before being read? = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` +warning: unused variable: `z` + --> $DIR/liveness-consts.rs:60:13 + | +LL | let z = 42; + | ^ help: if this is intentional, prefix it with an underscore: `_z` + warning: value assigned to `t` is never read --> $DIR/liveness-consts.rs:42:9 | @@ -54,11 +60,5 @@ warning: unused variable: `w` LL | let w = 10; | ^ help: if this is intentional, prefix it with an underscore: `_w` -warning: unused variable: `z` - --> $DIR/liveness-consts.rs:60:13 - | -LL | let z = 42; - | ^ help: if this is intentional, prefix it with an underscore: `_z` - warning: 8 warnings emitted diff --git a/tests/ui/liveness/liveness-forgot-ret.stderr b/tests/ui/liveness/liveness-forgot-ret.stderr index 8f26bbf16d9c..f72a30fc4e9c 100644 --- a/tests/ui/liveness/liveness-forgot-ret.stderr +++ b/tests/ui/liveness/liveness-forgot-ret.stderr @@ -1,14 +1,3 @@ -warning: function cannot return without recursing - --> $DIR/liveness-forgot-ret.rs:1:1 - | -LL | fn god_exists(a: isize) -> bool { return god_exists(a); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------- recursive call site - | | - | cannot return without recursing - | - = help: a `loop` may express intention better if this is on purpose - = note: `#[warn(unconditional_recursion)]` on by default - error[E0308]: mismatched types --> $DIR/liveness-forgot-ret.rs:4:19 | @@ -22,6 +11,17 @@ help: consider returning the local binding `a` LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a } | + +warning: function cannot return without recursing + --> $DIR/liveness-forgot-ret.rs:1:1 + | +LL | fn god_exists(a: isize) -> bool { return god_exists(a); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------- recursive call site + | | + | cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-unused.stderr b/tests/ui/liveness/liveness-unused.stderr index 9f9be8c897b5..f6c478ddbc72 100644 --- a/tests/ui/liveness/liveness-unused.stderr +++ b/tests/ui/liveness/liveness-unused.stderr @@ -1,3 +1,18 @@ +warning: unreachable statement + --> $DIR/liveness-unused.rs:92:9 + | +LL | continue; + | -------- any code following this expression is unreachable +LL | drop(*x as i32); + | ^^^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/liveness-unused.rs:1:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` + error: unused variable: `x` --> $DIR/liveness-unused.rs:8:7 | @@ -75,21 +90,6 @@ error: unused variable: `x` LL | for (x, _) in [1, 2, 3].iter().enumerate() { } | ^ help: if this is intentional, prefix it with an underscore: `_x` -warning: unreachable statement - --> $DIR/liveness-unused.rs:92:9 - | -LL | continue; - | -------- any code following this expression is unreachable -LL | drop(*x as i32); - | ^^^^^^^^^^^^^^^^ unreachable statement - | -note: the lint level is defined here - --> $DIR/liveness-unused.rs:1:9 - | -LL | #![warn(unused)] - | ^^^^^^ - = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` - error: unused variable: `x` --> $DIR/liveness-unused.rs:89:13 | diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index ab13b4876b10..5a02d01b4e1c 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -1,3 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 + | +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ---------------------------- ^ one type is more general than the other + | | + | expected due to this + | + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` + found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` + error: lifetime may not live long enough --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 | @@ -27,17 +38,6 @@ LL | a(x, y); = note: mutable references are invariant over their type parameter = help: see for more information about variance -error[E0308]: mismatched types - --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 - | -LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ one type is more general than the other - | | - | expected due to this - | - = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` - found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index f1ed0a6bb154..063ff46bb6c4 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -1,3 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 + | +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ----------------------------------------- ^ one type is more general than the other + | | + | expected due to this + | + = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)` + found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}` + error: lifetime may not live long enough --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 | @@ -27,17 +38,6 @@ LL | a(x, y, z); = note: mutable references are invariant over their type parameter = help: see for more information about variance -error[E0308]: mismatched types - --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 - | -LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ one type is more general than the other - | | - | expected due to this - | - = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)` - found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}` - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr index 807e8172d538..830a61a21f9d 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -1,3 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 + | +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ---------------------------- ^ one type is more general than the other + | | + | expected due to this + | + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` + found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` + error: lifetime may not live long enough --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5 | @@ -27,17 +38,6 @@ LL | a(x, y); = note: mutable references are invariant over their type parameter = help: see for more information about variance -error[E0308]: mismatched types - --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 - | -LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ one type is more general than the other - | | - | expected due to this - | - = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` - found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-102892.stderr b/tests/ui/suggestions/issue-102892.stderr index 58b201d1c774..38f19b332188 100644 --- a/tests/ui/suggestions/issue-102892.stderr +++ b/tests/ui/suggestions/issue-102892.stderr @@ -1,19 +1,3 @@ -error[E0507]: cannot move out of an `Arc` - --> $DIR/issue-102892.rs:11:18 - | -LL | let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! - | - - ^^^^^ - | | | - | | ...and here - | data moved here - | - = note: move occurs because these variables have types that don't implement the `Copy` trait -help: consider removing the dereference here - | -LL - let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! -LL + let (a, b) = *arc; // suggests putting `&**arc` here; with that, fixed! - | - error[E0308]: mismatched types --> $DIR/issue-102892.rs:16:26 | @@ -68,6 +52,22 @@ help: alternatively, consider changing the type annotation LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | + +error[E0507]: cannot move out of an `Arc` + --> $DIR/issue-102892.rs:11:18 + | +LL | let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! + | - - ^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the dereference here + | +LL - let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! +LL + let (a, b) = *arc; // suggests putting `&**arc` here; with that, fixed! + | + error: aborting due to 4 previous errors Some errors have detailed explanations: E0308, E0507. diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr index 3daacacdb4a3..1aaf36223b7f 100644 --- a/tests/ui/type-alias-impl-trait/variance.stderr +++ b/tests/ui/type-alias-impl-trait/variance.stderr @@ -1,69 +1,3 @@ -error: [*, o] - --> $DIR/variance.rs:8:29 - | -LL | type NotCapturedEarly<'a> = impl Sized; - | ^^^^^^^^^^ - -error: [*, o] - --> $DIR/variance.rs:11:26 - | -LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, o, o] - --> $DIR/variance.rs:14:56 - | -LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; - | ^^^^^^^^^^ - -error: [*, o, o] - --> $DIR/variance.rs:18:49 - | -LL | type Captured<'a> = dyn for<'b> Iterator>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, *, o, o, o] - --> $DIR/variance.rs:22:27 - | -LL | type Bar<'a, 'b: 'b, T> = impl Sized; - | ^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:34:32 - | -LL | type ImplicitCapture<'a> = impl Sized; - | ^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:37:42 - | -LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:40:39 - | -LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:45:32 - | -LL | type ImplicitCapture<'a> = impl Sized; - | ^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:48:42 - | -LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:51:39 - | -LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type --> $DIR/variance.rs:14:56 | @@ -176,6 +110,72 @@ LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl +error: [*, o] + --> $DIR/variance.rs:8:29 + | +LL | type NotCapturedEarly<'a> = impl Sized; + | ^^^^^^^^^^ + +error: [*, o] + --> $DIR/variance.rs:11:26 + | +LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, o, o] + --> $DIR/variance.rs:14:56 + | +LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; + | ^^^^^^^^^^ + +error: [*, o, o] + --> $DIR/variance.rs:18:49 + | +LL | type Captured<'a> = dyn for<'b> Iterator>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, *, o, o, o] + --> $DIR/variance.rs:22:27 + | +LL | type Bar<'a, 'b: 'b, T> = impl Sized; + | ^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:34:32 + | +LL | type ImplicitCapture<'a> = impl Sized; + | ^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:37:42 + | +LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:40:39 + | +LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:45:32 + | +LL | type ImplicitCapture<'a> = impl Sized; + | ^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:48:42 + | +LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:51:39 + | +LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 24 previous errors For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr index b910f668db52..f41574ca3a37 100644 --- a/tests/ui/variance/variance-associated-consts.stderr +++ b/tests/ui/variance/variance-associated-consts.stderr @@ -1,9 +1,3 @@ -error: [o] - --> $DIR/variance-associated-consts.rs:13:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^^ - error: unconstrained generic constant --> $DIR/variance-associated-consts.rs:14:12 | @@ -12,5 +6,11 @@ LL | field: [u8; ::Const] | = help: try adding a `where` bound using this expression: `where [(); ::Const]:` +error: [o] + --> $DIR/variance-associated-consts.rs:13:1 + | +LL | struct Foo { + | ^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 2 previous errors diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr index 5ac538982aa8..edfc888f6566 100644 --- a/tests/ui/variance/variance-regions-direct.stderr +++ b/tests/ui/variance/variance-regions-direct.stderr @@ -1,3 +1,11 @@ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/variance-regions-direct.rs:52:14 + | +LL | struct Test7<'a> { + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + error: [+, +, +] --> $DIR/variance-regions-direct.rs:9:1 | @@ -40,14 +48,6 @@ error: [-, +, o] LL | enum Test8<'a, 'b, 'c:'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0392]: lifetime parameter `'a` is never used - --> $DIR/variance-regions-direct.rs:52:14 - | -LL | struct Test7<'a> { - | ^^ unused lifetime parameter - | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` - error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr index b6b943026ebe..901ec0c6a762 100644 --- a/tests/ui/variance/variance-regions-indirect.stderr +++ b/tests/ui/variance/variance-regions-indirect.stderr @@ -1,33 +1,3 @@ -error: [-, +, o, *] - --> $DIR/variance-regions-indirect.rs:8:1 - | -LL | enum Base<'a, 'b, 'c:'b, 'd> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, o, +, -] - --> $DIR/variance-regions-indirect.rs:16:1 - | -LL | struct Derived1<'w, 'x:'y, 'y, 'z> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [o, o, *] - --> $DIR/variance-regions-indirect.rs:22:1 - | -LL | struct Derived2<'a, 'b:'a, 'c> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [o, +, *] - --> $DIR/variance-regions-indirect.rs:28:1 - | -LL | struct Derived3<'a:'b, 'b, 'c> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [-, +, o] - --> $DIR/variance-regions-indirect.rs:34:1 - | -LL | struct Derived4<'a, 'b, 'c:'b> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0392]: lifetime parameter `'d` is never used --> $DIR/variance-regions-indirect.rs:8:26 | @@ -60,6 +30,36 @@ LL | struct Derived3<'a:'b, 'b, 'c> { | = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` +error: [-, +, o, *] + --> $DIR/variance-regions-indirect.rs:8:1 + | +LL | enum Base<'a, 'b, 'c:'b, 'd> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, o, +, -] + --> $DIR/variance-regions-indirect.rs:16:1 + | +LL | struct Derived1<'w, 'x:'y, 'y, 'z> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o, o, *] + --> $DIR/variance-regions-indirect.rs:22:1 + | +LL | struct Derived2<'a, 'b:'a, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o, +, *] + --> $DIR/variance-regions-indirect.rs:28:1 + | +LL | struct Derived3<'a:'b, 'b, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [-, +, o] + --> $DIR/variance-regions-indirect.rs:34:1 + | +LL | struct Derived4<'a, 'b, 'c:'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr index 9d106fb11f6a..95ed18c1ad2b 100644 --- a/tests/ui/variance/variance-trait-bounds.stderr +++ b/tests/ui/variance/variance-trait-bounds.stderr @@ -1,27 +1,3 @@ -error: [+, +] - --> $DIR/variance-trait-bounds.rs:16:1 - | -LL | struct TestStruct> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, +] - --> $DIR/variance-trait-bounds.rs:21:1 - | -LL | enum TestEnum> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, +] - --> $DIR/variance-trait-bounds.rs:27:1 - | -LL | struct TestContraStruct> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, +] - --> $DIR/variance-trait-bounds.rs:33:1 - | -LL | struct TestBox+Setter> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0392]: type parameter `U` is never used --> $DIR/variance-trait-bounds.rs:21:15 | @@ -49,6 +25,30 @@ LL | struct TestBox+Setter> { = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead +error: [+, +] + --> $DIR/variance-trait-bounds.rs:16:1 + | +LL | struct TestStruct> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, +] + --> $DIR/variance-trait-bounds.rs:21:1 + | +LL | enum TestEnum> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, +] + --> $DIR/variance-trait-bounds.rs:27:1 + | +LL | struct TestContraStruct> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, +] + --> $DIR/variance-trait-bounds.rs:33:1 + | +LL | struct TestBox+Setter> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0392`. From 2eb9c6d49ef949c551892fa58270071f5e997416 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 18 Feb 2024 19:42:27 -0500 Subject: [PATCH 35/99] Lower transmutes from int to pointer type as gep on null --- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 4 ++-- tests/codegen/intrinsics/transmute.rs | 4 ++-- tests/codegen/transmute-scalar.rs | 2 +- tests/ui/abi/foreign/foreign-call-no-runtime.rs | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 9ae82d4845e1..65e90401701b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -306,11 +306,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.bitcast(imm, to_backend_ty) } (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), - (Int(..), Pointer(..)) => bx.inttoptr(imm, to_backend_ty), + (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm), (Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty), (F16 | F32 | F64 | F128, Pointer(..)) => { let int_imm = bx.bitcast(imm, bx.cx().type_isize()); - bx.inttoptr(int_imm, to_backend_ty) + bx.ptradd(bx.const_null(bx.type_ptr()), int_imm) } (Pointer(..), F16 | F32 | F64 | F128) => { let int_imm = bx.ptrtoint(imm, bx.cx().type_isize()); diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index 5a503e86010b..f858562b5f11 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -296,7 +296,7 @@ pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) { pub unsafe fn check_float_to_pointer(x: f64) -> *const () { // CHECK-NOT: alloca // CHECK: %0 = bitcast double %x to i64 - // CHECK: %_0 = inttoptr i64 %0 to ptr + // CHECK: %_0 = getelementptr i8, ptr null, i64 %0 // CHECK: ret ptr %_0 transmute(x) } @@ -371,7 +371,7 @@ pub unsafe fn check_issue_110005(x: (usize, bool)) -> Option> { // CHECK-LABEL: @check_pair_to_dst_ref( #[no_mangle] pub unsafe fn check_pair_to_dst_ref<'a>(x: (usize, usize)) -> &'a [u8] { - // CHECK: %_0.0 = inttoptr i64 %x.0 to ptr + // CHECK: %_0.0 = getelementptr i8, ptr null, i64 %x.0 // CHECK: %0 = insertvalue { ptr, i64 } poison, ptr %_0.0, 0 // CHECK: %1 = insertvalue { ptr, i64 } %0, i64 %x.1, 1 // CHECK: ret { ptr, i64 } %1 diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs index 7a5eb4dfcd5c..caaa70962d5b 100644 --- a/tests/codegen/transmute-scalar.rs +++ b/tests/codegen/transmute-scalar.rs @@ -49,7 +49,7 @@ pub fn ptr_to_int(p: *mut u16) -> usize { } // CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] %i) -// CHECK: %_0 = inttoptr [[USIZE]] %i to ptr +// CHECK: %_0 = getelementptr i8, ptr null, [[USIZE]] %i // CHECK-NEXT: ret ptr %_0 #[no_mangle] pub fn int_to_ptr(i: usize) -> *mut u16 { diff --git a/tests/ui/abi/foreign/foreign-call-no-runtime.rs b/tests/ui/abi/foreign/foreign-call-no-runtime.rs index 42d8d7b1d259..fccd62b6100f 100644 --- a/tests/ui/abi/foreign/foreign-call-no-runtime.rs +++ b/tests/ui/abi/foreign/foreign-call-no-runtime.rs @@ -40,21 +40,21 @@ pub fn main() { extern "C" fn callback_isize(data: libc::uintptr_t) { unsafe { - let data: *const isize = mem::transmute(data); + let data = data as *const isize; assert_eq!(*data, 100); } } extern "C" fn callback_i64(data: libc::uintptr_t) { unsafe { - let data: *const i64 = mem::transmute(data); + let data = data as *const i64; assert_eq!(*data, 100); } } extern "C" fn callback_i32(data: libc::uintptr_t) { unsafe { - let data: *const i32 = mem::transmute(data); + let data = data as *const i32; assert_eq!(*data, 100); } } From 7f1d08e575a6578c9a591f9a78ab13deb33704f8 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 11 Mar 2024 23:49:15 +0000 Subject: [PATCH 36/99] bootstrap: Don't eagerly format verbose messages --- src/bootstrap/src/core/build_steps/compile.rs | 7 ++--- src/bootstrap/src/core/build_steps/dist.rs | 2 +- src/bootstrap/src/core/build_steps/test.rs | 6 ++--- src/bootstrap/src/core/builder.rs | 25 +++++++++--------- src/bootstrap/src/core/config/config.rs | 7 ++--- src/bootstrap/src/core/download.rs | 26 +++++++++++-------- src/bootstrap/src/lib.rs | 25 +++++++++--------- src/bootstrap/src/utils/cc_detect.rs | 10 +++---- src/bootstrap/src/utils/render_tests.rs | 2 +- src/bootstrap/src/utils/tarball.rs | 4 ++- 10 files changed, 62 insertions(+), 52 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 242fe3c12b99..94ea2a01a405 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1536,7 +1536,8 @@ impl Step for Sysroot { }; let sysroot = sysroot_dir(compiler.stage); - builder.verbose(&format!("Removing sysroot {} to avoid caching bugs", sysroot.display())); + builder + .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display())); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); @@ -1606,7 +1607,7 @@ impl Step for Sysroot { return true; } if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) { - builder.verbose_than(1, &format!("ignoring {}", path.display())); + builder.verbose_than(1, || println!("ignoring {}", path.display())); false } else { true @@ -2085,7 +2086,7 @@ pub fn stream_cargo( cargo.arg(arg); } - builder.verbose(&format!("running: {cargo:?}")); + builder.verbose(|| println!("running: {cargo:?}")); if builder.config.dry_run() { return true; diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 613c58252d3b..3efdfc324b86 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2107,7 +2107,7 @@ fn maybe_install_llvm( { let mut cmd = Command::new(llvm_config); cmd.arg("--libfiles"); - builder.verbose(&format!("running {cmd:?}")); + builder.verbose(|| println!("running {cmd:?}")); let files = if builder.config.dry_run() { "".into() } else { output(&mut cmd) }; let build_llvm_out = &builder.llvm_out(builder.config.build); let target_llvm_out = &builder.llvm_out(target); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 248d831b6e30..2c63cde093a9 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -551,7 +551,7 @@ impl Miri { if builder.config.dry_run() { String::new() } else { - builder.verbose(&format!("running: {cargo:?}")); + builder.verbose(|| println!("running: {cargo:?}")); let out = cargo.output().expect("We already ran `cargo miri setup` before and that worked"); assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code"); @@ -559,7 +559,7 @@ impl Miri { let stdout = String::from_utf8(out.stdout) .expect("`cargo miri setup` stdout is not valid UTF-8"); let sysroot = stdout.trim_end(); - builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {sysroot:?}")); + builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}")); sysroot.to_owned() } } @@ -2326,7 +2326,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> } } - builder.verbose(&format!("doc tests for: {}", markdown.display())); + builder.verbose(|| println!("doc tests for: {}", markdown.display())); let mut cmd = builder.rustdoc_cmd(compiler); builder.add_rust_test_threads(&mut cmd); // allow for unstable options such as new editions diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 5e5d6d024ee8..db1f0bc082ab 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -382,10 +382,12 @@ impl StepDescription { } if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) { - builder.verbose(&format!( - "{:?} not skipped for {:?} -- not in {:?}", - pathset, self.name, builder.config.skip - )); + builder.verbose(|| { + println!( + "{:?} not skipped for {:?} -- not in {:?}", + pathset, self.name, builder.config.skip + ) + }); } false } @@ -1093,10 +1095,9 @@ impl<'a> Builder<'a> { // Avoid deleting the rustlib/ directory we just copied // (in `impl Step for Sysroot`). if !builder.download_rustc() { - builder.verbose(&format!( - "Removing sysroot {} to avoid caching bugs", - sysroot.display() - )); + builder.verbose(|| { + println!("Removing sysroot {} to avoid caching bugs", sysroot.display()) + }); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); } @@ -1436,7 +1437,7 @@ impl<'a> Builder<'a> { let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8"); if !matches!(self.config.dry_run, DryRun::SelfCheck) { - self.verbose_than(0, &format!("using sysroot {sysroot_str}")); + self.verbose_than(0, || println!("using sysroot {sysroot_str}")); } let mut rustflags = Rustflags::new(target); @@ -2102,11 +2103,11 @@ impl<'a> Builder<'a> { panic!("{}", out); } if let Some(out) = self.cache.get(&step) { - self.verbose_than(1, &format!("{}c {:?}", " ".repeat(stack.len()), step)); + self.verbose_than(1, || println!("{}c {:?}", " ".repeat(stack.len()), step)); return out; } - self.verbose_than(1, &format!("{}> {:?}", " ".repeat(stack.len()), step)); + self.verbose_than(1, || println!("{}> {:?}", " ".repeat(stack.len()), step)); stack.push(Box::new(step.clone())); } @@ -2144,7 +2145,7 @@ impl<'a> Builder<'a> { let cur_step = stack.pop().expect("step stack empty"); assert_eq!(cur_step.downcast_ref(), Some(&step)); } - self.verbose_than(1, &format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); + self.verbose_than(1, || println!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); self.cache.put(step, out.clone()); out } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index ae5169e93839..d317e92a1819 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2043,7 +2043,7 @@ impl Config { if self.dry_run() { return Ok(()); } - self.verbose(&format!("running: {cmd:?}")); + self.verbose(|| println!("running: {cmd:?}")); build_helper::util::try_run(cmd, self.is_verbose()) } @@ -2230,9 +2230,10 @@ impl Config { } } - pub fn verbose(&self, msg: &str) { + /// Runs a function if verbosity is greater than 0 + pub fn verbose(&self, f: impl Fn()) { if self.verbose > 0 { - println!("{msg}"); + f() } } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 27829eab9379..251138388caf 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -61,7 +61,7 @@ impl Config { if self.dry_run() { return true; } - self.verbose(&format!("running: {cmd:?}")); + self.verbose(|| println!("running: {cmd:?}")); check_run(cmd, self.is_verbose()) } @@ -195,7 +195,7 @@ impl Config { } fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) { - self.verbose(&format!("download {url}")); + self.verbose(|| println!("download {url}")); // Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/. let tempfile = self.tempdir().join(dest_path.file_name().unwrap()); // While bootstrap itself only supports http and https downloads, downstream forks might @@ -300,7 +300,9 @@ impl Config { } short_path = t!(short_path.strip_prefix(pattern)); let dst_path = dst.join(short_path); - self.verbose(&format!("extracting {} to {}", original_path.display(), dst.display())); + self.verbose(|| { + println!("extracting {} to {}", original_path.display(), dst.display()) + }); if !t!(member.unpack_in(dst)) { panic!("path traversal attack ??"); } @@ -323,7 +325,7 @@ impl Config { pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool { use sha2::Digest; - self.verbose(&format!("verifying {}", path.display())); + self.verbose(|| println!("verifying {}", path.display())); if self.dry_run() { return false; @@ -379,7 +381,7 @@ enum DownloadSource { /// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions. impl Config { pub(crate) fn download_clippy(&self) -> PathBuf { - self.verbose("downloading stage0 clippy artifacts"); + self.verbose(|| println!("downloading stage0 clippy artifacts")); let date = &self.stage0_metadata.compiler.date; let version = &self.stage0_metadata.compiler.version; @@ -469,7 +471,7 @@ impl Config { } pub(crate) fn download_ci_rustc(&self, commit: &str) { - self.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})")); + self.verbose(|| println!("using downloaded stage2 artifacts from CI (commit {commit})")); let version = self.artifact_version_part(commit); // download-rustc doesn't need its own cargo, it can just use beta's. But it does need the @@ -486,7 +488,7 @@ impl Config { } pub(crate) fn download_beta_toolchain(&self) { - self.verbose("downloading stage0 beta artifacts"); + self.verbose(|| println!("downloading stage0 beta artifacts")); let date = &self.stage0_metadata.compiler.date; let version = &self.stage0_metadata.compiler.version; @@ -625,10 +627,12 @@ impl Config { self.unpack(&tarball, &bin_root, prefix); return; } else { - self.verbose(&format!( - "ignoring cached file {} due to failed verification", - tarball.display() - )); + self.verbose(|| { + println!( + "ignoring cached file {} due to failed verification", + tarball.display() + ) + }); self.remove(&tarball); } } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 6520b7ed0898..b3e6989b33d1 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -288,7 +288,7 @@ macro_rules! forward { } forward! { - verbose(msg: &str), + verbose(f: impl Fn()), is_verbose() -> bool, create(path: &Path, s: &str), remove(f: &Path), @@ -440,11 +440,11 @@ impl Build { .unwrap() .trim(); if local_release.split('.').take(2).eq(version.split('.').take(2)) { - build.verbose(&format!("auto-detected local-rebuild {local_release}")); + build.verbose(|| println!("auto-detected local-rebuild {local_release}")); build.local_rebuild = true; } - build.verbose("finding compilers"); + build.verbose(|| println!("finding compilers")); utils::cc_detect::find(&build); // When running `setup`, the profile is about to change, so any requirements we have now may // be different on the next invocation. Don't check for them until the next time x.py is @@ -452,7 +452,7 @@ impl Build { // // Similarly, for `setup` we don't actually need submodules or cargo metadata. if !matches!(build.config.cmd, Subcommand::Setup { .. }) { - build.verbose("running sanity check"); + build.verbose(|| println!("running sanity check")); crate::core::sanity::check(&mut build); // Make sure we update these before gathering metadata so we don't get an error about missing @@ -464,7 +464,7 @@ impl Build { // Now, update all existing submodules. build.update_existing_submodules(); - build.verbose("learning about cargo"); + build.verbose(|| println!("learning about cargo")); crate::core::metadata::build(&mut build); } @@ -693,7 +693,7 @@ impl Build { let stamp = dir.join(".stamp"); let mut cleared = false; if mtime(&stamp) < mtime(input) { - self.verbose(&format!("Dirty - {}", dir.display())); + self.verbose(|| println!("Dirty - {}", dir.display())); let _ = fs::remove_dir_all(dir); cleared = true; } else if stamp.exists() { @@ -986,7 +986,7 @@ impl Build { } let command = cmd.into(); - self.verbose(&format!("running: {command:?}")); + self.verbose(|| println!("running: {command:?}")); let (output, print_error) = match command.output_mode { mode @ (OutputMode::PrintAll | OutputMode::PrintOutput) => ( @@ -1044,14 +1044,15 @@ impl Build { } } + /// Check if verbosity is greater than the `level` pub fn is_verbose_than(&self, level: usize) -> bool { self.verbosity > level } - /// Prints a message if this build is configured in more verbose mode than `level`. - fn verbose_than(&self, level: usize, msg: &str) { + /// Runs a function if verbosity is greater than `level`. + fn verbose_than(&self, level: usize, f: impl Fn()) { if self.is_verbose_than(level) { - println!("{msg}"); + f() } } @@ -1627,7 +1628,7 @@ impl Build { if self.config.dry_run() { return; } - self.verbose_than(1, &format!("Copy {src:?} to {dst:?}")); + self.verbose_than(1, || println!("Copy {src:?} to {dst:?}")); if src == dst { return; } @@ -1718,7 +1719,7 @@ impl Build { return; } let dst = dstdir.join(src.file_name().unwrap()); - self.verbose_than(1, &format!("Install {src:?} to {dst:?}")); + self.verbose_than(1, || println!("Install {src:?} to {dst:?}")); t!(fs::create_dir_all(dstdir)); if !src.exists() { panic!("ERROR: File \"{}\" not found!", src.display()); diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index ff2992bc896e..3ba4e0cb686e 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -145,15 +145,15 @@ pub fn find_target(build: &Build, target: TargetSelection) { build.cxx.borrow_mut().insert(target, compiler); } - build.verbose(&format!("CC_{} = {:?}", &target.triple, build.cc(target))); - build.verbose(&format!("CFLAGS_{} = {:?}", &target.triple, cflags)); + build.verbose(|| println!("CC_{} = {:?}", &target.triple, build.cc(target))); + build.verbose(|| println!("CFLAGS_{} = {:?}", &target.triple, cflags)); if let Ok(cxx) = build.cxx(target) { let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx); - build.verbose(&format!("CXX_{} = {:?}", &target.triple, cxx)); - build.verbose(&format!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags)); + build.verbose(|| println!("CXX_{} = {:?}", &target.triple, cxx)); + build.verbose(|| println!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags)); } if let Some(ar) = ar { - build.verbose(&format!("AR_{} = {:?}", &target.triple, ar)); + build.verbose(|| println!("AR_{} = {:?}", &target.triple, ar)); build.ar.borrow_mut().insert(target, ar); } diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index cbd01606a895..70f25b2cc87c 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -44,7 +44,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bo fn run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool { cmd.stdout(Stdio::piped()); - builder.verbose(&format!("running: {cmd:?}")); + builder.verbose(|| println!("running: {cmd:?}")); let mut process = cmd.spawn().unwrap(); diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index a14dfd1ca123..03f56cba29d8 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -328,7 +328,9 @@ impl<'a> Tarball<'a> { // For `x install` tarball files aren't needed, so we can speed up the process by not producing them. let compression_profile = if self.builder.kind == Kind::Install { - self.builder.verbose("Forcing dist.compression-profile = 'no-op' for `x install`."); + self.builder.verbose(|| { + println!("Forcing dist.compression-profile = 'no-op' for `x install`.") + }); // "no-op" indicates that the rust-installer won't produce compressed tarball sources. "no-op" } else { From f4b2a8a1ca52106bede3bb5de41080bb4669ce62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 12 Mar 2024 01:23:02 +0100 Subject: [PATCH 37/99] rustdoc: fix up old test --- src/tools/compiletest/src/header.rs | 1 - tests/rustdoc/line-breaks.rs | 41 ++++++++++++++++++----------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 213e2a63517e..69658222ff3e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -694,7 +694,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-stdout", "check-test-line-numbers-match", "compile-flags", - "count", "dont-check-compiler-stderr", "dont-check-compiler-stdout", "dont-check-failure-status", diff --git a/tests/rustdoc/line-breaks.rs b/tests/rustdoc/line-breaks.rs index 29c16fcd4f8a..21aa3a03ce43 100644 --- a/tests/rustdoc/line-breaks.rs +++ b/tests/rustdoc/line-breaks.rs @@ -1,26 +1,37 @@ #![crate_name = "foo"] -use std::ops::Add; use std::fmt::Display; +use std::ops::Add; -//@count foo/fn.function_with_a_really_long_name.html //pre/br 2 -pub fn function_with_a_really_long_name(parameter_one: i32, - parameter_two: i32) - -> Option { +// @matches foo/fn.function_with_a_really_long_name.html '//*[@class="rust item-decl"]//code' "\ +// function_with_a_really_long_name\(\n\ +// \ parameter_one: i32,\n\ +// \ parameter_two: i32\n\ +// \) -> Option$" +pub fn function_with_a_really_long_name(parameter_one: i32, parameter_two: i32) -> Option { Some(parameter_one + parameter_two) } -//@count foo/fn.short_name.html //pre/br 0 -pub fn short_name(param: i32) -> i32 { param + 1 } +// @matches foo/fn.short_name.html '//*[@class="rust item-decl"]//code' \ +// "short_name\(param: i32\) -> i32$" +pub fn short_name(param: i32) -> i32 { + param + 1 +} -//@count foo/fn.where_clause.html //pre/br 4 -pub fn where_clause(param_one: T, - param_two: U) - where T: Add + Display + Copy, - U: Add + Display + Copy, - T::Output: Display + Add + Copy, - >::Output: Display, - U::Output: Display + Copy +// @matches foo/fn.where_clause.html '//*[@class="rust item-decl"]//code' "\ +// where_clause\(param_one: T, param_two: U\)where\n\ +// \ T: Add \+ Display \+ Copy,\n\ +// \ U: Add \+ Display \+ Copy,\n\ +// \ T::Output: Display \+ Add \+ Copy,\n\ +// \ >::Output: Display,\n\ +// \ U::Output: Display \+ Copy,$" +pub fn where_clause(param_one: T, param_two: U) +where + T: Add + Display + Copy, + U: Add + Display + Copy, + T::Output: Display + Add + Copy, + >::Output: Display, + U::Output: Display + Copy, { let x = param_one + param_two; println!("{} + {} = {}", param_one, param_two, x); From 55ba7a7c622fb1ac95ef05e4a652cedf923a8164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 9 Mar 2024 09:29:16 +0100 Subject: [PATCH 38/99] Verify that query keys result in unique dep nodes --- compiler/rustc_interface/src/queries.rs | 2 + compiler/rustc_query_impl/src/lib.rs | 2 +- compiler/rustc_query_impl/src/plumbing.rs | 50 +++++++++++++++++++++++ compiler/rustc_session/src/options.rs | 4 +- 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index da11d090b749..c22188226961 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -321,6 +321,8 @@ impl Compiler { } self.sess.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); + + gcx.enter(rustc_query_impl::query_key_hash_verify_all); } // The timer's lifetime spans the dropping of `queries`, which contains diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 33116737a420..527671555327 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -41,7 +41,7 @@ use rustc_span::{ErrorGuaranteed, Span}; #[macro_use] mod plumbing; -pub use crate::plumbing::QueryCtxt; +pub use crate::plumbing::{query_key_hash_verify_all, QueryCtxt}; mod profiling_support; pub use self::profiling_support::alloc_self_profile_query_strings; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b06d75be3902..aa9657797310 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -7,6 +7,7 @@ use crate::rustc_middle::ty::TyEncoder; use crate::QueryConfigRestored; use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_data_structures::sync::Lock; +use rustc_data_structures::unord::UnordMap; use rustc_errors::DiagInner; use rustc_index::Idx; @@ -189,6 +190,16 @@ pub(super) fn encode_all_query_results<'tcx>( } } +pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) { + if tcx.sess().opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) { + tcx.sess.time("query_key_hash_verify_all", || { + for verify in super::QUERY_KEY_HASH_VERIFY.iter() { + verify(tcx); + } + }) + } +} + macro_rules! handle_cycle_error { ([]) => {{ rustc_query_system::HandleCycleError::Error @@ -370,6 +381,34 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>( }); } +pub(crate) fn query_key_hash_verify<'tcx>( + query: impl QueryConfig>, + qcx: QueryCtxt<'tcx>, +) { + let _timer = + qcx.profiler().generic_activity_with_arg("query_key_hash_verify_for", query.name()); + + let mut map = UnordMap::default(); + + let cache = query.query_cache(qcx); + cache.iter(&mut |key, _, _| { + let node = DepNode::construct(qcx.tcx, query.dep_kind(), key); + if let Some(other_key) = map.insert(node, *key) { + bug!( + "query key:\n\ + `{:?}`\n\ + and key:\n\ + `{:?}`\n\ + mapped to the same dep node:\n\ + {:?}", + key, + other_key, + node + ); + } + }); +} + fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) where Q: QueryConfig>, @@ -691,6 +730,13 @@ macro_rules! define_queries { ) } }} + + pub fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) { + $crate::plumbing::query_key_hash_verify( + query_impl::$name::QueryType::config(tcx), + QueryCtxt::new(tcx), + ) + } })*} pub(crate) fn engine(incremental: bool) -> QueryEngine { @@ -730,6 +776,10 @@ macro_rules! define_queries { > ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*]; + const QUERY_KEY_HASH_VERIFY: &[ + for<'tcx> fn(TyCtxt<'tcx>) + ] = &[$(query_impl::$name::query_key_hash_verify),*]; + #[allow(nonstandard_style)] mod query_callbacks { use super::*; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 93bef82e4ba1..0122b9ec33e9 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1674,7 +1674,9 @@ options! { "print high-level information about incremental reuse (or the lack thereof) \ (default: no)"), incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED], - "verify incr. comp. hashes of green query instances (default: no)"), + "verify extended properties for incr. comp. (default: no): + - hashes of green query instances + - hash collisions of query keys"), inline_in_all_cgus: Option = (None, parse_opt_bool, [TRACKED], "control whether `#[inline]` functions are in all CGUs"), inline_llvm: bool = (true, parse_bool, [TRACKED], From 98553ce27e68e2d7b8fb3919c9aec7253dfd3a5a Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sun, 10 Mar 2024 14:34:01 +0100 Subject: [PATCH 39/99] tests: Add ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs Which is a variant of [`unix_sigpipe-list.rs`][1] but where a string is used instead of an identifier. This makes it more similar to the proper form `#[unix_sigpipe = "sig_dfl"]` and thus more likely to be written by users by mistake. Also rename the first test to be more in line with the terminology of [The Reference][2]. [1]: https://github.com/rust-lang/rust/blob/master/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs [2]: https://doc.rust-lang.org/reference/attributes.html#meta-item-attribute-syntax --- .../{unix_sigpipe-list.rs => unix_sigpipe-ident-list.rs} | 0 ...sigpipe-list.stderr => unix_sigpipe-ident-list.stderr} | 2 +- tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs | 4 ++++ .../attributes/unix_sigpipe/unix_sigpipe-str-list.stderr | 8 ++++++++ 4 files changed, 13 insertions(+), 1 deletion(-) rename tests/ui/attributes/unix_sigpipe/{unix_sigpipe-list.rs => unix_sigpipe-ident-list.rs} (100%) rename tests/ui/attributes/unix_sigpipe/{unix_sigpipe-list.stderr => unix_sigpipe-ident-list.stderr} (84%) create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs similarity index 100% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs rename to tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr similarity index 84% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr rename to tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr index 66902f3ca9aa..a020f21e6ca7 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr @@ -1,5 +1,5 @@ error: malformed `unix_sigpipe` attribute input - --> $DIR/unix_sigpipe-list.rs:3:1 + --> $DIR/unix_sigpipe-ident-list.rs:3:1 | LL | #[unix_sigpipe(sig_dfl)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs new file mode 100644 index 000000000000..22326835623b --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs @@ -0,0 +1,4 @@ +#![feature(unix_sigpipe)] + +#[unix_sigpipe("sig_dfl")] //~ error: malformed `unix_sigpipe` attribute input +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr new file mode 100644 index 000000000000..b62c086e3605 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr @@ -0,0 +1,8 @@ +error: malformed `unix_sigpipe` attribute input + --> $DIR/unix_sigpipe-str-list.rs:3:1 + | +LL | #[unix_sigpipe("sig_dfl")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` + +error: aborting due to 1 previous error + From 0a2475c50aceeca97e157bf6826e5d48af967c31 Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Fri, 2 Sep 2022 19:12:03 -0400 Subject: [PATCH 40/99] Add tests showing how we duplicate allocations when we shouldn't --- .../consts/auxiliary/const_mut_refs_crate.rs | 23 ++++++++++++ tests/ui/consts/const-mut-refs-crate.rs | 35 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 tests/ui/consts/auxiliary/const_mut_refs_crate.rs create mode 100644 tests/ui/consts/const-mut-refs-crate.rs diff --git a/tests/ui/consts/auxiliary/const_mut_refs_crate.rs b/tests/ui/consts/auxiliary/const_mut_refs_crate.rs new file mode 100644 index 000000000000..8e78748e896e --- /dev/null +++ b/tests/ui/consts/auxiliary/const_mut_refs_crate.rs @@ -0,0 +1,23 @@ +// This is a support file for ../const-mut-refs-crate.rs + +// This is to test that static inners from an external +// crate like this one, still preserves the alloc. +// That is, the address from the standpoint of rustc+llvm +// is the same. +// The need for this test originated from the GH issue +// https://github.com/rust-lang/rust/issues/57349 + +// See also ../const-mut-refs-crate.rs for more details +// about this test. + +#![feature(const_mut_refs)] + +// if we used immutable references here, then promotion would +// turn the `&42` into a promoted, which gets duplicated arbitrarily. +pub static mut FOO: &'static mut i32 = &mut 42; +pub static mut BAR: &'static mut i32 = unsafe { FOO }; + +pub mod inner { + pub static INNER_MOD_FOO: &'static i32 = &43; + pub static INNER_MOD_BAR: &'static i32 = INNER_MOD_FOO; +} diff --git a/tests/ui/consts/const-mut-refs-crate.rs b/tests/ui/consts/const-mut-refs-crate.rs new file mode 100644 index 000000000000..96df2cefce27 --- /dev/null +++ b/tests/ui/consts/const-mut-refs-crate.rs @@ -0,0 +1,35 @@ +//@ run-pass +//@ aux-build:const_mut_refs_crate.rs + +#![feature(const_mut_refs)] + +//! Regression test for https://github.com/rust-lang/rust/issues/79738 +//! Show how we are duplicationg allocations, even though static items that +//! copy their value from another static should not also be duplicating +//! memory behind references. + +extern crate const_mut_refs_crate as other; + +use other::{ + inner::{INNER_MOD_BAR, INNER_MOD_FOO}, + BAR, FOO, +}; + +pub static LOCAL_FOO: &'static i32 = &41; +pub static LOCAL_BAR: &'static i32 = LOCAL_FOO; +pub static mut COPY_OF_REMOTE_FOO: &'static mut i32 = unsafe { FOO }; + +static DOUBLE_REF: &&i32 = &&99; +static ONE_STEP_ABOVE: &i32 = *DOUBLE_REF; + +pub fn main() { + unsafe { + assert_ne!(FOO as *const i32, BAR as *const i32); + assert_eq!(INNER_MOD_FOO as *const i32, INNER_MOD_BAR as *const i32); + assert_eq!(LOCAL_FOO as *const i32, LOCAL_BAR as *const i32); + assert_eq!(*DOUBLE_REF as *const i32, ONE_STEP_ABOVE as *const i32); + + // bug! + assert_ne!(FOO as *const i32, COPY_OF_REMOTE_FOO as *const i32); + } +} From dd1e27120d253017c85e40871b23e91faab56abd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 6 Oct 2023 12:16:56 +0000 Subject: [PATCH 41/99] Share the llvm type computation between both arms of a condition --- compiler/rustc_codegen_llvm/src/consts.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index ec2fb2c6e546..f8fca39ec3c8 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -17,7 +17,7 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, Instance, Ty}; +use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use rustc_session::config::Lto; use rustc_target::abi::{ @@ -147,11 +147,10 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: fn check_and_apply_linkage<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, attrs: &CodegenFnAttrs, - ty: Ty<'tcx>, + llty: &'ll Type, sym: &str, def_id: DefId, ) -> &'ll Value { - let llty = cx.layout_of(ty).llvm_type(cx); if let Some(linkage) = attrs.import_linkage { debug!("get_static: sym={} linkage={:?}", sym, linkage); @@ -245,9 +244,9 @@ impl<'ll> CodegenCx<'ll, '_> { let fn_attrs = self.tcx.codegen_fn_attrs(def_id); debug!("get_static: sym={} instance={:?} fn_attrs={:?}", sym, instance, fn_attrs); + let llty = self.layout_of(ty).llvm_type(self); let g = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) { - let llty = self.layout_of(ty).llvm_type(self); if let Some(g) = self.get_declared_value(sym) { if self.val_ty(g) != self.type_ptr() { span_bug!(self.tcx.def_span(def_id), "Conflicting types for static"); @@ -264,7 +263,7 @@ impl<'ll> CodegenCx<'ll, '_> { g } else { - check_and_apply_linkage(self, fn_attrs, ty, sym, def_id) + check_and_apply_linkage(self, fn_attrs, llty, sym, def_id) }; // Thread-local statics in some other crate need to *always* be linked From d4b30aa96c12191f3ee35d48b4827c5a2c7a712b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 6 Oct 2023 13:32:57 +0000 Subject: [PATCH 42/99] Reduce some duplicate work that is being done around statics --- compiler/rustc_codegen_llvm/src/consts.rs | 26 ++++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index f8fca39ec3c8..95f14780e578 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -225,9 +225,20 @@ impl<'ll> CodegenCx<'ll, '_> { } } + #[instrument(level = "debug", skip(self))] pub(crate) fn get_static(&self, def_id: DefId) -> &'ll Value { let instance = Instance::mono(self.tcx, def_id); - if let Some(&g) = self.instances.borrow().get(&instance) { + trace!(?instance); + let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + trace!(?ty); + let llty = self.layout_of(ty).llvm_type(self); + self.get_static_inner(def_id, llty) + } + + #[instrument(level = "debug", skip(self, llty))] + pub(crate) fn get_static_inner(&self, def_id: DefId, llty: &'ll Type) -> &'ll Value { + if let Some(&g) = self.instances.borrow().get(&Instance::mono(self.tcx, def_id)) { + trace!("used cached value"); return g; } @@ -239,12 +250,10 @@ impl<'ll> CodegenCx<'ll, '_> { statics defined in the same CGU, but did not for `{def_id:?}`" ); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); - let sym = self.tcx.symbol_name(instance).name; + let sym = self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name; let fn_attrs = self.tcx.codegen_fn_attrs(def_id); - debug!("get_static: sym={} instance={:?} fn_attrs={:?}", sym, instance, fn_attrs); - let llty = self.layout_of(ty).llvm_type(self); + debug!(?sym, ?fn_attrs); let g = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) { if let Some(g) = self.get_declared_value(sym) { @@ -331,7 +340,7 @@ impl<'ll> CodegenCx<'ll, '_> { } } - self.instances.borrow_mut().insert(instance, g); + self.instances.borrow_mut().insert(Instance::mono(self.tcx, def_id), g); g } } @@ -367,13 +376,14 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { }; let alloc = alloc.inner(); - let g = self.get_static(def_id); - let val_llty = self.val_ty(v); let instance = Instance::mono(self.tcx, def_id); let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); let llty = self.layout_of(ty).llvm_type(self); + + let g = self.get_static_inner(def_id, llty); + let g = if val_llty == llty { g } else { From 6719a8ef953ba9d90f2a589d80f41fae4531614f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 6 Oct 2023 14:12:51 +0000 Subject: [PATCH 43/99] Move `codegen_static` function body to an inherent method in preparation of splitting it. This should make the diff easier to read, as this commit does no functional changes at all. --- compiler/rustc_codegen_llvm/src/consts.rs | 50 ++++++++++++----------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 95f14780e578..9c1b64fdb006 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -343,30 +343,8 @@ impl<'ll> CodegenCx<'ll, '_> { self.instances.borrow_mut().insert(Instance::mono(self.tcx, def_id), g); g } -} -impl<'ll> StaticMethods for CodegenCx<'ll, '_> { - fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value { - if let Some(&gv) = self.const_globals.borrow().get(&cv) { - unsafe { - // Upgrade the alignment in cases where the same constant is used with different - // alignment requirements - let llalign = align.bytes() as u32; - if llalign > llvm::LLVMGetAlignment(gv) { - llvm::LLVMSetAlignment(gv, llalign); - } - } - return gv; - } - let gv = self.static_addr_of_mut(cv, align, kind); - unsafe { - llvm::LLVMSetGlobalConstant(gv, True); - } - self.const_globals.borrow_mut().insert(cv, gv); - gv - } - - fn codegen_static(&self, def_id: DefId, is_mutable: bool) { + fn codegen_static_item(&self, def_id: DefId, is_mutable: bool) { unsafe { let attrs = self.tcx.codegen_fn_attrs(def_id); @@ -550,6 +528,32 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { } } } +} + +impl<'ll> StaticMethods for CodegenCx<'ll, '_> { + fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value { + if let Some(&gv) = self.const_globals.borrow().get(&cv) { + unsafe { + // Upgrade the alignment in cases where the same constant is used with different + // alignment requirements + let llalign = align.bytes() as u32; + if llalign > llvm::LLVMGetAlignment(gv) { + llvm::LLVMSetAlignment(gv, llalign); + } + } + return gv; + } + let gv = self.static_addr_of_mut(cv, align, kind); + unsafe { + llvm::LLVMSetGlobalConstant(gv, True); + } + self.const_globals.borrow_mut().insert(cv, gv); + gv + } + + fn codegen_static(&self, def_id: DefId, is_mutable: bool) { + self.codegen_static_item(def_id, is_mutable) + } /// Add a global value to a list to be stored in the `llvm.used` variable, an array of ptr. fn add_used_global(&self, global: &'ll Value) { From fcb890ea0c2d47d2fe6ea45fbb41fd3cb78645c8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 6 Oct 2023 14:39:23 +0000 Subject: [PATCH 44/99] Use information from allocation instead of from the static's type --- compiler/rustc_codegen_llvm/src/consts.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 9c1b64fdb006..fbbc1ecbbca0 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -358,6 +358,10 @@ impl<'ll> CodegenCx<'ll, '_> { let instance = Instance::mono(self.tcx, def_id); let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + if !is_mutable { + debug_assert_eq!(alloc.mutability.is_not(), self.type_is_freeze(ty)); + } + debug_assert_eq!(alloc.align, self.align_of(ty)); let llty = self.layout_of(ty).llvm_type(self); let g = self.get_static_inner(def_id, llty); @@ -396,7 +400,7 @@ impl<'ll> CodegenCx<'ll, '_> { self.statics_to_rauw.borrow_mut().push((g, new_g)); new_g }; - set_global_alignment(self, g, self.align_of(ty)); + set_global_alignment(self, g, alloc.align); llvm::LLVMSetInitializer(g, v); if self.should_assume_dso_local(g, true) { @@ -405,7 +409,7 @@ impl<'ll> CodegenCx<'ll, '_> { // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. - if !is_mutable && self.type_is_freeze(ty) { + if !is_mutable && alloc.mutability.is_not() { llvm::LLVMSetGlobalConstant(g, llvm::True); } From f0fa06bb7a0fae8743e0b5b25ccd24e03ec2ef74 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 6 Oct 2023 14:43:37 +0000 Subject: [PATCH 45/99] Swap the order of a piece of code to make follow up diffs simpler --- compiler/rustc_codegen_llvm/src/consts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index fbbc1ecbbca0..5d25e6cf03fb 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -354,8 +354,6 @@ impl<'ll> CodegenCx<'ll, '_> { }; let alloc = alloc.inner(); - let val_llty = self.val_ty(v); - let instance = Instance::mono(self.tcx, def_id); let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); if !is_mutable { @@ -366,6 +364,8 @@ impl<'ll> CodegenCx<'ll, '_> { let g = self.get_static_inner(def_id, llty); + let val_llty = self.val_ty(v); + let g = if val_llty == llty { g } else { From 0ef52380a58d7224fac71cc36e9e4c0dc99aec33 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 6 Oct 2023 15:00:44 +0000 Subject: [PATCH 46/99] Check whether a static is mutable instead of passing it down --- compiler/rustc_codegen_gcc/src/consts.rs | 4 ++-- compiler/rustc_codegen_llvm/src/consts.rs | 10 +++++----- compiler/rustc_codegen_ssa/src/mono_item.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/statics.rs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 327c9bdada92..740956f6fdfd 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -63,7 +63,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { global_value } - fn codegen_static(&self, def_id: DefId, is_mutable: bool) { + fn codegen_static(&self, def_id: DefId) { let attrs = self.tcx.codegen_fn_attrs(def_id); let value = match codegen_static_initializer(&self, def_id) { @@ -92,7 +92,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. - if !is_mutable && self.type_is_freeze(ty) { + if !self.tcx.static_mutability(def_id).unwrap().is_mut() && self.type_is_freeze(ty) { #[cfg(feature = "master")] global.global_set_readonly(); } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 5d25e6cf03fb..4dde7ec9cf3f 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -344,7 +344,7 @@ impl<'ll> CodegenCx<'ll, '_> { g } - fn codegen_static_item(&self, def_id: DefId, is_mutable: bool) { + fn codegen_static_item(&self, def_id: DefId) { unsafe { let attrs = self.tcx.codegen_fn_attrs(def_id); @@ -356,7 +356,7 @@ impl<'ll> CodegenCx<'ll, '_> { let instance = Instance::mono(self.tcx, def_id); let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); - if !is_mutable { + if !self.tcx.is_mutable_static(def_id) { debug_assert_eq!(alloc.mutability.is_not(), self.type_is_freeze(ty)); } debug_assert_eq!(alloc.align, self.align_of(ty)); @@ -409,7 +409,7 @@ impl<'ll> CodegenCx<'ll, '_> { // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. - if !is_mutable && alloc.mutability.is_not() { + if alloc.mutability.is_not() { llvm::LLVMSetGlobalConstant(g, llvm::True); } @@ -555,8 +555,8 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { gv } - fn codegen_static(&self, def_id: DefId, is_mutable: bool) { - self.codegen_static_item(def_id, is_mutable) + fn codegen_static(&self, def_id: DefId) { + self.codegen_static_item(def_id) } /// Add a global value to a list to be stored in the `llvm.used` variable, an array of ptr. diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 1a4795c0213a..7b7cdae0ed61 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -30,7 +30,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { match *self { MonoItem::Static(def_id) => { - cx.codegen_static(def_id, cx.tcx().is_mutable_static(def_id)); + cx.codegen_static(def_id); } MonoItem::GlobalAsm(item_id) => { let item = cx.tcx().hir().item(item_id); diff --git a/compiler/rustc_codegen_ssa/src/traits/statics.rs b/compiler/rustc_codegen_ssa/src/traits/statics.rs index 413d31bb9429..737d93fd80ab 100644 --- a/compiler/rustc_codegen_ssa/src/traits/statics.rs +++ b/compiler/rustc_codegen_ssa/src/traits/statics.rs @@ -4,7 +4,7 @@ use rustc_target::abi::Align; pub trait StaticMethods: BackendTypes { fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; - fn codegen_static(&self, def_id: DefId, is_mutable: bool); + fn codegen_static(&self, def_id: DefId); /// Mark the given global value as "used", to prevent the compiler and linker from potentially /// removing a static variable that may otherwise appear unused. From 12e2846514b4caf54430e1a7fc84626d2c39928f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 23 Feb 2024 16:06:04 +0000 Subject: [PATCH 47/99] Stop requiring a type when codegenning types. We can get all the type info we need from the `ConstAllocation` --- compiler/rustc_codegen_llvm/src/consts.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 4dde7ec9cf3f..8acb3de88675 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -354,18 +354,11 @@ impl<'ll> CodegenCx<'ll, '_> { }; let alloc = alloc.inner(); - let instance = Instance::mono(self.tcx, def_id); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); - if !self.tcx.is_mutable_static(def_id) { - debug_assert_eq!(alloc.mutability.is_not(), self.type_is_freeze(ty)); - } - debug_assert_eq!(alloc.align, self.align_of(ty)); - let llty = self.layout_of(ty).llvm_type(self); - - let g = self.get_static_inner(def_id, llty); - let val_llty = self.val_ty(v); + let g = self.get_static_inner(def_id, val_llty); + let llty = self.val_ty(g); + let g = if val_llty == llty { g } else { From 98169159546b435305c3443e1bd69d69e2405289 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 23 Feb 2024 23:12:20 +0000 Subject: [PATCH 48/99] Change `DefKind::Static` to a struct variant --- compiler/rustc_ast_lowering/src/asm.rs | 2 +- .../src/back/symbol_export.rs | 4 ++-- .../src/const_eval/eval_queries.rs | 2 +- .../src/interpret/validity.rs | 19 ++++++++------- compiler/rustc_hir/src/def.rs | 13 ++++++---- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_hir/src/target.rs | 4 ++-- .../rustc_hir_analysis/src/astconv/mod.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 4 ++-- compiler/rustc_hir_analysis/src/check/errs.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/demand.rs | 2 +- .../src/mem_categorization.rs | 2 +- .../infer/error_reporting/note_and_explain.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 24 +++++++++---------- compiler/rustc_metadata/src/rmeta/table.rs | 4 ++-- compiler/rustc_middle/src/hir/map/mod.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 4 ++-- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 4 ++-- compiler/rustc_mir_build/src/build/mod.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 2 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 4 ++-- .../rustc_monomorphize/src/polymorphize.rs | 2 +- compiler/rustc_passes/src/dead.rs | 4 ++-- compiler/rustc_passes/src/reachable.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 8 +++---- .../rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/def_collector.rs | 4 ++-- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/late.rs | 4 ++-- compiler/rustc_smir/src/rustc_smir/context.rs | 2 +- compiler/rustc_smir/src/rustc_smir/mod.rs | 2 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 2 +- compiler/rustc_ty_utils/src/opaque_types.rs | 2 +- compiler/rustc_ty_utils/src/sig_types.rs | 2 +- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/utils.rs | 2 +- src/librustdoc/formats/item_type.rs | 2 +- .../passes/collect_intra_doc_links.rs | 6 ++--- .../src/loops/needless_range_loop.rs | 2 +- .../src/loops/while_immutable_condition.rs | 2 +- .../src/methods/expect_fun_call.rs | 2 +- .../src/multiple_unsafe_ops_per_block.rs | 4 ++-- 47 files changed, 90 insertions(+), 86 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index cef50a70534c..666e7763e627 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -196,7 +196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .get_partial_res(sym.id) .and_then(|res| res.full_res()) .and_then(|res| match res { - Res::Def(DefKind::Static(_), def_id) => Some(def_id), + Res::Def(DefKind::Static { .. }, def_id) => Some(def_id), _ => None, }); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 72648e5ade49..87b6f0e914c3 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -87,7 +87,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap {} + DefKind::Fn | DefKind::Static { .. } => {} DefKind::AssocFn if tcx.impl_of_method(def_id.to_def_id()).is_some() => {} _ => return None, }; @@ -483,7 +483,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel let target = &tcx.sess.target.llvm_target; // WebAssembly cannot export data symbols, so reduce their export level if target.contains("emscripten") { - if let DefKind::Static(_) = tcx.def_kind(sym_def_id) { + if let DefKind::Static { .. } = tcx.def_kind(sym_def_id) { return SymbolExportLevel::Rust; } } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 90884adb28c6..81a85dfa1896 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -37,7 +37,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( || matches!( ecx.tcx.def_kind(cid.instance.def_id()), DefKind::Const - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 972424bccfa0..f69788604399 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -457,15 +457,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Special handling for pointers to statics (irrespective of their type). assert!(!self.ecx.tcx.is_thread_local_static(did)); assert!(self.ecx.tcx.is_static(did)); - let is_mut = - matches!(self.ecx.tcx.def_kind(did), DefKind::Static(Mutability::Mut)) - || !self - .ecx - .tcx - .type_of(did) - .no_bound_vars() - .expect("statics should not have generic parameters") - .is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all()); + let is_mut = matches!( + self.ecx.tcx.def_kind(did), + DefKind::Static { mt: Mutability::Mut } + ) || !self + .ecx + .tcx + .type_of(did) + .no_bound_vars() + .expect("statics should not have generic parameters") + .is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all()); // Mode-specific checks match self.ctfe_mode { Some( diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 23943ee28e2e..3dc4a6a641f6 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -75,7 +75,10 @@ pub enum DefKind { Const, /// Constant generic parameter: `struct Foo { ... }` ConstParam, - Static(ast::Mutability), + Static { + /// Whether it's a `static mut` or just a `static`. + mt: ast::Mutability, + }, /// Refers to the struct or enum variant's constructor. /// /// The reason `Ctor` exists in addition to [`DefKind::Struct`] and @@ -136,7 +139,7 @@ impl DefKind { DefKind::Fn => "function", DefKind::Mod if def_id.is_crate_root() && !def_id.is_local() => "crate", DefKind::Mod => "module", - DefKind::Static(..) => "static", + DefKind::Static { .. } => "static", DefKind::Enum => "enum", DefKind::Variant => "variant", DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant", @@ -209,7 +212,7 @@ impl DefKind { DefKind::Fn | DefKind::Const | DefKind::ConstParam - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst => Some(Namespace::ValueNS), @@ -248,7 +251,7 @@ impl DefKind { DefKind::Fn | DefKind::Const | DefKind::ConstParam - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::AssocFn | DefKind::AssocConst | DefKind::Field => DefPathData::ValueNs(name), @@ -278,7 +281,7 @@ impl DefKind { | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure - | DefKind::Static(_) => true, + | DefKind::Static { .. } => true, DefKind::Mod | DefKind::Struct | DefKind::Union diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 18dabe67dae8..8a7d32997b02 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1616,7 +1616,7 @@ impl Expr<'_> { pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool { match self.kind { ExprKind::Path(QPath::Resolved(_, ref path)) => { - matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static(_), _) | Res::Err) + matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static { .. }, _) | Res::Err) } // Type ascription inherits its place expression kind from its diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 8948a03e4a6f..e448d29e55fb 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -107,7 +107,7 @@ impl Target { match item.kind { ItemKind::ExternCrate(..) => Target::ExternCrate, ItemKind::Use(..) => Target::Use, - ItemKind::Static(..) => Target::Static, + ItemKind::Static { .. } => Target::Static, ItemKind::Const(..) => Target::Const, ItemKind::Fn(..) => Target::Fn, ItemKind::Macro(..) => Target::MacroDef, @@ -130,7 +130,7 @@ impl Target { match def_kind { DefKind::ExternCrate => Target::ExternCrate, DefKind::Use => Target::Use, - DefKind::Static(..) => Target::Static, + DefKind::Static { .. } => Target::Static, DefKind::Const => Target::Const, DefKind::Fn => Target::Fn, DefKind::Macro(..) => Target::MacroDef, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 325342d653dd..25df76359a88 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1934,7 +1934,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } // Case 3. Reference to a top-level value. - DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static(_) => { + DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static { .. } => { path_segs.push(PathSeg(def_id, last)); } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index cb739ac48a8b..246140c9e95e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -226,7 +226,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { Ok(l) => l, // Foreign statics that overflow their allowed size should emit an error Err(LayoutError::SizeOverflow(_)) - if matches!(tcx.def_kind(def_id), DefKind::Static(_) + if matches!(tcx.def_kind(def_id), DefKind::Static{..} if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) => { tcx.dcx().emit_err(errors::TooLargeStatic { span }); @@ -505,7 +505,7 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) { pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { let _indenter = indenter(); match tcx.def_kind(def_id) { - DefKind::Static(..) => { + DefKind::Static { .. } => { tcx.ensure().typeck(def_id); maybe_check_static_with_link_section(tcx, def_id); check_static_inhabited(tcx, def_id); diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index 3d32fdd89c86..068b263fa869 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -48,7 +48,7 @@ fn is_path_static_mut(expr: hir::Expr<'_>) -> Option { if let hir::ExprKind::Path(qpath) = expr.kind && let hir::QPath::Resolved(_, path) = qpath && let hir::def::Res::Def(def_kind, _) = path.res - && let hir::def::DefKind::Static(mt) = def_kind + && let hir::def::DefKind::Static { mt } = def_kind && matches!(mt, Mutability::Mut) { return Some(qpath_to_string(&qpath)); diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 696c47710c23..b1b36ade5080 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -182,7 +182,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { tcx.hir().par_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); match def_kind { - DefKind::Static(_) => tcx.ensure().eval_static_initializer(item_def_id), + DefKind::Static { .. } => tcx.ensure().eval_static_initializer(item_def_id), DefKind::Const => tcx.ensure().const_eval_poly(item_def_id.into()), _ => (), } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0c5c80ea8907..71da65543403 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -699,7 +699,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Path { res: hir::def::Res::Def( - hir::def::DefKind::Static(_) | hir::def::DefKind::Const, + hir::def::DefKind::Static { .. } | hir::def::DefKind::Const, def_id, ), .. diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 1a860aa40679..9307cccf092c 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -398,7 +398,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ) | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, expr_ty)), - Res::Def(DefKind::Static(_), _) => { + Res::Def(DefKind::Static { .. }, _) => { Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new())) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 1cbb4b2b23d6..d14cabfc429b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -372,7 +372,7 @@ impl Trait for X { && matches!( tcx.def_kind(body_owner_def_id), DefKind::Fn - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Const | DefKind::AssocFn | DefKind::AssocConst diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 6e9cbfdcfee2..b87cda4a79f2 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -863,7 +863,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::LifetimeParam | DefKind::Fn | DefKind::Const - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst @@ -894,7 +894,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::AssocTy | DefKind::Fn | DefKind::Const - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::AssocFn | DefKind::AssocConst | DefKind::Macro(_) @@ -936,7 +936,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::Fn | DefKind::Const | DefKind::ConstParam - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst @@ -968,7 +968,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::AssocTy | DefKind::Fn | DefKind::Const - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst @@ -1001,7 +1001,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::AssocConst | DefKind::TyParam | DefKind::ConstParam - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Const | DefKind::Fn | DefKind::ForeignMod @@ -1099,7 +1099,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::AssocConst | DefKind::TyParam | DefKind::ConstParam - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Const | DefKind::ForeignMod | DefKind::Impl { .. } @@ -1131,7 +1131,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AssocTy | DefKind::Fn | DefKind::Const - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst @@ -1163,7 +1163,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Field | DefKind::Fn | DefKind::Const - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::TyAlias | DefKind::ForeignTy | DefKind::Impl { .. } @@ -1222,7 +1222,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::Variant | DefKind::Field | DefKind::Const - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::TyAlias | DefKind::OpaqueTy @@ -1263,7 +1263,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::Impl { of_trait: false } @@ -1295,7 +1295,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Ctor(..) | DefKind::Field | DefKind::Fn - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::ForeignTy @@ -1469,7 +1469,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { .coroutine_for_closure .set_some(def_id.index, self.tcx.coroutine_for_closure(def_id).into()); } - if let DefKind::Static(_) = def_kind { + if let DefKind::Static { .. } = def_kind { if !self.tcx.is_foreign_item(def_id) { let data = self.tcx.eval_static_initializer(def_id).unwrap(); record!(self.tables.eval_static_initializer[def_id] <- data); diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index c5f281964df0..dd5a560033f0 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -155,8 +155,8 @@ fixed_size_enum! { ( Impl { of_trait: false } ) ( Impl { of_trait: true } ) ( Closure ) - ( Static(ast::Mutability::Not) ) - ( Static(ast::Mutability::Mut) ) + ( Static{mt:ast::Mutability::Not} ) + ( Static{mt:ast::Mutability::Mut} ) ( Ctor(CtorOf::Struct, CtorKind::Fn) ) ( Ctor(CtorOf::Struct, CtorKind::Const) ) ( Ctor(CtorOf::Variant, CtorKind::Fn) ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4960369a0a7a..9e8d78354023 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -343,7 +343,7 @@ impl<'hir> Map<'hir> { DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, DefKind::Closure => BodyOwnerKind::Closure, - DefKind::Static(mt) => BodyOwnerKind::Static(mt), + DefKind::Static { mt } => BodyOwnerKind::Static(mt), dk => bug!("{:?} is not a body node: {:?}", def_id, dk), } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 090b84ff08fd..9651f8cc6611 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -498,8 +498,8 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: match (kind, body.source.promoted) { (_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts (DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?, - (DefKind::Static(hir::Mutability::Not), _) => write!(w, "static ")?, - (DefKind::Static(hir::Mutability::Mut), _) => write!(w, "static mut ")?, + (DefKind::Static { mt: hir::Mutability::Not }, _) => write!(w, "static ")?, + (DefKind::Static { mt: hir::Mutability::Mut }, _) => write!(w, "static mut ")?, (_, _) if is_function => write!(w, "fn ")?, (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item _ => bug!("Unexpected def kind {:?}", kind), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5c2d3973d61d..8565f90957f2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1708,7 +1708,7 @@ impl<'tcx> TyCtxt<'tcx> { debug!("returned from def_kind: {:?}", def_kind); match def_kind { DefKind::Const - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::AssocConst | DefKind::Ctor(..) | DefKind::AnonConst diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 33d63c2a5053..802953867ac1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -359,7 +359,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { | DefKind::TyAlias | DefKind::Fn | DefKind::Const - | DefKind::Static(_) = kind + | DefKind::Static { .. } = kind { } else { // If not covered above, like for example items out of `impl` blocks, fallback. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 4bb0d2c7d1c2..c2619772f769 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -616,12 +616,12 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `true` if the node pointed to by `def_id` is a `static` item. #[inline] pub fn is_static(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Static(_)) + matches!(self.def_kind(def_id), DefKind::Static { .. }) } #[inline] pub fn static_mutability(self, def_id: DefId) -> Option { - if let DefKind::Static(mt) = self.def_kind(def_id) { Some(mt) } else { None } + if let DefKind::Static { mt } = self.def_kind(def_id) { Some(mt) } else { None } } /// Returns `true` if this is a `static` item with the `#[thread_local]` attribute. diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 294b27def165..45954bdb114f 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -631,7 +631,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - | DefKind::AssocConst | DefKind::AnonConst | DefKind::InlineConst - | DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None), + | DefKind::Static { .. } => (vec![], tcx.type_of(def_id).instantiate_identity(), None), DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => { let sig = tcx.liberate_late_bound_regions( def_id.to_def_id(), diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 2318e84292b8..52d32a3b6266 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -942,7 +942,7 @@ impl<'tcx> Cx<'tcx> { // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is // a constant reference (or constant raw pointer for `static mut`) in MIR - Res::Def(DefKind::Static(_), id) => { + Res::Def(DefKind::Static { .. }, id) => { let ty = self.tcx.static_ptr_ty(id); let temp_lifetime = self .rvalue_scopes diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 0b03cb52373a..ac3043afcff0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -453,7 +453,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { Res::Def(DefKind::ConstParam, _) => { self.tcx.dcx().emit_err(ConstParamInPattern { span }) } - Res::Def(DefKind::Static(_), _) => { + Res::Def(DefKind::Static { .. }, _) => { self.tcx.dcx().emit_err(StaticInPattern { span }) } _ => self.tcx.dcx().emit_err(NonConstPath { span }), diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index cd9b98e4f32c..0491de782659 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -333,7 +333,7 @@ fn mir_promoted( } DefKind::AssocConst | DefKind::Const - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::InlineConst | DefKind::AnonConst => tcx.mir_const_qualif(def), _ => ConstQualifs::default(), diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index a18448eabf33..338dac14b0e3 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1037,7 +1037,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> return false; } - if let DefKind::Static(_) = tcx.def_kind(def_id) { + if let DefKind::Static { .. } = tcx.def_kind(def_id) { // We cannot monomorphize statics from upstream crates. return false; } @@ -1254,7 +1254,7 @@ impl<'v> RootCollector<'_, 'v> { ); self.output.push(dummy_spanned(MonoItem::GlobalAsm(id))); } - DefKind::Static(..) => { + DefKind::Static { .. } => { let def_id = id.owner_id.to_def_id(); debug!("RootCollector: ItemKind::Static({})", self.tcx.def_path_str(def_id)); self.output.push(dummy_spanned(MonoItem::Static(def_id))); diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 1070d1a1380d..6d237df073f8 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -150,7 +150,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::Fn | DefKind::Const | DefKind::ConstParam - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Ctor(_, _) | DefKind::AssocFn | DefKind::AssocConst diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index cdfde2b94052..0371bab83c04 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -801,7 +801,7 @@ fn check_foreign_item( worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, id: hir::ForeignItemId, ) { - if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn) + if matches!(tcx.def_kind(id.owner_id), DefKind::Static { .. } | DefKind::Fn) && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id) { worklist.push((id.owner_id.def_id, comes_from_allow)); @@ -1058,7 +1058,7 @@ impl<'tcx> DeadVisitor<'tcx> { DefKind::AssocConst | DefKind::AssocFn | DefKind::Fn - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Const | DefKind::TyAlias | DefKind::Enum diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index f46f831ddd7c..9a22f5a1b63a 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -73,7 +73,7 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> { match res { // Reachable constants and reachable statics can have their contents inlined // into other crates. Mark them as reachable and recurse into their body. - Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::Static(_), _) => { + Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::Static { .. }, _) => { self.worklist.push(def_id); } _ => { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index fe3598616817..9f8cb8fcb41e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -549,7 +549,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { self.update(def_id, macro_ev, Level::Reachable); match def_kind { // No type privacy, so can be directly marked as reachable. - DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias => { + DefKind::Const | DefKind::Static { .. } | DefKind::TraitAlias | DefKind::TyAlias => { if vis.is_accessible_from(module, self.tcx) { self.update(def_id, macro_ev, Level::Reachable); } @@ -1170,12 +1170,12 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { let def = def.filter(|(kind, _)| { matches!( kind, - DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static(_) + DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static { .. } ) }); if let Some((kind, def_id)) = def { let is_local_static = - if let DefKind::Static(_) = kind { def_id.is_local() } else { false }; + if let DefKind::Static { .. } = kind { def_id.is_local() } else { false }; if !self.item_is_accessible(def_id) && !is_local_static { let name = match *qpath { hir::QPath::LangItem(it, ..) => { @@ -1496,7 +1496,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> { let def_kind = tcx.def_kind(def_id); match def_kind { - DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => { + DefKind::Const | DefKind::Static { .. } | DefKind::Fn | DefKind::TyAlias => { if let DefKind::TyAlias = def_kind { self.check_unnameable(def_id, effective_vis); } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index dd18ab7d9d23..375f20dd809f 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -990,7 +990,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { Res::Def( DefKind::Fn | DefKind::AssocFn - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Const | DefKind::AssocConst | DefKind::Ctor(..), diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index bb3b902c0de6..6c207c4756ce 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -127,7 +127,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ItemKind::Union(..) => DefKind::Union, ItemKind::ExternCrate(..) => DefKind::ExternCrate, ItemKind::TyAlias(..) => DefKind::TyAlias, - ItemKind::Static(s) => DefKind::Static(s.mutability), + ItemKind::Static(s) => DefKind::Static { mt: s.mutability }, ItemKind::Const(..) => DefKind::Const, ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, ItemKind::MacroDef(..) => { @@ -214,7 +214,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(_, mt, _) => DefKind::Static(mt), + ForeignItemKind::Static(_, mt, _) => DefKind::Static { mt }, ForeignItemKind::Fn(_) => DefKind::Fn, ForeignItemKind::TyAlias(_) => DefKind::ForeignTy, ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 0bb2a69ae992..cd4626fc9848 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -574,7 +574,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => { use errs::GenericParamsFromOuterItemLabel as Label; let static_or_const = match def_kind { - DefKind::Static(_) => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), + DefKind::Static{..} => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const), _ => None, }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ea07ed9e6546..0ab101f72a6a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -500,7 +500,7 @@ impl<'a> PathSource<'a> { Res::Def( DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn) | DefKind::Const - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Fn | DefKind::AssocFn | DefKind::AssocConst @@ -3645,7 +3645,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } Some(res) } - Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static(_), _) => { + Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static{..}, _) => { // This is unambiguously a fresh binding, either syntactically // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves // to something unusable as a pattern (e.g., constructor function), diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 540bc4835486..158d62a4830f 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -264,7 +264,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { use rustc_hir::def::DefKind; match tcx.def_kind(def_id) { DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)), - DefKind::Static(..) => ForeignItemKind::Static(tables.static_def(def_id)), + DefKind::Static { .. } => ForeignItemKind::Static(tables.static_def(def_id)), DefKind::ForeignTy => ForeignItemKind::Type( tables.intern_ty(rustc_middle::ty::Ty::new_foreign(tcx, def_id)), ), diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index bd02e52794c0..aba7e7dc9c21 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -95,7 +95,7 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind { DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => { ItemKind::Const } - DefKind::Static(_) => ItemKind::Static, + DefKind::Static { .. } => ItemKind::Static, DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const), DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn), } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 87462963c27c..e1534af4987d 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -134,7 +134,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::TyParam | DefKind::Const | DefKind::ConstParam - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Ctor(_, _) | DefKind::Macro(_) | DefKind::ExternCrate diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 4a1064b29f6f..96d00dc05fdb 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -318,7 +318,7 @@ fn opaque_types_defined_by<'tcx>( match kind { DefKind::AssocFn | DefKind::Fn - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 72fcc95c3b35..c752de195653 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -43,7 +43,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Walk over the type behind the alias DefKind::TyAlias {..} | DefKind::AssocTy | // Walk over the type of the item - DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { + DefKind::Static{..} | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { // If the type of the item uses `_`, we're gonna error out anyway, but // typeck (which type_of invokes below), will call back into opaque_types_defined_by diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 03f62f41a26f..77a78f57e950 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -120,7 +120,7 @@ pub(crate) fn try_inline( record_extern_fqn(cx, did, ItemType::Module); clean::ModuleItem(build_module(cx, did, visited)) } - Res::Def(DefKind::Static(_), did) => { + Res::Def(DefKind::Static { .. }, did) => { record_extern_fqn(cx, did, ItemType::Static); cx.with_param_env(did, |cx| { clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did))) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 0b7d35d7be4c..57916ff0ff78 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -526,7 +526,7 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { | Mod | ForeignTy | Const - | Static(_) + | Static { .. } | Macro(..) | TraitAlias), did, diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index f10c829bf4ee..d5468798bd39 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -128,7 +128,7 @@ impl ItemType { DefKind::Fn => Self::Function, DefKind::Mod => Self::Module, DefKind::Const => Self::Constant, - DefKind::Static(_) => Self::Static, + DefKind::Static { .. } => Self::Static, DefKind::Struct => Self::Struct, DefKind::Union => Self::Union, DefKind::Trait => Self::Trait, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index a5f5fca3d15d..8f32f5fceb13 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -123,7 +123,7 @@ impl Res { DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst => { "const" } - DefKind::Static(_) => "static", + DefKind::Static { .. } => "static", // Now handle things that don't have a specific disambiguator _ => match kind .ns() @@ -1514,7 +1514,7 @@ impl Disambiguator { "union" => Kind(DefKind::Union), "module" | "mod" => Kind(DefKind::Mod), "const" | "constant" => Kind(DefKind::Const), - "static" => Kind(DefKind::Static(Mutability::Not)), + "static" => Kind(DefKind::Static { mt: Mutability::Not }), "function" | "fn" | "method" => Kind(DefKind::Fn), "derive" => Kind(DefKind::Macro(MacroKind::Derive)), "type" => NS(Namespace::TypeNS), @@ -1926,7 +1926,7 @@ fn resolution_failure( | OpaqueTy | TraitAlias | TyParam - | Static(_) => "associated item", + | Static { .. } => "associated item", Impl { .. } | GlobalAsm => unreachable!("not a path"), } } else { diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 08b8a9e2ff07..47dc3807e624 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -273,7 +273,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { } return false; // no need to walk further *on the variable* }, - Res::Def(DefKind::Static(_) | DefKind::Const, ..) => { + Res::Def(DefKind::Static{..} | DefKind::Const, ..) => { if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs index 9fd9b7a16312..3511d24e8134 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { Res::Local(hir_id) => { self.ids.insert(hir_id); }, - Res::Def(DefKind::Static(_), def_id) => { + Res::Def(DefKind::Static{..}, def_id) => { let mutable = self.cx.tcx.is_mutable_static(def_id); self.def_ids.insert(def_id, mutable); }, diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs index f0fc925799a3..e2c2997594ad 100644 --- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs @@ -91,7 +91,7 @@ pub(super) fn check<'tcx>( }, hir::ExprKind::Path(ref p) => matches!( cx.qpath_res(p, arg.hir_id), - hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static(_), _) + hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static{..}, _) ), _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 049f44f3246f..d8caa632b938 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -109,7 +109,7 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static(Mutability::Mut), _), + res: Res::Def(DefKind::Static{mt:Mutability::Mut}, _), .. }, )) => { @@ -149,7 +149,7 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static(Mutability::Mut), _), + res: Res::Def(DefKind::Static{mt:Mutability::Mut}, _), .. } )) From 0b4cbee660a5c07e17ba86f3d1a51c4c1f9d5a13 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 23 Feb 2024 23:29:09 +0000 Subject: [PATCH 49/99] Add `nested` bool to `DefKind::Static`. Will be used in the next commit --- compiler/rustc_const_eval/src/interpret/validity.rs | 2 +- compiler/rustc_hir/src/def.rs | 2 ++ compiler/rustc_hir_analysis/src/check/errs.rs | 2 +- compiler/rustc_metadata/src/rmeta/table.rs | 6 ++++-- compiler/rustc_middle/src/hir/map/mod.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 6 ++++-- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_resolve/src/def_collector.rs | 4 ++-- src/librustdoc/passes/collect_intra_doc_links.rs | 2 +- .../clippy_lints/src/multiple_unsafe_ops_per_block.rs | 4 ++-- 10 files changed, 19 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index f69788604399..22a17eff6ff5 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -459,7 +459,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' assert!(self.ecx.tcx.is_static(did)); let is_mut = matches!( self.ecx.tcx.def_kind(did), - DefKind::Static { mt: Mutability::Mut } + DefKind::Static { mt: Mutability::Mut, .. } ) || !self .ecx .tcx diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 3dc4a6a641f6..63dee3a5738c 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -78,6 +78,8 @@ pub enum DefKind { Static { /// Whether it's a `static mut` or just a `static`. mt: ast::Mutability, + /// Whether it's an anonymous static generated for nested allocations. + nested: bool, }, /// Refers to the struct or enum variant's constructor. /// diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index 068b263fa869..3f2c8d79ed28 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -48,7 +48,7 @@ fn is_path_static_mut(expr: hir::Expr<'_>) -> Option { if let hir::ExprKind::Path(qpath) = expr.kind && let hir::QPath::Resolved(_, path) = qpath && let hir::def::Res::Def(def_kind, _) = path.res - && let hir::def::DefKind::Static { mt } = def_kind + && let hir::def::DefKind::Static { mt, nested: false } = def_kind && matches!(mt, Mutability::Mut) { return Some(qpath_to_string(&qpath)); diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index dd5a560033f0..3c966cf3a9f7 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -155,8 +155,10 @@ fixed_size_enum! { ( Impl { of_trait: false } ) ( Impl { of_trait: true } ) ( Closure ) - ( Static{mt:ast::Mutability::Not} ) - ( Static{mt:ast::Mutability::Mut} ) + ( Static{mt:ast::Mutability::Not, nested: false}) + ( Static{mt:ast::Mutability::Mut, nested: false}) + ( Static{mt:ast::Mutability::Not, nested: true}) + ( Static{mt:ast::Mutability::Mut, nested: true}) ( Ctor(CtorOf::Struct, CtorKind::Fn) ) ( Ctor(CtorOf::Struct, CtorKind::Const) ) ( Ctor(CtorOf::Variant, CtorKind::Fn) ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 9e8d78354023..4a683a5f864e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -343,7 +343,7 @@ impl<'hir> Map<'hir> { DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, DefKind::Closure => BodyOwnerKind::Closure, - DefKind::Static { mt } => BodyOwnerKind::Static(mt), + DefKind::Static { mt, nested: false } => BodyOwnerKind::Static(mt), dk => bug!("{:?} is not a body node: {:?}", def_id, dk), } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 9651f8cc6611..27d7f3967980 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -498,8 +498,10 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: match (kind, body.source.promoted) { (_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts (DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?, - (DefKind::Static { mt: hir::Mutability::Not }, _) => write!(w, "static ")?, - (DefKind::Static { mt: hir::Mutability::Mut }, _) => write!(w, "static mut ")?, + (DefKind::Static { mt: hir::Mutability::Not, nested: false }, _) => write!(w, "static ")?, + (DefKind::Static { mt: hir::Mutability::Mut, nested: false }, _) => { + write!(w, "static mut ")? + } (_, _) if is_function => write!(w, "fn ")?, (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item _ => bug!("Unexpected def kind {:?}", kind), diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c2619772f769..b854ac6783d3 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -621,7 +621,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn static_mutability(self, def_id: DefId) -> Option { - if let DefKind::Static { mt } = self.def_kind(def_id) { Some(mt) } else { None } + if let DefKind::Static { mt, .. } = self.def_kind(def_id) { Some(mt) } else { None } } /// Returns `true` if this is a `static` item with the `#[thread_local]` attribute. diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6c207c4756ce..929b77bbd223 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -127,7 +127,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ItemKind::Union(..) => DefKind::Union, ItemKind::ExternCrate(..) => DefKind::ExternCrate, ItemKind::TyAlias(..) => DefKind::TyAlias, - ItemKind::Static(s) => DefKind::Static { mt: s.mutability }, + ItemKind::Static(s) => DefKind::Static { mt: s.mutability, nested: false }, ItemKind::Const(..) => DefKind::Const, ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, ItemKind::MacroDef(..) => { @@ -214,7 +214,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(_, mt, _) => DefKind::Static { mt }, + ForeignItemKind::Static(_, mt, _) => DefKind::Static { mt, nested: false }, ForeignItemKind::Fn(_) => DefKind::Fn, ForeignItemKind::TyAlias(_) => DefKind::ForeignTy, ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 8f32f5fceb13..7487c98657b0 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1514,7 +1514,7 @@ impl Disambiguator { "union" => Kind(DefKind::Union), "module" | "mod" => Kind(DefKind::Mod), "const" | "constant" => Kind(DefKind::Const), - "static" => Kind(DefKind::Static { mt: Mutability::Not }), + "static" => Kind(DefKind::Static { mt: Mutability::Not, nested: false }), "function" | "fn" | "method" => Kind(DefKind::Fn), "derive" => Kind(DefKind::Macro(MacroKind::Derive)), "type" => NS(Namespace::TypeNS), diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index d8caa632b938..4155e608026e 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -109,7 +109,7 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static{mt:Mutability::Mut}, _), + res: Res::Def(DefKind::Static{mt:Mutability::Mut, ..}, _), .. }, )) => { @@ -149,7 +149,7 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static{mt:Mutability::Mut}, _), + res: Res::Def(DefKind::Static{mt:Mutability::Mut, ..}, _), .. } )) From 92414ab25d5b9ddbee37d458e53e70ee4813d5ca Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 26 Feb 2024 17:43:18 +0000 Subject: [PATCH 50/99] Make some functions private that are only ever used in the same module --- compiler/rustc_codegen_gcc/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/consts.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 740956f6fdfd..3d73a60b2550 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -349,7 +349,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>( cx.const_struct(&llvals, true) } -pub fn codegen_static_initializer<'gcc, 'tcx>( +fn codegen_static_initializer<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId, ) -> Result<(RValue<'gcc>, ConstAllocation<'tcx>), ErrorHandled> { diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 8acb3de88675..0a56e056bb87 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -114,7 +114,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation< cx.const_struct(&llvals, true) } -pub fn codegen_static_initializer<'ll, 'tcx>( +fn codegen_static_initializer<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, ) -> Result<(&'ll Value, ConstAllocation<'tcx>), ErrorHandled> { From d3514a036dc65c1d31ee5b1b4bd58b9be1edf5af Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 26 Feb 2024 18:03:06 +0000 Subject: [PATCH 51/99] Ensure nested allocations in statics do not get deduplicated --- compiler/rustc_codegen_gcc/src/mono_item.rs | 11 ++++- compiler/rustc_codegen_llvm/src/consts.rs | 21 +++++++-- .../src/debuginfo/metadata.rs | 6 +++ compiler/rustc_codegen_llvm/src/mono_item.rs | 11 ++++- .../src/const_eval/eval_queries.rs | 6 ++- .../src/const_eval/machine.rs | 11 +++-- .../rustc_const_eval/src/interpret/intern.rs | 47 +++++++++++++++++-- .../rustc_const_eval/src/interpret/memory.rs | 38 +++++++++++---- .../rustc_const_eval/src/interpret/mod.rs | 2 +- .../rustc_const_eval/src/interpret/util.rs | 10 ++-- .../src/interpret/validity.rs | 32 ++++++++----- compiler/rustc_hir/src/def.rs | 3 ++ compiler/rustc_metadata/src/rmeta/encoder.rs | 9 ++-- .../rustc_middle/src/mir/interpret/mod.rs | 12 ++++- compiler/rustc_middle/src/query/mod.rs | 2 + .../src/dataflow_const_prop.rs | 8 +++- compiler/rustc_monomorphize/src/collector.rs | 8 +++- compiler/rustc_passes/src/reachable.rs | 39 ++++++++++++++- compiler/rustc_span/src/symbol.rs | 1 + tests/ui/consts/const-mut-refs-crate.rs | 12 +++-- tests/ui/statics/nested_struct.rs | 24 ++++++++++ 21 files changed, 259 insertions(+), 54 deletions(-) create mode 100644 tests/ui/statics/nested_struct.rs diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index e56c49686c01..ceaf87d16481 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -1,7 +1,9 @@ #[cfg(feature = "master")] use gccjit::{FnAttribute, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineMethods; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; @@ -23,7 +25,14 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ) { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; + // Nested statics do not have a type, so pick a random type and let `define_static` figure out + // the gcc type from the actual evaluated initializer. + let ty = if nested { + self.tcx.types.unit + } else { + instance.ty(self.tcx, ty::ParamEnv::reveal_all()) + }; let gcc_type = self.layout_of(ty).gcc_type(self); let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 0a56e056bb87..8e047f124eeb 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -9,6 +9,7 @@ use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; use rustc_codegen_ssa::traits::*; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ @@ -229,9 +230,17 @@ impl<'ll> CodegenCx<'ll, '_> { pub(crate) fn get_static(&self, def_id: DefId) -> &'ll Value { let instance = Instance::mono(self.tcx, def_id); trace!(?instance); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); - trace!(?ty); - let llty = self.layout_of(ty).llvm_type(self); + + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; + // Nested statics do not have a type, so pick a random type and let `define_static` figure out + // the llvm type from the actual evaluated initializer. + let llty = if nested { + self.type_i8() + } else { + let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + trace!(?ty); + self.layout_of(ty).llvm_type(self) + }; self.get_static_inner(def_id, llty) } @@ -346,6 +355,12 @@ impl<'ll> CodegenCx<'ll, '_> { fn codegen_static_item(&self, def_id: DefId) { unsafe { + assert!( + llvm::LLVMGetInitializer( + self.instances.borrow().get(&Instance::mono(self.tcx, def_id)).unwrap() + ) + .is_none() + ); let attrs = self.tcx.codegen_fn_attrs(def_id); let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 660f16473677..5782b156335f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -26,6 +26,7 @@ use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind; use rustc_codegen_ssa::traits::*; use rustc_fs_util::path_to_c_string; use rustc_hir::def::CtorKind; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; @@ -1309,6 +1310,11 @@ pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, glo }; let is_local_to_unit = is_node_local_to_unit(cx, def_id); + + let DefKind::Static { nested, .. } = cx.tcx.def_kind(def_id) else { bug!() }; + if nested { + return; + } let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); let type_di_node = type_di_node(cx, variable_type); let var_name = tcx.item_name(def_id); diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index f76307193683..81ac95718858 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -5,7 +5,9 @@ use crate::errors::SymbolAlreadyDefined; use crate::llvm; use crate::type_of::LayoutLlvmExt; use rustc_codegen_ssa::traits::*; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::bug; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; @@ -21,7 +23,14 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { symbol_name: &str, ) { let instance = Instance::mono(self.tcx, def_id); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; + // Nested statics do not have a type, so pick a random type and let `define_static` figure out + // the llvm type from the actual evaluated initializer. + let ty = if nested { + self.tcx.types.unit + } else { + instance.ty(self.tcx, ty::ParamEnv::reveal_all()) + }; let llty = self.layout_of(ty).llvm_type(self); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 81a85dfa1896..5f4408ebbc6c 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -59,7 +59,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( }; let ret = if let InternKind::Static(_) = intern_kind { - create_static_alloc(ecx, cid.instance.def_id(), layout)? + create_static_alloc(ecx, cid.instance.def_id().expect_local(), layout)? } else { ecx.allocate(layout, MemoryKind::Stack)? }; @@ -380,7 +380,11 @@ pub fn eval_in_interpreter<'mir, 'tcx>( } Ok(mplace) => { // Since evaluation had no errors, validate the resulting constant. + + // Temporarily allow access to the static_root_ids for the purpose of validation. + let static_root_ids = ecx.machine.static_root_ids.take(); let res = const_validate_mplace(&ecx, &mplace, cid); + ecx.machine.static_root_ids = static_root_ids; let alloc_id = mplace.ptr().provenance.unwrap().alloc_id(); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index f104b8367161..dd835279df33 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -8,6 +8,7 @@ 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; use rustc_middle::mir; use rustc_middle::mir::AssertMessage; @@ -59,8 +60,10 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { /// Whether to check alignment during evaluation. pub(super) check_alignment: CheckAlignment, - /// Used to prevent reads from a static's base allocation, as that may allow for self-initialization. - pub(crate) static_root_alloc_id: Option, + /// If `Some`, we are evaluating the initializer of the static with the given `LocalDefId`, + /// storing the result in the given `AllocId`. + /// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops. + pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>, } #[derive(Copy, Clone)] @@ -94,7 +97,7 @@ impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { stack: Vec::new(), can_access_mut_global, check_alignment, - static_root_alloc_id: None, + static_root_ids: None, } } } @@ -749,7 +752,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ecx: &InterpCx<'mir, 'tcx, Self>, alloc_id: AllocId, ) -> InterpResult<'tcx> { - if Some(alloc_id) == ecx.machine.static_root_alloc_id { + if Some(alloc_id) == ecx.machine.static_root_ids.map(|(id, _)| id) { Err(ConstEvalErrKind::RecursiveStatic.into()) } else { Ok(()) diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 82ce9ecd21d1..26f60f75fbbd 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -13,12 +13,16 @@ //! but that would require relying on type information, and given how many ways Rust has to lie //! about type information, we want to avoid doing that. +use hir::def::DefKind; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_middle::mir::interpret::{CtfeProvenance, InterpResult}; +use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult}; +use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::TyAndLayout; +use rustc_span::def_id::LocalDefId; +use rustc_span::sym; use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy}; use crate::const_eval; @@ -33,7 +37,19 @@ pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine< FrameExtra = (), AllocExtra = (), MemoryMap = FxIndexMap, Allocation)>, - >; + > + HasStaticRootDefId; + +pub trait HasStaticRootDefId { + /// Returns the `DefId` of the static item that is currently being evaluated. + /// Used for interning to be able to handle nested allocations. + fn static_def_id(&self) -> Option; +} + +impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_, '_> { + fn static_def_id(&self) -> Option { + Some(self.static_root_ids?.1) + } +} /// Intern an allocation. Returns `Err` if the allocation does not exist in the local memory. /// @@ -67,10 +83,35 @@ fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>( } // link the alloc id to the actual allocation let alloc = ecx.tcx.mk_const_alloc(alloc); - ecx.tcx.set_alloc_id_memory(alloc_id, alloc); + if let Some(static_id) = ecx.machine.static_def_id() { + intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc); + } else { + ecx.tcx.set_alloc_id_memory(alloc_id, alloc); + } Ok(alloc.0.0.provenance().ptrs().iter().map(|&(_, prov)| prov)) } +/// Creates a new `DefId` and feeds all the right queries to make this `DefId` +/// appear as if it were a user-written `static` (though it has no HIR). +fn intern_as_new_static<'tcx>( + tcx: TyCtxtAt<'tcx>, + static_id: LocalDefId, + alloc_id: AllocId, + alloc: ConstAllocation<'tcx>, +) { + let feed = tcx.create_def( + static_id, + sym::nested, + DefKind::Static { mt: alloc.0.mutability, nested: true }, + ); + tcx.set_nested_alloc_id_static(alloc_id, feed.def_id()); + feed.codegen_fn_attrs(tcx.codegen_fn_attrs(static_id).clone()); + feed.eval_static_initializer(Ok(alloc)); + feed.generics_of(tcx.generics_of(static_id).clone()); + feed.def_ident_span(tcx.def_ident_span(static_id)); + feed.explicit_predicates_of(tcx.explicit_predicates_of(static_id)); +} + /// How a constant value should be interned. #[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)] pub enum InternKind { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index cf7f165b87c4..e011edcfb295 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -15,6 +15,7 @@ use std::ptr; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_hir::def::DefKind; use rustc_middle::mir::display_allocation; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; use rustc_target::abi::{Align, HasDataLayout, Size}; @@ -761,19 +762,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // be held throughout the match. match self.tcx.try_get_global_alloc(id) { Some(GlobalAlloc::Static(def_id)) => { - assert!(self.tcx.is_static(def_id)); // Thread-local statics do not have a constant address. They *must* be accessed via // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value. assert!(!self.tcx.is_thread_local_static(def_id)); - // Use size and align of the type. - let ty = self - .tcx - .type_of(def_id) - .no_bound_vars() - .expect("statics should not have generic parameters"); - let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); - assert!(layout.is_sized()); - (layout.size, layout.align.abi, AllocKind::LiveData) + + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { + bug!("GlobalAlloc::Static is not a static") + }; + + let (size, align) = if nested { + // Nested anonymous statics are untyped, so let's get their + // size and alignment from the allocaiton itself. This always + // succeeds, as the query is fed at DefId creation time, so no + // evaluation actually occurs. + let alloc = self.tcx.eval_static_initializer(def_id).unwrap(); + (alloc.0.size(), alloc.0.align) + } else { + // Use size and align of the type for everything else. We need + // to do that to + // * avoid cycle errors in case of self-referential statics, + // * be able to get information on extern statics. + let ty = self + .tcx + .type_of(def_id) + .no_bound_vars() + .expect("statics should not have generic parameters"); + let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); + assert!(layout.is_sized()); + (layout.size, layout.align.abi) + }; + (size, align, AllocKind::LiveData) } Some(GlobalAlloc::Memory(alloc)) => { // Need to duplicate the logic here, because the global allocations have diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index a15e52d07e60..2ed879ca72b5 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -22,7 +22,7 @@ pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in pub use self::eval_context::{format_interp_error, Frame, FrameInfo, InterpCx, StackPopCleanup}; pub use self::intern::{ - intern_const_alloc_for_constprop, intern_const_alloc_recursive, InternKind, + intern_const_alloc_for_constprop, intern_const_alloc_recursive, HasStaticRootDefId, InternKind, }; pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump}; pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 3427368421f8..086475f72c5d 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,11 +1,11 @@ use crate::const_eval::CompileTimeEvalContext; use crate::interpret::{MemPlaceMeta, MemoryKind}; +use rustc_hir::def_id::LocalDefId; use rustc_middle::mir::interpret::{AllocId, Allocation, InterpResult, Pointer}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_span::def_id::DefId; use std::ops::ControlFlow; use super::MPlaceTy; @@ -89,13 +89,13 @@ pub(crate) fn take_static_root_alloc<'mir, 'tcx: 'mir>( pub(crate) fn create_static_alloc<'mir, 'tcx: 'mir>( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, - static_def_id: DefId, + static_def_id: LocalDefId, layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { let alloc = Allocation::try_uninit(layout.size, layout.align.abi)?; - let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id); - assert_eq!(ecx.machine.static_root_alloc_id, None); - ecx.machine.static_root_alloc_id = Some(alloc_id); + let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into()); + assert_eq!(ecx.machine.static_root_ids, None); + ecx.machine.static_root_ids = Some((alloc_id, static_def_id)); assert!(ecx.memory.alloc_map.insert(alloc_id, (MemoryKind::Stack, alloc)).is_none()); Ok(ecx.ptr_with_meta_to_mplace(Pointer::from(alloc_id).into(), MemPlaceMeta::None, layout)) } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 22a17eff6ff5..ee60bd021790 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -457,16 +457,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Special handling for pointers to statics (irrespective of their type). assert!(!self.ecx.tcx.is_thread_local_static(did)); assert!(self.ecx.tcx.is_static(did)); - let is_mut = matches!( - self.ecx.tcx.def_kind(did), - DefKind::Static { mt: Mutability::Mut, .. } - ) || !self - .ecx - .tcx - .type_of(did) - .no_bound_vars() - .expect("statics should not have generic parameters") - .is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all()); // Mode-specific checks match self.ctfe_mode { Some( @@ -491,8 +481,26 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } None => {} } - // Return alloc mutability - if is_mut { Mutability::Mut } else { Mutability::Not } + // Return alloc mutability. For "root" statics we look at the type to account for interior + // mutability; for nested statics we have no type and directly use the annotated mutability. + match self.ecx.tcx.def_kind(did) { + DefKind::Static { mt: Mutability::Mut, .. } => Mutability::Mut, + DefKind::Static { mt: Mutability::Not, nested: true } => { + Mutability::Not + } + DefKind::Static { mt: Mutability::Not, nested: false } + if !self + .ecx + .tcx + .type_of(did) + .no_bound_vars() + .expect("statics should not have generic parameters") + .is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all()) => + { + Mutability::Mut + } + _ => Mutability::Not, + } } GlobalAlloc::Memory(alloc) => alloc.inner().mutability, GlobalAlloc::Function(..) | GlobalAlloc::VTable(..) => { diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 63dee3a5738c..361ca167010b 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -250,6 +250,9 @@ impl DefKind { | DefKind::AssocTy | DefKind::TyParam | DefKind::ExternCrate => DefPathData::TypeNs(name), + // It's not exactly an anon const, but wrt DefPathData, there + // is not difference. + DefKind::Static { nested: true, .. } => DefPathData::AnonConst, DefKind::Fn | DefKind::Const | DefKind::ConstParam diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b87cda4a79f2..26226386ef72 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -894,7 +894,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::AssocTy | DefKind::Fn | DefKind::Const - | DefKind::Static { .. } + | DefKind::Static { nested: false, .. } | DefKind::AssocFn | DefKind::AssocConst | DefKind::Macro(_) @@ -915,6 +915,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::LifetimeParam + | DefKind::Static { nested: true, .. } | DefKind::GlobalAsm => false, } } @@ -968,7 +969,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::AssocTy | DefKind::Fn | DefKind::Const - | DefKind::Static { .. } + | DefKind::Static { nested: false, .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst @@ -981,6 +982,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::LifetimeParam | DefKind::AnonConst | DefKind::InlineConst + | DefKind::Static { nested: true, .. } | DefKind::OpaqueTy | DefKind::GlobalAsm | DefKind::Impl { .. } @@ -1163,7 +1165,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Field | DefKind::Fn | DefKind::Const - | DefKind::Static { .. } + | DefKind::Static { nested: false, .. } | DefKind::TyAlias | DefKind::ForeignTy | DefKind::Impl { .. } @@ -1205,6 +1207,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Mod | DefKind::ForeignMod | DefKind::Macro(..) + | DefKind::Static { nested: true, .. } | DefKind::Use | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 94b9afa1deef..f9edbb3c5ae2 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -130,7 +130,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{HashMapExt, Lock}; use rustc_data_structures::tiny_list::TinyList; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; @@ -627,6 +627,16 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Freezes an `AllocId` created with `reserve` by pointing it at a static item. Trying to + /// call this function twice, even with the same `DefId` will ICE the compiler. + pub fn set_nested_alloc_id_static(self, id: AllocId, def_id: LocalDefId) { + if let Some(old) = + self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Static(def_id.to_def_id())) + { + bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}"); + } + } + /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called /// twice for the same `(AllocId, Allocation)` pair. fn set_alloc_id_same_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 332ebdbdd944..83ded5859c67 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1062,6 +1062,7 @@ rustc_queries! { } cache_on_disk_if { key.is_local() } separate_provide_extern + feedable } /// Evaluates const items or anonymous constants @@ -1220,6 +1221,7 @@ rustc_queries! { arena_cache cache_on_disk_if { def_id.is_local() } separate_provide_extern + feedable } query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 19109735d487..c3e932fe1872 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -3,7 +3,7 @@ //! Currently, this pass only propagates scalar values. use rustc_const_eval::interpret::{ - ImmTy, Immediate, InterpCx, OpTy, PlaceTy, PointerArithmetic, Projectable, + HasStaticRootDefId, ImmTy, Immediate, InterpCx, OpTy, PlaceTy, PointerArithmetic, Projectable, }; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; @@ -889,6 +889,12 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> { pub(crate) struct DummyMachine; +impl HasStaticRootDefId for DummyMachine { + fn static_def_id(&self) -> Option { + None + } +} + impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine { rustc_const_eval::interpret::compile_time_machine!(<'mir, 'tcx>); type MemoryKind = !; diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 338dac14b0e3..33a446eb55a1 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -380,8 +380,12 @@ fn collect_items_rec<'tcx>( // Sanity check whether this ended up being collected accidentally debug_assert!(should_codegen_locally(tcx, &instance)); - let ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); - visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items); + let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() }; + // Nested statics have no type. + if !nested { + let ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items); + } recursion_depth_reset = None; diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 9a22f5a1b63a..e86c0522b3cd 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -13,6 +13,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::middle::privacy::{self, Level}; +use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::CrateType; @@ -197,10 +198,23 @@ impl<'tcx> ReachableContext<'tcx> { // Reachable constants will be inlined into other crates // unconditionally, so we need to make sure that their // contents are also reachable. - hir::ItemKind::Const(_, _, init) | hir::ItemKind::Static(_, _, init) => { + hir::ItemKind::Const(_, _, init) => { self.visit_nested_body(init); } + // Reachable statics are inlined if read from another constant or static + // in other crates. Additionally anonymous nested statics may be created + // when evaluating a static, so preserve those, too. + hir::ItemKind::Static(_, _, init) => { + // FIXME(oli-obk): remove this body walking and instead walk the evaluated initializer + // to find nested items that end up in the final value instead of also marking symbols + // as reachable that are only needed for evaluation. + self.visit_nested_body(init); + if let Ok(alloc) = self.tcx.eval_static_initializer(item.owner_id.def_id) { + self.propagate_statics_from_alloc(item.owner_id.def_id, alloc); + } + } + // These are normal, nothing reachable about these // inherently and their children are already in the // worklist, as determined by the privacy pass @@ -266,6 +280,29 @@ impl<'tcx> ReachableContext<'tcx> { } } } + + /// Finds anonymous nested statics created for nested allocations and adds them to `reachable_symbols`. + fn propagate_statics_from_alloc(&mut self, root: LocalDefId, alloc: ConstAllocation<'tcx>) { + if !self.any_library { + return; + } + for (_, prov) in alloc.0.provenance().ptrs().iter() { + match self.tcx.global_alloc(prov.alloc_id()) { + GlobalAlloc::Static(def_id) => { + if let Some(def_id) = def_id.as_local() + && self.tcx.local_parent(def_id) == root + // This is the main purpose of this function: add the def_id we find + // to `reachable_symbols`. + && self.reachable_symbols.insert(def_id) + && let Ok(alloc) = self.tcx.eval_static_initializer(def_id) + { + self.propagate_statics_from_alloc(root, alloc); + } + } + GlobalAlloc::Function(_) | GlobalAlloc::VTable(_, _) | GlobalAlloc::Memory(_) => {} + } + } + } } fn check_item<'tcx>( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f592c1d3dd37..7de0555bb220 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1205,6 +1205,7 @@ symbols! { negative_bounds, negative_impls, neon, + nested, never, never_patterns, never_type, diff --git a/tests/ui/consts/const-mut-refs-crate.rs b/tests/ui/consts/const-mut-refs-crate.rs index 96df2cefce27..dcc8ff370e1e 100644 --- a/tests/ui/consts/const-mut-refs-crate.rs +++ b/tests/ui/consts/const-mut-refs-crate.rs @@ -4,8 +4,8 @@ #![feature(const_mut_refs)] //! Regression test for https://github.com/rust-lang/rust/issues/79738 -//! Show how we are duplicationg allocations, even though static items that -//! copy their value from another static should not also be duplicating +//! Show how we are not duplicating allocations anymore. Statics that +//! copy their value from another static used to also duplicate //! memory behind references. extern crate const_mut_refs_crate as other; @@ -21,15 +21,17 @@ pub static mut COPY_OF_REMOTE_FOO: &'static mut i32 = unsafe { FOO }; static DOUBLE_REF: &&i32 = &&99; static ONE_STEP_ABOVE: &i32 = *DOUBLE_REF; +static mut DOUBLE_REF_MUT: &mut &mut i32 = &mut &mut 99; +static mut ONE_STEP_ABOVE_MUT: &mut i32 = unsafe { *DOUBLE_REF_MUT }; pub fn main() { unsafe { - assert_ne!(FOO as *const i32, BAR as *const i32); + assert_eq!(FOO as *const i32, BAR as *const i32); assert_eq!(INNER_MOD_FOO as *const i32, INNER_MOD_BAR as *const i32); assert_eq!(LOCAL_FOO as *const i32, LOCAL_BAR as *const i32); assert_eq!(*DOUBLE_REF as *const i32, ONE_STEP_ABOVE as *const i32); + assert_eq!(*DOUBLE_REF_MUT as *mut i32, ONE_STEP_ABOVE_MUT as *mut i32); - // bug! - assert_ne!(FOO as *const i32, COPY_OF_REMOTE_FOO as *const i32); + assert_eq!(FOO as *const i32, COPY_OF_REMOTE_FOO as *const i32); } } diff --git a/tests/ui/statics/nested_struct.rs b/tests/ui/statics/nested_struct.rs new file mode 100644 index 000000000000..f5819f50789c --- /dev/null +++ b/tests/ui/statics/nested_struct.rs @@ -0,0 +1,24 @@ +//@ check-pass +/// oli-obk added this test after messing up the interner logic +/// around mutability of nested allocations. This was not caught +/// by the test suite, but by trying to build stage2 rustc. +/// There is no real explanation for this test, as it was just +/// a bug during a refactoring. + +pub struct Lint { + pub name: &'static str, + pub desc: &'static str, + pub report_in_external_macro: bool, + pub is_loaded: bool, + pub crate_level_only: bool, +} + +static FOO: &Lint = &Lint { + name: &"foo", + desc: "desc", + report_in_external_macro: false, + is_loaded: true, + crate_level_only: false, +}; + +fn main() {} From 926bfe507800daa905a06efa8da619ed9993577c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 11 Mar 2024 17:33:57 +0000 Subject: [PATCH 52/99] s/mt/mutability/ --- compiler/rustc_const_eval/src/interpret/intern.rs | 2 +- compiler/rustc_const_eval/src/interpret/validity.rs | 6 +++--- compiler/rustc_hir/src/def.rs | 2 +- compiler/rustc_hir_analysis/src/check/errs.rs | 3 +-- compiler/rustc_metadata/src/rmeta/table.rs | 8 ++++---- compiler/rustc_middle/src/hir/map/mod.rs | 4 ++-- compiler/rustc_middle/src/mir/pretty.rs | 6 ++++-- compiler/rustc_middle/src/ty/util.rs | 6 +++++- compiler/rustc_resolve/src/def_collector.rs | 6 ++++-- src/librustdoc/passes/collect_intra_doc_links.rs | 2 +- .../clippy_lints/src/multiple_unsafe_ops_per_block.rs | 4 ++-- 11 files changed, 28 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 26f60f75fbbd..55d4b9edd59b 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -102,7 +102,7 @@ fn intern_as_new_static<'tcx>( let feed = tcx.create_def( static_id, sym::nested, - DefKind::Static { mt: alloc.0.mutability, nested: true }, + DefKind::Static { mutability: alloc.0.mutability, nested: true }, ); tcx.set_nested_alloc_id_static(alloc_id, feed.def_id()); feed.codegen_fn_attrs(tcx.codegen_fn_attrs(static_id).clone()); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index ee60bd021790..44409d46473d 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -484,11 +484,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Return alloc mutability. For "root" statics we look at the type to account for interior // mutability; for nested statics we have no type and directly use the annotated mutability. match self.ecx.tcx.def_kind(did) { - DefKind::Static { mt: Mutability::Mut, .. } => Mutability::Mut, - DefKind::Static { mt: Mutability::Not, nested: true } => { + DefKind::Static { mutability: Mutability::Mut, .. } => Mutability::Mut, + DefKind::Static { mutability: Mutability::Not, nested: true } => { Mutability::Not } - DefKind::Static { mt: Mutability::Not, nested: false } + DefKind::Static { mutability: Mutability::Not, nested: false } if !self .ecx .tcx diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 361ca167010b..f6a616109c97 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -77,7 +77,7 @@ pub enum DefKind { ConstParam, Static { /// Whether it's a `static mut` or just a `static`. - mt: ast::Mutability, + mutability: ast::Mutability, /// Whether it's an anonymous static generated for nested allocations. nested: bool, }, diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index 3f2c8d79ed28..b9dc5cbc4d20 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -48,8 +48,7 @@ fn is_path_static_mut(expr: hir::Expr<'_>) -> Option { if let hir::ExprKind::Path(qpath) = expr.kind && let hir::QPath::Resolved(_, path) = qpath && let hir::def::Res::Def(def_kind, _) = path.res - && let hir::def::DefKind::Static { mt, nested: false } = def_kind - && matches!(mt, Mutability::Mut) + && let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind { return Some(qpath_to_string(&qpath)); } diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 3c966cf3a9f7..019cb91c765e 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -155,10 +155,10 @@ fixed_size_enum! { ( Impl { of_trait: false } ) ( Impl { of_trait: true } ) ( Closure ) - ( Static{mt:ast::Mutability::Not, nested: false}) - ( Static{mt:ast::Mutability::Mut, nested: false}) - ( Static{mt:ast::Mutability::Not, nested: true}) - ( Static{mt:ast::Mutability::Mut, nested: true}) + ( Static { mutability: ast::Mutability::Not, nested: false } ) + ( Static { mutability: ast::Mutability::Mut, nested: false } ) + ( Static { mutability: ast::Mutability::Not, nested: true } ) + ( Static { mutability: ast::Mutability::Mut, nested: true } ) ( Ctor(CtorOf::Struct, CtorKind::Fn) ) ( Ctor(CtorOf::Struct, CtorKind::Const) ) ( Ctor(CtorOf::Variant, CtorKind::Fn) ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4a683a5f864e..c05da3623585 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -343,7 +343,7 @@ impl<'hir> Map<'hir> { DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, DefKind::Closure => BodyOwnerKind::Closure, - DefKind::Static { mt, nested: false } => BodyOwnerKind::Static(mt), + DefKind::Static { mutability, nested: false } => BodyOwnerKind::Static(mutability), dk => bug!("{:?} is not a body node: {:?}", def_id, dk), } } @@ -359,7 +359,7 @@ impl<'hir> Map<'hir> { let def_id = def_id.into(); let ccx = match self.body_owner_kind(def_id) { BodyOwnerKind::Const { inline } => ConstContext::Const { inline }, - BodyOwnerKind::Static(mt) => ConstContext::Static(mt), + BodyOwnerKind::Static(mutability) => ConstContext::Static(mutability), BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None, BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id) => { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 27d7f3967980..8ae65f3832fd 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -498,8 +498,10 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: match (kind, body.source.promoted) { (_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts (DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?, - (DefKind::Static { mt: hir::Mutability::Not, nested: false }, _) => write!(w, "static ")?, - (DefKind::Static { mt: hir::Mutability::Mut, nested: false }, _) => { + (DefKind::Static { mutability: hir::Mutability::Not, nested: false }, _) => { + write!(w, "static ")? + } + (DefKind::Static { mutability: hir::Mutability::Mut, nested: false }, _) => { write!(w, "static mut ")? } (_, _) if is_function => write!(w, "fn ")?, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b854ac6783d3..a6526b068517 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -621,7 +621,11 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn static_mutability(self, def_id: DefId) -> Option { - if let DefKind::Static { mt, .. } = self.def_kind(def_id) { Some(mt) } else { None } + if let DefKind::Static { mutability, .. } = self.def_kind(def_id) { + Some(mutability) + } else { + None + } } /// Returns `true` if this is a `static` item with the `#[thread_local]` attribute. diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 929b77bbd223..bef95aca0d1c 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -127,7 +127,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ItemKind::Union(..) => DefKind::Union, ItemKind::ExternCrate(..) => DefKind::ExternCrate, ItemKind::TyAlias(..) => DefKind::TyAlias, - ItemKind::Static(s) => DefKind::Static { mt: s.mutability, nested: false }, + ItemKind::Static(s) => DefKind::Static { mutability: s.mutability, nested: false }, ItemKind::Const(..) => DefKind::Const, ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, ItemKind::MacroDef(..) => { @@ -214,7 +214,9 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(_, mt, _) => DefKind::Static { mt, nested: false }, + ForeignItemKind::Static(_, mutability, _) => { + DefKind::Static { mutability, nested: false } + } ForeignItemKind::Fn(_) => DefKind::Fn, ForeignItemKind::TyAlias(_) => DefKind::ForeignTy, ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 7487c98657b0..577d4b89c8dc 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1514,7 +1514,7 @@ impl Disambiguator { "union" => Kind(DefKind::Union), "module" | "mod" => Kind(DefKind::Mod), "const" | "constant" => Kind(DefKind::Const), - "static" => Kind(DefKind::Static { mt: Mutability::Not, nested: false }), + "static" => Kind(DefKind::Static { mutability: Mutability::Not, nested: false }), "function" | "fn" | "method" => Kind(DefKind::Fn), "derive" => Kind(DefKind::Macro(MacroKind::Derive)), "type" => NS(Namespace::TypeNS), diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 4155e608026e..70fd07cd93ce 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -109,7 +109,7 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static{mt:Mutability::Mut, ..}, _), + res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _), .. }, )) => { @@ -149,7 +149,7 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static{mt:Mutability::Mut, ..}, _), + res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _), .. } )) From bbbf06d5e9bb977b09a6c4aeb50b5b8a9488d475 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 11 Mar 2024 17:47:45 +0000 Subject: [PATCH 53/99] Manual rustfmt --- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_ty_utils/src/sig_types.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 246140c9e95e..1b8174d3d18f 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -226,7 +226,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { Ok(l) => l, // Foreign statics that overflow their allowed size should emit an error Err(LayoutError::SizeOverflow(_)) - if matches!(tcx.def_kind(def_id), DefKind::Static{..} + if matches!(tcx.def_kind(def_id), DefKind::Static{ .. } if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) => { tcx.dcx().emit_err(errors::TooLargeStatic { span }); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index cd4626fc9848..476b31f44ae6 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -574,7 +574,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => { use errs::GenericParamsFromOuterItemLabel as Label; let static_or_const = match def_kind { - DefKind::Static{..} => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), + DefKind::Static{ .. } => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const), _ => None, }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0ab101f72a6a..a996188db022 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3645,7 +3645,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } Some(res) } - Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static{..}, _) => { + Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static { .. }, _) => { // This is unambiguously a fresh binding, either syntactically // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves // to something unusable as a pattern (e.g., constructor function), diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index c752de195653..63654a453dde 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -41,9 +41,9 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( } } // Walk over the type behind the alias - DefKind::TyAlias {..} | DefKind::AssocTy | + DefKind::TyAlias { .. } | DefKind::AssocTy | // Walk over the type of the item - DefKind::Static{..} | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { + DefKind::Static { .. } | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { // If the type of the item uses `_`, we're gonna error out anyway, but // typeck (which type_of invokes below), will call back into opaque_types_defined_by From bbedde835e1b9bb3ec9255c2b49e5cac2398ece0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 11 Mar 2024 17:50:26 +0000 Subject: [PATCH 54/99] Exhaustively match on the mutability and nestedness --- .../rustc_const_eval/src/interpret/validity.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 44409d46473d..d18600ce7d75 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -483,12 +483,14 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } // Return alloc mutability. For "root" statics we look at the type to account for interior // mutability; for nested statics we have no type and directly use the annotated mutability. - match self.ecx.tcx.def_kind(did) { - DefKind::Static { mutability: Mutability::Mut, .. } => Mutability::Mut, - DefKind::Static { mutability: Mutability::Not, nested: true } => { - Mutability::Not - } - DefKind::Static { mutability: Mutability::Not, nested: false } + let DefKind::Static { mutability, nested } = self.ecx.tcx.def_kind(did) + else { + bug!() + }; + match (mutability, nested) { + (Mutability::Mut, _) => Mutability::Mut, + (Mutability::Not, true) => Mutability::Not, + (Mutability::Not, false) if !self .ecx .tcx @@ -499,7 +501,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' { Mutability::Mut } - _ => Mutability::Not, + (Mutability::Not, false) => Mutability::Not, } } GlobalAlloc::Memory(alloc) => alloc.inner().mutability, From 783490da703617b030b29301c844c93fe672f777 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 12 Mar 2024 06:03:43 +0000 Subject: [PATCH 55/99] Fix stack overflow with recursive associated types --- compiler/rustc_ty_utils/src/opaque_types.rs | 4 ++++ tests/ui/impl-trait/associated-type-cycle.rs | 14 ++++++++++++++ tests/ui/impl-trait/associated-type-cycle.stderr | 12 ++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 tests/ui/impl-trait/associated-type-cycle.rs create mode 100644 tests/ui/impl-trait/associated-type-cycle.stderr diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 4a1064b29f6f..d86efe6b4914 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -240,6 +240,10 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { continue; } + if !self.seen.insert(assoc.def_id.expect_local()) { + return; + } + let impl_args = alias_ty.args.rebase_onto( self.tcx, impl_trait_ref.def_id, diff --git a/tests/ui/impl-trait/associated-type-cycle.rs b/tests/ui/impl-trait/associated-type-cycle.rs new file mode 100644 index 000000000000..4c1fc1a0fa61 --- /dev/null +++ b/tests/ui/impl-trait/associated-type-cycle.rs @@ -0,0 +1,14 @@ +trait Foo { + type Bar; + fn foo(self) -> Self::Bar; +} + +impl Foo for Box { + //~^ ERROR: the value of the associated type `Bar` in `Foo` must be specified + type Bar = ::Bar; + fn foo(self) -> ::Bar { + (*self).foo() + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/associated-type-cycle.stderr b/tests/ui/impl-trait/associated-type-cycle.stderr new file mode 100644 index 000000000000..7eef8d1e3389 --- /dev/null +++ b/tests/ui/impl-trait/associated-type-cycle.stderr @@ -0,0 +1,12 @@ +error[E0191]: the value of the associated type `Bar` in `Foo` must be specified + --> $DIR/associated-type-cycle.rs:6:22 + | +LL | type Bar; + | -------- `Bar` defined here +... +LL | impl Foo for Box { + | ^^^ help: specify the associated type: `Foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0191`. From 9962a01e9f5d5a48b170b7e362958fca3236b702 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 7 Feb 2024 16:21:07 +0100 Subject: [PATCH 56/99] Use `min_exhaustive_patterns` in core & std --- library/core/src/lib.rs | 3 ++- library/std/src/lib.rs | 3 ++- library/std/src/sync/poison.rs | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6bcf7c13e64e..9b786feba898 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -203,8 +203,10 @@ // Language features: // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(diagnostic_namespace))] +#![cfg_attr(bootstrap, feature(exhaustive_patterns))] #![cfg_attr(bootstrap, feature(platform_intrinsics))] #![cfg_attr(not(bootstrap), feature(freeze_impls))] +#![cfg_attr(not(bootstrap), feature(min_exhaustive_patterns))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -229,7 +231,6 @@ #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] #![feature(effects)] -#![feature(exhaustive_patterns)] #![feature(extern_types)] #![feature(fundamental)] #![feature(generic_arg_infer)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8cf44f4760da..3db5cda83b7d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -270,7 +270,9 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(exhaustive_patterns))] #![cfg_attr(bootstrap, feature(platform_intrinsics))] +#![cfg_attr(not(bootstrap), feature(min_exhaustive_patterns))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] @@ -289,7 +291,6 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -#![feature(exhaustive_patterns)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] #![feature(lang_items)] diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs index 3c51389fa349..f4975088b372 100644 --- a/library/std/src/sync/poison.rs +++ b/library/std/src/sync/poison.rs @@ -270,6 +270,8 @@ impl fmt::Debug for TryLockError { match *self { #[cfg(panic = "unwind")] TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f), + #[cfg(not(panic = "unwind"))] + TryLockError::Poisoned(ref p) => match p._never {}, TryLockError::WouldBlock => "WouldBlock".fmt(f), } } @@ -281,6 +283,8 @@ impl fmt::Display for TryLockError { match *self { #[cfg(panic = "unwind")] TryLockError::Poisoned(..) => "poisoned lock: another task failed inside", + #[cfg(not(panic = "unwind"))] + TryLockError::Poisoned(ref p) => match p._never {}, TryLockError::WouldBlock => "try_lock failed because the operation would block", } .fmt(f) @@ -294,6 +298,8 @@ impl Error for TryLockError { match *self { #[cfg(panic = "unwind")] TryLockError::Poisoned(ref p) => p.description(), + #[cfg(not(panic = "unwind"))] + TryLockError::Poisoned(ref p) => match p._never {}, TryLockError::WouldBlock => "try_lock failed because the operation would block", } } @@ -303,6 +309,8 @@ impl Error for TryLockError { match *self { #[cfg(panic = "unwind")] TryLockError::Poisoned(ref p) => Some(p), + #[cfg(not(panic = "unwind"))] + TryLockError::Poisoned(ref p) => match p._never {}, _ => None, } } From e91f93777997ee647768afa60d565a0a62aefa49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Horstmann?= Date: Sat, 2 Mar 2024 10:59:11 +0100 Subject: [PATCH 57/99] Add tests for the generated assembly of mask related simd instructions. The tests show that the code generation currently uses the least significant bits of vector masks when converting to . This leads to an additional left shift operation in the assembly for x86, since mask operations on x86 operate based on the most significant bit. On aarch64 the left shift is followed by a comparison against zero, which repeats the sign bit across the whole lane. The exception, which does not introduce an unneeded shift, is simd_bitmask, because the code generation already shifts before truncating. By using the "C" calling convention the tests should be stable regarding changes in register allocation, but it is possible that future llvm updates will require updating some of the checks. This additional instruction would be removed by the fix in #104693, which uses the most significant bit for all mask operations. --- tests/assembly/simd-bitmask.rs | 149 +++++++++++++++++++ tests/assembly/simd-intrinsic-gather.rs | 44 ++++++ tests/assembly/simd-intrinsic-mask-load.rs | 88 +++++++++++ tests/assembly/simd-intrinsic-mask-reduce.rs | 60 ++++++++ tests/assembly/simd-intrinsic-mask-store.rs | 86 +++++++++++ tests/assembly/simd-intrinsic-scatter.rs | 40 +++++ tests/assembly/simd-intrinsic-select.rs | 130 ++++++++++++++++ 7 files changed, 597 insertions(+) create mode 100644 tests/assembly/simd-bitmask.rs create mode 100644 tests/assembly/simd-intrinsic-gather.rs create mode 100644 tests/assembly/simd-intrinsic-mask-load.rs create mode 100644 tests/assembly/simd-intrinsic-mask-reduce.rs create mode 100644 tests/assembly/simd-intrinsic-mask-store.rs create mode 100644 tests/assembly/simd-intrinsic-scatter.rs create mode 100644 tests/assembly/simd-intrinsic-select.rs diff --git a/tests/assembly/simd-bitmask.rs b/tests/assembly/simd-bitmask.rs new file mode 100644 index 000000000000..8264a7068520 --- /dev/null +++ b/tests/assembly/simd-bitmask.rs @@ -0,0 +1,149 @@ +//@ revisions: x86 x86-avx2 x86-avx512 aarch64 +//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86] needs-llvm-components: x86 +//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx2] compile-flags: -C target-feature=+avx2 +//@ [x86-avx2] needs-llvm-components: x86 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [aarch64] needs-llvm-components: aarch64 +//@ [aarch64] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct m8x16([i8; 16]); + +#[repr(simd)] +pub struct m8x64([i8; 64]); + +#[repr(simd)] +pub struct m32x4([i32; 4]); + +#[repr(simd)] +pub struct m64x2([i64; 2]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +extern "rust-intrinsic" { + fn simd_bitmask(mask: V) -> B; +} + +// CHECK-LABEL: bitmask_m8x16 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m8x16(mask: m8x16) -> u16 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit + // of each byte into the right position. + // + // x86-NOT: psllw + // x86: movmskb eax, xmm0 + // + // x86-avx2-NOT: vpsllw + // x86-avx2: vpmovmskb eax, xmm0 + // + // x86-avx512-NOT: vpsllw xmm0 + // x86-avx512: vpmovmskb eax, xmm0 + // + // aarch64: adrp + // aarch64-NEXT: cmlt + // aarch64-NEXT: ldr + // aarch64-NEXT: and + // aarch64-NEXT: ext + // aarch64-NEXT: zip1 + // aarch64-NEXT: addv + // aarch64-NEXT: fmov + simd_bitmask(mask) +} + +// CHECK-LABEL: bitmask_m8x64 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m8x64(mask: m8x64) -> u64 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit + // of each byte into the right position. + // + // The parameter is a 512 bit vector which in the C abi is only valid for avx512 targets. + // + // x86-avx512-NOT: vpsllw + // x86-avx512: vpmovb2m k0, zmm0 + // x86-avx512: kmovq rax, k0 + simd_bitmask(mask) +} + +// CHECK-LABEL: bitmask_m32x4 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m32x4(mask: m32x4) -> u8 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // + // x86-NOT: psllq + // x86: movmskps eax, xmm0 + // + // x86-avx2-NOT: vpsllq + // x86-avx2: vmovmskps eax, xmm0 + // + // x86-avx512-NOT: vpsllq + // x86-avx512: vmovmskps eax, xmm0 + // + // aarch64: adrp + // aarch64-NEXT: cmlt + // aarch64-NEXT: ldr + // aarch64-NEXT: and + // aarch64-NEXT: addv + // aarch64-NEXT: fmov + // aarch64-NEXT: and + simd_bitmask(mask) +} + +// CHECK-LABEL: bitmask_m64x2 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m64x2(mask: m64x2) -> u8 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // + // x86-NOT: psllq + // x86: movmskpd eax, xmm0 + // + // x86-avx2-NOT: vpsllq + // x86-avx2: vmovmskpd eax, xmm0 + // + // x86-avx512-NOT: vpsllq + // x86-avx512: vmovmskpd eax, xmm0 + // + // aarch64: adrp + // aarch64-NEXT: cmlt + // aarch64-NEXT: ldr + // aarch64-NEXT: and + // aarch64-NEXT: addp + // aarch64-NEXT: fmov + // aarch64-NEXT: and + simd_bitmask(mask) +} + +// CHECK-LABEL: bitmask_m64x4 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m64x4(mask: m64x4) -> u8 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // + // The parameter is a 256 bit vector which in the C abi is only valid for avx/avx512 targets. + // + // x86-avx2-NOT: vpsllq + // x86-avx2: vmovmskpd eax, ymm0 + // + // x86-avx512-NOT: vpsllq + // x86-avx512: vmovmskpd eax, ymm0 + simd_bitmask(mask) +} diff --git a/tests/assembly/simd-intrinsic-gather.rs b/tests/assembly/simd-intrinsic-gather.rs new file mode 100644 index 000000000000..ef6b597c25f1 --- /dev/null +++ b/tests/assembly/simd-intrinsic-gather.rs @@ -0,0 +1,44 @@ +//@ revisions: x86-avx512 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ [x86-avx512] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +#[repr(simd)] +pub struct pf64x4([*const f64; 4]); + +extern "rust-intrinsic" { + fn simd_gather(values: V, mask: M, pointer: P) -> V; +} + +// CHECK-LABEL: gather_f64x4 +#[no_mangle] +pub unsafe extern "C" fn gather_f64x4(mask: m64x4, ptrs: pf64x4) -> f64x4 { + // FIXME: This should also get checked to generate a gather instruction for avx2. + // Currently llvm scalarizes this code, see https://github.com/llvm/llvm-project/issues/59789 + // + // x86-avx512: vpsllq ymm0, ymm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NEXT: vpxor xmm0, xmm0, xmm0 + // x86-avx512-NEXT: vgatherqpd ymm0 {k1}, ymmword ptr [1*ymm1] + simd_gather(f64x4([0_f64, 0_f64, 0_f64, 0_f64]), ptrs, mask) +} diff --git a/tests/assembly/simd-intrinsic-mask-load.rs b/tests/assembly/simd-intrinsic-mask-load.rs new file mode 100644 index 000000000000..49d231c45f85 --- /dev/null +++ b/tests/assembly/simd-intrinsic-mask-load.rs @@ -0,0 +1,88 @@ +//@ revisions: x86-avx2 x86-avx512 +//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx2] compile-flags: -C target-feature=+avx2 +//@ [x86-avx2] needs-llvm-components: x86 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct i8x16([i8; 16]); + +#[repr(simd)] +pub struct m8x16([i8; 16]); + +#[repr(simd)] +pub struct f32x8([f32; 8]); + +#[repr(simd)] +pub struct m32x8([i32; 8]); + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +extern "rust-intrinsic" { + fn simd_masked_load(mask: M, pointer: P, values: T) -> T; +} + +// CHECK-LABEL: load_i8x16 +#[no_mangle] +pub unsafe extern "C" fn load_i8x16(mask: m8x16, pointer: *const i8) -> i8x16 { + // Since avx2 supports no masked loads for bytes, the code tests each individual bit + // and jumps to code that inserts individual bytes. + // x86-avx2: vpsllw xmm0, xmm0, 7 + // x86-avx2-NEXT: vpmovmskb eax, xmm0 + // x86-avx2-NEXT: vpxor xmm0, xmm0 + // x86-avx2-NEXT: test al, 1 + // x86-avx2-NEXT: jne + // x86-avx2-NEXT: test al, 2 + // x86-avx2-NEXT: jne + // x86-avx2-DAG: movzx [[REG:[a-z]+]], byte ptr [rdi] + // x86-avx2-NEXT: vmovd xmm0, [[REG]] + // x86-avx2-DAG: vpinsrb xmm0, xmm0, byte ptr [rdi + 1], 1 + // + // x86-avx512: vpsllw xmm0, xmm0, 7 + // x86-avx512-NEXT: vpmovb2m k1, xmm0 + // x86-avx512-NEXT: vmovdqu8 xmm0 {k1} {z}, xmmword ptr [rdi] + simd_masked_load(mask, pointer, i8x16([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) +} + +// CHECK-LABEL: load_f32x8 +#[no_mangle] +pub unsafe extern "C" fn load_f32x8(mask: m32x8, pointer: *const f32) -> f32x8 { + // x86-avx2: vpslld ymm0, ymm0, 31 + // x86-avx2-NEXT: vmaskmovps ymm0, ymm0, ymmword ptr [rdi] + // + // x86-avx512: vpslld ymm0, ymm0, 31 + // x86-avx512-NEXT: vpmovd2m k1, ymm0 + // x86-avx512-NEXT: vmovups ymm0 {k1} {z}, ymmword ptr [rdi] + simd_masked_load(mask, pointer, f32x8([0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32])) +} + +// CHECK-LABEL: load_f64x4 +#[no_mangle] +pub unsafe extern "C" fn load_f64x4(mask: m64x4, pointer: *const f64) -> f64x4 { + // x86-avx2: vpsllq ymm0, ymm0, 63 + // x86-avx2-NEXT: vmaskmovpd ymm0, ymm0, ymmword ptr [rdi] + // + // x86-avx512: vpsllq ymm0, ymm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NEXT: vmovupd ymm0 {k1} {z}, ymmword ptr [rdi] + simd_masked_load(mask, pointer, f64x4([0_f64, 0_f64, 0_f64, 0_f64])) +} diff --git a/tests/assembly/simd-intrinsic-mask-reduce.rs b/tests/assembly/simd-intrinsic-mask-reduce.rs new file mode 100644 index 000000000000..763401755fad --- /dev/null +++ b/tests/assembly/simd-intrinsic-mask-reduce.rs @@ -0,0 +1,60 @@ +// verify that simd mask reductions do not introduce additional bit shift operations +//@ revisions: x86 aarch64 +//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86] needs-llvm-components: x86 +//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [aarch64] needs-llvm-components: aarch64 +//@ [aarch64] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct mask8x16([i8; 16]); + +extern "rust-intrinsic" { + fn simd_reduce_all(x: T) -> bool; + fn simd_reduce_any(x: T) -> bool; +} + +// CHECK-LABEL: mask_reduce_all: +#[no_mangle] +pub unsafe extern "C" fn mask_reduce_all(m: mask8x16) -> bool { + // x86: psllw xmm0, 7 + // x86-NEXT: pmovmskb eax, xmm0 + // x86-NEXT: {{cmp ax, -1|xor eax, 65535}} + // x86-NEXT: sete al + // + // aarch64: shl v0.16b, v0.16b, #7 + // aarch64-NEXT: cmlt v0.16b, v0.16b, #0 + // aarch64-NEXT: uminv b0, v0.16b + // aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0 + // aarch64-NEXT: and w0, [[REG]], #0x1 + simd_reduce_all(m) +} + +// CHECK-LABEL: mask_reduce_any: +#[no_mangle] +pub unsafe extern "C" fn mask_reduce_any(m: mask8x16) -> bool { + // x86: psllw xmm0, 7 + // x86-NEXT: pmovmskb + // x86-NEXT: test eax, eax + // x86-NEXT: setne al + // + // aarch64: shl v0.16b, v0.16b, #7 + // aarch64-NEXT: cmlt v0.16b, v0.16b, #0 + // aarch64-NEXT: umaxv b0, v0.16b + // aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0 + // aarch64-NEXT: and w0, [[REG]], #0x1 + simd_reduce_any(m) +} diff --git a/tests/assembly/simd-intrinsic-mask-store.rs b/tests/assembly/simd-intrinsic-mask-store.rs new file mode 100644 index 000000000000..a6611e1c23d5 --- /dev/null +++ b/tests/assembly/simd-intrinsic-mask-store.rs @@ -0,0 +1,86 @@ +//@ revisions: x86-avx2 x86-avx512 +//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx2] compile-flags: -C target-feature=+avx2 +//@ [x86-avx2] needs-llvm-components: x86 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct i8x16([i8; 16]); + +#[repr(simd)] +pub struct m8x16([i8; 16]); + +#[repr(simd)] +pub struct f32x8([f32; 8]); + +#[repr(simd)] +pub struct m32x8([i32; 8]); + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +extern "rust-intrinsic" { + fn simd_masked_store(mask: M, pointer: P, values: T); +} + +// CHECK-LABEL: store_i8x16 +#[no_mangle] +pub unsafe extern "C" fn store_i8x16(mask: m8x16, pointer: *mut i8, value: i8x16) { + // Since avx2 supports no masked stores for bytes, the code tests each individual bit + // and jumps to code that extracts individual bytes to memory. + // x86-avx2: vpsllw xmm0, xmm0, 7 + // x86-avx2-NEXT: vpmovmskb eax, xmm0 + // x86-avx2-NEXT: test al, 1 + // x86-avx2-NEXT: jne + // x86-avx2-NEXT: test al, 2 + // x86-avx2-NEXT: jne + // x86-avx2-DAG: vpextrb byte ptr [rdi + 1], xmm1, 1 + // x86-avx2-DAG: vpextrb byte ptr [rdi], xmm1, 0 + // + // x86-avx512: vpsllw xmm0, xmm0, 7 + // x86-avx512-NEXT: vpmovb2m k1, xmm0 + // x86-avx512-NEXT: vmovdqu8 xmmword ptr [rdi] {k1}, xmm1 + simd_masked_store(mask, pointer, value) +} + +// CHECK-LABEL: store_f32x8 +#[no_mangle] +pub unsafe extern "C" fn store_f32x8(mask: m32x8, pointer: *mut f32, value: f32x8) { + // x86-avx2: vpslld ymm0, ymm0, 31 + // x86-avx2-NEXT: vmaskmovps ymmword ptr [rdi], ymm0, ymm1 + // + // x86-avx512: vpslld ymm0, ymm0, 31 + // x86-avx512-NEXT: vpmovd2m k1, ymm0 + // x86-avx512-NEXT: vmovups ymmword ptr [rdi] {k1}, ymm1 + simd_masked_store(mask, pointer, value) +} + +// CHECK-LABEL: store_f64x4 +#[no_mangle] +pub unsafe extern "C" fn store_f64x4(mask: m64x4, pointer: *mut f64, value: f64x4) { + // x86-avx2: vpsllq ymm0, ymm0, 63 + // x86-avx2-NEXT: vmaskmovpd ymmword ptr [rdi], ymm0, ymm1 + // + // x86-avx512: vpsllq ymm0, ymm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NEXT: vmovupd ymmword ptr [rdi] {k1}, ymm1 + simd_masked_store(mask, pointer, value) +} diff --git a/tests/assembly/simd-intrinsic-scatter.rs b/tests/assembly/simd-intrinsic-scatter.rs new file mode 100644 index 000000000000..6ffefb0801ae --- /dev/null +++ b/tests/assembly/simd-intrinsic-scatter.rs @@ -0,0 +1,40 @@ +//@ revisions: x86-avx512 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ [x86-avx512] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +#[repr(simd)] +pub struct pf64x4([*mut f64; 4]); + +extern "rust-intrinsic" { + fn simd_scatter(values: V, pointer: P, mask: M); +} + +// CHECK-LABEL: scatter_f64x4 +#[no_mangle] +pub unsafe extern "C" fn scatter_f64x4(values: f64x4, ptrs: pf64x4, mask: m64x4) { + // x86-avx512: vpsllq ymm2, ymm2, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm2 + // x86-avx512-NEXT: vscatterqpd ymmword ptr [1*ymm1] {k1}, ymm0 + simd_scatter(values, ptrs, mask) +} diff --git a/tests/assembly/simd-intrinsic-select.rs b/tests/assembly/simd-intrinsic-select.rs new file mode 100644 index 000000000000..3f36402e3d0d --- /dev/null +++ b/tests/assembly/simd-intrinsic-select.rs @@ -0,0 +1,130 @@ +//@ revisions: x86-avx2 x86-avx512 aarch64 +//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx2] compile-flags: -C target-feature=+avx2 +//@ [x86-avx2] needs-llvm-components: x86 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [aarch64] needs-llvm-components: aarch64 +//@ [aarch64] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct i8x16([i8; 16]); + +#[repr(simd)] +pub struct m8x16([i8; 16]); + +#[repr(simd)] +pub struct f32x4([f32; 4]); + +#[repr(simd)] +pub struct m32x4([i32; 4]); + +#[repr(simd)] +pub struct f64x2([f64; 2]); + +#[repr(simd)] +pub struct m64x2([i64; 2]); + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +#[repr(simd)] +pub struct f64x8([f64; 8]); + +#[repr(simd)] +pub struct m64x8([i64; 8]); + +extern "rust-intrinsic" { + fn simd_select(mask: M, a: V, b: V) -> V; +} + +// CHECK-LABEL: select_i8x16 +#[no_mangle] +pub unsafe extern "C" fn select_i8x16(mask: m8x16, a: i8x16, b: i8x16) -> i8x16 { + // x86-avx2: vpsllw xmm0, xmm0, 7 + // x86-avx2-NEXT: vpblendvb xmm0, xmm2, xmm1, xmm0 + // + // x86-avx512: vpsllw xmm0, xmm0, 7 + // x86-avx512-NEXT: vpmovb2m k1, xmm0 + // x86-avx512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1 + // + // aarch64: shl v0.16b, v0.16b, #7 + // aarch64-NEXT: cmlt v0.16b, v0.16b, #0 + // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b + simd_select(mask, a, b) +} + +// CHECK-LABEL: select_f32x4 +#[no_mangle] +pub unsafe extern "C" fn select_f32x4(mask: m32x4, a: f32x4, b: f32x4) -> f32x4 { + // x86-avx2: vpslld xmm0, xmm0, 31 + // x86-avx2-NEXT: vblendvps xmm0, xmm2, xmm1, xmm0 + // + // x86-avx512: vpslld xmm0, xmm0, 31 + // x86-avx512-NEXT: vpmovd2m k1, xmm0 + // x86-avx512-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1 + // + // aarch64: shl v0.4s, v0.4s, #31 + // aarch64-NEXT: cmlt v0.4s, v0.4s, #0 + // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b + simd_select(mask, a, b) +} + +// CHECK-LABEL: select_f64x2 +#[no_mangle] +pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2 { + // x86-avx2: vpsllq xmm0, xmm0, 63 + // x86-avx2-NEXT: vblendvpd xmm0, xmm2, xmm1, xmm0 + // + // x86-avx512: vpsllq xmm0, xmm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, xmm0 + // x86-avx512-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1 + // + // aarch64: shl v0.2d, v0.2d, #63 + // aarch64-NEXT: cmlt v0.2d, v0.2d, #0 + // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b + simd_select(mask, a, b) +} + +// CHECK-LABEL: select_f64x4 +#[no_mangle] +pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 { + // The parameter is a 256 bit vector which in the C abi is only valid for avx targets. + // + // x86-avx2: vpsllq ymm0, ymm0, 63 + // x86-avx2-NEXT: vblendvpd ymm0, ymm2, ymm1, ymm0 + // + // x86-avx512: vpsllq ymm0, ymm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1 + simd_select(mask, a, b) +} + +// CHECK-LABEL: select_f64x8 +#[no_mangle] +pub unsafe extern "C" fn select_f64x8(mask: m64x8, a: f64x8, b: f64x8) -> f64x8 { + // The parameter is a 256 bit vector which in the C abi is only valid for avx512 targets. + // + // x86-avx512: vpsllq zmm0, zmm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, zmm0 + // x86-avx512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1 + simd_select(mask, a, b) +} From e2773733f35f71dba92588d6b29e43d2cc035a34 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 11 Mar 2024 18:39:23 +0000 Subject: [PATCH 58/99] Some comment nits --- compiler/rustc_codegen_gcc/src/mono_item.rs | 2 +- compiler/rustc_codegen_llvm/src/consts.rs | 5 ++--- compiler/rustc_codegen_llvm/src/mono_item.rs | 2 +- compiler/rustc_hir/src/def.rs | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index ceaf87d16481..359d3c70b4ca 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -26,7 +26,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; - // Nested statics do not have a type, so pick a random type and let `define_static` figure out + // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out // the gcc type from the actual evaluated initializer. let ty = if nested { self.tcx.types.unit diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 8e047f124eeb..4afa230e598b 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -232,7 +232,7 @@ impl<'ll> CodegenCx<'ll, '_> { trace!(?instance); let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; - // Nested statics do not have a type, so pick a random type and let `define_static` figure out + // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out // the llvm type from the actual evaluated initializer. let llty = if nested { self.type_i8() @@ -415,8 +415,7 @@ impl<'ll> CodegenCx<'ll, '_> { llvm::LLVMRustSetDSOLocal(g, true); } - // As an optimization, all shared statics which do not have interior - // mutability are placed into read-only memory. + // Forward the allocation's mutability (picked by the const interner) to LLVM. if alloc.mutability.is_not() { llvm::LLVMSetGlobalConstant(g, llvm::True); } diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 81ac95718858..29100a641712 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -24,7 +24,7 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { ) { let instance = Instance::mono(self.tcx, def_id); let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; - // Nested statics do not have a type, so pick a random type and let `define_static` figure out + // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out // the llvm type from the actual evaluated initializer. let ty = if nested { self.tcx.types.unit diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index f6a616109c97..1810193c16bd 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -251,7 +251,7 @@ impl DefKind { | DefKind::TyParam | DefKind::ExternCrate => DefPathData::TypeNs(name), // It's not exactly an anon const, but wrt DefPathData, there - // is not difference. + // is no difference. DefKind::Static { nested: true, .. } => DefPathData::AnonConst, DefKind::Fn | DefKind::Const From 5336a02d280c8d69e5bbcf2ec11887e4b2aa86e2 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Tue, 12 Mar 2024 14:37:13 +0300 Subject: [PATCH 59/99] Fix discriminant_kind copy paste from the pointee trait case --- compiler/rustc_trait_selection/src/traits/project.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 68c03e3c73e7..6756b5dec231 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1061,8 +1061,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // Integers and floats always have `u8` as their discriminant. | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, - // type parameters, opaques, and unnormalized projections have pointer - // metadata if they're known (e.g. by the param_env) to be sized + // type parameters, opaques, and unnormalized projections don't have + // a known discriminant and may need to be normalized further or rely + // on param env for discriminant projections ty::Param(_) | ty::Alias(..) | ty::Bound(..) From e8cef43dd8bebc4a318970a83f938931ad663d0c Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 12 Mar 2024 12:09:42 +0000 Subject: [PATCH 60/99] Properly rebuild rustbooks --- src/bootstrap/src/core/build_steps/doc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index c23cd9374a6b..1d4d9d4c2e1b 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -145,7 +145,8 @@ impl Step for RustbookSrc

{ let rustbook = builder.tool_exe(Tool::Rustbook); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); - if !builder.config.dry_run() && !(up_to_date(&src, &index) || up_to_date(&rustbook, &index)) + if !builder.config.dry_run() + && (!up_to_date(&src, &index) || !up_to_date(&rustbook, &index)) { builder.info(&format!("Rustbook ({target}) - {name}")); let _ = fs::remove_dir_all(&out); From 34e59f49d5ef9742e69c421207a53163618eeb1b Mon Sep 17 00:00:00 2001 From: Jonathan Jensen Date: Tue, 12 Mar 2024 13:35:14 +0100 Subject: [PATCH 61/99] Fix typo in lib.rs of proc_macro --- library/proc_macro/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 610966625b53..e04bf69ef511 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -73,7 +73,7 @@ pub fn is_available() -> bool { /// The main type provided by this crate, representing an abstract stream of /// tokens, or, more specifically, a sequence of token trees. -/// The type provide interfaces for iterating over those token trees and, conversely, +/// The type provides interfaces for iterating over those token trees and, conversely, /// collecting a number of token trees into one stream. /// /// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]` From 0a2ddcd46b53cf1c1c0944fb69928af99fa05561 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Tue, 12 Mar 2024 12:39:25 +0000 Subject: [PATCH 62/99] llvm-wrapper: adapt for LLVM API changes Adapts rust for https://github.com/llvm/llvm-project/commit/9997e0397156ff7e01aecbd17bdeb7bfe5fb15b0. --- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index d76dea6f86cc..1632b9e12490 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1112,11 +1112,16 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo, uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL, LLVMBasicBlockRef InsertAtEnd) { - return wrap(Builder->insertDeclare( + auto Result = Builder->insertDeclare( unwrap(V), unwrap(VarInfo), Builder->createExpression(llvm::ArrayRef(AddrOps, AddrOpsCount)), DebugLoc(cast(unwrap(DL))), - unwrap(InsertAtEnd))); + unwrap(InsertAtEnd)); +#if LLVM_VERSION_GE(19, 0) + return wrap(Result.get()); +#else + return wrap(Result); +#endif } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator( From aa71151bea7a30bd8fb56a6307fd6927e2dcc5b3 Mon Sep 17 00:00:00 2001 From: apiraino Date: Tue, 12 Mar 2024 13:59:19 +0100 Subject: [PATCH 63/99] Enable PR tracking review assignment --- triagebot.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 98f31743d4aa..a2150a487e66 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -854,3 +854,7 @@ project-stable-mir = [ "/src/tools/tidy" = ["bootstrap"] "/src/tools/x" = ["bootstrap"] "/src/tools/rustdoc-gui-test" = ["bootstrap", "@onur-ozkan"] + +# Enable tracking of PR review assignment +# Documentation at: https://forge.rust-lang.org/triagebot/pr-assignment-tracking.html +[pr-tracking] From 22a5267c83a3e17f2b763279eb24bb632c45dc6b Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 12 Mar 2024 14:55:06 +0100 Subject: [PATCH 64/99] std: move `Once` implementations to `sys` --- .reuse/dep5 | 2 +- library/std/src/sync/condvar.rs | 2 +- library/std/src/sync/mutex.rs | 2 +- library/std/src/sync/once.rs | 2 +- library/std/src/sync/reentrant_lock.rs | 2 +- library/std/src/sync/rwlock.rs | 2 +- library/std/src/sys/mod.rs | 2 +- library/std/src/sys/pal/teeos/mod.rs | 2 -- library/std/src/sys/pal/uefi/mod.rs | 2 -- library/std/src/sys/pal/unsupported/mod.rs | 1 - library/std/src/sys/pal/wasi/mod.rs | 2 -- library/std/src/sys/pal/wasip2/mod.rs | 4 ---- library/std/src/sys/pal/wasm/mod.rs | 2 -- library/std/src/sys/pal/zkvm/mod.rs | 2 -- library/std/src/sys/{locks => sync}/condvar/futex.rs | 2 +- library/std/src/sys/{locks => sync}/condvar/itron.rs | 2 +- library/std/src/sys/{locks => sync}/condvar/mod.rs | 0 library/std/src/sys/{locks => sync}/condvar/no_threads.rs | 2 +- library/std/src/sys/{locks => sync}/condvar/pthread.rs | 2 +- library/std/src/sys/{locks => sync}/condvar/sgx.rs | 2 +- library/std/src/sys/{locks => sync}/condvar/teeos.rs | 2 +- library/std/src/sys/{locks => sync}/condvar/windows7.rs | 2 +- library/std/src/sys/{locks => sync}/condvar/xous.rs | 2 +- library/std/src/sys/{locks => sync}/mod.rs | 2 ++ library/std/src/sys/{locks => sync}/mutex/fuchsia.rs | 0 library/std/src/sys/{locks => sync}/mutex/futex.rs | 0 library/std/src/sys/{locks => sync}/mutex/itron.rs | 0 library/std/src/sys/{locks => sync}/mutex/mod.rs | 0 library/std/src/sys/{locks => sync}/mutex/no_threads.rs | 0 library/std/src/sys/{locks => sync}/mutex/pthread.rs | 0 library/std/src/sys/{locks => sync}/mutex/sgx.rs | 0 library/std/src/sys/{locks => sync}/mutex/windows7.rs | 0 library/std/src/sys/{locks => sync}/mutex/xous.rs | 0 library/std/src/{sys_common => sys/sync}/once/futex.rs | 0 library/std/src/{sys_common => sys/sync}/once/mod.rs | 3 ++- .../sys/{pal/unsupported/once.rs => sync/once/no_threads.rs} | 0 library/std/src/{sys_common => sys/sync}/once/queue.rs | 0 library/std/src/sys/{locks => sync}/rwlock/futex.rs | 0 library/std/src/sys/{locks => sync}/rwlock/mod.rs | 0 library/std/src/sys/{locks => sync}/rwlock/no_threads.rs | 0 library/std/src/sys/{locks => sync}/rwlock/queue.rs | 0 library/std/src/sys/{locks => sync}/rwlock/sgx.rs | 0 library/std/src/sys/{locks => sync}/rwlock/sgx/tests.rs | 0 library/std/src/sys/{locks => sync}/rwlock/solid.rs | 0 library/std/src/sys/{locks => sync}/rwlock/teeos.rs | 2 +- library/std/src/sys/{locks => sync}/rwlock/windows7.rs | 0 library/std/src/sys/{locks => sync}/rwlock/xous.rs | 0 library/std/src/sys_common/mod.rs | 1 - tests/debuginfo/mutex.rs | 2 +- tests/debuginfo/rwlock-read.rs | 2 +- 50 files changed, 22 insertions(+), 35 deletions(-) rename library/std/src/sys/{locks => sync}/condvar/futex.rs (98%) rename library/std/src/sys/{locks => sync}/condvar/itron.rs (99%) rename library/std/src/sys/{locks => sync}/condvar/mod.rs (100%) rename library/std/src/sys/{locks => sync}/condvar/no_threads.rs (94%) rename library/std/src/sys/{locks => sync}/condvar/pthread.rs (99%) rename library/std/src/sys/{locks => sync}/condvar/sgx.rs (97%) rename library/std/src/sys/{locks => sync}/condvar/teeos.rs (98%) rename library/std/src/sys/{locks => sync}/condvar/windows7.rs (96%) rename library/std/src/sys/{locks => sync}/condvar/xous.rs (99%) rename library/std/src/sys/{locks => sync}/mod.rs (71%) rename library/std/src/sys/{locks => sync}/mutex/fuchsia.rs (100%) rename library/std/src/sys/{locks => sync}/mutex/futex.rs (100%) rename library/std/src/sys/{locks => sync}/mutex/itron.rs (100%) rename library/std/src/sys/{locks => sync}/mutex/mod.rs (100%) rename library/std/src/sys/{locks => sync}/mutex/no_threads.rs (100%) rename library/std/src/sys/{locks => sync}/mutex/pthread.rs (100%) rename library/std/src/sys/{locks => sync}/mutex/sgx.rs (100%) rename library/std/src/sys/{locks => sync}/mutex/windows7.rs (100%) rename library/std/src/sys/{locks => sync}/mutex/xous.rs (100%) rename library/std/src/{sys_common => sys/sync}/once/futex.rs (100%) rename library/std/src/{sys_common => sys/sync}/once/mod.rs (94%) rename library/std/src/sys/{pal/unsupported/once.rs => sync/once/no_threads.rs} (100%) rename library/std/src/{sys_common => sys/sync}/once/queue.rs (100%) rename library/std/src/sys/{locks => sync}/rwlock/futex.rs (100%) rename library/std/src/sys/{locks => sync}/rwlock/mod.rs (100%) rename library/std/src/sys/{locks => sync}/rwlock/no_threads.rs (100%) rename library/std/src/sys/{locks => sync}/rwlock/queue.rs (100%) rename library/std/src/sys/{locks => sync}/rwlock/sgx.rs (100%) rename library/std/src/sys/{locks => sync}/rwlock/sgx/tests.rs (100%) rename library/std/src/sys/{locks => sync}/rwlock/solid.rs (100%) rename library/std/src/sys/{locks => sync}/rwlock/teeos.rs (95%) rename library/std/src/sys/{locks => sync}/rwlock/windows7.rs (100%) rename library/std/src/sys/{locks => sync}/rwlock/xous.rs (100%) diff --git a/.reuse/dep5 b/.reuse/dep5 index 6c39025b5de0..06afec2b3fae 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -52,7 +52,7 @@ Copyright: 2019 The Crossbeam Project Developers The Rust Project Developers (see https://thanks.rust-lang.org) License: MIT OR Apache-2.0 -Files: library/std/src/sys/locks/mutex/fuchsia.rs +Files: library/std/src/sys/sync/mutex/fuchsia.rs Copyright: 2016 The Fuchsia Authors The Rust Project Developers (see https://thanks.rust-lang.org) License: BSD-2-Clause AND (MIT OR Apache-2.0) diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index 9c4b926b7ecd..b20574e4f149 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -3,7 +3,7 @@ mod tests; use crate::fmt; use crate::sync::{mutex, poison, LockResult, MutexGuard, PoisonError}; -use crate::sys::locks as sys; +use crate::sys::sync as sys; use crate::time::{Duration, Instant}; /// A type indicating whether a timed wait on a condition variable returned diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index 65ff10e02d46..895fcbd6b7ed 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -8,7 +8,7 @@ use crate::mem::ManuallyDrop; use crate::ops::{Deref, DerefMut}; use crate::ptr::NonNull; use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; -use crate::sys::locks as sys; +use crate::sys::sync as sys; /// A mutual exclusion primitive useful for protecting shared data /// diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 2bb4f3f9e038..608229fd674d 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -8,7 +8,7 @@ mod tests; use crate::fmt; use crate::panic::{RefUnwindSafe, UnwindSafe}; -use crate::sys_common::once as sys; +use crate::sys::sync as sys; /// A synchronization primitive which can be used to run a one-time global /// initialization. Useful for one-time initialization for FFI or related diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index 9a44998ebf64..80b9e0cf1521 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -6,7 +6,7 @@ use crate::fmt; use crate::ops::Deref; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; -use crate::sys::locks as sys; +use crate::sys::sync as sys; /// A re-entrant mutual exclusion lock /// diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 0b3d25c32980..f7f098c082a0 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -8,7 +8,7 @@ use crate::mem::ManuallyDrop; use crate::ops::{Deref, DerefMut}; use crate::ptr::NonNull; use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; -use crate::sys::locks as sys; +use crate::sys::sync as sys; /// A reader-writer lock /// diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 81200e0061e0..bbd1d840e92d 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -6,9 +6,9 @@ mod pal; mod personality; pub mod cmath; -pub mod locks; pub mod os_str; pub mod path; +pub mod sync; #[allow(dead_code)] #[allow(unused_imports)] pub mod thread_local; diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 1fb9d5438dee..c392a0ea264b 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -19,8 +19,6 @@ pub mod fs; #[path = "../unsupported/io.rs"] pub mod io; pub mod net; -#[path = "../unsupported/once.rs"] -pub mod once; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 7c5b37fb4900..562b00c2c01a 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -21,8 +21,6 @@ pub mod fs; pub mod io; #[path = "../unsupported/net.rs"] pub mod net; -#[path = "../unsupported/once.rs"] -pub mod once; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index 9ce275ee72d5..be344fb7caed 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -6,7 +6,6 @@ pub mod env; pub mod fs; pub mod io; pub mod net; -pub mod once; pub mod os; pub mod pipe; pub mod process; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 308dd2960048..a78547261adf 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -41,8 +41,6 @@ pub mod time; cfg_if::cfg_if! { if #[cfg(not(target_feature = "atomics"))] { - #[path = "../unsupported/once.rs"] - pub mod once; #[path = "../unsupported/thread_parking.rs"] pub mod thread_parking; } diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index b12a8d5ea11c..d1d444d7b798 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -51,10 +51,6 @@ cfg_if::cfg_if! { if #[cfg(target_feature = "atomics")] { compile_error!("The wasm32-wasip2 target does not support atomics"); } else { - #[path = "../unsupported/locks/mod.rs"] - pub mod locks; - #[path = "../unsupported/once.rs"] - pub mod once; #[path = "../unsupported/thread_parking.rs"] pub mod thread_parking; } diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 40b15120e6da..5cbc3e453410 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -48,8 +48,6 @@ cfg_if::cfg_if! { #[path = "atomics/thread.rs"] pub mod thread; } else { - #[path = "../unsupported/once.rs"] - pub mod once; #[path = "../unsupported/thread.rs"] pub mod thread; #[path = "../unsupported/thread_parking.rs"] diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 6c714f76309a..228a976dbabc 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -21,8 +21,6 @@ pub mod fs; pub mod io; #[path = "../unsupported/net.rs"] pub mod net; -#[path = "../unsupported/once.rs"] -pub mod once; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/locks/condvar/futex.rs b/library/std/src/sys/sync/condvar/futex.rs similarity index 98% rename from library/std/src/sys/locks/condvar/futex.rs rename to library/std/src/sys/sync/condvar/futex.rs index 3ad93ce07f75..4586d0fd941a 100644 --- a/library/std/src/sys/locks/condvar/futex.rs +++ b/library/std/src/sys/sync/condvar/futex.rs @@ -1,6 +1,6 @@ use crate::sync::atomic::{AtomicU32, Ordering::Relaxed}; use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; -use crate::sys::locks::Mutex; +use crate::sys::sync::Mutex; use crate::time::Duration; pub struct Condvar { diff --git a/library/std/src/sys/locks/condvar/itron.rs b/library/std/src/sys/sync/condvar/itron.rs similarity index 99% rename from library/std/src/sys/locks/condvar/itron.rs rename to library/std/src/sys/sync/condvar/itron.rs index 4c6f5e9dad26..9b64d241efd1 100644 --- a/library/std/src/sys/locks/condvar/itron.rs +++ b/library/std/src/sys/sync/condvar/itron.rs @@ -2,7 +2,7 @@ use crate::sys::pal::itron::{ abi, error::expect_success_aborting, spin::SpinMutex, task, time::with_tmos_strong, }; -use crate::{mem::replace, ptr::NonNull, sys::locks::Mutex, time::Duration}; +use crate::{mem::replace, ptr::NonNull, sys::sync::Mutex, time::Duration}; // The implementation is inspired by the queue-based implementation shown in // Andrew D. Birrell's paper "Implementing Condition Variables with Semaphores" diff --git a/library/std/src/sys/locks/condvar/mod.rs b/library/std/src/sys/sync/condvar/mod.rs similarity index 100% rename from library/std/src/sys/locks/condvar/mod.rs rename to library/std/src/sys/sync/condvar/mod.rs diff --git a/library/std/src/sys/locks/condvar/no_threads.rs b/library/std/src/sys/sync/condvar/no_threads.rs similarity index 94% rename from library/std/src/sys/locks/condvar/no_threads.rs rename to library/std/src/sys/sync/condvar/no_threads.rs index 3f0943b50ee4..36b89c5f5bef 100644 --- a/library/std/src/sys/locks/condvar/no_threads.rs +++ b/library/std/src/sys/sync/condvar/no_threads.rs @@ -1,4 +1,4 @@ -use crate::sys::locks::Mutex; +use crate::sys::sync::Mutex; use crate::time::Duration; pub struct Condvar {} diff --git a/library/std/src/sys/locks/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs similarity index 99% rename from library/std/src/sys/locks/condvar/pthread.rs rename to library/std/src/sys/sync/condvar/pthread.rs index 094738d5a3f2..728371685eee 100644 --- a/library/std/src/sys/locks/condvar/pthread.rs +++ b/library/std/src/sys/sync/condvar/pthread.rs @@ -1,7 +1,7 @@ use crate::cell::UnsafeCell; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed}; -use crate::sys::locks::{mutex, Mutex}; +use crate::sys::sync::{mutex, Mutex}; #[cfg(not(target_os = "nto"))] use crate::sys::time::TIMESPEC_MAX; #[cfg(target_os = "nto")] diff --git a/library/std/src/sys/locks/condvar/sgx.rs b/library/std/src/sys/sync/condvar/sgx.rs similarity index 97% rename from library/std/src/sys/locks/condvar/sgx.rs rename to library/std/src/sys/sync/condvar/sgx.rs index cabd3250275a..ecb5872f60d9 100644 --- a/library/std/src/sys/locks/condvar/sgx.rs +++ b/library/std/src/sys/sync/condvar/sgx.rs @@ -1,5 +1,5 @@ -use crate::sys::locks::Mutex; use crate::sys::pal::waitqueue::{SpinMutex, WaitQueue, WaitVariable}; +use crate::sys::sync::Mutex; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; use crate::time::Duration; diff --git a/library/std/src/sys/locks/condvar/teeos.rs b/library/std/src/sys/sync/condvar/teeos.rs similarity index 98% rename from library/std/src/sys/locks/condvar/teeos.rs rename to library/std/src/sys/sync/condvar/teeos.rs index c08e8145b8c3..0a931f407d2f 100644 --- a/library/std/src/sys/locks/condvar/teeos.rs +++ b/library/std/src/sys/sync/condvar/teeos.rs @@ -1,7 +1,7 @@ use crate::cell::UnsafeCell; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed}; -use crate::sys::locks::mutex::{self, Mutex}; +use crate::sys::sync::mutex::{self, Mutex}; use crate::sys::time::TIMESPEC_MAX; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; use crate::time::Duration; diff --git a/library/std/src/sys/locks/condvar/windows7.rs b/library/std/src/sys/sync/condvar/windows7.rs similarity index 96% rename from library/std/src/sys/locks/condvar/windows7.rs rename to library/std/src/sys/sync/condvar/windows7.rs index 28a288335d2f..07fa5fdd698e 100644 --- a/library/std/src/sys/locks/condvar/windows7.rs +++ b/library/std/src/sys/sync/condvar/windows7.rs @@ -1,7 +1,7 @@ use crate::cell::UnsafeCell; use crate::sys::c; -use crate::sys::locks::{mutex, Mutex}; use crate::sys::os; +use crate::sys::sync::{mutex, Mutex}; use crate::time::Duration; pub struct Condvar { diff --git a/library/std/src/sys/locks/condvar/xous.rs b/library/std/src/sys/sync/condvar/xous.rs similarity index 99% rename from library/std/src/sys/locks/condvar/xous.rs rename to library/std/src/sys/sync/condvar/xous.rs index 0e51449e0afa..7b218818ef8e 100644 --- a/library/std/src/sys/locks/condvar/xous.rs +++ b/library/std/src/sys/sync/condvar/xous.rs @@ -1,6 +1,6 @@ use crate::os::xous::ffi::{blocking_scalar, scalar}; use crate::os::xous::services::{ticktimer_server, TicktimerScalar}; -use crate::sys::locks::Mutex; +use crate::sys::sync::Mutex; use crate::time::Duration; use core::sync::atomic::{AtomicUsize, Ordering}; diff --git a/library/std/src/sys/locks/mod.rs b/library/std/src/sys/sync/mod.rs similarity index 71% rename from library/std/src/sys/locks/mod.rs rename to library/std/src/sys/sync/mod.rs index 0bdc4a1e1db8..623e6bccd515 100644 --- a/library/std/src/sys/locks/mod.rs +++ b/library/std/src/sys/sync/mod.rs @@ -1,7 +1,9 @@ mod condvar; mod mutex; +mod once; mod rwlock; pub use condvar::Condvar; pub use mutex::Mutex; +pub use once::{Once, OnceState}; pub use rwlock::RwLock; diff --git a/library/std/src/sys/locks/mutex/fuchsia.rs b/library/std/src/sys/sync/mutex/fuchsia.rs similarity index 100% rename from library/std/src/sys/locks/mutex/fuchsia.rs rename to library/std/src/sys/sync/mutex/fuchsia.rs diff --git a/library/std/src/sys/locks/mutex/futex.rs b/library/std/src/sys/sync/mutex/futex.rs similarity index 100% rename from library/std/src/sys/locks/mutex/futex.rs rename to library/std/src/sys/sync/mutex/futex.rs diff --git a/library/std/src/sys/locks/mutex/itron.rs b/library/std/src/sys/sync/mutex/itron.rs similarity index 100% rename from library/std/src/sys/locks/mutex/itron.rs rename to library/std/src/sys/sync/mutex/itron.rs diff --git a/library/std/src/sys/locks/mutex/mod.rs b/library/std/src/sys/sync/mutex/mod.rs similarity index 100% rename from library/std/src/sys/locks/mutex/mod.rs rename to library/std/src/sys/sync/mutex/mod.rs diff --git a/library/std/src/sys/locks/mutex/no_threads.rs b/library/std/src/sys/sync/mutex/no_threads.rs similarity index 100% rename from library/std/src/sys/locks/mutex/no_threads.rs rename to library/std/src/sys/sync/mutex/no_threads.rs diff --git a/library/std/src/sys/locks/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs similarity index 100% rename from library/std/src/sys/locks/mutex/pthread.rs rename to library/std/src/sys/sync/mutex/pthread.rs diff --git a/library/std/src/sys/locks/mutex/sgx.rs b/library/std/src/sys/sync/mutex/sgx.rs similarity index 100% rename from library/std/src/sys/locks/mutex/sgx.rs rename to library/std/src/sys/sync/mutex/sgx.rs diff --git a/library/std/src/sys/locks/mutex/windows7.rs b/library/std/src/sys/sync/mutex/windows7.rs similarity index 100% rename from library/std/src/sys/locks/mutex/windows7.rs rename to library/std/src/sys/sync/mutex/windows7.rs diff --git a/library/std/src/sys/locks/mutex/xous.rs b/library/std/src/sys/sync/mutex/xous.rs similarity index 100% rename from library/std/src/sys/locks/mutex/xous.rs rename to library/std/src/sys/sync/mutex/xous.rs diff --git a/library/std/src/sys_common/once/futex.rs b/library/std/src/sys/sync/once/futex.rs similarity index 100% rename from library/std/src/sys_common/once/futex.rs rename to library/std/src/sys/sync/once/futex.rs diff --git a/library/std/src/sys_common/once/mod.rs b/library/std/src/sys/sync/once/mod.rs similarity index 94% rename from library/std/src/sys_common/once/mod.rs rename to library/std/src/sys/sync/once/mod.rs index ec57568c54c4..61b29713fa1a 100644 --- a/library/std/src/sys_common/once/mod.rs +++ b/library/std/src/sys/sync/once/mod.rs @@ -30,6 +30,7 @@ cfg_if::cfg_if! { mod queue; pub use queue::{Once, OnceState}; } else { - pub use crate::sys::once::{Once, OnceState}; + mod no_threads; + pub use no_threads::{Once, OnceState}; } } diff --git a/library/std/src/sys/pal/unsupported/once.rs b/library/std/src/sys/sync/once/no_threads.rs similarity index 100% rename from library/std/src/sys/pal/unsupported/once.rs rename to library/std/src/sys/sync/once/no_threads.rs diff --git a/library/std/src/sys_common/once/queue.rs b/library/std/src/sys/sync/once/queue.rs similarity index 100% rename from library/std/src/sys_common/once/queue.rs rename to library/std/src/sys/sync/once/queue.rs diff --git a/library/std/src/sys/locks/rwlock/futex.rs b/library/std/src/sys/sync/rwlock/futex.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/futex.rs rename to library/std/src/sys/sync/rwlock/futex.rs diff --git a/library/std/src/sys/locks/rwlock/mod.rs b/library/std/src/sys/sync/rwlock/mod.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/mod.rs rename to library/std/src/sys/sync/rwlock/mod.rs diff --git a/library/std/src/sys/locks/rwlock/no_threads.rs b/library/std/src/sys/sync/rwlock/no_threads.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/no_threads.rs rename to library/std/src/sys/sync/rwlock/no_threads.rs diff --git a/library/std/src/sys/locks/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/queue.rs rename to library/std/src/sys/sync/rwlock/queue.rs diff --git a/library/std/src/sys/locks/rwlock/sgx.rs b/library/std/src/sys/sync/rwlock/sgx.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/sgx.rs rename to library/std/src/sys/sync/rwlock/sgx.rs diff --git a/library/std/src/sys/locks/rwlock/sgx/tests.rs b/library/std/src/sys/sync/rwlock/sgx/tests.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/sgx/tests.rs rename to library/std/src/sys/sync/rwlock/sgx/tests.rs diff --git a/library/std/src/sys/locks/rwlock/solid.rs b/library/std/src/sys/sync/rwlock/solid.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/solid.rs rename to library/std/src/sys/sync/rwlock/solid.rs diff --git a/library/std/src/sys/locks/rwlock/teeos.rs b/library/std/src/sys/sync/rwlock/teeos.rs similarity index 95% rename from library/std/src/sys/locks/rwlock/teeos.rs rename to library/std/src/sys/sync/rwlock/teeos.rs index 27cdb88788fc..ef9b1ab51546 100644 --- a/library/std/src/sys/locks/rwlock/teeos.rs +++ b/library/std/src/sys/sync/rwlock/teeos.rs @@ -1,4 +1,4 @@ -use crate::sys::locks::mutex::Mutex; +use crate::sys::sync::mutex::Mutex; /// we do not supported rwlock, so use mutex to simulate rwlock. /// it's useful because so many code in std will use rwlock. diff --git a/library/std/src/sys/locks/rwlock/windows7.rs b/library/std/src/sys/sync/rwlock/windows7.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/windows7.rs rename to library/std/src/sys/sync/rwlock/windows7.rs diff --git a/library/std/src/sys/locks/rwlock/xous.rs b/library/std/src/sys/sync/rwlock/xous.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/xous.rs rename to library/std/src/sys/sync/rwlock/xous.rs diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index c9025a81bf3d..5410f135a73f 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -24,7 +24,6 @@ pub mod backtrace; pub mod fs; pub mod io; pub mod lazy_box; -pub mod once; pub mod process; pub mod thread; pub mod thread_info; diff --git a/tests/debuginfo/mutex.rs b/tests/debuginfo/mutex.rs index affc1558ffa9..4f458c0d7e0d 100644 --- a/tests/debuginfo/mutex.rs +++ b/tests/debuginfo/mutex.rs @@ -10,7 +10,7 @@ // // cdb-command:dx m,d // cdb-check:m,d [Type: std::sync::mutex::Mutex] -// cdb-check: [...] inner [Type: std::sys::locks::mutex::futex::Mutex] +// cdb-check: [...] inner [Type: std::sys::sync::mutex::futex::Mutex] // cdb-check: [...] poison [Type: std::sync::poison::Flag] // cdb-check: [...] data : 0 [Type: core::cell::UnsafeCell] diff --git a/tests/debuginfo/rwlock-read.rs b/tests/debuginfo/rwlock-read.rs index 76dbc73a1e94..3fd6ac337265 100644 --- a/tests/debuginfo/rwlock-read.rs +++ b/tests/debuginfo/rwlock-read.rs @@ -16,7 +16,7 @@ // cdb-command:dx r // cdb-check:r [Type: std::sync::rwlock::RwLockReadGuard] // cdb-check: [...] data : NonNull([...]: 0) [Type: core::ptr::non_null::NonNull] -// cdb-check: [...] inner_lock : [...] [Type: std::sys::locks::rwlock::futex::RwLock *] +// cdb-check: [...] inner_lock : [...] [Type: std::sys::sync::rwlock::futex::RwLock *] #[allow(unused_variables)] From e322fef0c2fadd2330daad8f7e3116bd66927aa4 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 12 Mar 2024 13:19:25 -0400 Subject: [PATCH 65/99] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index a4c63fe5388b..7065f0ef4aa2 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit a4c63fe5388beaa09e5f91196c86addab0a03580 +Subproject commit 7065f0ef4aa267a7455e1c478b5ccacb7baea59c From 96b8225d8dd971bc2ecc7aa12068adcda9a9f20f Mon Sep 17 00:00:00 2001 From: Veera Date: Mon, 11 Mar 2024 23:05:43 -0400 Subject: [PATCH 66/99] Don't Create `ParamCandidate` When Obligation Contains Errors Fixes #121941 --- .../src/traits/select/candidate_assembly.rs | 7 +++++++ ...r-ty-with-calller-supplied-obligation-issue-121941.rs | 5 +++++ ...-with-calller-supplied-obligation-issue-121941.stderr | 9 +++++++++ 3 files changed, 21 insertions(+) create mode 100644 tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs create mode 100644 tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 66f740b761d3..89654ed61aeb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -219,6 +219,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result<(), SelectionError<'tcx>> { debug!(?stack.obligation); + // An error type will unify with anything. So, avoid + // matching an error type with `ParamCandidate`. + // This helps us avoid spurious errors like issue #121941. + if stack.obligation.predicate.references_error() { + return Ok(()); + } + let all_bounds = stack .obligation .param_env diff --git a/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs new file mode 100644 index 000000000000..a08407683d8f --- /dev/null +++ b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs @@ -0,0 +1,5 @@ +fn function() { + foo == 2; //~ ERROR cannot find value `foo` in this scope [E0425] +} + +fn main() {} diff --git a/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr new file mode 100644 index 000000000000..2da731dcc4b1 --- /dev/null +++ b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `foo` in this scope + --> $DIR/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs:2:5 + | +LL | foo == 2; + | ^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. From eab1f30c297027f2349ecd1322573ae3b5c9d668 Mon Sep 17 00:00:00 2001 From: Daniel Sedlak Date: Tue, 12 Mar 2024 19:23:53 +0100 Subject: [PATCH 67/99] Fix ICE in diagnostics for parenthesized type arguments --- compiler/rustc_parse/src/parser/path.rs | 52 +++++++++++-------- ...hesized-type-arguments-ice-issue-122345.rs | 7 +++ ...zed-type-arguments-ice-issue-122345.stderr | 16 ++++++ 3 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs create mode 100644 tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 2edf2111de73..163d10d03f03 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -449,9 +449,13 @@ impl<'a> Parser<'a> { prev_token_before_parsing: Token, error: &mut Diag<'_>, ) { - if ((style == PathStyle::Expr && self.parse_paren_comma_seq(|p| p.parse_expr()).is_ok()) - || (style == PathStyle::Pat - && self + match style { + PathStyle::Expr + if let Ok(_) = self + .parse_paren_comma_seq(|p| p.parse_expr()) + .map_err(|error| error.cancel()) => {} + PathStyle::Pat + if let Ok(_) = self .parse_paren_comma_seq(|p| { p.parse_pat_allow_top_alt( None, @@ -460,25 +464,31 @@ impl<'a> Parser<'a> { CommaRecoveryMode::LikelyTuple, ) }) - .is_ok())) - && !matches!(self.token.kind, token::ModSep | token::RArrow) - { - error.span_suggestion_verbose( - prev_token_before_parsing.span, - format!( - "consider removing the `::` here to {}", - match style { - PathStyle::Expr => "call the expression", - PathStyle::Pat => "turn this into a tuple struct pattern", - _ => { - return; - } - } - ), - "", - Applicability::MaybeIncorrect, - ); + .map_err(|error| error.cancel()) => {} + _ => { + return; + } } + + if let token::ModSep | token::RArrow = self.token.kind { + return; + } + + error.span_suggestion_verbose( + prev_token_before_parsing.span, + format!( + "consider removing the `::` here to {}", + match style { + PathStyle::Expr => "call the expression", + PathStyle::Pat => "turn this into a tuple struct pattern", + _ => { + return; + } + } + ), + "", + Applicability::MaybeIncorrect, + ); } /// Parses generic args (within a path segment) with recovery for extra leading angle brackets. diff --git a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs new file mode 100644 index 000000000000..47df107a2612 --- /dev/null +++ b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs @@ -0,0 +1,7 @@ +fn main() { + unsafe { + dealloc(ptr2, Layout::(x: !)(1, 1)); //~ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` + //~^ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` + //~| while parsing this parenthesized list of type arguments starting here + } +} diff --git a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr new file mode 100644 index 000000000000..8067c97ae4b5 --- /dev/null +++ b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr @@ -0,0 +1,16 @@ +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:3:33 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | --- ^ expected one of 7 possible tokens + | | + | while parsing this parenthesized list of type arguments starting here + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:3:43 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to 2 previous errors + From f3b348bf969d40a95838d7eec20b010a64ccf6e0 Mon Sep 17 00:00:00 2001 From: Elijah Riggs Date: Tue, 12 Mar 2024 15:00:22 -0700 Subject: [PATCH 68/99] rustdoc: do not preload fonts when browsing locally --- src/librustdoc/html/templates/page.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index e5bb8e6d19ce..0f3debae66c7 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -6,11 +6,13 @@ {# #} {# #} {{page.title}} {# #} + {# #} {# #} Date: Fri, 8 Mar 2024 19:11:59 +0000 Subject: [PATCH 69/99] Add `intrinsic_name` to get plain intrinsic name --- compiler/rustc_smir/src/rustc_smir/context.rs | 10 ++++++++++ compiler/stable_mir/src/compiler_interface.rs | 1 + compiler/stable_mir/src/mir/mono.rs | 11 +++++++++++ tests/ui-fulldeps/stable-mir/check_defs.rs | 14 +++++++++++++- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 540bc4835486..fed1d98d5e6a 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -587,6 +587,16 @@ impl<'tcx> Context for TablesWrapper<'tcx> { } } + /// Retrieve the plain intrinsic name of an instance. + /// + /// This assumes that the instance is an intrinsic. + fn intrinsic_name(&self, def: InstanceDef) -> Symbol { + let tables = self.0.borrow_mut(); + let instance = tables.instances[def]; + let intrinsic = tables.tcx.intrinsic(instance.def_id()).unwrap(); + intrinsic.name.to_string() + } + fn ty_layout(&self, ty: Ty) -> Result { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 0f7d8d7e083b..1c51c175d81b 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -183,6 +183,7 @@ pub trait Context { fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option; fn krate(&self, def_id: DefId) -> Crate; fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol; + fn intrinsic_name(&self, def: InstanceDef) -> Symbol; /// Return information about the target machine. fn target_info(&self) -> MachineInfo; diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 97f57d2c7b35..38e5776c48ce 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -90,6 +90,17 @@ impl Instance { with(|context| context.instance_name(self.def, true)) } + /// Retrieve the plain intrinsic name of an instance if it's an intrinsic. + /// + /// The plain name does not include type arguments (as `trimmed_name` does), + /// which is more convenient to match with intrinsic symbols. + pub fn intrinsic_name(&self) -> Option { + match self.kind { + InstanceKind::Intrinsic => Some(with(|context| context.intrinsic_name(self.def))), + InstanceKind::Item | InstanceKind::Virtual { .. } | InstanceKind::Shim => None, + } + } + /// Resolve an instance starting from a function definition and generic arguments. pub fn resolve(def: FnDef, args: &GenericArgs) -> Result { with(|context| { diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index 27b9b059c209..5bb1053f1879 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -19,6 +19,7 @@ extern crate stable_mir; use std::assert_matches::assert_matches; use mir::{mono::Instance, TerminatorKind::*}; +use stable_mir::mir::mono::InstanceKind; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind, Ty, UintTy}; use stable_mir::*; @@ -35,9 +36,10 @@ fn test_stable_mir() -> ControlFlow<()> { assert_eq!(main_fn.trimmed_name(), "main"); let instances = get_instances(main_fn.body().unwrap()); - assert_eq!(instances.len(), 2); + assert_eq!(instances.len(), 3); test_fn(instances[0], "from_u32", "std::char::from_u32", "core"); test_fn(instances[1], "Vec::::new", "std::vec::Vec::::new", "alloc"); + test_fn(instances[2], "ctpop::", "std::intrinsics::ctpop::", "core"); test_vec_new(instances[1]); ControlFlow::Continue(()) } @@ -48,6 +50,14 @@ fn test_fn(instance: Instance, expected_trimmed: &str, expected_qualified: &str, assert_eq!(&trimmed, expected_trimmed); assert_eq!(&qualified, expected_qualified); + if instance.kind == InstanceKind::Intrinsic { + let intrinsic = instance.intrinsic_name().unwrap(); + let (trimmed_base, _trimmed_args) = trimmed.split_once("::").unwrap(); + assert_eq!(intrinsic, trimmed_base); + return; + } + assert!(instance.intrinsic_name().is_none()); + let item = CrateItem::try_from(instance).unwrap(); let trimmed = item.trimmed_name(); let qualified = item.name(); @@ -119,10 +129,12 @@ fn generate_input(path: &str) -> std::io::Result<()> { write!( file, r#" + #![feature(core_intrinsics)] fn main() {{ let _c = core::char::from_u32(99); let _v = Vec::::new(); + let _i = std::intrinsics::ctpop::(0); }} "# )?; From 81d630453b08253dc1d6bcc4139dde16530887d9 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 21 Feb 2024 18:58:12 -0500 Subject: [PATCH 70/99] Avoid lowering code under dead SwitchInt targets --- compiler/rustc_codegen_ssa/src/mir/block.rs | 10 ++ compiler/rustc_codegen_ssa/src/mir/mod.rs | 11 +- compiler/rustc_middle/src/mir/mod.rs | 127 +++++++++++++++++++- compiler/rustc_middle/src/mir/traversal.rs | 2 - tests/codegen/precondition-checks.rs | 27 +++++ tests/codegen/skip-mono-inside-if-false.rs | 41 +++++++ 6 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 tests/codegen/precondition-checks.rs create mode 100644 tests/codegen/skip-mono-inside-if-false.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index d3f5de25d9a2..9bb2a5282658 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1237,6 +1237,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + pub fn codegen_block_as_unreachable(&mut self, bb: mir::BasicBlock) { + let llbb = match self.try_llbb(bb) { + Some(llbb) => llbb, + None => return, + }; + let bx = &mut Bx::build(self.cx, llbb); + debug!("codegen_block_as_unreachable({:?})", bb); + bx.unreachable(); + } + fn codegen_terminator( &mut self, bx: &mut Bx, diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index a6fcf1fd38c1..bac10f313366 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -256,13 +256,22 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Apply debuginfo to the newly allocated locals. fx.debug_introduce_locals(&mut start_bx); + let reachable_blocks = mir.reachable_blocks_in_mono(cx.tcx(), instance); + // The builders will be created separately for each basic block at `codegen_block`. // So drop the builder of `start_llbb` to avoid having two at the same time. drop(start_bx); // Codegen the body of each block using reverse postorder for (bb, _) in traversal::reverse_postorder(mir) { - fx.codegen_block(bb); + if reachable_blocks.contains(bb) { + fx.codegen_block(bb); + } else { + // This may have references to things we didn't monomorphize, so we + // don't actually codegen the body. We still create the block so + // terminators in other blocks can reference it without worry. + fx.codegen_block_as_unreachable(bb); + } } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4b5a08d6af3c..b71c614dc4fe 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -10,7 +10,7 @@ use crate::ty::print::{pretty_print_const, with_no_trimmed_paths}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, List, Ty, TyCtxt}; -use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex}; +use crate::ty::{AdtDef, Instance, InstanceDef, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_data_structures::captures::Captures; @@ -27,6 +27,8 @@ pub use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_index::bit_set::BitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::symbol::Symbol; @@ -640,6 +642,129 @@ impl<'tcx> Body<'tcx> { self.injection_phase.is_some() } + /// Finds which basic blocks are actually reachable for a specific + /// monomorphization of this body. + /// + /// This is allowed to have false positives; just because this says a block + /// is reachable doesn't mean that's necessarily true. It's thus always + /// legal for this to return a filled set. + /// + /// Regardless, the [`BitSet::domain_size`] of the returned set will always + /// exactly match the number of blocks in the body so that `contains` + /// checks can be done without worrying about panicking. + /// + /// This is mostly useful because it lets us skip lowering the `false` side + /// of `if ::CONST`, as well as `intrinsics::debug_assertions`. + pub fn reachable_blocks_in_mono( + &self, + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + ) -> BitSet { + let mut set = BitSet::new_empty(self.basic_blocks.len()); + self.reachable_blocks_in_mono_from(tcx, instance, &mut set, START_BLOCK); + set + } + + fn reachable_blocks_in_mono_from( + &self, + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + set: &mut BitSet, + bb: BasicBlock, + ) { + if !set.insert(bb) { + return; + } + + let data = &self.basic_blocks[bb]; + + if let Some((bits, targets)) = Self::try_const_mono_switchint(tcx, instance, data) { + let target = targets.target_for_value(bits); + ensure_sufficient_stack(|| { + self.reachable_blocks_in_mono_from(tcx, instance, set, target) + }); + return; + } + + for target in data.terminator().successors() { + ensure_sufficient_stack(|| { + self.reachable_blocks_in_mono_from(tcx, instance, set, target) + }); + } + } + + /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the + /// dimscriminant in monomorphization, we return the discriminant bits and the + /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator. + fn try_const_mono_switchint<'a>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + block: &'a BasicBlockData<'tcx>, + ) -> Option<(u128, &'a SwitchTargets)> { + // There are two places here we need to evaluate a constant. + let eval_mono_const = |constant: &ConstOperand<'tcx>| { + let env = ty::ParamEnv::reveal_all(); + let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions( + tcx, + env, + crate::ty::EarlyBinder::bind(constant.const_), + ); + let Some(bits) = mono_literal.try_eval_bits(tcx, env) else { + bug!("Couldn't evaluate constant {:?} in mono {:?}", constant, instance); + }; + bits + }; + + let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else { + return None; + }; + + // If this is a SwitchInt(const _), then we can just evaluate the constant and return. + let discr = match discr { + Operand::Constant(constant) => { + let bits = eval_mono_const(constant); + return Some((bits, targets)); + } + Operand::Move(place) | Operand::Copy(place) => place, + }; + + // MIR for `if false` actually looks like this: + // _1 = const _ + // SwitchInt(_1) + // + // And MIR for if intrinsics::debug_assertions() looks like this: + // _1 = cfg!(debug_assertions) + // SwitchInt(_1) + // + // So we're going to try to recognize this pattern. + // + // If we have a SwitchInt on a non-const place, we find the most recent statement that + // isn't a storage marker. If that statement is an assignment of a const to our + // discriminant place, we evaluate and return the const, as if we've const-propagated it + // into the SwitchInt. + + let last_stmt = block.statements.iter().rev().find(|stmt| { + !matches!(stmt.kind, StatementKind::StorageDead(_) | StatementKind::StorageLive(_)) + })?; + + let (place, rvalue) = last_stmt.kind.as_assign()?; + + if discr != place { + return None; + } + + match rvalue { + Rvalue::NullaryOp(NullOp::UbCheck(_), _) => { + Some((tcx.sess.opts.debug_assertions as u128, targets)) + } + Rvalue::Use(Operand::Constant(constant)) => { + let bits = eval_mono_const(constant); + Some((bits, targets)) + } + _ => None, + } + } + /// For a `Location` in this scope, determine what the "caller location" at that point is. This /// is interesting because of inlining: the `#[track_caller]` attribute of inlined functions /// must be honored. Falls back to the `tracked_caller` value for `#[track_caller]` functions, diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index a1ff8410eac4..0a938bcd3156 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -1,5 +1,3 @@ -use rustc_index::bit_set::BitSet; - use super::*; /// Preorder traversal of a graph. diff --git a/tests/codegen/precondition-checks.rs b/tests/codegen/precondition-checks.rs new file mode 100644 index 000000000000..191494450037 --- /dev/null +++ b/tests/codegen/precondition-checks.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 -Cdebug-assertions=no + +// This test ensures that in a debug build which turns off debug assertions, we do not monomorphize +// any of the standard library's unsafe precondition checks. +// The naive codegen of those checks contains the actual check underneath an `if false`, which +// could be optimized out if optimizations are enabled. But if we rely on optimizations to remove +// panic branches, then we can't link compiler_builtins without optimizing it, which means that +// -Zbuild-std doesn't work with -Copt-level=0. +// +// In other words, this tests for a mandatory optimization. + +#![crate_type = "lib"] + +use std::ptr::NonNull; + +// CHECK-LABEL: ; core::ptr::non_null::NonNull::new_unchecked +// CHECK-NOT: call +// CHECK: } + +// CHECK-LABEL: @nonnull_new +#[no_mangle] +pub unsafe fn nonnull_new(ptr: *mut u8) -> NonNull { + // CHECK: ; call core::ptr::non_null::NonNull::new_unchecked + unsafe { + NonNull::new_unchecked(ptr) + } +} diff --git a/tests/codegen/skip-mono-inside-if-false.rs b/tests/codegen/skip-mono-inside-if-false.rs new file mode 100644 index 000000000000..8b95de99dd3b --- /dev/null +++ b/tests/codegen/skip-mono-inside-if-false.rs @@ -0,0 +1,41 @@ +//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 + +#![crate_type = "lib"] + +#[no_mangle] +pub fn demo_for_i32() { + generic_impl::(); +} + +// Two important things here: +// - We replace the "then" block with `unreachable` to avoid linking problems +// - We neither declare nor define the `big_impl` that said block "calls". + +// CHECK-LABEL: ; skip_mono_inside_if_false::generic_impl +// CHECK: start: +// CHECK-NEXT: br label %[[ELSE_BRANCH:bb[0-9]+]] +// CHECK: [[ELSE_BRANCH]]: +// CHECK-NEXT: call skip_mono_inside_if_false::small_impl +// CHECK: bb{{[0-9]+}}: +// CHECK-NEXT: ret void +// CHECK: bb{{[0-9+]}}: +// CHECK-NEXT: unreachable + +fn generic_impl() { + trait MagicTrait { + const IS_BIG: bool; + } + impl MagicTrait for T { + const IS_BIG: bool = std::mem::size_of::() > 10; + } + if T::IS_BIG { + big_impl::(); + } else { + small_impl::(); + } +} + +#[inline(never)] +fn small_impl() {} +#[inline(never)] +fn big_impl() {} From 1f544ce305bc207c9d0539938219caf01ea230c9 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 12 Mar 2024 12:30:33 +1100 Subject: [PATCH 71/99] coverage: Remove all unstable values of `-Cinstrument-coverage` --- .../src/coverageinfo/mapgen.rs | 13 +++---- .../rustc_monomorphize/src/partitioning.rs | 4 +- compiler/rustc_session/src/config.rs | 38 +------------------ compiler/rustc_session/src/options.rs | 22 +++-------- compiler/rustc_session/src/session.rs | 12 ------ src/doc/rustc/src/instrument-coverage.md | 9 ----- tests/coverage/auxiliary/used_crate.rs | 15 +++----- tests/coverage/uses_crate.coverage | 15 +++----- .../instrument-coverage/bad-value.bad.stderr | 2 +- .../bad-value.blank.stderr | 2 +- .../unstable.branch.stderr | 2 - .../unstable.except-unused-functions.stderr | 2 - .../unstable.except-unused-generics.stderr | 2 - tests/ui/instrument-coverage/unstable.rs | 6 --- 14 files changed, 26 insertions(+), 118 deletions(-) delete mode 100644 tests/ui/instrument-coverage/unstable.branch.stderr delete mode 100644 tests/ui/instrument-coverage/unstable.except-unused-functions.stderr delete mode 100644 tests/ui/instrument-coverage/unstable.except-unused-generics.stderr delete mode 100644 tests/ui/instrument-coverage/unstable.rs diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index c45787f35aae..ee7ea3423016 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -355,21 +355,20 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) { let tcx = cx.tcx; - let ignore_unused_generics = tcx.sess.instrument_coverage_except_unused_generics(); - let eligible_def_ids = tcx.mir_keys(()).iter().filter_map(|local_def_id| { let def_id = local_def_id.to_def_id(); let kind = tcx.def_kind(def_id); // `mir_keys` will give us `DefId`s for all kinds of things, not // just "functions", like consts, statics, etc. Filter those out. - // If `ignore_unused_generics` was specified, filter out any - // generic functions from consideration as well. if !matches!(kind, DefKind::Fn | DefKind::AssocFn | DefKind::Closure) { return None; } - if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) { - return None; - } + + // FIXME(79651): Consider trying to filter out dummy instantiations of + // unused generic functions from library crates, because they can produce + // "unused instantiation" in coverage reports even when they are actually + // used by some downstream crate in the same binary. + Some(local_def_id.to_def_id()) }); diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 8bebc30e4356..296eb3120ee4 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -175,9 +175,7 @@ where } // Mark one CGU for dead code, if necessary. - let instrument_dead_code = - tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions(); - if instrument_dead_code { + if tcx.sess.instrument_coverage() { mark_code_coverage_dead_code_cgu(&mut codegen_units); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index b947ac818057..0657d2830194 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -134,31 +134,13 @@ pub enum LtoCli { /// and higher). Nevertheless, there are many variables, depending on options /// selected, code structure, and enabled attributes. If errors are encountered, /// either while compiling or when generating `llvm-cov show` reports, consider -/// lowering the optimization level, including or excluding `-C link-dead-code`, -/// or using `-Zunstable-options -C instrument-coverage=except-unused-functions` -/// or `-Zunstable-options -C instrument-coverage=except-unused-generics`. -/// -/// Note that `ExceptUnusedFunctions` means: When `mapgen.rs` generates the -/// coverage map, it will not attempt to generate synthetic functions for unused -/// (and not code-generated) functions (whether they are generic or not). As a -/// result, non-codegenned functions will not be included in the coverage map, -/// and will not appear, as covered or uncovered, in coverage reports. -/// -/// `ExceptUnusedGenerics` will add synthetic functions to the coverage map, -/// unless the function has type parameters. +/// lowering the optimization level, or including/excluding `-C link-dead-code`. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum InstrumentCoverage { /// `-C instrument-coverage=no` (or `off`, `false` etc.) No, /// `-C instrument-coverage` or `-C instrument-coverage=yes` Yes, - /// Additionally, instrument branches and output branch coverage. - /// `-Zunstable-options -C instrument-coverage=branch` - Branch, - /// `-Zunstable-options -C instrument-coverage=except-unused-generics` - ExceptUnusedGenerics, - /// `-Zunstable-options -C instrument-coverage=except-unused-functions` - ExceptUnusedFunctions, } /// Settings for `-Z instrument-xray` flag. @@ -2718,24 +2700,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M } } - // Check for unstable values of `-C instrument-coverage`. - // This is what prevents them from being used on stable compilers. - match cg.instrument_coverage { - // Stable values: - InstrumentCoverage::Yes | InstrumentCoverage::No => {} - // Unstable values: - InstrumentCoverage::Branch - | InstrumentCoverage::ExceptUnusedFunctions - | InstrumentCoverage::ExceptUnusedGenerics => { - if !unstable_opts.unstable_options { - early_dcx.early_fatal( - "`-C instrument-coverage=branch` and `-C instrument-coverage=except-*` \ - require `-Z unstable-options`", - ); - } - } - } - if cg.instrument_coverage != InstrumentCoverage::No { if cg.profile_generate.enabled() || cg.profile_use.is_some() { early_dcx.early_fatal( diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index ea4b8f2463e7..a51d153225d6 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -395,7 +395,7 @@ mod desc { pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); 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 = "either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions`"; + pub const parse_instrument_coverage: &str = parse_bool; 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"; @@ -928,15 +928,10 @@ mod parse { return true; }; + // Parse values that have historically been accepted by stable compilers, + // even though they're currently just aliases for boolean values. *slot = match v { "all" => InstrumentCoverage::Yes, - "branch" => InstrumentCoverage::Branch, - "except-unused-generics" | "except_unused_generics" => { - InstrumentCoverage::ExceptUnusedGenerics - } - "except-unused-functions" | "except_unused_functions" => { - InstrumentCoverage::ExceptUnusedFunctions - } "0" => InstrumentCoverage::No, _ => return false, }; @@ -1445,14 +1440,9 @@ options! { "set the threshold for inlining a function"), #[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")] instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED], - "instrument the generated code to support LLVM source-based code coverage \ - reports (note, the compiler build config must include `profiler = true`); \ - implies `-C symbol-mangling-version=v0`. Optional values are: - `=no` `=n` `=off` `=false` (default) - `=yes` `=y` `=on` `=true` (implicit value) - `=branch` (unstable) - `=except-unused-generics` (unstable) - `=except-unused-functions` (unstable)"), + "instrument the generated code to support LLVM source-based code coverage reports \ + (note, the compiler build config must include `profiler = true`); \ + implies `-C symbol-mangling-version=v0`"), link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED], "a single extra argument to append to the linker invocation (can be used several times)"), link_args: Vec = (Vec::new(), parse_list, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ab636b14d19a..10251d6d4ce7 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -352,18 +352,6 @@ impl Session { self.opts.cg.instrument_coverage() != InstrumentCoverage::No } - pub fn instrument_coverage_branch(&self) -> bool { - self.opts.cg.instrument_coverage() == InstrumentCoverage::Branch - } - - pub fn instrument_coverage_except_unused_generics(&self) -> bool { - self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedGenerics - } - - pub fn instrument_coverage_except_unused_functions(&self) -> bool { - self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedFunctions - } - pub fn is_sanitizer_cfi_enabled(&self) -> bool { self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI) } diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index 2f93252eddcd..23cb1e05ed15 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -346,15 +346,6 @@ $ llvm-cov report \ more fine-grained coverage options are added. Using this value is currently not recommended. -### Unstable values - -- `-Z unstable-options -C instrument-coverage=branch`: - Placeholder for potential branch coverage support in the future. -- `-Z unstable-options -C instrument-coverage=except-unused-generics`: - Instrument all functions except unused generics. -- `-Z unstable-options -C instrument-coverage=except-unused-functions`: - Instrument only used (called) functions and instantiated generic functions. - ## Other references Rust's implementation and workflow for source-based code coverage is based on the same library and tools used to implement [source-based code coverage in Clang]. (This document is partially based on the Clang guide.) diff --git a/tests/coverage/auxiliary/used_crate.rs b/tests/coverage/auxiliary/used_crate.rs index 22837ef6d3cb..72d479c74a68 100644 --- a/tests/coverage/auxiliary/used_crate.rs +++ b/tests/coverage/auxiliary/used_crate.rs @@ -76,13 +76,8 @@ fn use_this_lib_crate() { // ``` // // The notice is triggered because the function is unused by the library itself, -// and when the library is compiled, a synthetic function is generated, so -// unused function coverage can be reported. Coverage can be skipped for unused -// generic functions with: -// -// ```shell -// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...` -// ``` +// so when the library is compiled, an "unused" set of mappings for that function +// is included in the library's coverage metadata. // // Even though this function is used by `uses_crate.rs` (and // counted), with substitutions for `T`, those instantiations are only generated @@ -98,6 +93,6 @@ fn use_this_lib_crate() { // another binary that never used this generic function, then it would be valid // to show the unused generic, with unknown substitution (`_`). // -// The alternative is to exclude all generics from being included in the "unused -// functions" list, which would then omit coverage results for -// `unused_generic_function()`, below. +// The alternative would be to exclude all generics from being included in the +// "unused functions" list, which would then omit coverage results for +// `unused_generic_function()`. diff --git a/tests/coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage index 3ab47dbca79c..a6a570a08502 100644 --- a/tests/coverage/uses_crate.coverage +++ b/tests/coverage/uses_crate.coverage @@ -124,13 +124,8 @@ $DIR/auxiliary/used_crate.rs: LL| |// ``` LL| |// LL| |// The notice is triggered because the function is unused by the library itself, - LL| |// and when the library is compiled, a synthetic function is generated, so - LL| |// unused function coverage can be reported. Coverage can be skipped for unused - LL| |// generic functions with: - LL| |// - LL| |// ```shell - LL| |// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...` - LL| |// ``` + LL| |// so when the library is compiled, an "unused" set of mappings for that function + LL| |// is included in the library's coverage metadata. LL| |// LL| |// Even though this function is used by `uses_crate.rs` (and LL| |// counted), with substitutions for `T`, those instantiations are only generated @@ -146,9 +141,9 @@ $DIR/auxiliary/used_crate.rs: LL| |// another binary that never used this generic function, then it would be valid LL| |// to show the unused generic, with unknown substitution (`_`). LL| |// - LL| |// The alternative is to exclude all generics from being included in the "unused - LL| |// functions" list, which would then omit coverage results for - LL| |// `unused_generic_function()`, below. + LL| |// The alternative would be to exclude all generics from being included in the + LL| |// "unused functions" list, which would then omit coverage results for + LL| |// `unused_generic_function()`. $DIR/uses_crate.rs: LL| |// This test was failing on Linux for a while due to #110393 somehow making diff --git a/tests/ui/instrument-coverage/bad-value.bad.stderr b/tests/ui/instrument-coverage/bad-value.bad.stderr index 0411a1f98a3e..d3415fb35d06 100644 --- a/tests/ui/instrument-coverage/bad-value.bad.stderr +++ b/tests/ui/instrument-coverage/bad-value.bad.stderr @@ -1,2 +1,2 @@ -error: incorrect value `bad-value` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected +error: incorrect value `bad-value` for codegen option `instrument-coverage` - one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false` was expected diff --git a/tests/ui/instrument-coverage/bad-value.blank.stderr b/tests/ui/instrument-coverage/bad-value.blank.stderr index b3a8e7cf9478..04c0eab28489 100644 --- a/tests/ui/instrument-coverage/bad-value.blank.stderr +++ b/tests/ui/instrument-coverage/bad-value.blank.stderr @@ -1,2 +1,2 @@ -error: incorrect value `` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected +error: incorrect value `` for codegen option `instrument-coverage` - one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false` was expected diff --git a/tests/ui/instrument-coverage/unstable.branch.stderr b/tests/ui/instrument-coverage/unstable.branch.stderr deleted file mode 100644 index acc633a2a6d2..000000000000 --- a/tests/ui/instrument-coverage/unstable.branch.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` - diff --git a/tests/ui/instrument-coverage/unstable.except-unused-functions.stderr b/tests/ui/instrument-coverage/unstable.except-unused-functions.stderr deleted file mode 100644 index acc633a2a6d2..000000000000 --- a/tests/ui/instrument-coverage/unstable.except-unused-functions.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` - diff --git a/tests/ui/instrument-coverage/unstable.except-unused-generics.stderr b/tests/ui/instrument-coverage/unstable.except-unused-generics.stderr deleted file mode 100644 index acc633a2a6d2..000000000000 --- a/tests/ui/instrument-coverage/unstable.except-unused-generics.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` - diff --git a/tests/ui/instrument-coverage/unstable.rs b/tests/ui/instrument-coverage/unstable.rs deleted file mode 100644 index ea2279aaf0cd..000000000000 --- a/tests/ui/instrument-coverage/unstable.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ revisions: branch except-unused-functions except-unused-generics -//@ [branch] compile-flags: -Cinstrument-coverage=branch -//@ [except-unused-functions] compile-flags: -Cinstrument-coverage=except-unused-functions -//@ [except-unused-generics] compile-flags: -Cinstrument-coverage=except-unused-generics - -fn main() {} From 3407fcc12ee1ace7267611c91b579f6f5cfcb01b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 8 Mar 2024 18:07:04 +1100 Subject: [PATCH 72/99] coverage: Add `-Zcoverage-options` for fine control of coverage This new nightly-only flag can be used to toggle fine-grained flags that control the details of coverage instrumentation. Currently the only supported flag value is `branch` (or `no-branch`), which is a placeholder for upcoming support for branch coverage. Other flag values can be added in the future, to prototype proposed new behaviour, or to enable special non-default behaviour. --- compiler/rustc_interface/src/tests.rs | 12 +++++---- compiler/rustc_session/src/config.rs | 26 ++++++++++++++----- compiler/rustc_session/src/options.rs | 21 +++++++++++++++ compiler/rustc_session/src/session.rs | 4 +++ src/doc/rustc/src/instrument-coverage.md | 8 ++++++ .../src/compiler-flags/coverage-options.md | 8 ++++++ .../coverage-options.bad.stderr | 2 ++ .../instrument-coverage/coverage-options.rs | 14 ++++++++++ 8 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/coverage-options.md create mode 100644 tests/ui/instrument-coverage/coverage-options.bad.stderr create mode 100644 tests/ui/instrument-coverage/coverage-options.rs diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 42fff01c11c9..4d8e749d1da7 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,11 +4,12 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - CollapseMacroDebuginfo, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, - ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, - InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, - OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, - ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, + CollapseMacroDebuginfo, CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, + ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, + InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, + NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, + Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, + WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -750,6 +751,7 @@ fn test_unstable_options_tracking_hash() { ); tracked!(codegen_backend, Some("abc".to_string())); tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes); + tracked!(coverage_options, CoverageOptions { branch: true }); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 0657d2830194..5c52ee66128c 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -143,6 +143,19 @@ pub enum InstrumentCoverage { Yes, } +/// Individual flag values controlled by `-Z coverage-options`. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct CoverageOptions { + /// Add branch coverage instrumentation (placeholder flag; not yet implemented). + pub branch: bool, +} + +impl Default for CoverageOptions { + fn default() -> Self { + Self { branch: false } + } +} + /// Settings for `-Z instrument-xray` flag. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] pub struct InstrumentXRay { @@ -3168,12 +3181,12 @@ pub enum WasiExecModel { /// how the hash should be calculated when adding a new command-line argument. pub(crate) mod dep_tracking { use super::{ - BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CrateType, DebugInfo, - DebugInfoCompression, ErrorOutputType, FunctionReturn, InliningThreshold, - InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, - NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius, - RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, - SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, + BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions, + CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn, + InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, + LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, + Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, + SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3243,6 +3256,7 @@ pub(crate) mod dep_tracking { CodeModel, TlsModel, InstrumentCoverage, + CoverageOptions, InstrumentXRay, CrateType, MergeFunctions, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a51d153225d6..ab79e3ecae49 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -396,6 +396,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 = "`branch` or `no-branch`"; 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"; @@ -938,6 +939,24 @@ mod parse { true } + pub(crate) fn parse_coverage_options(slot: &mut CoverageOptions, v: Option<&str>) -> bool { + let Some(v) = v else { return true }; + + for option in v.split(',') { + let (option, enabled) = match option.strip_prefix("no-") { + Some(without_no) => (without_no, false), + None => (option, true), + }; + let slot = match option { + "branch" => &mut slot.branch, + _ => return false, + }; + *slot = enabled; + } + + true + } + pub(crate) fn parse_instrument_xray( slot: &mut Option, v: Option<&str>, @@ -1564,6 +1583,8 @@ options! { "set option to collapse debuginfo for macros"), combine_cgu: bool = (false, parse_bool, [TRACKED], "combine CGUs into a single one"), + coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED], + "control details of coverage instrumentation"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 10251d6d4ce7..9c94fd7027fd 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -352,6 +352,10 @@ impl Session { self.opts.cg.instrument_coverage() != InstrumentCoverage::No } + pub fn instrument_coverage_branch(&self) -> bool { + self.instrument_coverage() && self.opts.unstable_opts.coverage_options.branch + } + pub fn is_sanitizer_cfi_enabled(&self) -> bool { self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI) } diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index 23cb1e05ed15..7780f2102ba6 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -346,6 +346,14 @@ $ llvm-cov report \ more fine-grained coverage options are added. Using this value is currently not recommended. +## `-Z coverage-options=` + +This unstable option provides finer control over some aspects of coverage +instrumentation. Pass one or more of the following values, separated by commas. + +- `branch` or `no-branch` + - Placeholder for potential branch coverage support in the future. + ## Other references Rust's implementation and workflow for source-based code coverage is based on the same library and tools used to implement [source-based code coverage in Clang]. (This document is partially based on the Clang guide.) diff --git a/src/doc/unstable-book/src/compiler-flags/coverage-options.md b/src/doc/unstable-book/src/compiler-flags/coverage-options.md new file mode 100644 index 000000000000..105dce615117 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/coverage-options.md @@ -0,0 +1,8 @@ +# `coverage-options` + +This option controls details of the coverage instrumentation performed by +`-C instrument-coverage`. + +Multiple options can be passed, separated by commas. Valid options are: + +- `branch` or `no-branch`: Placeholder for future branch coverage support. diff --git a/tests/ui/instrument-coverage/coverage-options.bad.stderr b/tests/ui/instrument-coverage/coverage-options.bad.stderr new file mode 100644 index 000000000000..ca82dc5bdb93 --- /dev/null +++ b/tests/ui/instrument-coverage/coverage-options.bad.stderr @@ -0,0 +1,2 @@ +error: incorrect value `bad` for unstable option `coverage-options` - `branch` or `no-branch` was expected + diff --git a/tests/ui/instrument-coverage/coverage-options.rs b/tests/ui/instrument-coverage/coverage-options.rs new file mode 100644 index 000000000000..a62e0554f769 --- /dev/null +++ b/tests/ui/instrument-coverage/coverage-options.rs @@ -0,0 +1,14 @@ +//@ needs-profiler-support +//@ revisions: branch no-branch bad +//@ compile-flags -Cinstrument-coverage + +//@ [branch] check-pass +//@ [branch] compile-flags: -Zcoverage-options=branch + +//@ [no-branch] check-pass +//@ [no-branch] compile-flags: -Zcoverage-options=no-branch + +//@ [bad] check-fail +//@ [bad] compile-flags: -Zcoverage-options=bad + +fn main() {} From 9f55200a42f599549fee0f003b27888d03604861 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Wed, 13 Mar 2024 01:17:15 -0400 Subject: [PATCH 73/99] refine common_prim test Co-authored-by: Scott McMurray --- tests/codegen/common_prim_int_ptr.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tests/codegen/common_prim_int_ptr.rs b/tests/codegen/common_prim_int_ptr.rs index 666ccc5a2cff..87fa89abb866 100644 --- a/tests/codegen/common_prim_int_ptr.rs +++ b/tests/codegen/common_prim_int_ptr.rs @@ -1,6 +1,7 @@ //@ compile-flags: -O #![crate_type = "lib"] +#![feature(core_intrinsics)] // Tests that codegen works properly when enums like `Result>` // are represented as `{ u64, ptr }`, i.e., for `Ok(123)`, `123` is stored @@ -26,18 +27,25 @@ pub fn insert_box(x: Box<()>) -> Result> { } // CHECK-LABEL: @extract_int +// CHECK-NOT: nonnull +// CHECK-SAME: (i{{[0-9]+}} {{[^,]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]]) #[no_mangle] pub unsafe fn extract_int(x: Result>) -> usize { - // CHECK: ptrtoint - x.unwrap_unchecked() + // CHECK: [[TEMP:%.+]] = ptrtoint ptr [[PAYLOAD]] to [[USIZE:i[0-9]+]] + // CHECK: ret [[USIZE]] [[TEMP]] + match x { + Ok(v) => v, + Err(_) => std::intrinsics::unreachable(), + } } // CHECK-LABEL: @extract_box +// CHECK-SAME: (i{{[0-9]+}} {{[^,]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]]) #[no_mangle] -pub unsafe fn extract_box(x: Result>) -> Box<()> { - // CHECK-NOT: ptrtoint - // CHECK-NOT: inttoptr - // CHECK-NOT: load - // CHECK-NOT: store - x.unwrap_err_unchecked() +pub unsafe fn extract_box(x: Result>) -> Box { + // CHECK: ret ptr [[PAYLOAD]] + match x { + Ok(_) => std::intrinsics::unreachable(), + Err(e) => e, + } } From 8f21da1df333bdef7024266f6181ea7891bd3bea Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Mon, 11 Mar 2024 19:26:44 +0100 Subject: [PATCH 74/99] compiletest: Allow `only-unix` in test headers The header `ignore-unix` is already allowed. Also extend tests. --- src/tools/compiletest/src/header.rs | 1 + src/tools/compiletest/src/header/tests.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 69658222ff3e..a512599f723b 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -852,6 +852,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-sparc64", "only-stable", "only-thumb", + "only-unix", "only-wasm32", "only-wasm32-bare", "only-windows", diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 433f3e8b5559..cf300fbe74fe 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -285,6 +285,7 @@ fn ignore_target() { assert!(check_ignore(&config, "//@ ignore-x86_64-unknown-linux-gnu")); assert!(check_ignore(&config, "//@ ignore-x86_64")); assert!(check_ignore(&config, "//@ ignore-linux")); + assert!(check_ignore(&config, "//@ ignore-unix")); assert!(check_ignore(&config, "//@ ignore-gnu")); assert!(check_ignore(&config, "//@ ignore-64bit")); @@ -300,6 +301,7 @@ fn only_target() { assert!(check_ignore(&config, "//@ only-x86")); assert!(check_ignore(&config, "//@ only-linux")); + assert!(check_ignore(&config, "//@ only-unix")); assert!(check_ignore(&config, "//@ only-msvc")); assert!(check_ignore(&config, "//@ only-32bit")); From ee8efd705b72584f7dff96a6c833b209b89d0b1e Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Wed, 13 Mar 2024 13:57:23 +0800 Subject: [PATCH 75/99] fix: typos Signed-off-by: guoguangwu --- compiler/rustc_target/src/spec/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c264a1fbce95..941d767b850d 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -211,7 +211,7 @@ impl ToJson for LldFlavor { impl LinkerFlavor { /// At this point the target's reference linker flavor doesn't yet exist and we need to infer - /// it. The inference always succeds and gives some result, and we don't report any flavor + /// it. The inference always succeeds and gives some result, and we don't report any flavor /// incompatibility errors for json target specs. The CLI flavor is used as the main source /// of truth, other flags are used in case of ambiguities. fn from_cli_json(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor { @@ -581,7 +581,7 @@ impl LinkSelfContainedDefault { self == LinkSelfContainedDefault::False } - /// Returns whether the target spec explictly requests self-contained linking, i.e. not via + /// Returns whether the target spec explicitly requests self-contained linking, i.e. not via /// inference. pub fn is_linker_enabled(self) -> bool { match self { @@ -2090,7 +2090,7 @@ pub struct TargetOptions { /// If `None`, then `CFG_DEFAULT_CODEGEN_BACKEND` environmental variable captured when /// compiling `rustc` will be used instead (or llvm if it is not set). /// - /// N.B. when *using* the compiler, backend can always be overriden with `-Zcodegen-backend`. + /// N.B. when *using* the compiler, backend can always be overridden with `-Zcodegen-backend`. pub default_codegen_backend: Option>, /// Whether to generate trap instructions in places where optimization would From cdeeed8dec647fc6063416f5194336b687d93dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 13 Mar 2024 08:31:07 +0100 Subject: [PATCH 76/99] Increase timeout for new bors bot --- rust-bors.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-bors.toml b/rust-bors.toml index 54f4f641248c..f27eb2393675 100644 --- a/rust-bors.toml +++ b/rust-bors.toml @@ -1 +1 @@ -timeout = 7200 +timeout = 14400 From e0488c0961e5ba693d19f6e1e3f4c9b20631353b Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 13 Mar 2024 00:36:54 -0700 Subject: [PATCH 77/99] Fix StableMIR is_full computation `WrappingRange::is_full` computation assumed that to be full the range couldn't wrap, which is not necessarily true. For example, a range of 1..=0 is a valid representation of a full wrapping range. --- compiler/stable_mir/src/abi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 7fda9ceb79ac..92bc2e34561a 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -383,7 +383,7 @@ impl WrappingRange { return Err(error!("Expected size <= 128 bits, but found {} instead", size.bits())); }; if self.start <= max_value && self.end <= max_value { - Ok(self.start == 0 && max_value == self.end) + Ok(self.start == (self.end.wrapping_add(1) & max_value)) } else { Err(error!("Range `{self:?}` out of bounds for size `{}` bits.", size.bits())) } From 8fcdf54a6b98c129e951caf3a97cbf20db677ee3 Mon Sep 17 00:00:00 2001 From: bohan Date: Tue, 12 Mar 2024 10:55:17 +0800 Subject: [PATCH 78/99] delay expand macro bang when there has indeterminate path --- compiler/rustc_builtin_macros/src/asm.rs | 76 ++++++----- compiler/rustc_builtin_macros/src/assert.rs | 8 +- compiler/rustc_builtin_macros/src/cfg.rs | 8 +- .../rustc_builtin_macros/src/compile_error.rs | 14 +- compiler/rustc_builtin_macros/src/concat.rs | 25 ++-- .../rustc_builtin_macros/src/concat_bytes.rs | 25 ++-- .../rustc_builtin_macros/src/concat_idents.rs | 12 +- .../rustc_builtin_macros/src/edition_panic.rs | 10 +- compiler/rustc_builtin_macros/src/env.rs | 54 +++++--- compiler/rustc_builtin_macros/src/format.rs | 121 ++++++++++-------- .../rustc_builtin_macros/src/log_syntax.rs | 8 +- .../rustc_builtin_macros/src/source_util.rs | 80 ++++++------ .../rustc_builtin_macros/src/trace_macros.rs | 6 +- .../rustc_builtin_macros/src/type_ascribe.rs | 8 +- compiler/rustc_expand/src/base.rs | 95 ++++++++++---- compiler/rustc_expand/src/expand.rs | 13 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 14 +- compiler/rustc_resolve/src/macros.rs | 85 +++++++----- tests/ui/macros/expand-full-asm.rs | 27 ++++ tests/ui/macros/expand-full-in-format-str.rs | 33 +++++ tests/ui/macros/expand-full-no-resolution.rs | 20 +++ .../macros/expand-full-no-resolution.stderr | 30 +++++ 22 files changed, 509 insertions(+), 263 deletions(-) create mode 100644 tests/ui/macros/expand-full-asm.rs create mode 100644 tests/ui/macros/expand-full-in-format-str.rs create mode 100644 tests/ui/macros/expand-full-no-resolution.rs create mode 100644 tests/ui/macros/expand-full-no-resolution.stderr diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index bc851fadc2e2..62c02817011f 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -5,7 +5,7 @@ use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::PResult; -use rustc_expand::base::{self, *}; +use rustc_expand::base::*; use rustc_index::bit_set::GrowableBitSet; use rustc_parse::parser::Parser; use rustc_parse_format as parse; @@ -443,7 +443,7 @@ fn parse_reg<'a>( fn expand_preparsed_asm( ecx: &mut ExtCtxt<'_>, args: AsmArgs, -) -> Result { +) -> ExpandResult, ()> { let mut template = vec![]; // Register operands are implicitly used since they are not allowed to be // referenced in the template string. @@ -465,16 +465,20 @@ fn expand_preparsed_asm( let msg = "asm template must be a string literal"; let template_sp = template_expr.span; - let (template_str, template_style, template_span) = - match expr_to_spanned_string(ecx, template_expr, msg) { + let (template_str, template_style, template_span) = { + let ExpandResult::Ready(mac) = expr_to_spanned_string(ecx, template_expr, msg) else { + return ExpandResult::Retry(()); + }; + match mac { Ok(template_part) => template_part, Err(err) => { - return Err(match err { + return ExpandResult::Ready(Err(match err { Ok((err, _)) => err.emit(), Err(guar) => guar, - }); + })); } - }; + } + }; let str_style = match template_style { ast::StrStyle::Cooked => None, @@ -562,7 +566,7 @@ fn expand_preparsed_asm( e.span_label(err_sp, label); } let guar = e.emit(); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } curarg = parser.curarg; @@ -729,24 +733,27 @@ fn expand_preparsed_asm( } } - Ok(ast::InlineAsm { + ExpandResult::Ready(Ok(ast::InlineAsm { template, template_strs: template_strs.into_boxed_slice(), operands: args.operands, clobber_abis: args.clobber_abis, options: args.options, line_spans, - }) + })) } pub(super) fn expand_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - match parse_args(ecx, sp, tts, false) { +) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { Ok(args) => { - let expr = match expand_preparsed_asm(ecx, args) { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + return ExpandResult::Retry(()); + }; + let expr = match mac { Ok(inline_asm) => P(ast::Expr { id: ast::DUMMY_NODE_ID, kind: ast::ExprKind::InlineAsm(P(inline_asm)), @@ -762,34 +769,39 @@ pub(super) fn expand_asm<'cx>( let guar = err.emit(); DummyResult::any(sp, guar) } - } + }) } pub(super) fn expand_global_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - match parse_args(ecx, sp, tts, true) { - Ok(args) => match expand_preparsed_asm(ecx, args) { - Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item { - ident: Ident::empty(), - attrs: ast::AttrVec::new(), - id: ast::DUMMY_NODE_ID, - kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), - vis: ast::Visibility { - span: sp.shrink_to_lo(), - kind: ast::VisibilityKind::Inherited, +) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(match parse_args(ecx, sp, tts, true) { + Ok(args) => { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + return ExpandResult::Retry(()); + }; + match mac { + Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item { + ident: Ident::empty(), + attrs: ast::AttrVec::new(), + id: ast::DUMMY_NODE_ID, + kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), + vis: ast::Visibility { + span: sp.shrink_to_lo(), + kind: ast::VisibilityKind::Inherited, + tokens: None, + }, + span: sp, tokens: None, - }, - span: sp, - tokens: None, - })]), - Err(guar) => DummyResult::any(sp, guar), - }, + })]), + Err(guar) => DummyResult::any(sp, guar), + } + } Err(err) => { let guar = err.emit(); DummyResult::any(sp, guar) } - } + }) } diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 613ce43dec2d..35a0857fe51c 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -9,7 +9,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp}; use rustc_ast_pretty::pprust; use rustc_errors::PResult; -use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_parse::parser::Parser; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -19,12 +19,12 @@ pub fn expand_assert<'cx>( cx: &'cx mut ExtCtxt<'_>, span: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) { Ok(assert) => assert, Err(err) => { let guar = err.emit(); - return DummyResult::any(span, guar); + return ExpandResult::Ready(DummyResult::any(span, guar)); } }; @@ -92,7 +92,7 @@ pub fn expand_assert<'cx>( expr_if_not(cx, call_site_span, cond_expr, then, None) }; - MacEager::expr(expr) + ExpandResult::Ready(MacEager::expr(expr)) } struct Assert { diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 04bf7dceeff4..9197b9ebdf9f 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -8,17 +8,17 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_attr as attr; use rustc_errors::PResult; -use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::Span; pub fn expand_cfg( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); - match parse_cfg(cx, sp, tts) { + ExpandResult::Ready(match parse_cfg(cx, sp, tts) { Ok(cfg) => { let matches_cfg = attr::cfg_matches( &cfg, @@ -32,7 +32,7 @@ pub fn expand_cfg( let guar = err.emit(); DummyResult::any(sp, guar) } - } + }) } fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> { diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs index b4455d7823f3..2f2a87fc9aa0 100644 --- a/compiler/rustc_builtin_macros/src/compile_error.rs +++ b/compiler/rustc_builtin_macros/src/compile_error.rs @@ -1,22 +1,26 @@ // The compiler code necessary to support the compile_error! extension. use rustc_ast::tokenstream::TokenStream; -use rustc_expand::base::{get_single_str_from_tts, DummyResult, ExtCtxt, MacResult}; +use rustc_expand::base::get_single_str_from_tts; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_span::Span; pub fn expand_compile_error<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { +) -> MacroExpanderResult<'cx> { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "compile_error!") else { + return ExpandResult::Retry(()); + }; + let var = match mac { Ok(var) => var, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; #[expect(rustc::diagnostic_outside_of_impl, reason = "diagnostic message is specified by user")] #[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")] let guar = cx.dcx().span_err(sp, var.to_string()); - DummyResult::any(sp, guar) + ExpandResult::Ready(DummyResult::any(sp, guar)) } diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index 0bfb848859bd..93a7ac05a9be 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -1,6 +1,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{ExprKind, LitKind, UnOp}; -use rustc_expand::base::{get_exprs_from_tts, DummyResult, ExtCtxt, MacEager, MacResult}; +use rustc_expand::base::get_exprs_from_tts; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_session::errors::report_lit_error; use rustc_span::symbol::Symbol; @@ -10,10 +11,13 @@ pub fn expand_concat( cx: &mut ExtCtxt<'_>, sp: rustc_span::Span, tts: TokenStream, -) -> Box { - let es = match get_exprs_from_tts(cx, tts) { +) -> MacroExpanderResult<'static> { + let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else { + return ExpandResult::Retry(()); + }; + let es = match mac { Ok(es) => es, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let mut accumulator = String::new(); let mut missing_literal = vec![]; @@ -70,12 +74,13 @@ pub fn expand_concat( } } - if !missing_literal.is_empty() { + ExpandResult::Ready(if !missing_literal.is_empty() { let guar = cx.dcx().emit_err(errors::ConcatMissingLiteral { spans: missing_literal }); - return DummyResult::any(sp, guar); + DummyResult::any(sp, guar) } else if let Some(guar) = guar { - return DummyResult::any(sp, guar); - } - let sp = cx.with_def_site_ctxt(sp); - MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) + DummyResult::any(sp, guar) + } else { + let sp = cx.with_def_site_ctxt(sp); + MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) + }) } diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 502bfb4467e5..a2f827c5567d 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -1,5 +1,6 @@ use rustc_ast::{ptr::P, token, tokenstream::TokenStream, ExprKind, LitIntType, LitKind, UintTy}; -use rustc_expand::base::{get_exprs_from_tts, DummyResult, ExtCtxt, MacEager, MacResult}; +use rustc_expand::base::get_exprs_from_tts; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_session::errors::report_lit_error; use rustc_span::{ErrorGuaranteed, Span}; @@ -111,10 +112,13 @@ pub fn expand_concat_bytes( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - let es = match get_exprs_from_tts(cx, tts) { +) -> MacroExpanderResult<'static> { + let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else { + return ExpandResult::Retry(()); + }; + let es = match mac { Ok(es) => es, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let mut accumulator = Vec::new(); let mut missing_literals = vec![]; @@ -170,12 +174,13 @@ pub fn expand_concat_bytes( } } } - if !missing_literals.is_empty() { + ExpandResult::Ready(if !missing_literals.is_empty() { let guar = cx.dcx().emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals }); - return MacEager::expr(DummyResult::raw_expr(sp, Some(guar))); + MacEager::expr(DummyResult::raw_expr(sp, Some(guar))) } else if let Some(guar) = guar { - return MacEager::expr(DummyResult::raw_expr(sp, Some(guar))); - } - let sp = cx.with_def_site_ctxt(sp); - MacEager::expr(cx.expr_byte_str(sp, accumulator)) + MacEager::expr(DummyResult::raw_expr(sp, Some(guar))) + } else { + let sp = cx.with_def_site_ctxt(sp); + MacEager::expr(cx.expr_byte_str(sp, accumulator)) + }) } diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs index fffcddc5325b..3ddb0ae45b51 100644 --- a/compiler/rustc_builtin_macros/src/concat_idents.rs +++ b/compiler/rustc_builtin_macros/src/concat_idents.rs @@ -2,7 +2,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Token}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::{AttrVec, Expr, ExprKind, Path, Ty, TyKind, DUMMY_NODE_ID}; -use rustc_expand::base::{DummyResult, ExtCtxt, MacResult}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::Span; @@ -12,10 +12,10 @@ pub fn expand_concat_idents<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { if tts.is_empty() { let guar = cx.dcx().emit_err(errors::ConcatIdentsMissingArgs { span: sp }); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } let mut res_str = String::new(); @@ -25,7 +25,7 @@ pub fn expand_concat_idents<'cx>( TokenTree::Token(Token { kind: token::Comma, .. }, _) => {} _ => { let guar = cx.dcx().emit_err(errors::ConcatIdentsMissingComma { span: sp }); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } } } else { @@ -37,7 +37,7 @@ pub fn expand_concat_idents<'cx>( } let guar = cx.dcx().emit_err(errors::ConcatIdentsIdentArgs { span: sp }); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } } @@ -68,5 +68,5 @@ pub fn expand_concat_idents<'cx>( } } - Box::new(ConcatIdentsResult { ident }) + ExpandResult::Ready(Box::new(ConcatIdentsResult { ident })) } diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs index 1e1dadab4806..fa22e9116423 100644 --- a/compiler/rustc_builtin_macros/src/edition_panic.rs +++ b/compiler/rustc_builtin_macros/src/edition_panic.rs @@ -20,7 +20,7 @@ pub fn expand_panic<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let mac = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 }; expand(mac, cx, sp, tts) } @@ -33,7 +33,7 @@ pub fn expand_unreachable<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let mac = if use_panic_2021(sp) { sym::unreachable_2021 } else { sym::unreachable_2015 }; expand(mac, cx, sp, tts) } @@ -43,10 +43,10 @@ fn expand<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let sp = cx.with_call_site_ctxt(sp); - MacEager::expr( + ExpandResult::Ready(MacEager::expr( cx.expr( sp, ExprKind::MacCall(P(MacCall { @@ -66,7 +66,7 @@ fn expand<'cx>( }), })), ), - ) + )) } pub fn use_panic_2021(mut span: Span) -> bool { diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 193b38a83238..bce710e5cab1 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -6,10 +6,8 @@ use rustc_ast::token::{self, LitKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AstDeref, ExprKind, GenericArg, Mutability}; -use rustc_expand::base::{ - expr_to_string, get_exprs_from_tts, get_single_str_from_tts, DummyResult, ExtCtxt, MacEager, - MacResult, -}; +use rustc_expand::base::{expr_to_string, get_exprs_from_tts, get_single_str_from_tts}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::env; @@ -31,10 +29,13 @@ pub fn expand_option_env<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") { +) -> MacroExpanderResult<'cx> { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "option_env!") else { + return ExpandResult::Retry(()); + }; + let var = match mac { Ok(var) => var, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let sp = cx.with_def_site_ctxt(sp); @@ -61,35 +62,48 @@ pub fn expand_option_env<'cx>( thin_vec![cx.expr_str(sp, value)], ), }; - MacEager::expr(e) + ExpandResult::Ready(MacEager::expr(e)) } pub fn expand_env<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - let mut exprs = match get_exprs_from_tts(cx, tts) { +) -> MacroExpanderResult<'cx> { + let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else { + return ExpandResult::Retry(()); + }; + let mut exprs = match mac { Ok(exprs) if exprs.is_empty() || exprs.len() > 2 => { let guar = cx.dcx().emit_err(errors::EnvTakesArgs { span: sp }); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), Ok(exprs) => exprs.into_iter(), }; let var_expr = exprs.next().unwrap(); - let var = match expr_to_string(cx, var_expr.clone(), "expected string literal") { + let ExpandResult::Ready(mac) = expr_to_string(cx, var_expr.clone(), "expected string literal") + else { + return ExpandResult::Retry(()); + }; + let var = match mac { Ok((var, _)) => var, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let custom_msg = match exprs.next() { None => None, - Some(second) => match expr_to_string(cx, second, "expected string literal") { - Ok((s, _)) => Some(s), - Err(guar) => return DummyResult::any(sp, guar), - }, + Some(second) => { + let ExpandResult::Ready(mac) = expr_to_string(cx, second, "expected string literal") + else { + return ExpandResult::Retry(()); + }; + match mac { + Ok((s, _)) => Some(s), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), + } + } }; let span = cx.with_def_site_ctxt(sp); @@ -120,11 +134,11 @@ pub fn expand_env<'cx>( }) }; - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } Some(value) => cx.expr_str(span, value), }; - MacEager::expr(e) + ExpandResult::Ready(MacEager::expr(e)) } /// Returns `true` if an environment variable from `env!` is one used by Cargo. diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 385c90ff14b2..6f031f270cae 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -9,7 +9,7 @@ use rustc_ast::{ }; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans}; -use rustc_expand::base::{self, *}; +use rustc_expand::base::*; use rustc_parse::parser::Recovered; use rustc_parse_format as parse; use rustc_span::symbol::{Ident, Symbol}; @@ -40,6 +40,7 @@ use PositionUsedAs::*; use crate::errors; +#[derive(Debug)] struct MacroInput { fmtstr: P, args: FormatArguments, @@ -160,54 +161,61 @@ fn make_format_args( ecx: &mut ExtCtxt<'_>, input: MacroInput, append_newline: bool, -) -> Result { +) -> ExpandResult, ()> { let msg = "format argument must be a string literal"; let unexpanded_fmt_span = input.fmtstr.span; let MacroInput { fmtstr: efmt, mut args, is_direct_literal } = input; - let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt.clone(), msg) { - Ok(mut fmt) if append_newline => { - fmt.0 = Symbol::intern(&format!("{}\n", fmt.0)); - fmt - } - Ok(fmt) => fmt, - Err(err) => { - let guar = match err { - Ok((mut err, suggested)) => { - if !suggested { - if let ExprKind::Block(block, None) = &efmt.kind - && block.stmts.len() == 1 - && let StmtKind::Expr(expr) = &block.stmts[0].kind - && let ExprKind::Path(None, path) = &expr.kind - && path.is_potential_trivial_const_arg() - { - err.multipart_suggestion( - "quote your inlined format argument to use as string literal", - vec![ - (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()), - (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()), - ], - Applicability::MaybeIncorrect, - ); - } else { - let sugg_fmt = match args.explicit_args().len() { - 0 => "{}".to_string(), - _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())), - }; - err.span_suggestion( - unexpanded_fmt_span.shrink_to_lo(), - "you might be missing a string literal to format with", - format!("\"{sugg_fmt}\", "), - Applicability::MaybeIncorrect, - ); + let (fmt_str, fmt_style, fmt_span) = { + let ExpandResult::Ready(mac) = expr_to_spanned_string(ecx, efmt.clone(), msg) else { + return ExpandResult::Retry(()); + }; + match mac { + Ok(mut fmt) if append_newline => { + fmt.0 = Symbol::intern(&format!("{}\n", fmt.0)); + fmt + } + Ok(fmt) => fmt, + Err(err) => { + let guar = match err { + Ok((mut err, suggested)) => { + if !suggested { + if let ExprKind::Block(block, None) = &efmt.kind + && block.stmts.len() == 1 + && let StmtKind::Expr(expr) = &block.stmts[0].kind + && let ExprKind::Path(None, path) = &expr.kind + && path.is_potential_trivial_const_arg() + { + err.multipart_suggestion( + "quote your inlined format argument to use as string literal", + vec![ + (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()), + (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } else { + let sugg_fmt = match args.explicit_args().len() { + 0 => "{}".to_string(), + _ => { + format!("{}{{}}", "{} ".repeat(args.explicit_args().len())) + } + }; + err.span_suggestion( + unexpanded_fmt_span.shrink_to_lo(), + "you might be missing a string literal to format with", + format!("\"{sugg_fmt}\", "), + Applicability::MaybeIncorrect, + ); + } } + err.emit() } - err.emit() - } - Err(guar) => guar, - }; - return Err(guar); + Err(guar) => guar, + }; + return ExpandResult::Ready(Err(guar)); + } } }; @@ -297,7 +305,7 @@ fn make_format_args( } } let guar = ecx.dcx().emit_err(e); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } let to_span = |inner_span: rustc_parse_format::InnerSpan| { @@ -564,7 +572,7 @@ fn make_format_args( } } - Ok(FormatArgs { span: fmt_span, template, arguments: args }) + ExpandResult::Ready(Ok(FormatArgs { span: fmt_span, template, arguments: args })) } fn invalid_placeholder_type_error( @@ -972,25 +980,32 @@ fn expand_format_args_impl<'cx>( mut sp: Span, tts: TokenStream, nl: bool, -) -> Box { +) -> MacroExpanderResult<'cx> { sp = ecx.with_def_site_ctxt(sp); - match parse_args(ecx, sp, tts) { - Ok(input) => match make_format_args(ecx, input, nl) { - Ok(format_args) => MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args)))), - Err(guar) => MacEager::expr(DummyResult::raw_expr(sp, Some(guar))), - }, + ExpandResult::Ready(match parse_args(ecx, sp, tts) { + Ok(input) => { + let ExpandResult::Ready(mac) = make_format_args(ecx, input, nl) else { + return ExpandResult::Retry(()); + }; + match mac { + Ok(format_args) => { + MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args)))) + } + Err(guar) => MacEager::expr(DummyResult::raw_expr(sp, Some(guar))), + } + } Err(err) => { let guar = err.emit(); DummyResult::any(sp, guar) } - } + }) } pub fn expand_format_args<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { expand_format_args_impl(ecx, sp, tts, false) } @@ -998,6 +1013,6 @@ pub fn expand_format_args_nl<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { expand_format_args_impl(ecx, sp, tts, true) } diff --git a/compiler/rustc_builtin_macros/src/log_syntax.rs b/compiler/rustc_builtin_macros/src/log_syntax.rs index ede34a761258..288a475ac241 100644 --- a/compiler/rustc_builtin_macros/src/log_syntax.rs +++ b/compiler/rustc_builtin_macros/src/log_syntax.rs @@ -1,14 +1,14 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; -use rustc_expand::base; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; pub fn expand_log_syntax<'cx>( - _cx: &'cx mut base::ExtCtxt<'_>, + _cx: &'cx mut ExtCtxt<'_>, sp: rustc_span::Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { println!("{}", pprust::tts_to_string(&tts)); // any so that `log_syntax` can be invoked as an expression and item. - base::DummyResult::any_valid(sp) + ExpandResult::Ready(DummyResult::any_valid(sp)) } diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 2da9bda19e03..dbb86df6811d 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -3,10 +3,9 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; -use rustc_expand::base::{ - check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path, DummyResult, ExtCtxt, - MacEager, MacResult, -}; +use rustc_expand::base::{check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt}; +use rustc_expand::base::{MacEager, MacResult, MacroExpanderResult}; use rustc_expand::module::DirOwnership; use rustc_parse::new_parser_from_file; use rustc_parse::parser::{ForceCollect, Parser}; @@ -26,14 +25,14 @@ pub fn expand_line( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "line!"); let topmost = cx.expansion_cause().unwrap_or(sp); let loc = cx.source_map().lookup_char_pos(topmost.lo()); - MacEager::expr(cx.expr_u32(topmost, loc.line as u32)) + ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.line as u32))) } /* column!(): expands to the current column number */ @@ -41,14 +40,14 @@ pub fn expand_column( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "column!"); let topmost = cx.expansion_cause().unwrap_or(sp); let loc = cx.source_map().lookup_char_pos(topmost.lo()); - MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1)) + ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))) } /// file!(): expands to the current filename */ @@ -58,7 +57,7 @@ pub fn expand_file( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "file!"); @@ -66,35 +65,35 @@ pub fn expand_file( let loc = cx.source_map().lookup_char_pos(topmost.lo()); use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt}; - MacEager::expr(cx.expr_str( + ExpandResult::Ready(MacEager::expr(cx.expr_str( topmost, Symbol::intern( &loc.file.name.for_scope(cx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(), ), - )) + ))) } pub fn expand_stringify( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); let s = pprust::tts_to_string(&tts); - MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))) + ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))) } pub fn expand_mod( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "module_path!"); let mod_path = &cx.current_expansion.module.mod_path; let string = mod_path.iter().map(|x| x.to_string()).collect::>().join("::"); - MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))) + ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))) } /// include! : parse the given file as an expr @@ -104,18 +103,21 @@ pub fn expand_include<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include!") { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else { + return ExpandResult::Retry(()); + }; + let file = match mac { Ok(file) => file, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; // The file will be added to the code map by the parser let file = match resolve_path(&cx.sess, file.as_str(), sp) { Ok(f) => f, Err(err) => { let guar = err.emit(); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } }; let p = new_parser_from_file(cx.psess(), &file, Some(sp)); @@ -128,12 +130,12 @@ pub fn expand_include<'cx>( cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path)); cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None }; - struct ExpandResult<'a> { + struct ExpandInclude<'a> { p: Parser<'a>, node_id: ast::NodeId, } - impl<'a> MacResult for ExpandResult<'a> { - fn make_expr(mut self: Box>) -> Option> { + impl<'a> MacResult for ExpandInclude<'a> { + fn make_expr(mut self: Box>) -> Option> { let expr = parse_expr(&mut self.p).ok()?; if self.p.token != token::Eof { self.p.psess.buffer_lint( @@ -146,7 +148,7 @@ pub fn expand_include<'cx>( Some(expr) } - fn make_items(mut self: Box>) -> Option; 1]>> { + fn make_items(mut self: Box>) -> Option; 1]>> { let mut ret = SmallVec::new(); loop { match self.p.parse_item(ForceCollect::No) { @@ -170,7 +172,7 @@ pub fn expand_include<'cx>( } } - Box::new(ExpandResult { p, node_id: cx.current_expansion.lint_node_id }) + ExpandResult::Ready(Box::new(ExpandInclude { p, node_id: cx.current_expansion.lint_node_id })) } /// `include_str!`: read the given file, insert it as a literal string expr @@ -178,20 +180,23 @@ pub fn expand_include_str( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include_str!") else { + return ExpandResult::Retry(()); + }; + let file = match mac { Ok(file) => file, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let file = match resolve_path(&cx.sess, file.as_str(), sp) { Ok(f) => f, Err(err) => { let guar = err.emit(); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } }; - match cx.source_map().load_binary_file(&file) { + ExpandResult::Ready(match cx.source_map().load_binary_file(&file) { Ok(bytes) => match std::str::from_utf8(&bytes) { Ok(src) => { let interned_src = Symbol::intern(src); @@ -206,27 +211,30 @@ pub fn expand_include_str( let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e)); DummyResult::any(sp, guar) } - } + }) } pub fn expand_include_bytes( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else { + return ExpandResult::Retry(()); + }; + let file = match mac { Ok(file) => file, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let file = match resolve_path(&cx.sess, file.as_str(), sp) { Ok(f) => f, Err(err) => { let guar = err.emit(); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } }; - match cx.source_map().load_binary_file(&file) { + ExpandResult::Ready(match cx.source_map().load_binary_file(&file) { Ok(bytes) => { let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes)); MacEager::expr(expr) @@ -235,5 +243,5 @@ pub fn expand_include_bytes( let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e)); DummyResult::any(sp, guar) } - } + }) } diff --git a/compiler/rustc_builtin_macros/src/trace_macros.rs b/compiler/rustc_builtin_macros/src/trace_macros.rs index e076aa6da73d..696d99004ba0 100644 --- a/compiler/rustc_builtin_macros/src/trace_macros.rs +++ b/compiler/rustc_builtin_macros/src/trace_macros.rs @@ -1,6 +1,6 @@ use crate::errors; use rustc_ast::tokenstream::{TokenStream, TokenTree}; -use rustc_expand::base::{self, ExtCtxt}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_span::symbol::kw; use rustc_span::Span; @@ -8,7 +8,7 @@ pub fn expand_trace_macros( cx: &mut ExtCtxt<'_>, sp: Span, tt: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let mut cursor = tt.trees(); let mut err = false; let value = match &cursor.next() { @@ -26,5 +26,5 @@ pub fn expand_trace_macros( cx.set_trace_macros(value); } - base::DummyResult::any_valid(sp) + ExpandResult::Ready(DummyResult::any_valid(sp)) } diff --git a/compiler/rustc_builtin_macros/src/type_ascribe.rs b/compiler/rustc_builtin_macros/src/type_ascribe.rs index e8b8fe75338c..f3e66ffc759d 100644 --- a/compiler/rustc_builtin_macros/src/type_ascribe.rs +++ b/compiler/rustc_builtin_macros/src/type_ascribe.rs @@ -2,25 +2,25 @@ use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{token, Expr, ExprKind, Ty}; use rustc_errors::PResult; -use rustc_expand::base::{self, DummyResult, ExtCtxt, MacEager}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::Span; pub fn expand_type_ascribe( cx: &mut ExtCtxt<'_>, span: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let (expr, ty) = match parse_ascribe(cx, tts) { Ok(parsed) => parsed, Err(err) => { let guar = err.emit(); - return DummyResult::any(span, guar); + return ExpandResult::Ready(DummyResult::any(span, guar)); } }; let asc_expr = cx.expr(span, ExprKind::Type(expr, ty)); - return MacEager::expr(asc_expr); + ExpandResult::Ready(MacEager::expr(asc_expr)) } fn parse_ascribe<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P, P)> { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 69dfb48919cd..30ee02ea3c0a 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -245,6 +245,15 @@ pub enum ExpandResult { Retry(U), } +impl ExpandResult { + pub fn map E>(self, f: F) -> ExpandResult { + match self { + ExpandResult::Ready(t) => ExpandResult::Ready(f(t)), + ExpandResult::Retry(u) => ExpandResult::Retry(u), + } + } +} + pub trait MultiItemModifier { /// `meta_item` is the attribute, and `item` is the item being modified. fn expand( @@ -330,22 +339,24 @@ pub trait TTMacroExpander { ecx: &'cx mut ExtCtxt<'_>, span: Span, input: TokenStream, - ) -> Box; + ) -> MacroExpanderResult<'cx>; } +pub type MacroExpanderResult<'cx> = ExpandResult, ()>; + pub type MacroExpanderFn = - for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box; + for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>; impl TTMacroExpander for F where - F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box, + F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>, { fn expand<'cx>( &self, ecx: &'cx mut ExtCtxt<'_>, span: Span, input: TokenStream, - ) -> Box { + ) -> MacroExpanderResult<'cx> { self(ecx, span, input) } } @@ -904,8 +915,11 @@ impl SyntaxExtension { cx: &'cx mut ExtCtxt<'_>, span: Span, _: TokenStream, - ) -> Box { - DummyResult::any(span, cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro")) + ) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(DummyResult::any( + span, + cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro"), + )) } SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Box::new(expander)), edition) } @@ -1008,6 +1022,11 @@ pub trait ResolverExpand { expn_id: LocalExpnId, path: &ast::Path, ) -> Result; + fn macro_accessible( + &mut self, + expn_id: LocalExpnId, + path: &ast::Path, + ) -> Result; /// Decodes the proc-macro quoted span in the specified crate, with the specified id. /// No caching is performed. @@ -1253,6 +1272,15 @@ pub fn resolve_path(sess: &Session, path: impl Into, span: Span) -> PRe } } +/// `Ok` represents successfully retrieving the string literal at the correct +/// position, e.g., `println("abc")`. +type ExprToSpannedStringResult<'a> = Result<(Symbol, ast::StrStyle, Span), UnexpectedExprKind<'a>>; + +/// - `Ok` is returned when the conversion to a string literal is unsuccessful, +/// but another type of expression is obtained instead. +/// - `Err` is returned when the conversion process fails. +type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), ErrorGuaranteed>; + /// Extracts a string literal from the macro expanded version of `expr`, /// returning a diagnostic error of `err_msg` if `expr` is not a string literal. /// The returned bool indicates whether an applicable suggestion has already been @@ -1264,17 +1292,23 @@ pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, expr: P, err_msg: &'static str, -) -> Result< - (Symbol, ast::StrStyle, Span), - Result<(Diag<'a>, bool /* has_suggestions */), ErrorGuaranteed>, -> { +) -> ExpandResult, ()> { + if !cx.force_mode + && let ast::ExprKind::MacCall(m) = &expr.kind + && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() + { + return ExpandResult::Retry(()); + } + // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); - Err(match expr.kind { + ExpandResult::Ready(Err(match expr.kind { ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { - Ok(ast::LitKind::Str(s, style)) => return Ok((s, style, expr.span)), + Ok(ast::LitKind::Str(s, style)) => { + return ExpandResult::Ready(Ok((s, style, expr.span))); + } Ok(ast::LitKind::ByteStr(..)) => { let mut err = cx.dcx().struct_span_err(expr.span, err_msg); let span = expr.span.shrink_to_lo(); @@ -1295,7 +1329,7 @@ pub fn expr_to_spanned_string<'a>( cx.dcx().span_bug(expr.span, "tried to get a string literal from `ExprKind::Dummy`") } _ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)), - }) + })) } /// Extracts a string literal from the macro expanded version of `expr`, @@ -1305,13 +1339,14 @@ pub fn expr_to_string( cx: &mut ExtCtxt<'_>, expr: P, err_msg: &'static str, -) -> Result<(Symbol, ast::StrStyle), ErrorGuaranteed> { - expr_to_spanned_string(cx, expr, err_msg) - .map_err(|err| match err { +) -> ExpandResult, ()> { + expr_to_spanned_string(cx, expr, err_msg).map(|res| { + res.map_err(|err| match err { Ok((err, _)) => err.emit(), Err(guar) => guar, }) .map(|(symbol, style, _)| (symbol, style)) + }) } /// Non-fatally assert that `tts` is empty. Note that this function @@ -1343,19 +1378,22 @@ pub fn get_single_str_from_tts( span: Span, tts: TokenStream, name: &str, -) -> Result { +) -> ExpandResult, ()> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } - let ret = parse_expr(&mut p)?; + let ret = match parse_expr(&mut p) { + Ok(ret) => ret, + Err(guar) => return ExpandResult::Ready(Err(guar)), + }; let _ = p.eat(&token::Comma); if p.token != token::Eof { cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); } - expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s) + expr_to_string(cx, ret, "argument must be a string literal").map(|s| s.map(|(s, _)| s)) } /// Extracts comma-separated expressions from `tts`. @@ -1363,11 +1401,20 @@ pub fn get_single_str_from_tts( pub fn get_exprs_from_tts( cx: &mut ExtCtxt<'_>, tts: TokenStream, -) -> Result>, ErrorGuaranteed> { +) -> ExpandResult>, ErrorGuaranteed>, ()> { let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - let expr = parse_expr(&mut p)?; + let expr = match parse_expr(&mut p) { + Ok(expr) => expr, + Err(guar) => return ExpandResult::Ready(Err(guar)), + }; + if !cx.force_mode + && let ast::ExprKind::MacCall(m) = &expr.kind + && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() + { + return ExpandResult::Retry(()); + } // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. @@ -1379,10 +1426,10 @@ pub fn get_exprs_from_tts( } if p.token != token::Eof { let guar = cx.dcx().emit_err(errors::ExpectedCommaInList { span: p.token.span }); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } } - Ok(es) + ExpandResult::Ready(Ok(es)) } pub fn parse_macro_name_and_helper_attrs( diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index fcc439e71f95..3544a8f0a8d9 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -659,7 +659,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); ExpandResult::Ready(match invoc.kind { - InvocationKind::Bang { mac, .. } => match ext { + InvocationKind::Bang { mac, span } => match ext { SyntaxExtensionKind::Bang(expander) => { match expander.expand(self.cx, span, mac.args.tokens.clone()) { Ok(tok_result) => { @@ -669,7 +669,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } SyntaxExtensionKind::LegacyBang(expander) => { - let tok_result = expander.expand(self.cx, span, mac.args.tokens.clone()); + let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) { + ExpandResult::Ready(tok_result) => tok_result, + ExpandResult::Retry(_) => { + // retry the original + return ExpandResult::Retry(Invocation { + kind: InvocationKind::Bang { mac, span }, + ..invoc + }); + } + }; let result = if let Some(result) = fragment_kind.make_from(tok_result) { result } else { diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 8903fc45defb..3f29d7f74659 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1,5 +1,5 @@ -use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; -use crate::base::{SyntaxExtension, SyntaxExtensionKind}; +use crate::base::{DummyResult, SyntaxExtension, SyntaxExtensionKind}; +use crate::base::{ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, TTMacroExpander}; use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind}; use crate::mbe; use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg}; @@ -111,8 +111,8 @@ impl TTMacroExpander for MacroRulesMacroExpander { cx: &'cx mut ExtCtxt<'_>, sp: Span, input: TokenStream, - ) -> Box { - expand_macro( + ) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(expand_macro( cx, sp, self.span, @@ -122,7 +122,7 @@ impl TTMacroExpander for MacroRulesMacroExpander { input, &self.lhses, &self.rhses, - ) + )) } } @@ -134,8 +134,8 @@ impl TTMacroExpander for DummyExpander { _: &'cx mut ExtCtxt<'_>, span: Span, _: TokenStream, - ) -> Box { - DummyResult::any(span, self.0) + ) -> ExpandResult, ()> { + ExpandResult::Ready(DummyResult::any(span, self.0)) } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index d8fd8d22439c..dbca2f9895d2 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -19,7 +19,7 @@ use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, Resolver use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion}; -use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; +use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::RegisteredTools; @@ -431,40 +431,15 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { expn_id: LocalExpnId, path: &ast::Path, ) -> Result { - let span = path.span; - let path = &Segment::from_path(path); - let parent_scope = self.invocation_parent_scopes[&expn_id]; + self.path_accessible(expn_id, path, &[TypeNS, ValueNS, MacroNS]) + } - let mut indeterminate = false; - for ns in [TypeNS, ValueNS, MacroNS].iter().copied() { - match self.maybe_resolve_path(path, Some(ns), &parent_scope) { - PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true), - PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => { - return Ok(true); - } - PathResult::NonModule(..) | - // HACK(Urgau): This shouldn't be necessary - PathResult::Failed { is_error_from_last_segment: false, .. } => { - self.dcx() - .emit_err(errors::CfgAccessibleUnsure { span }); - - // If we get a partially resolved NonModule in one namespace, we should get the - // same result in any other namespaces, so we can return early. - return Ok(false); - } - PathResult::Indeterminate => indeterminate = true, - // We can only be sure that a path doesn't exist after having tested all the - // possibilities, only at that time we can return false. - PathResult::Failed { .. } => {} - PathResult::Module(_) => panic!("unexpected path resolution"), - } - } - - if indeterminate { - return Err(Indeterminate); - } - - Ok(false) + fn macro_accessible( + &mut self, + expn_id: LocalExpnId, + path: &ast::Path, + ) -> Result { + self.path_accessible(expn_id, path, &[MacroNS]) } fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span { @@ -960,4 +935,46 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let ItemKind::MacroDef(def) = &item.kind else { unreachable!() }; MacroData { ext: Lrc::new(ext), rule_spans, macro_rules: def.macro_rules } } + + fn path_accessible( + &mut self, + expn_id: LocalExpnId, + path: &ast::Path, + namespaces: &[Namespace], + ) -> Result { + let span = path.span; + let path = &Segment::from_path(path); + let parent_scope = self.invocation_parent_scopes[&expn_id]; + + let mut indeterminate = false; + for ns in namespaces { + match self.maybe_resolve_path(path, Some(*ns), &parent_scope) { + PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true), + PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => { + return Ok(true); + } + PathResult::NonModule(..) | + // HACK(Urgau): This shouldn't be necessary + PathResult::Failed { is_error_from_last_segment: false, .. } => { + self.dcx() + .emit_err(errors::CfgAccessibleUnsure { span }); + + // If we get a partially resolved NonModule in one namespace, we should get the + // same result in any other namespaces, so we can return early. + return Ok(false); + } + PathResult::Indeterminate => indeterminate = true, + // We can only be sure that a path doesn't exist after having tested all the + // possibilities, only at that time we can return false. + PathResult::Failed { .. } => {} + PathResult::Module(_) => panic!("unexpected path resolution"), + } + } + + if indeterminate { + return Err(Indeterminate); + } + + Ok(false) + } } diff --git a/tests/ui/macros/expand-full-asm.rs b/tests/ui/macros/expand-full-asm.rs new file mode 100644 index 000000000000..0b61aa718f30 --- /dev/null +++ b/tests/ui/macros/expand-full-asm.rs @@ -0,0 +1,27 @@ +//@only-aarch64 +//@check-pass +//@edition: 2018 + +// https://github.com/rust-lang/rust/issues/98291 + +use std::arch::{asm, global_asm}; + +macro_rules! wrap { + () => { + macro_rules! _a { + () => { + "nop" + }; + } + }; +} + +wrap!(); + +use _a as a; + +fn main() { + unsafe { asm!(a!()); } +} + +global_asm!(a!()); diff --git a/tests/ui/macros/expand-full-in-format-str.rs b/tests/ui/macros/expand-full-in-format-str.rs new file mode 100644 index 000000000000..f47f7651a812 --- /dev/null +++ b/tests/ui/macros/expand-full-in-format-str.rs @@ -0,0 +1,33 @@ +//@check-pass +//@edition: 2018 + +// https://github.com/rust-lang/rust/issues/98291 + +macro_rules! wrap { + () => { + macro_rules! _a { + () => { + "auxiliary/macro-include-items-expr.rs" + }; + } + macro_rules! _env_name { + () => { + "PATH" + } + } + }; +} + +wrap!(); + +use _a as a; +use _env_name as env_name; + +fn main() { + format_args!(a!()); + include!(a!()); + include_str!(a!()); + include_bytes!(a!()); + env!(env_name!()); + option_env!(env_name!()); +} diff --git a/tests/ui/macros/expand-full-no-resolution.rs b/tests/ui/macros/expand-full-no-resolution.rs new file mode 100644 index 000000000000..4d90b8e2a531 --- /dev/null +++ b/tests/ui/macros/expand-full-no-resolution.rs @@ -0,0 +1,20 @@ +//@edition: 2018 + +// https://github.com/rust-lang/rust/issues/98291 + +macro_rules! wrap { + () => { + macro_rules! _a { + () => { + "" + }; + } + }; +} + +wrap!(); + +fn main() { + format_args!(a!()); //~ ERROR: cannot find macro `a` in this scope + env!(a!()); //~ ERROR: cannot find macro `a` in this scope +} diff --git a/tests/ui/macros/expand-full-no-resolution.stderr b/tests/ui/macros/expand-full-no-resolution.stderr new file mode 100644 index 000000000000..2537a5032a92 --- /dev/null +++ b/tests/ui/macros/expand-full-no-resolution.stderr @@ -0,0 +1,30 @@ +error: cannot find macro `a` in this scope + --> $DIR/expand-full-no-resolution.rs:18:18 + | +LL | macro_rules! _a { + | --------------- similarly named macro `_a` defined here +... +LL | format_args!(a!()); + | ^ + | +help: a macro with a similar name exists, consider renaming `_a` into `a` + | +LL | macro_rules! a { + | ~ + +error: cannot find macro `a` in this scope + --> $DIR/expand-full-no-resolution.rs:19:10 + | +LL | macro_rules! _a { + | --------------- similarly named macro `_a` defined here +... +LL | env!(a!()); + | ^ + | +help: a macro with a similar name exists, consider renaming `_a` into `a` + | +LL | macro_rules! a { + | ~ + +error: aborting due to 2 previous errors + From d919b04e59b0e357b509cb9c0127dce45f532996 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 Mar 2024 11:24:51 +0100 Subject: [PATCH 79/99] Generate link to `Local` in `hir::Let` documentation --- compiler/rustc_hir/src/hir.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 7d5b4c0f06de..fd069eb09e25 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1253,11 +1253,11 @@ pub struct Arm<'hir> { pub body: &'hir Expr<'hir>, } -/// Represents a `let [: ] = ` expression (not a Local), occurring in an `if-let` or -/// `let-else`, evaluating to a boolean. Typically the pattern is refutable. +/// Represents a `let [: ] = ` expression (not a [`Local`]), occurring in an `if-let` +/// or `let-else`, evaluating to a boolean. Typically the pattern is refutable. /// -/// In an if-let, imagine it as `if (let = ) { ... }`; in a let-else, it is part of the -/// desugaring to if-let. Only let-else supports the type annotation at present. +/// In an `if let`, imagine it as `if (let = ) { ... }`; in a let-else, it is part of +/// the desugaring to if-let. Only let-else supports the type annotation at present. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Let<'hir> { pub span: Span, From cb15bf6256495201c6b94ae5e51fe88be6100c00 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 13 Mar 2024 13:53:18 +0100 Subject: [PATCH 80/99] Rename `ValidityConstraint` -> `PlaceValidity` The old name came from a time where I wanted to reuse it for differentiating wildcards from bindings. I don't plan to do this anymore. --- compiler/rustc_pattern_analysis/src/lib.rs | 4 +-- .../rustc_pattern_analysis/src/usefulness.rs | 28 +++++++------------ 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index f632eaf7ea4f..41ae60a8b7ff 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -179,10 +179,10 @@ pub fn analyze_match<'p, 'tcx>( pattern_complexity_limit: Option, ) -> Result, ErrorGuaranteed> { use lints::lint_nonexhaustive_missing_variants; - use usefulness::{compute_match_usefulness, ValidityConstraint}; + use usefulness::{compute_match_usefulness, PlaceValidity}; let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); - let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee); + let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee); let report = compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity, pattern_complexity_limit)?; diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 0834d08106f3..495785066ce6 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -540,8 +540,8 @@ //! We track in the algorithm whether a given place is known to contain valid data. This is done //! first by inspecting the scrutinee syntactically (which gives us `cx.known_valid_scrutinee`), and //! then by tracking validity of each column of the matrix (which correspond to places) as we -//! recurse into subpatterns. That second part is done through [`ValidityConstraint`], most notably -//! [`ValidityConstraint::specialize`]. +//! recurse into subpatterns. That second part is done through [`PlaceValidity`], most notably +//! [`PlaceValidity::specialize`]. //! //! Having said all that, in practice we don't fully follow what's been presented in this section. //! Let's call "toplevel exception" the case where the match scrutinee itself has type `!` or @@ -718,7 +718,7 @@ use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat}; use crate::{Captures, MatchArm, PrivateUninhabitedField, TypeCx}; -use self::ValidityConstraint::*; +use self::PlaceValidity::*; #[cfg(feature = "rustc")] use rustc_data_structures::stack::ensure_sufficient_stack; @@ -780,18 +780,14 @@ impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { } } -/// Serves two purposes: -/// - in a wildcard, tracks whether the wildcard matches only valid values (i.e. is a binding `_a`) -/// or also invalid values (i.e. is a true `_` pattern). -/// - in the matrix, track whether a given place (aka column) is known to contain a valid value or -/// not. +/// Track whether a given place (aka column) is known to contain a valid value or not. #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ValidityConstraint { +pub enum PlaceValidity { ValidOnly, MaybeInvalid, } -impl ValidityConstraint { +impl PlaceValidity { pub fn from_bool(is_valid_only: bool) -> Self { if is_valid_only { ValidOnly } else { MaybeInvalid } } @@ -817,7 +813,7 @@ impl ValidityConstraint { } } -impl fmt::Display for ValidityConstraint { +impl fmt::Display for PlaceValidity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { ValidOnly => "✓", @@ -836,7 +832,7 @@ struct PlaceInfo { /// so that we don't observe its emptiness. private_uninhabited: bool, /// Whether the place is known to contain valid data. - validity: ValidityConstraint, + validity: PlaceValidity, /// Whether the place is the scrutinee itself or a subplace of it. is_scrutinee: bool, } @@ -1155,11 +1151,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { } /// Build a new matrix from an iterator of `MatchArm`s. - fn new( - arms: &[MatchArm<'p, Cx>], - scrut_ty: Cx::Ty, - scrut_validity: ValidityConstraint, - ) -> Self { + fn new(arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, scrut_validity: PlaceValidity) -> Self { let place_info = PlaceInfo { ty: scrut_ty, private_uninhabited: false, @@ -1754,7 +1746,7 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>( tycx: &Cx, arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, - scrut_validity: ValidityConstraint, + scrut_validity: PlaceValidity, complexity_limit: Option, ) -> Result, Cx::Error> { let mut cx = UsefulnessCtxt { From 4fc35c46ff70821a37fec5f7a4c36087704d9f23 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 13 Mar 2024 13:56:06 +0100 Subject: [PATCH 81/99] Rename `TypeCx` -> `PatCx` --- .../rustc_pattern_analysis/src/constructor.rs | 18 ++--- compiler/rustc_pattern_analysis/src/lib.rs | 8 +- compiler/rustc_pattern_analysis/src/pat.rs | 26 +++---- .../rustc_pattern_analysis/src/pat_column.rs | 6 +- compiler/rustc_pattern_analysis/src/rustc.rs | 4 +- .../rustc_pattern_analysis/src/usefulness.rs | 74 +++++++++---------- 6 files changed, 68 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 2d55785cd069..1faecb7e1dd8 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -40,7 +40,7 @@ //! - That have no non-trivial intersection with any of the constructors in the column (i.e. they're //! each either disjoint with or covered by any given column constructor). //! -//! We compute this in two steps: first [`TypeCx::ctors_for_ty`] determines the +//! We compute this in two steps: first [`PatCx::ctors_for_ty`] determines the //! set of all possible constructors for the type. Then [`ConstructorSet::split`] looks at the //! column of constructors and splits the set into groups accordingly. The precise invariants of //! [`ConstructorSet::split`] is described in [`SplitConstructorSet`]. @@ -136,7 +136,7 @@ //! the algorithm can't distinguish them from a nonempty constructor. The only known case where this //! could happen is the `[..]` pattern on `[!; N]` with `N > 0` so we must take care to not emit it. //! -//! This is all handled by [`TypeCx::ctors_for_ty`] and +//! This is all handled by [`PatCx::ctors_for_ty`] and //! [`ConstructorSet::split`]. The invariants of [`SplitConstructorSet`] are also of interest. //! //! @@ -162,7 +162,7 @@ use self::MaybeInfiniteInt::*; use self::SliceKind::*; use crate::index; -use crate::TypeCx; +use crate::PatCx; /// Whether we have seen a constructor in the column or not. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] @@ -651,7 +651,7 @@ impl OpaqueId { /// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and /// `Fields`. #[derive(Debug)] -pub enum Constructor { +pub enum Constructor { /// Tuples and structs. Struct, /// Enum variants. @@ -696,7 +696,7 @@ pub enum Constructor { PrivateUninhabited, } -impl Clone for Constructor { +impl Clone for Constructor { fn clone(&self) -> Self { match self { Constructor::Struct => Constructor::Struct, @@ -720,7 +720,7 @@ impl Clone for Constructor { } } -impl Constructor { +impl Constructor { pub(crate) fn is_non_exhaustive(&self) -> bool { matches!(self, NonExhaustive) } @@ -838,7 +838,7 @@ pub enum VariantVisibility { /// In terms of division of responsibility, [`ConstructorSet::split`] handles all of the /// `exhaustive_patterns` feature. #[derive(Debug)] -pub enum ConstructorSet { +pub enum ConstructorSet { /// The type is a tuple or struct. `empty` tracks whether the type is empty. Struct { empty: bool }, /// This type has the following list of constructors. If `variants` is empty and @@ -889,13 +889,13 @@ pub enum ConstructorSet { /// of the `ConstructorSet` for the type, yet if we forgot to include them in `present` we would be /// ignoring any row with `Opaque`s in the algorithm. Hence the importance of point 4. #[derive(Debug)] -pub struct SplitConstructorSet { +pub struct SplitConstructorSet { pub present: SmallVec<[Constructor; 1]>, pub missing: Vec>, pub missing_empty: Vec>, } -impl ConstructorSet { +impl ConstructorSet { /// This analyzes a column of constructors to 1/ determine which constructors of the type (if /// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 41ae60a8b7ff..ff085d2a422d 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -84,7 +84,7 @@ pub struct PrivateUninhabitedField(pub bool); /// Context that provides type information about constructors. /// /// Most of the crate is parameterized on a type that implements this trait. -pub trait TypeCx: Sized + fmt::Debug { +pub trait PatCx: Sized + fmt::Debug { /// The type of a pattern. type Ty: Clone + fmt::Debug; /// Errors that can abort analysis. @@ -155,19 +155,19 @@ pub trait TypeCx: Sized + fmt::Debug { /// The arm of a match expression. #[derive(Debug)] -pub struct MatchArm<'p, Cx: TypeCx> { +pub struct MatchArm<'p, Cx: PatCx> { pub pat: &'p DeconstructedPat, pub has_guard: bool, pub arm_data: Cx::ArmData, } -impl<'p, Cx: TypeCx> Clone for MatchArm<'p, Cx> { +impl<'p, Cx: PatCx> Clone for MatchArm<'p, Cx> { fn clone(&self) -> Self { Self { pat: self.pat, has_guard: self.has_guard, arm_data: self.arm_data } } } -impl<'p, Cx: TypeCx> Copy for MatchArm<'p, Cx> {} +impl<'p, Cx: PatCx> Copy for MatchArm<'p, Cx> {} /// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are /// useful, and runs some lints. diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index cefc1d8e3b3a..e3667d44bc97 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -5,7 +5,7 @@ use std::fmt; use smallvec::{smallvec, SmallVec}; use crate::constructor::{Constructor, Slice, SliceKind}; -use crate::{PrivateUninhabitedField, TypeCx}; +use crate::{PatCx, PrivateUninhabitedField}; use self::Constructor::*; @@ -21,7 +21,7 @@ impl PatId { } /// A pattern with an index denoting which field it corresponds to. -pub struct IndexedPat { +pub struct IndexedPat { pub idx: usize, pub pat: DeconstructedPat, } @@ -29,7 +29,7 @@ pub struct IndexedPat { /// Values and patterns can be represented as a constructor applied to some fields. This represents /// a pattern in this form. A `DeconstructedPat` will almost always come from user input; the only /// exception are some `Wildcard`s introduced during pattern lowering. -pub struct DeconstructedPat { +pub struct DeconstructedPat { ctor: Constructor, fields: Vec>, /// The number of fields in this pattern. E.g. if the pattern is `SomeStruct { field12: true, .. @@ -43,7 +43,7 @@ pub struct DeconstructedPat { pub(crate) uid: PatId, } -impl DeconstructedPat { +impl DeconstructedPat { pub fn new( ctor: Constructor, fields: Vec>, @@ -136,7 +136,7 @@ impl DeconstructedPat { } /// This is best effort and not good enough for a `Display` impl. -impl fmt::Debug for DeconstructedPat { +impl fmt::Debug for DeconstructedPat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let pat = self; let mut first = true; @@ -219,14 +219,14 @@ impl fmt::Debug for DeconstructedPat { /// algorithm. Do not use `Wild` to represent a wildcard pattern comping from user input. /// /// This is morally `Option<&'p DeconstructedPat>` where `None` is interpreted as a wildcard. -pub(crate) enum PatOrWild<'p, Cx: TypeCx> { +pub(crate) enum PatOrWild<'p, Cx: PatCx> { /// A non-user-provided wildcard, created during specialization. Wild, /// A user-provided pattern. Pat(&'p DeconstructedPat), } -impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { +impl<'p, Cx: PatCx> Clone for PatOrWild<'p, Cx> { fn clone(&self) -> Self { match self { PatOrWild::Wild => PatOrWild::Wild, @@ -235,9 +235,9 @@ impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { } } -impl<'p, Cx: TypeCx> Copy for PatOrWild<'p, Cx> {} +impl<'p, Cx: PatCx> Copy for PatOrWild<'p, Cx> {} -impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { +impl<'p, Cx: PatCx> PatOrWild<'p, Cx> { pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat> { match self { PatOrWild::Wild => None, @@ -283,7 +283,7 @@ impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { } } -impl<'p, Cx: TypeCx> fmt::Debug for PatOrWild<'p, Cx> { +impl<'p, Cx: PatCx> fmt::Debug for PatOrWild<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { PatOrWild::Wild => write!(f, "_"), @@ -295,19 +295,19 @@ impl<'p, Cx: TypeCx> fmt::Debug for PatOrWild<'p, Cx> { /// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics /// purposes. As such they don't use interning and can be cloned. #[derive(Debug)] -pub struct WitnessPat { +pub struct WitnessPat { ctor: Constructor, pub(crate) fields: Vec>, ty: Cx::Ty, } -impl Clone for WitnessPat { +impl Clone for WitnessPat { fn clone(&self) -> Self { Self { ctor: self.ctor.clone(), fields: self.fields.clone(), ty: self.ty.clone() } } } -impl WitnessPat { +impl WitnessPat { pub(crate) fn new(ctor: Constructor, fields: Vec, ty: Cx::Ty) -> Self { Self { ctor, fields, ty } } diff --git a/compiler/rustc_pattern_analysis/src/pat_column.rs b/compiler/rustc_pattern_analysis/src/pat_column.rs index ce14fdc364f7..eb4e095c1c66 100644 --- a/compiler/rustc_pattern_analysis/src/pat_column.rs +++ b/compiler/rustc_pattern_analysis/src/pat_column.rs @@ -1,6 +1,6 @@ use crate::constructor::{Constructor, SplitConstructorSet}; use crate::pat::{DeconstructedPat, PatOrWild}; -use crate::{Captures, MatchArm, TypeCx}; +use crate::{Captures, MatchArm, PatCx}; /// A column of patterns in a match, where a column is the intuitive notion of "subpatterns that /// inspect the same subvalue/place". @@ -11,12 +11,12 @@ use crate::{Captures, MatchArm, TypeCx}; /// /// This is not used in the usefulness algorithm; only in lints. #[derive(Debug)] -pub struct PatternColumn<'p, Cx: TypeCx> { +pub struct PatternColumn<'p, Cx: PatCx> { /// This must not contain an or-pattern. `expand_and_push` takes care to expand them. patterns: Vec<&'p DeconstructedPat>, } -impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { +impl<'p, Cx: PatCx> PatternColumn<'p, Cx> { pub fn new(arms: &[MatchArm<'p, Cx>]) -> Self { let patterns = Vec::with_capacity(arms.len()); let mut column = PatternColumn { patterns }; diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 53a32d3237e6..6de12f1f6baa 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -18,7 +18,7 @@ use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; use crate::constructor::{ IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility, }; -use crate::{errors, Captures, PrivateUninhabitedField, TypeCx}; +use crate::{errors, Captures, PatCx, PrivateUninhabitedField}; use crate::constructor::Constructor::*; @@ -843,7 +843,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { } } -impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> PatCx for RustcMatchCheckCtxt<'p, 'tcx> { type Ty = RevealedTy<'tcx>; type Error = ErrorGuaranteed; type VariantIdx = VariantIdx; diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 495785066ce6..3760db8b6889 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -242,7 +242,7 @@ //! Therefore `usefulness(tp_1, tp_2, tq)` returns the single witness-tuple `[Variant2(Some(true), 0)]`. //! //! -//! Computing the set of constructors for a type is done in [`TypeCx::ctors_for_ty`]. See +//! Computing the set of constructors for a type is done in [`PatCx::ctors_for_ty`]. See //! the following sections for more accurate versions of the algorithm and corresponding links. //! //! @@ -716,7 +716,7 @@ use std::fmt; use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat}; -use crate::{Captures, MatchArm, PrivateUninhabitedField, TypeCx}; +use crate::{Captures, MatchArm, PatCx, PrivateUninhabitedField}; use self::PlaceValidity::*; @@ -728,7 +728,7 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { } /// Context that provides information for usefulness checking. -struct UsefulnessCtxt<'a, Cx: TypeCx> { +struct UsefulnessCtxt<'a, Cx: PatCx> { /// The context for type information. tycx: &'a Cx, /// Collect the patterns found useful during usefulness checking. This is used to lint @@ -738,7 +738,7 @@ struct UsefulnessCtxt<'a, Cx: TypeCx> { complexity_level: usize, } -impl<'a, Cx: TypeCx> UsefulnessCtxt<'a, Cx> { +impl<'a, Cx: PatCx> UsefulnessCtxt<'a, Cx> { fn increase_complexity_level(&mut self, complexity_add: usize) -> Result<(), Cx::Error> { self.complexity_level += complexity_add; if self @@ -752,26 +752,26 @@ impl<'a, Cx: TypeCx> UsefulnessCtxt<'a, Cx> { } /// Context that provides information local to a place under investigation. -struct PlaceCtxt<'a, Cx: TypeCx> { +struct PlaceCtxt<'a, Cx: PatCx> { cx: &'a Cx, /// Type of the place under investigation. ty: &'a Cx::Ty, } -impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {} -impl<'a, Cx: TypeCx> Clone for PlaceCtxt<'a, Cx> { +impl<'a, Cx: PatCx> Copy for PlaceCtxt<'a, Cx> {} +impl<'a, Cx: PatCx> Clone for PlaceCtxt<'a, Cx> { fn clone(&self) -> Self { Self { cx: self.cx, ty: self.ty } } } -impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> { +impl<'a, Cx: PatCx> fmt::Debug for PlaceCtxt<'a, Cx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("PlaceCtxt").field("ty", self.ty).finish() } } -impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { +impl<'a, Cx: PatCx> PlaceCtxt<'a, Cx> { fn ctor_arity(&self, ctor: &Constructor) -> usize { self.cx.ctor_arity(ctor, self.ty) } @@ -802,7 +802,7 @@ impl PlaceValidity { /// /// Pending further opsem decisions, the current behavior is: validity is preserved, except /// inside `&` and union fields where validity is reset to `MaybeInvalid`. - fn specialize(self, ctor: &Constructor) -> Self { + fn specialize(self, ctor: &Constructor) -> Self { // We preserve validity except when we go inside a reference or a union field. if matches!(ctor, Constructor::Ref | Constructor::UnionField) { // Validity of `x: &T` does not imply validity of `*x: T`. @@ -825,7 +825,7 @@ impl fmt::Display for PlaceValidity { /// Data about a place under investigation. Its methods contain a lot of the logic used to analyze /// the constructors in the matrix. -struct PlaceInfo { +struct PlaceInfo { /// The type of the place. ty: Cx::Ty, /// Whether the place is a private uninhabited field. If so we skip this field during analysis @@ -837,7 +837,7 @@ struct PlaceInfo { is_scrutinee: bool, } -impl PlaceInfo { +impl PlaceInfo { /// Given a constructor for the current place, we return one `PlaceInfo` for each field of the /// constructor. fn specialize<'a>( @@ -932,7 +932,7 @@ impl PlaceInfo { } } -impl Clone for PlaceInfo { +impl Clone for PlaceInfo { fn clone(&self) -> Self { Self { ty: self.ty.clone(), @@ -947,7 +947,7 @@ impl Clone for PlaceInfo { // The three lifetimes are: // - 'p coming from the input // - Cx global compilation context -struct PatStack<'p, Cx: TypeCx> { +struct PatStack<'p, Cx: PatCx> { // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well. pats: SmallVec<[PatOrWild<'p, Cx>; 2]>, /// Sometimes we know that as far as this row is concerned, the current case is already handled @@ -956,13 +956,13 @@ struct PatStack<'p, Cx: TypeCx> { relevant: bool, } -impl<'p, Cx: TypeCx> Clone for PatStack<'p, Cx> { +impl<'p, Cx: PatCx> Clone for PatStack<'p, Cx> { fn clone(&self) -> Self { Self { pats: self.pats.clone(), relevant: self.relevant } } } -impl<'p, Cx: TypeCx> PatStack<'p, Cx> { +impl<'p, Cx: PatCx> PatStack<'p, Cx> { fn from_pattern(pat: &'p DeconstructedPat) -> Self { PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true } } @@ -1022,7 +1022,7 @@ impl<'p, Cx: TypeCx> PatStack<'p, Cx> { } } -impl<'p, Cx: TypeCx> fmt::Debug for PatStack<'p, Cx> { +impl<'p, Cx: PatCx> fmt::Debug for PatStack<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // We pretty-print similarly to the `Debug` impl of `Matrix`. write!(f, "+")?; @@ -1035,7 +1035,7 @@ impl<'p, Cx: TypeCx> fmt::Debug for PatStack<'p, Cx> { /// A row of the matrix. #[derive(Clone)] -struct MatrixRow<'p, Cx: TypeCx> { +struct MatrixRow<'p, Cx: PatCx> { // The patterns in the row. pats: PatStack<'p, Cx>, /// Whether the original arm had a guard. This is inherited when specializing. @@ -1055,7 +1055,7 @@ struct MatrixRow<'p, Cx: TypeCx> { intersects: BitSet, } -impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> { +impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { fn is_empty(&self) -> bool { self.pats.is_empty() } @@ -1104,7 +1104,7 @@ impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> { } } -impl<'p, Cx: TypeCx> fmt::Debug for MatrixRow<'p, Cx> { +impl<'p, Cx: PatCx> fmt::Debug for MatrixRow<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.pats.fmt(f) } @@ -1121,7 +1121,7 @@ impl<'p, Cx: TypeCx> fmt::Debug for MatrixRow<'p, Cx> { /// specializing `(,)` and `Some` on a pattern of type `(Option, bool)`, the first column of /// the matrix will correspond to `scrutinee.0.Some.0` and the second column to `scrutinee.1`. #[derive(Clone)] -struct Matrix<'p, Cx: TypeCx> { +struct Matrix<'p, Cx: PatCx> { /// Vector of rows. The rows must form a rectangular 2D array. Moreover, all the patterns of /// each column must have the same type. Each column corresponds to a place within the /// scrutinee. @@ -1134,7 +1134,7 @@ struct Matrix<'p, Cx: TypeCx> { wildcard_row_is_relevant: bool, } -impl<'p, Cx: TypeCx> Matrix<'p, Cx> { +impl<'p, Cx: PatCx> Matrix<'p, Cx> { /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively /// expands it. Internal method, prefer [`Matrix::new`]. fn expand_and_push(&mut self, mut row: MatrixRow<'p, Cx>) { @@ -1256,7 +1256,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { /// + _ + [_, _, tail @ ..] + /// | ✓ | ? | // column validity /// ``` -impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> { +impl<'p, Cx: PatCx> fmt::Debug for Matrix<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "\n")?; @@ -1347,15 +1347,15 @@ impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> { /// /// See the top of the file for more detailed explanations and examples. #[derive(Debug)] -struct WitnessStack(Vec>); +struct WitnessStack(Vec>); -impl Clone for WitnessStack { +impl Clone for WitnessStack { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl WitnessStack { +impl WitnessStack { /// Asserts that the witness contains a single pattern, and returns it. fn single_pattern(self) -> WitnessPat { assert_eq!(self.0.len(), 1); @@ -1400,15 +1400,15 @@ impl WitnessStack { /// Just as the `Matrix` starts with a single column, by the end of the algorithm, this has a single /// column, which contains the patterns that are missing for the match to be exhaustive. #[derive(Debug)] -struct WitnessMatrix(Vec>); +struct WitnessMatrix(Vec>); -impl Clone for WitnessMatrix { +impl Clone for WitnessMatrix { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl WitnessMatrix { +impl WitnessMatrix { /// New matrix with no witnesses. fn empty() -> Self { WitnessMatrix(Vec::new()) @@ -1482,7 +1482,7 @@ impl WitnessMatrix { /// /// We can however get false negatives because exhaustiveness does not explore all cases. See the /// section on relevancy at the top of the file. -fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( +fn collect_overlapping_range_endpoints<'p, Cx: PatCx>( cx: &Cx, overlap_range: IntRange, matrix: &Matrix<'p, Cx>, @@ -1541,7 +1541,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( } /// Collect ranges that have a singleton gap between them. -fn collect_non_contiguous_range_endpoints<'p, Cx: TypeCx>( +fn collect_non_contiguous_range_endpoints<'p, Cx: PatCx>( cx: &Cx, gap_range: &IntRange, matrix: &Matrix<'p, Cx>, @@ -1582,7 +1582,7 @@ fn collect_non_contiguous_range_endpoints<'p, Cx: TypeCx>( /// (using `apply_constructor` and by updating `row.useful` for each parent row). /// This is all explained at the top of the file. #[instrument(level = "debug", skip(mcx), ret)] -fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( +fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( mcx: &mut UsefulnessCtxt<'a, Cx>, matrix: &mut Matrix<'p, Cx>, ) -> Result, Cx::Error> { @@ -1679,7 +1679,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( /// Indicates whether or not a given arm is useful. #[derive(Clone, Debug)] -pub enum Usefulness<'p, Cx: TypeCx> { +pub enum Usefulness<'p, Cx: PatCx> { /// The arm is useful. This additionally carries a set of or-pattern branches that have been /// found to be redundant despite the overall arm being useful. Used only in the presence of /// or-patterns, otherwise it stays empty. @@ -1690,11 +1690,11 @@ pub enum Usefulness<'p, Cx: TypeCx> { } /// Report whether this pattern was found useful, and its subpatterns that were not useful if any. -fn collect_pattern_usefulness<'p, Cx: TypeCx>( +fn collect_pattern_usefulness<'p, Cx: PatCx>( useful_subpatterns: &FxHashSet, pat: &'p DeconstructedPat, ) -> Usefulness<'p, Cx> { - fn pat_is_useful<'p, Cx: TypeCx>( + fn pat_is_useful<'p, Cx: PatCx>( useful_subpatterns: &FxHashSet, pat: &'p DeconstructedPat, ) -> bool { @@ -1732,7 +1732,7 @@ fn collect_pattern_usefulness<'p, Cx: TypeCx>( } /// The output of checking a match for exhaustiveness and arm usefulness. -pub struct UsefulnessReport<'p, Cx: TypeCx> { +pub struct UsefulnessReport<'p, Cx: PatCx> { /// For each arm of the input, whether that arm is useful after the arms above it. pub arm_usefulness: Vec<(MatchArm<'p, Cx>, Usefulness<'p, Cx>)>, /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of @@ -1742,7 +1742,7 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> { /// Computes whether a match is exhaustive and which of its arms are useful. #[instrument(skip(tycx, arms), level = "debug")] -pub fn compute_match_usefulness<'p, Cx: TypeCx>( +pub fn compute_match_usefulness<'p, Cx: PatCx>( tycx: &Cx, arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, From f27540697e7f17b77dd2fae9fe5d9df8a5eb24c0 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 13 Mar 2024 14:07:44 +0100 Subject: [PATCH 82/99] Rename `RustcMatchCheckCtxt` -> `RustcPatCtxt` --- compiler/rustc_mir_build/src/errors.rs | 4 +- .../src/thir/pattern/check_match.rs | 29 ++++++------- compiler/rustc_pattern_analysis/src/errors.rs | 4 +- compiler/rustc_pattern_analysis/src/lib.rs | 2 +- compiler/rustc_pattern_analysis/src/lints.rs | 12 +++--- compiler/rustc_pattern_analysis/src/rustc.rs | 41 ++++++++----------- 6 files changed, 42 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 2b4c65418577..848da56f9816 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -6,7 +6,7 @@ use rustc_errors::{ }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; -use rustc_pattern_analysis::{errors::Uncovered, rustc::RustcMatchCheckCtxt}; +use rustc_pattern_analysis::{errors::Uncovered, rustc::RustcPatCtxt}; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -455,7 +455,7 @@ pub enum UnusedUnsafeEnclosing { } pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { - pub cx: &'m RustcMatchCheckCtxt<'p, 'tcx>, + pub cx: &'m RustcPatCtxt<'p, 'tcx>, pub expr_span: Span, pub span: Span, pub ty: Ty<'tcx>, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index f395bb44f574..20d3b3f98ce3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1,7 +1,7 @@ use rustc_pattern_analysis::errors::Uncovered; use rustc_pattern_analysis::rustc::{ - Constructor, DeconstructedPat, MatchArm, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness, - UsefulnessReport, WitnessPat, + Constructor, DeconstructedPat, MatchArm, RustcPatCtxt as PatCtxt, Usefulness, UsefulnessReport, + WitnessPat, }; use crate::errors::*; @@ -276,7 +276,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { fn lower_pattern( &mut self, - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, pat: &'p Pat<'tcx>, ) -> Result<&'p DeconstructedPat<'p, 'tcx>, ErrorGuaranteed> { if let Err(err) = pat.pat_error_reported() { @@ -375,7 +375,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { whole_match_span: Option, scrutinee: Option<&Expr<'tcx>>, scrut_span: Span, - ) -> MatchCheckCtxt<'p, 'tcx> { + ) -> PatCtxt<'p, 'tcx> { let refutable = match refutability { Irrefutable => false, Refutable => true, @@ -384,7 +384,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // require validity. let known_valid_scrutinee = scrutinee.map(|scrut| self.is_known_valid_scrutinee(scrut)).unwrap_or(true); - MatchCheckCtxt { + PatCtxt { tcx: self.tcx, typeck_results: self.typeck_results, param_env: self.param_env, @@ -400,7 +400,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { fn analyze_patterns( &mut self, - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, arms: &[MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, ) -> Result, ErrorGuaranteed> { @@ -584,7 +584,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { pat: &'p Pat<'tcx>, refutability: RefutableFlag, scrut: Option<&Expr<'tcx>>, - ) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> { + ) -> Result<(PatCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> { let cx = self.new_cx(refutability, None, scrut, pat.span); let pat = self.lower_pattern(&cx, pat)?; let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }]; @@ -849,7 +849,7 @@ fn check_for_bindings_named_same_as_variants( /// Check that never patterns are only used on inhabited types. fn check_never_pattern<'tcx>( - cx: &MatchCheckCtxt<'_, 'tcx>, + cx: &PatCtxt<'_, 'tcx>, pat: &Pat<'tcx>, ) -> Result<(), ErrorGuaranteed> { if let PatKind::Never = pat.kind { @@ -884,7 +884,7 @@ fn report_irrefutable_let_patterns( /// Report unreachable arms, if any. fn report_unreachable_pattern<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, hir_id: HirId, span: Span, catchall: Option, @@ -898,10 +898,7 @@ fn report_unreachable_pattern<'p, 'tcx>( } /// Report unreachable arms, if any. -fn report_arm_reachability<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, - report: &UsefulnessReport<'p, 'tcx>, -) { +fn report_arm_reachability<'p, 'tcx>(cx: &PatCtxt<'p, 'tcx>, report: &UsefulnessReport<'p, 'tcx>) { let mut catchall = None; for (arm, is_useful) in report.arm_usefulness.iter() { if matches!(is_useful, Usefulness::Redundant) { @@ -926,7 +923,7 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { /// Report that a match is not exhaustive. fn report_non_exhaustive_match<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, thir: &Thir<'tcx>, scrut_ty: Ty<'tcx>, sp: Span, @@ -1126,7 +1123,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( } fn joined_uncovered_patterns<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, witnesses: &[WitnessPat<'p, 'tcx>], ) -> String { const LIMIT: usize = 3; @@ -1147,7 +1144,7 @@ fn joined_uncovered_patterns<'p, 'tcx>( } fn collect_non_exhaustive_tys<'tcx>( - cx: &MatchCheckCtxt<'_, 'tcx>, + cx: &PatCtxt<'_, 'tcx>, pat: &WitnessPat<'_, 'tcx>, non_exhaustive_tys: &mut FxIndexSet>, ) { diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 21a61d46ccb7..75b7b7c8f678 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -4,7 +4,7 @@ use rustc_middle::thir::Pat; use rustc_middle::ty::Ty; use rustc_span::Span; -use crate::rustc::{RustcMatchCheckCtxt, WitnessPat}; +use crate::rustc::{RustcPatCtxt, WitnessPat}; #[derive(Subdiagnostic)] #[label(pattern_analysis_uncovered)] @@ -21,7 +21,7 @@ pub struct Uncovered<'tcx> { impl<'tcx> Uncovered<'tcx> { pub fn new<'p>( span: Span, - cx: &RustcMatchCheckCtxt<'p, 'tcx>, + cx: &RustcPatCtxt<'p, 'tcx>, witnesses: Vec>, ) -> Self where diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index ff085d2a422d..5c57c990323c 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -173,7 +173,7 @@ impl<'p, Cx: PatCx> Copy for MatchArm<'p, Cx> {} /// useful, and runs some lints. #[cfg(feature = "rustc")] pub fn analyze_match<'p, 'tcx>( - tycx: &rustc::RustcMatchCheckCtxt<'p, 'tcx>, + tycx: &rustc::RustcPatCtxt<'p, 'tcx>, arms: &[rustc::MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, pattern_complexity_limit: Option, diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 072a8e4bfe5a..3ca5ebdb0dd1 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -4,15 +4,15 @@ use rustc_span::ErrorGuaranteed; use crate::constructor::Constructor; use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered}; use crate::pat_column::PatternColumn; -use crate::rustc::{RevealedTy, RustcMatchCheckCtxt, WitnessPat}; +use crate::rustc::{RevealedTy, RustcPatCtxt, WitnessPat}; use crate::MatchArm; /// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned /// in a given column. #[instrument(level = "debug", skip(cx), ret)] fn collect_nonexhaustive_missing_variants<'p, 'tcx>( - cx: &RustcMatchCheckCtxt<'p, 'tcx>, - column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, + cx: &RustcPatCtxt<'p, 'tcx>, + column: &PatternColumn<'p, RustcPatCtxt<'p, 'tcx>>, ) -> Result>, ErrorGuaranteed> { let Some(&ty) = column.head_ty() else { return Ok(Vec::new()); @@ -57,9 +57,9 @@ fn collect_nonexhaustive_missing_variants<'p, 'tcx>( } pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( - rcx: &RustcMatchCheckCtxt<'p, 'tcx>, - arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>], - pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, + rcx: &RustcPatCtxt<'p, 'tcx>, + arms: &[MatchArm<'p, RustcPatCtxt<'p, 'tcx>>], + pat_column: &PatternColumn<'p, RustcPatCtxt<'p, 'tcx>>, scrut_ty: RevealedTy<'tcx>, ) -> Result<(), ErrorGuaranteed> { if !matches!( diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 6de12f1f6baa..d00faadccb09 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -23,15 +23,14 @@ use crate::{errors, Captures, PatCx, PrivateUninhabitedField}; use crate::constructor::Constructor::*; // Re-export rustc-specific versions of all these types. -pub type Constructor<'p, 'tcx> = crate::constructor::Constructor>; -pub type ConstructorSet<'p, 'tcx> = - crate::constructor::ConstructorSet>; -pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat>; -pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>; +pub type Constructor<'p, 'tcx> = crate::constructor::Constructor>; +pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet>; +pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat>; +pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcPatCtxt<'p, 'tcx>>; +pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcPatCtxt<'p, 'tcx>>; pub type UsefulnessReport<'p, 'tcx> = - crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat>; + crate::usefulness::UsefulnessReport<'p, RustcPatCtxt<'p, 'tcx>>; +pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat>; /// A type which has gone through `cx.reveal_opaque_ty`, i.e. if it was opaque it was replaced by /// the hidden type if allowed in the current body. This ensures we consistently inspect the hidden @@ -62,7 +61,7 @@ impl<'tcx> RevealedTy<'tcx> { } #[derive(Clone)] -pub struct RustcMatchCheckCtxt<'p, 'tcx: 'p> { +pub struct RustcPatCtxt<'p, 'tcx: 'p> { pub tcx: TyCtxt<'tcx>, pub typeck_results: &'tcx ty::TypeckResults<'tcx>, /// The module in which the match occurs. This is necessary for @@ -87,22 +86,19 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx: 'p> { pub known_valid_scrutinee: bool, } -impl<'p, 'tcx: 'p> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> fmt::Debug for RustcPatCtxt<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RustcMatchCheckCtxt").finish() + f.debug_struct("RustcPatCtxt").finish() } } -impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Type inference occasionally gives us opaque types in places where corresponding patterns /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited /// types, we use the corresponding concrete type if possible. #[inline] pub fn reveal_opaque_ty(&self, ty: Ty<'tcx>) -> RevealedTy<'tcx> { - fn reveal_inner<'tcx>( - cx: &RustcMatchCheckCtxt<'_, 'tcx>, - ty: Ty<'tcx>, - ) -> RevealedTy<'tcx> { + fn reveal_inner<'tcx>(cx: &RustcPatCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> RevealedTy<'tcx> { let ty::Alias(ty::Opaque, alias_ty) = *ty.kind() else { bug!() }; if let Some(local_def_id) = alias_ty.def_id.as_local() { let key = ty::OpaqueTypeKey { def_id: local_def_id, args: alias_ty.args }; @@ -199,7 +195,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { + ExactSizeIterator + Captures<'a> { fn reveal_and_alloc<'a, 'tcx>( - cx: &'a RustcMatchCheckCtxt<'_, 'tcx>, + cx: &'a RustcPatCtxt<'_, 'tcx>, iter: impl Iterator>, ) -> &'a [(RevealedTy<'tcx>, PrivateUninhabitedField)] { cx.dropless_arena.alloc_from_iter( @@ -218,7 +214,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { reveal_and_alloc(cx, once(args.type_at(0))) } else { let variant = - &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt)); + &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt)); // In the cases of either a `#[non_exhaustive]` field list or a non-public // field, we skip uninhabited fields in order not to reveal the @@ -270,7 +266,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { // patterns. If we're here we can assume this is a box pattern. 1 } else { - let variant_idx = RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt); + let variant_idx = RustcPatCtxt::variant_index_for_adt(&ctor, *adt); adt.variant(variant_idx).fields.len() } } @@ -506,7 +502,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { _ => bug!(), }; let variant = - &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt)); + &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt)); arity = variant.fields.len(); fields = subpatterns .iter() @@ -774,8 +770,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { PatKind::Deref { subpattern: subpatterns.next().unwrap() } } ty::Adt(adt_def, args) => { - let variant_index = - RustcMatchCheckCtxt::variant_index_for_adt(&pat.ctor(), *adt_def); + let variant_index = RustcPatCtxt::variant_index_for_adt(&pat.ctor(), *adt_def); let subpatterns = subpatterns .enumerate() .map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern }) @@ -843,7 +838,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { } } -impl<'p, 'tcx: 'p> PatCx for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> { type Ty = RevealedTy<'tcx>; type Error = ErrorGuaranteed; type VariantIdx = VariantIdx; From c4236785c72fdf04176716393c910b1fb011d15f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 13 Mar 2024 14:17:11 +0100 Subject: [PATCH 83/99] Remove `MaybeInfiniteInt::JustAfterMax` It was inherited from before half-open ranges, but it doesn't pull its weight anymore. We lose a tiny bit of diagnostic precision. --- .../rustc_pattern_analysis/src/constructor.rs | 13 +++++-------- compiler/rustc_pattern_analysis/src/rustc.rs | 2 +- .../half-open-range-pats-exhaustive-fail.stderr | 16 ++++++++-------- .../integer-ranges/exhaustiveness.stderr | 8 ++++---- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 2d55785cd069..ab75b2fef997 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -195,8 +195,6 @@ pub enum MaybeInfiniteInt { /// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite_{int,uint}`. #[non_exhaustive] Finite(u128), - /// The integer after `u128::MAX`. We need it to represent `x..=u128::MAX` as an exclusive range. - JustAfterMax, PosInfinity, } @@ -232,18 +230,18 @@ impl MaybeInfiniteInt { pub fn minus_one(self) -> Option { match self { Finite(n) => n.checked_sub(1).map(Finite), - JustAfterMax => Some(Finite(u128::MAX)), x => Some(x), } } - /// Note: this will not turn a finite value into an infinite one or vice-versa. + /// Note: this will turn `u128::MAX` into `PosInfinity`. This means `plus_one` and `minus_one` + /// are not strictly inverses, but that poses no problem in our use of them. + /// this will not turn a finite value into an infinite one or vice-versa. pub fn plus_one(self) -> Option { match self { Finite(n) => match n.checked_add(1) { Some(m) => Some(Finite(m)), - None => Some(JustAfterMax), + None => Some(PosInfinity), }, - JustAfterMax => None, x => Some(x), } } @@ -277,8 +275,7 @@ impl IntRange { } /// Construct a range with these boundaries. - /// `lo` must not be `PosInfinity` or `JustAfterMax`. `hi` must not be `NegInfinity`. - /// If `end` is `Included`, `hi` must also not be `JustAfterMax`. + /// `lo` must not be `PosInfinity`. `hi` must not be `NegInfinity`. #[inline] pub fn from_range(lo: MaybeInfiniteInt, mut hi: MaybeInfiniteInt, end: RangeEnd) -> IntRange { if end == RangeEnd::Included { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 53a32d3237e6..f4a398333851 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -710,7 +710,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => PatRangeBoundary::PosInfinity, } } - JustAfterMax | PosInfinity => PatRangeBoundary::PosInfinity, + PosInfinity => PatRangeBoundary::PosInfinity, } } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr index 6b20a820b730..bb4c2a4c5235 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr @@ -394,17 +394,17 @@ help: ensure that all possible cases are being handled by adding a match arm wit LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ -error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..=u128::MAX` not covered +error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..` not covered --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 | LL | m!(0, ..ALMOST_MAX); - | ^ pattern `340282366920938463463374607431768211454_u128..=u128::MAX` not covered + | ^ pattern `340282366920938463463374607431768211454_u128..` not covered | = note: the matched value is of type `u128` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u128..=u128::MAX => todo!() } - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u128.. => todo!() } + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u128` not covered --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 @@ -754,17 +754,17 @@ help: ensure that all possible cases are being handled by adding a match arm wit LL | match $s { $($t)+ => {}, i128::MAX => todo!() } | ++++++++++++++++++++++ -error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..=i128::MAX` not covered +error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..` not covered --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 | LL | m!(0, ..ALMOST_MAX); - | ^ pattern `170141183460469231731687303715884105726_i128..=i128::MAX` not covered + | ^ pattern `170141183460469231731687303715884105726_i128..` not covered | = note: the matched value is of type `i128` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i128..=i128::MAX => todo!() } - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i128.. => todo!() } + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MIN` not covered --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr index 90d0fd7483a9..68976c1b0576 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr @@ -107,17 +107,17 @@ help: ensure that all possible cases are being handled by adding a match arm wit LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ -error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered +error[E0004]: non-exhaustive patterns: `5_u128..` not covered --> $DIR/exhaustiveness.rs:61:8 | LL | m!(0u128, 0..=4); - | ^^^^^ pattern `5_u128..=u128::MAX` not covered + | ^^^^^ pattern `5_u128..` not covered | = note: the matched value is of type `u128` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | match $s { $($t)+ => {}, 5_u128..=u128::MAX => todo!() } - | +++++++++++++++++++++++++++++++ +LL | match $s { $($t)+ => {}, 5_u128.. => todo!() } + | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u128` not covered --> $DIR/exhaustiveness.rs:62:8 From a8549b4152566d8fbd34c097236df1db3d9afd3c Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 8 Mar 2024 11:24:48 -0500 Subject: [PATCH 84/99] downgrade mutable-ptr-in-final-value from hard-error to future-incompat lint to address issue 121610. --- compiler/rustc_const_eval/src/errors.rs | 7 ++-- .../rustc_const_eval/src/interpret/intern.rs | 12 ++++--- compiler/rustc_lint_defs/src/builtin.rs | 36 +++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 249c02b75f7d..46790264359b 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -25,10 +25,13 @@ pub(crate) struct DanglingPtrInFinal { pub kind: InternKind, } -#[derive(Diagnostic)] +#[derive(LintDiagnostic)] #[diag(const_eval_mutable_ptr_in_final)] pub(crate) struct MutablePtrInFinal { - #[primary_span] + // rust-lang/rust#122153: This was marked as `#[primary_span]` under + // `derive(Diagnostic)`. Since we expect we may hard-error in future, we are + // keeping the field (and skipping it under `derive(LintDiagnostic)`). + #[skip_arg] pub span: Span, pub kind: InternKind, } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 55d4b9edd59b..0994ace814c9 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -23,6 +23,7 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::TyAndLayout; use rustc_span::def_id::LocalDefId; use rustc_span::sym; +use rustc_session::lint; use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy}; use crate::const_eval; @@ -262,10 +263,13 @@ pub fn intern_const_alloc_recursive< })?); } if found_bad_mutable_pointer { - return Err(ecx - .tcx - .dcx() - .emit_err(MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind })); + let err_diag = MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }; + ecx.tcx.emit_node_span_lint( + lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, + ecx.best_lint_scope(), + err_diag.span, + err_diag, + ) } Ok(()) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index f2560b35aa2e..3dfc2d026bdb 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -30,6 +30,7 @@ declare_lint_pass! { CENUM_IMPL_DROP_CAST, COHERENCE_LEAK_CHECK, CONFLICTING_REPR_HINTS, + CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, CONST_EVALUATABLE_UNCHECKED, CONST_ITEM_MUTATION, DEAD_CODE, @@ -2796,6 +2797,41 @@ declare_lint! { @feature_gate = sym::strict_provenance; } +declare_lint! { + /// The `const_eval_mutable_ptr_in_final_value` lint detects if a mutable pointer + /// has leaked into the final value of a const expression. + /// + /// ### Example + /// + /// ```rust + /// pub enum JsValue { + /// Undefined, + /// Object(std::cell::Cell), + /// } + /// + /// impl ::std::ops::Drop for JsValue { + /// fn drop(&mut self) {} + /// } + /// + /// const UNDEFINED: &JsValue = &JsValue::Undefined; + /// + /// fn main() { + /// } + /// ``` + /// + /// This is a [future-incompatible] lint to ease the transition to an error. + /// See [issue #122153] for more details. + /// + /// [issue #122153]: https://github.com/rust-lang/rust/issues/122153 + pub CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, + Warn, + "detects a mutable pointer that has leaked into final value of a const expression", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #122153 ", + }; +} + declare_lint! { /// The `const_evaluatable_unchecked` lint detects a generic constant used /// in a type. From f86b46a9cc0dadaee69ca4e4a911ce122db17b24 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 8 Mar 2024 11:46:17 -0500 Subject: [PATCH 85/99] regression test from 121610. --- ...pat-mutable-in-final-value-issue-121610.rs | 18 +++++++++++++++ ...mutable-in-final-value-issue-121610.stderr | 23 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs create mode 100644 tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr diff --git a/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs new file mode 100644 index 000000000000..ca119f831b14 --- /dev/null +++ b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs @@ -0,0 +1,18 @@ +//@ check-pass +use std::cell::Cell; + +pub enum JsValue { + Undefined, + Object(Cell), +} + +impl ::std::ops::Drop for JsValue { + fn drop(&mut self) {} +} + +const UNDEFINED: &JsValue = &JsValue::Undefined; + //~^ WARN encountered mutable pointer in final value of constant + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +fn main() { +} diff --git a/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr new file mode 100644 index 000000000000..85de4e7ff32e --- /dev/null +++ b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr @@ -0,0 +1,23 @@ +warning: encountered mutable pointer in final value of constant + --> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1 + | +LL | const UNDEFINED: &JsValue = &JsValue::Undefined; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: encountered mutable pointer in final value of constant + --> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1 + | +LL | const UNDEFINED: &JsValue = &JsValue::Undefined; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default + From 1c3424bfc1354db47fd3901cb1b76c22fbe33392 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 8 Mar 2024 14:13:57 -0500 Subject: [PATCH 86/99] Added `deny(const_eval_mutable_ptr_in_final_value)` attribute to all tests that were expecting the hard error for it. I attempted to do this in a manner that preserved the line numbers to reduce the review effort on the resulting diff, but we still have to deal with the ramifications of how a future-incompat lint behaves compared to a hard-error (in terms of its impact on the diagnostic output). --- .../heap/alloc_intrinsic_untyped.rs | 2 + .../heap/alloc_intrinsic_untyped.stderr | 25 +- .../miri_unleashed/mutable_references.rs | 10 +- .../miri_unleashed/mutable_references.stderr | 151 ++++++++++- .../miri_unleashed/mutable_references_err.rs | 19 +- .../mutable_references_err.stderr | 256 ++++++++++++++++-- .../static-no-inner-mut.64bit.stderr | 220 +++++++++++++-- .../miri_unleashed/static-no-inner-mut.rs | 29 +- 8 files changed, 643 insertions(+), 69 deletions(-) diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs index 105e8e38d84e..b8fed212c97f 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs @@ -1,9 +1,11 @@ #![feature(core_intrinsics)] #![feature(const_heap)] #![feature(const_mut_refs)] +#![deny(const_eval_mutable_ptr_in_final_value)] use std::intrinsics; const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; //~^ error: mutable pointer in final value of constant +//~| WARNING this was previously accepted by the compiler fn main() {} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr index bd82e6781be1..bb47adacb9f9 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr @@ -1,8 +1,31 @@ error: encountered mutable pointer in final value of constant - --> $DIR/alloc_intrinsic_untyped.rs:6:1 + --> $DIR/alloc_intrinsic_untyped.rs:7:1 | LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/alloc_intrinsic_untyped.rs:4:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/alloc_intrinsic_untyped.rs:7:1 + | +LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/alloc_intrinsic_untyped.rs:4:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/miri_unleashed/mutable_references.rs b/tests/ui/consts/miri_unleashed/mutable_references.rs index ce7df4b16208..550515ff80e5 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references.rs @@ -1,19 +1,23 @@ //@ compile-flags: -Zunleash-the-miri-inside-of-you - +#![deny(const_eval_mutable_ptr_in_final_value)] use std::cell::UnsafeCell; // a test demonstrating what things we could allow with a smarter const qualification static FOO: &&mut u32 = &&mut 42; //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value static BAR: &mut () = &mut (); //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler struct Foo(T); static BOO: &mut Foo<()> = &mut Foo(()); //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler struct Meh { x: &'static UnsafeCell, @@ -21,9 +25,13 @@ struct Meh { unsafe impl Sync for Meh {} static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value static OH_YES: &mut i32 = &mut 42; //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value fn main() { unsafe { diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr index 532d7408e68f..ede2e7a724f0 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr @@ -3,33 +3,86 @@ error: encountered mutable pointer in final value of static | LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:2:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references.rs:7:1 + | +LL | static FOO: &&mut u32 = &&mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ + } error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:10:1 + --> $DIR/mutable_references.rs:12:1 | LL | static BAR: &mut () = &mut (); | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:15:1 + --> $DIR/mutable_references.rs:18:1 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:22:1 + --> $DIR/mutable_references.rs:26:1 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references.rs:26:1 + | +LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC1╼ │ ╾──────╼ + } error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:25:1 + --> $DIR/mutable_references.rs:31:1 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references.rs:31:1 + | +LL | static OH_YES: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC2╼ │ ╾──────╼ + } error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item - --> $DIR/mutable_references.rs:32:5 + --> $DIR/mutable_references.rs:40:5 | LL | *OH_YES = 99; | ^^^^^^^^^^^^ cannot assign @@ -42,26 +95,102 @@ help: skipping check that does not even have a feature gate LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:10:23 + --> $DIR/mutable_references.rs:12:23 | LL | static BAR: &mut () = &mut (); | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:15:28 + --> $DIR/mutable_references.rs:18:28 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:22:28 + --> $DIR/mutable_references.rs:26:28 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:25:27 + --> $DIR/mutable_references.rs:31:27 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 9 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0080, E0594. +For more information about an error, try `rustc --explain E0080`. +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:7:1 + | +LL | static FOO: &&mut u32 = &&mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:2:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:12:1 + | +LL | static BAR: &mut () = &mut (); + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:2:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:18:1 + | +LL | static BOO: &mut Foo<()> = &mut Foo(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:2:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:26:1 + | +LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:2:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:31:1 + | +LL | static OH_YES: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:2:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.rs b/tests/ui/consts/miri_unleashed/mutable_references_err.rs index 3f3e5f571758..97b8a71cafa3 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.rs @@ -2,7 +2,7 @@ //@ normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" //@ normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" #![allow(invalid_reference_casting, static_mut_refs)] - +#![deny(const_eval_mutable_ptr_in_final_value)] use std::cell::UnsafeCell; use std::sync::atomic::*; @@ -17,6 +17,8 @@ unsafe impl Sync for Meh {} // all allocs interned here will be marked immutable. const MUH: Meh = Meh { //~^ ERROR encountered mutable pointer in final value of constant + //~| WARNING this was previously accepted by the compiler + //~| ERROR: it is undefined behavior to use this value x: &UnsafeCell::new(42), }; @@ -28,14 +30,19 @@ unsafe impl Sync for Synced {} // Make sure we also catch this behind a type-erased `dyn Trait` reference. const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value // Make sure we also catch mutable references in values that shouldn't have them. static mut FOO: i32 = 0; const SUBTLE: &mut i32 = unsafe { &mut FOO }; //~^ ERROR: it is undefined behavior to use this value //~| static + const BLUNT: &mut i32 = &mut 42; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value // Check for mutable references to read-only memory. static READONLY: i32 = 0; @@ -56,10 +63,15 @@ const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler struct SyncPtr { x: *const T, @@ -72,10 +84,15 @@ unsafe impl Sync for SyncPtr {} // (Also see `static-no-inner-mut` for similar tests on `static`.) const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler fn main() { unsafe { diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.stderr index c86e2ea081ff..45615f523a6f 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.stderr @@ -3,15 +3,48 @@ error: encountered mutable pointer in final value of constant | LL | const MUH: Meh = Meh { | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:18:1 + | +LL | const MUH: Meh = Meh { + | ^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:29:1 + --> $DIR/mutable_references_err.rs:31:1 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references_err.rs:34:1 + --> $DIR/mutable_references_err.rs:31:1 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ...x: encountered `UnsafeCell` in read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:38:1 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` @@ -22,14 +55,28 @@ LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; } error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:37:1 + --> $DIR/mutable_references_err.rs:42:1 | LL | const BLUNT: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:42:1 | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:49:1 + | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | @@ -39,7 +86,7 @@ LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references_err.rs:49:1 + --> $DIR/mutable_references_err.rs:56:1 | LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` @@ -50,131 +97,284 @@ LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; } note: erroneous constant encountered - --> $DIR/mutable_references_err.rs:51:34 + --> $DIR/mutable_references_err.rs:58:34 | LL | const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1; | ^^^^^^^^^^^^^^^^^^ error[E0080]: evaluation of constant value failed - --> $DIR/mutable_references_err.rs:53:43 + --> $DIR/mutable_references_err.rs:60:43 | LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; | ^^^^^^^^^^^^^ constant accesses mutable global memory error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:57:1 + --> $DIR/mutable_references_err.rs:64:1 | LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:59:1 + --> $DIR/mutable_references_err.rs:68:1 | LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:61:1 + --> $DIR/mutable_references_err.rs:72:1 | LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:73:1 + --> $DIR/mutable_references_err.rs:85:1 | LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:75:1 + --> $DIR/mutable_references_err.rs:89:1 | LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:77:1 + --> $DIR/mutable_references_err.rs:93:1 | LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:20:8 + --> $DIR/mutable_references_err.rs:22:8 | LL | x: &UnsafeCell::new(42), | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:29:27 + --> $DIR/mutable_references_err.rs:31:27 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:34:40 + --> $DIR/mutable_references_err.rs:38:40 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references_err.rs:34:35 + --> $DIR/mutable_references_err.rs:38:35 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:37:25 + --> $DIR/mutable_references_err.rs:42:25 | LL | const BLUNT: &mut i32 = &mut 42; | ^^^^^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references_err.rs:42:49 + --> $DIR/mutable_references_err.rs:49:49 | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references_err.rs:42:49 + --> $DIR/mutable_references_err.rs:49:49 | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:49:44 + --> $DIR/mutable_references_err.rs:56:44 | LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; | ^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:53:45 + --> $DIR/mutable_references_err.rs:60:45 | LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; | ^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:57:45 + --> $DIR/mutable_references_err.rs:64:45 | LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:59:46 + --> $DIR/mutable_references_err.rs:68:46 | LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:61:47 + --> $DIR/mutable_references_err.rs:72:47 | LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:73:51 + --> $DIR/mutable_references_err.rs:85:51 | LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:75:49 + --> $DIR/mutable_references_err.rs:89:49 | LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:77:51 + --> $DIR/mutable_references_err.rs:93:51 | LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 13 previous errors; 1 warning emitted +error: aborting due to 16 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0080`. +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:18:1 + | +LL | const MUH: Meh = Meh { + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:31:1 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:42:1 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:64:1 + | +LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:68:1 + | +LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:72:1 + | +LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:85:1 + | +LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:89:1 + | +LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:93:1 + | +LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr index e8ed6742fab3..e6e81ce648d6 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr @@ -3,42 +3,112 @@ error: encountered mutable pointer in final value of static | LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^^^^ - -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:10:1 | -LL | static REFMUT: &mut i32 = &mut 0; - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:13:1 + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 | -LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:9:1 + | +LL | static REF: &AtomicI32 = &AtomicI32::new(42); + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..v: encountered `UnsafeCell` in read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ + } error: encountered mutable pointer in final value of static --> $DIR/static-no-inner-mut.rs:14:1 | -LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:14:1 + | +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC1╼ │ ╾──────╼ + } error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:29:1 + --> $DIR/static-no-inner-mut.rs:20:1 + | +LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:20:1 + | +LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..v: encountered `UnsafeCell` in read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC2╼ │ ╾──────╼ + } + +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:25:1 + | +LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:25:1 + | +LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC3╼ │ ╾──────╼ + } + +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:43:1 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:31:1 + --> $DIR/static-no-inner-mut.rs:47:1 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:33:1 + --> $DIR/static-no-inner-mut.rs:51:1 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 warning: skipping const checks | @@ -48,35 +118,141 @@ help: skipping check that does not even have a feature gate LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:10:27 + --> $DIR/static-no-inner-mut.rs:14:27 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:13:56 + --> $DIR/static-no-inner-mut.rs:20:56 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:14:44 + --> $DIR/static-no-inner-mut.rs:25:44 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:29:52 + --> $DIR/static-no-inner-mut.rs:43:52 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:31:51 + --> $DIR/static-no-inner-mut.rs:47:51 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:33:52 + --> $DIR/static-no-inner-mut.rs:51:52 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 11 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:9:1 + | +LL | static REF: &AtomicI32 = &AtomicI32::new(42); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:14:1 + | +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:20:1 + | +LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:25:1 + | +LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:43:1 + | +LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:47:1 + | +LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:51:1 + | +LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs index 4219f6fa683b..c423bf73a9b6 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs @@ -3,15 +3,29 @@ #![feature(const_refs_to_cell, const_mut_refs)] // All "inner" allocations that come with a `static` are interned immutably. This means it is // crucial that we do not accept any form of (interior) mutability there. - +#![deny(const_eval_mutable_ptr_in_final_value)] use std::sync::atomic::*; -static REF: &AtomicI32 = &AtomicI32::new(42); //~ERROR mutable pointer in final value -static REFMUT: &mut i32 = &mut 0; //~ERROR mutable pointer in final value +static REF: &AtomicI32 = &AtomicI32::new(42); +//~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value + +static REFMUT: &mut i32 = &mut 0; +//~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value // Different way of writing this that avoids promotion. -static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; //~ERROR mutable pointer in final value -static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; //~ERROR mutable pointer in final value +static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; +//~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value + +static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; +//~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value // This one is obvious, since it is non-Sync. (It also suppresses the other errors, so it is // commented out.) @@ -28,9 +42,14 @@ unsafe impl Sync for SyncPtr {} // non-dangling raw pointers. static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler fn main() {} From 6ca46daded8320dffe437b9008c2b353563af0a5 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 11 Mar 2024 11:16:23 -0400 Subject: [PATCH 87/99] Added an "Explanation" header and expanded that section for the newly added lint. --- compiler/rustc_lint_defs/src/builtin.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 3dfc2d026bdb..7ab610ab970b 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2819,10 +2819,18 @@ declare_lint! { /// } /// ``` /// + /// ### Explanation + /// + /// In the 1.77 release, the const evaluation machinery adopted some + /// stricter rules to reject expressions with values that could + /// end up holding mutable references to state stored in static memory + /// (which is inherently immutable). + /// /// This is a [future-incompatible] lint to ease the transition to an error. /// See [issue #122153] for more details. /// /// [issue #122153]: https://github.com/rust-lang/rust/issues/122153 + /// [future-incompatible]: ../index.md#future-incompatible-lints pub CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, Warn, "detects a mutable pointer that has leaked into final value of a const expression", From 354c41eeb6ecf5f2b95954381283a4df65a4ce3a Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 11 Mar 2024 11:16:43 -0400 Subject: [PATCH 88/99] Updated the test to include more output normalization. --- .../miri_unleashed/mutable_references.rs | 3 + .../miri_unleashed/mutable_references.stderr | 62 +++++++++---------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/tests/ui/consts/miri_unleashed/mutable_references.rs b/tests/ui/consts/miri_unleashed/mutable_references.rs index 550515ff80e5..b44443672c4d 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references.rs @@ -1,4 +1,7 @@ //@ compile-flags: -Zunleash-the-miri-inside-of-you +//@ normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +//@ normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" + #![deny(const_eval_mutable_ptr_in_final_value)] use std::cell::UnsafeCell; diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr index ede2e7a724f0..47a6b9c2274f 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr @@ -1,5 +1,5 @@ error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:7:1 + --> $DIR/mutable_references.rs:10:1 | LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,24 +7,24 @@ LL | static FOO: &&mut u32 = &&mut 42; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #122153 note: the lint level is defined here - --> $DIR/mutable_references.rs:2:9 + --> $DIR/mutable_references.rs:5:9 | LL | #![deny(const_eval_mutable_ptr_in_final_value)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:7:1 + --> $DIR/mutable_references.rs:10:1 | LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered mutable reference or box pointing to read-only memory | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP } error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:12:1 + --> $DIR/mutable_references.rs:15:1 | LL | static BAR: &mut () = &mut (); | ^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | static BAR: &mut () = &mut (); = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:18:1 + --> $DIR/mutable_references.rs:21:1 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | static BOO: &mut Foo<()> = &mut Foo(()); = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:26:1 + --> $DIR/mutable_references.rs:29:1 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^ @@ -51,18 +51,18 @@ LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; = note: for more information, see issue #122153 error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:26:1 + --> $DIR/mutable_references.rs:29:1 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in read-only memory | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC1╼ │ ╾──────╼ + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP } error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:31:1 + --> $DIR/mutable_references.rs:34:1 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,18 +71,18 @@ LL | static OH_YES: &mut i32 = &mut 42; = note: for more information, see issue #122153 error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:31:1 + --> $DIR/mutable_references.rs:34:1 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC2╼ │ ╾──────╼ + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP } error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item - --> $DIR/mutable_references.rs:40:5 + --> $DIR/mutable_references.rs:43:5 | LL | *OH_YES = 99; | ^^^^^^^^^^^^ cannot assign @@ -90,27 +90,27 @@ LL | *OH_YES = 99; warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:7:26 + --> $DIR/mutable_references.rs:10:26 | LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:12:23 + --> $DIR/mutable_references.rs:15:23 | LL | static BAR: &mut () = &mut (); | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:18:28 + --> $DIR/mutable_references.rs:21:28 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:26:28 + --> $DIR/mutable_references.rs:29:28 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:31:27 + --> $DIR/mutable_references.rs:34:27 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^ @@ -121,7 +121,7 @@ Some errors have detailed explanations: E0080, E0594. For more information about an error, try `rustc --explain E0080`. Future incompatibility report: Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:7:1 + --> $DIR/mutable_references.rs:10:1 | LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^^^^^^^^^^^^^^^ @@ -129,14 +129,14 @@ LL | static FOO: &&mut u32 = &&mut 42; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #122153 note: the lint level is defined here - --> $DIR/mutable_references.rs:2:9 + --> $DIR/mutable_references.rs:5:9 | LL | #![deny(const_eval_mutable_ptr_in_final_value)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:12:1 + --> $DIR/mutable_references.rs:15:1 | LL | static BAR: &mut () = &mut (); | ^^^^^^^^^^^^^^^^^^^ @@ -144,14 +144,14 @@ LL | static BAR: &mut () = &mut (); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #122153 note: the lint level is defined here - --> $DIR/mutable_references.rs:2:9 + --> $DIR/mutable_references.rs:5:9 | LL | #![deny(const_eval_mutable_ptr_in_final_value)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:18:1 + --> $DIR/mutable_references.rs:21:1 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -159,14 +159,14 @@ LL | static BOO: &mut Foo<()> = &mut Foo(()); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #122153 note: the lint level is defined here - --> $DIR/mutable_references.rs:2:9 + --> $DIR/mutable_references.rs:5:9 | LL | #![deny(const_eval_mutable_ptr_in_final_value)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:26:1 + --> $DIR/mutable_references.rs:29:1 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^ @@ -174,14 +174,14 @@ LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #122153 note: the lint level is defined here - --> $DIR/mutable_references.rs:2:9 + --> $DIR/mutable_references.rs:5:9 | LL | #![deny(const_eval_mutable_ptr_in_final_value)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:31:1 + --> $DIR/mutable_references.rs:34:1 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | static OH_YES: &mut i32 = &mut 42; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #122153 note: the lint level is defined here - --> $DIR/mutable_references.rs:2:9 + --> $DIR/mutable_references.rs:5:9 | LL | #![deny(const_eval_mutable_ptr_in_final_value)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From ae374cf04a30eac81de24c4fbdfb4d1c7f4f34e4 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 11 Mar 2024 15:33:17 -0500 Subject: [PATCH 89/99] Add produces as tidy requires --- compiler/rustc_lint_defs/src/builtin.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 7ab610ab970b..20e492dbd8a7 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2819,6 +2819,8 @@ declare_lint! { /// } /// ``` /// + /// {{produces}} + /// /// ### Explanation /// /// In the 1.77 release, the const evaluation machinery adopted some From 1ea091a7fc5ed30ca712cd1d05d8ab4838e2a1a2 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 13 Mar 2024 10:50:17 -0400 Subject: [PATCH 90/99] Rebase. Update expected output to match current output. --- .../miri_unleashed/mutable_references.rs | 2 - .../miri_unleashed/mutable_references.stderr | 52 ++++------- .../static-no-inner-mut.64bit.stderr | 88 +++++++------------ .../miri_unleashed/static-no-inner-mut.rs | 2 - tests/ui/consts/refs-to-cell-in-final.rs | 3 +- tests/ui/consts/refs-to-cell-in-final.stderr | 19 +++- 6 files changed, 67 insertions(+), 99 deletions(-) diff --git a/tests/ui/consts/miri_unleashed/mutable_references.rs b/tests/ui/consts/miri_unleashed/mutable_references.rs index b44443672c4d..8878e8eccf12 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references.rs @@ -10,7 +10,6 @@ use std::cell::UnsafeCell; static FOO: &&mut u32 = &&mut 42; //~^ ERROR encountered mutable pointer in final value of static //~| WARNING this was previously accepted by the compiler -//~| ERROR it is undefined behavior to use this value static BAR: &mut () = &mut (); //~^ ERROR encountered mutable pointer in final value of static @@ -29,7 +28,6 @@ unsafe impl Sync for Meh {} static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; //~^ ERROR encountered mutable pointer in final value of static //~| WARNING this was previously accepted by the compiler -//~| ERROR it is undefined behavior to use this value static OH_YES: &mut i32 = &mut 42; //~^ ERROR encountered mutable pointer in final value of static diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr index 47a6b9c2274f..7122eb609f15 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr @@ -12,19 +12,8 @@ note: the lint level is defined here LL | #![deny(const_eval_mutable_ptr_in_final_value)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:10:1 - | -LL | static FOO: &&mut u32 = &&mut 42; - | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered mutable reference or box pointing to read-only memory - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } - error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:15:1 + --> $DIR/mutable_references.rs:14:1 | LL | static BAR: &mut () = &mut (); | ^^^^^^^^^^^^^^^^^^^ @@ -33,7 +22,7 @@ LL | static BAR: &mut () = &mut (); = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:21:1 + --> $DIR/mutable_references.rs:20:1 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +31,7 @@ LL | static BOO: &mut Foo<()> = &mut Foo(()); = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:29:1 + --> $DIR/mutable_references.rs:28:1 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^ @@ -50,19 +39,8 @@ LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #122153 -error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:29:1 - | -LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; - | ^^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in read-only memory - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } - error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:34:1 + --> $DIR/mutable_references.rs:32:1 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +49,7 @@ LL | static OH_YES: &mut i32 = &mut 42; = note: for more information, see issue #122153 error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:34:1 + --> $DIR/mutable_references.rs:32:1 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory @@ -82,7 +60,7 @@ LL | static OH_YES: &mut i32 = &mut 42; } error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item - --> $DIR/mutable_references.rs:43:5 + --> $DIR/mutable_references.rs:41:5 | LL | *OH_YES = 99; | ^^^^^^^^^^^^ cannot assign @@ -95,27 +73,27 @@ help: skipping check that does not even have a feature gate LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:15:23 + --> $DIR/mutable_references.rs:14:23 | LL | static BAR: &mut () = &mut (); | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:21:28 + --> $DIR/mutable_references.rs:20:28 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:29:28 + --> $DIR/mutable_references.rs:28:28 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:34:27 + --> $DIR/mutable_references.rs:32:27 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^ -error: aborting due to 9 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted Some errors have detailed explanations: E0080, E0594. For more information about an error, try `rustc --explain E0080`. @@ -136,7 +114,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:15:1 + --> $DIR/mutable_references.rs:14:1 | LL | static BAR: &mut () = &mut (); | ^^^^^^^^^^^^^^^^^^^ @@ -151,7 +129,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:21:1 + --> $DIR/mutable_references.rs:20:1 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -166,7 +144,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:29:1 + --> $DIR/mutable_references.rs:28:1 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^ @@ -181,7 +159,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:34:1 + --> $DIR/mutable_references.rs:32:1 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr index e6e81ce648d6..5aa1cd0b15fc 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr @@ -12,11 +12,20 @@ note: the lint level is defined here LL | #![deny(const_eval_mutable_ptr_in_final_value)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:9:1 +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:13:1 | -LL | static REF: &AtomicI32 = &AtomicI32::new(42); - | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..v: encountered `UnsafeCell` in read-only memory +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:13:1 + | +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -24,27 +33,7 @@ LL | static REF: &AtomicI32 = &AtomicI32::new(42); } error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:14:1 - | -LL | static REFMUT: &mut i32 = &mut 0; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 - -error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:14:1 - | -LL | static REFMUT: &mut i32 = &mut 0; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC1╼ │ ╾──────╼ - } - -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:20:1 + --> $DIR/static-no-inner-mut.rs:19:1 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,19 +41,8 @@ LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #122153 -error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:20:1 - | -LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..v: encountered `UnsafeCell` in read-only memory - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC2╼ │ ╾──────╼ - } - error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:25:1 + --> $DIR/static-no-inner-mut.rs:23:1 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,18 +51,18 @@ LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; = note: for more information, see issue #122153 error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:25:1 + --> $DIR/static-no-inner-mut.rs:23:1 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC3╼ │ ╾──────╼ + ╾ALLOC1╼ │ ╾──────╼ } error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:43:1 + --> $DIR/static-no-inner-mut.rs:41:1 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -93,7 +71,7 @@ LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:47:1 + --> $DIR/static-no-inner-mut.rs:45:1 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -102,7 +80,7 @@ LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *con = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:51:1 + --> $DIR/static-no-inner-mut.rs:49:1 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,37 +96,37 @@ help: skipping check that does not even have a feature gate LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:14:27 + --> $DIR/static-no-inner-mut.rs:13:27 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:20:56 + --> $DIR/static-no-inner-mut.rs:19:56 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:25:44 + --> $DIR/static-no-inner-mut.rs:23:44 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:43:52 + --> $DIR/static-no-inner-mut.rs:41:52 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:47:51 + --> $DIR/static-no-inner-mut.rs:45:51 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:51:52 + --> $DIR/static-no-inner-mut.rs:49:52 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 11 previous errors; 1 warning emitted +error: aborting due to 9 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0080`. Future incompatibility report: Future breakage diagnostic: @@ -168,7 +146,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:14:1 + --> $DIR/static-no-inner-mut.rs:13:1 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -183,7 +161,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:20:1 + --> $DIR/static-no-inner-mut.rs:19:1 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -198,7 +176,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:25:1 + --> $DIR/static-no-inner-mut.rs:23:1 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -213,7 +191,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:43:1 + --> $DIR/static-no-inner-mut.rs:41:1 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -228,7 +206,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:47:1 + --> $DIR/static-no-inner-mut.rs:45:1 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -243,7 +221,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)] Future breakage diagnostic: error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:51:1 + --> $DIR/static-no-inner-mut.rs:49:1 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs index c423bf73a9b6..e82ca50d8822 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs @@ -9,7 +9,6 @@ use std::sync::atomic::*; static REF: &AtomicI32 = &AtomicI32::new(42); //~^ ERROR mutable pointer in final value //~| WARNING this was previously accepted by the compiler -//~| ERROR it is undefined behavior to use this value static REFMUT: &mut i32 = &mut 0; //~^ ERROR mutable pointer in final value @@ -20,7 +19,6 @@ static REFMUT: &mut i32 = &mut 0; static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; //~^ ERROR mutable pointer in final value //~| WARNING this was previously accepted by the compiler -//~| ERROR it is undefined behavior to use this value static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; //~^ ERROR mutable pointer in final value diff --git a/tests/ui/consts/refs-to-cell-in-final.rs b/tests/ui/consts/refs-to-cell-in-final.rs index ada56a82a5d1..c7ccd25fc4cb 100644 --- a/tests/ui/consts/refs-to-cell-in-final.rs +++ b/tests/ui/consts/refs-to-cell-in-final.rs @@ -28,7 +28,8 @@ impl Drop for JsValue { fn drop(&mut self) {} } const UNDEFINED: &JsValue = &JsValue::Undefined; -//~^ERROR: mutable pointer in final value of constant +//~^ WARNING: mutable pointer in final value of constant +//~| WARNING: this was previously accepted by the compiler but is being phased out // In contrast, this one works since it is being promoted. const NONE: &'static Option> = &None; diff --git a/tests/ui/consts/refs-to-cell-in-final.stderr b/tests/ui/consts/refs-to-cell-in-final.stderr index b06db3e116ce..2a7a858ebc9b 100644 --- a/tests/ui/consts/refs-to-cell-in-final.stderr +++ b/tests/ui/consts/refs-to-cell-in-final.stderr @@ -12,12 +12,27 @@ error[E0492]: constants cannot refer to interior mutable data LL | const RAW_SYNC_C: SyncPtr> = SyncPtr { x: &Cell::new(42) }; | ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value -error: encountered mutable pointer in final value of constant +warning: encountered mutable pointer in final value of constant --> $DIR/refs-to-cell-in-final.rs:30:1 | LL | const UNDEFINED: &JsValue = &JsValue::Undefined; | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0492`. +Future incompatibility report: Future breakage diagnostic: +warning: encountered mutable pointer in final value of constant + --> $DIR/refs-to-cell-in-final.rs:30:1 + | +LL | const UNDEFINED: &JsValue = &JsValue::Undefined; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default + From 9c33cc62aad65456b2f580eb788615c4d0a66304 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 13 Mar 2024 10:51:12 -0400 Subject: [PATCH 91/99] placate tidy. --- compiler/rustc_const_eval/src/interpret/intern.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 0994ace814c9..c30a13624178 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -21,9 +21,9 @@ use rustc_hir as hir; use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::TyAndLayout; +use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::sym; -use rustc_session::lint; use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy}; use crate::const_eval; From 2366d97d81d03a4b4876adfb5b0c3b94fd562918 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 13 Mar 2024 16:11:48 +0100 Subject: [PATCH 92/99] extend docs of -Zprint-mono-items --- compiler/rustc_session/src/options.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 2f018fbaa867..9c03bdb21874 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1831,7 +1831,9 @@ options! { print_llvm_passes: bool = (false, parse_bool, [UNTRACKED], "print the LLVM optimization passes being run (default: no)"), print_mono_items: Option = (None, parse_opt_string, [UNTRACKED], - "print the result of the monomorphization collection pass"), + "print the result of the monomorphization collection pass. \ + Value `lazy` means to use normal collection; `eager` means to collect all items. + Note that this overwrites the effect `-Clink-dead-code` has on collection!"), print_type_sizes: bool = (false, parse_bool, [UNTRACKED], "print layout information for each type encountered (default: no)"), print_vtable_sizes: bool = (false, parse_bool, [UNTRACKED], From 533ddf97c6f48905ebadf200a2069a8f50853e7c Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Wed, 13 Mar 2024 03:17:47 -0700 Subject: [PATCH 93/99] Add Exploit Mitigations PG to triagebot.toml Add autolabels and mentions for the Exploit Mitigations PG to triagebot.toml. --- triagebot.toml | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 98f31743d4aa..07d38921a830 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -377,6 +377,25 @@ trigger_files = [ "compiler/rustc_middle/src/traits/solve" ] +[autolabel."PG-exploit-mitigations"] +trigger_files = [ + "compiler/rustc_symbol_mangling/src/typeid", + "src/doc/rustc/src/exploit-mitigations.md", + "src/doc/unstable-book/src/compiler-flags/branch-protection.md", + "src/doc/unstable-book/src/compiler-flags/cf-protection.md", + "src/doc/unstable-book/src/compiler-flags/control-flow-guard.md", + "src/doc/unstable-book/src/compiler-flags/sanitizer.md", + "src/doc/unstable-book/src/language-features/cfg-sanitize.md", + "src/doc/unstable-book/src/language-features/cfi-encoding.md", + "src/doc/unstable-book/src/language-features/no-sanitize.md", + "tests/codegen/sanitizer", + "tests/codegen/split-lto-unit.rs", + "tests/codegen/stack-probes-inline.rs", + "tests/codegen/stack-protector.rs", + "tests/ui/sanitizer", + "tests/ui/stack-protector" +] + [notify-zulip."I-prioritize"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts topic = "#{number} {title}" @@ -642,6 +661,51 @@ cc = ["@nnethercote"] message = "Changes to the size of AST and/or HIR nodes." cc = ["@nnethercote"] +[mentions."compiler/rustc_symbol_mangling/src/typeid"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/rustc/src/exploit-mitigations.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/compiler-flags/branch-protection.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/compiler-flags/cf-protection.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/compiler-flags/control-flow-guard.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/compiler-flags/sanitizer.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/language-features/cfg-sanitize.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/language-features/cfi-encoding.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/language-features/no-sanitize.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/codegen/sanitizer"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/codegen/split-lto-unit.rs"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/codegen/stack-probes-inline.rs"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/codegen/stack-protector.rs"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/ui/sanitizer"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/ui/stack-protector"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" @@ -783,6 +847,11 @@ project-stable-mir = [ "@ouz-a", ] +project-exploit-mitigations = [ + "@cuviper", + "@rcvalle", +] + [assign.owners] "/.github/workflows" = ["infra-ci"] "/Cargo.lock" = ["@Mark-Simulacrum"] From 216df4a8e6358a515ba95fb1a92864d1b94c37f3 Mon Sep 17 00:00:00 2001 From: Jack Wrenn Date: Wed, 13 Mar 2024 00:11:36 +0000 Subject: [PATCH 94/99] safe transmute: require that src referent is smaller than dst The source referent absolutely must be smaller than the destination referent of a ref-to-ref transmute; the excess bytes referenced cannot arise from thin air, even if those bytes are uninitialized. --- .../error_reporting/type_err_ctxt_ext.rs | 7 +++ compiler/rustc_transmute/src/layout/mod.rs | 21 ++++++++ compiler/rustc_transmute/src/layout/tree.rs | 5 +- compiler/rustc_transmute/src/lib.rs | 11 ++++- .../src/maybe_transmutable/mod.rs | 5 ++ .../references/reject_extension.rs | 49 +++++++++++++++++++ .../references/reject_extension.stderr | 25 ++++++++++ .../references/unit-to-u8.stderr | 4 +- 8 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 tests/ui/transmutability/references/reject_extension.rs create mode 100644 tests/ui/transmutability/references/reject_extension.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index ad5b7debad7b..d18acb8c864b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -3091,6 +3091,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { rustc_transmute::Reason::DstIsTooBig => { format!("The size of `{src}` is smaller than the size of `{dst}`") } + rustc_transmute::Reason::DstRefIsTooBig { src, dst } => { + let src_size = src.size; + let dst_size = dst.size; + format!( + "The referent size of `{src}` ({src_size} bytes) is smaller than that of `{dst}` ({dst_size} bytes)" + ) + } rustc_transmute::Reason::SrcSizeOverflow => { format!( "values of the type `{src}` are too big for the current architecture" diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs index 0441b49cb14c..a7c60c3b4904 100644 --- a/compiler/rustc_transmute/src/layout/mod.rs +++ b/compiler/rustc_transmute/src/layout/mod.rs @@ -35,6 +35,8 @@ pub(crate) trait Def: Debug + Hash + Eq + PartialEq + Copy + Clone { pub trait Ref: Debug + Hash + Eq + PartialEq + Copy + Clone { fn min_align(&self) -> usize; + fn size(&self) -> usize; + fn is_mutable(&self) -> bool; } @@ -48,6 +50,9 @@ impl Ref for ! { fn min_align(&self) -> usize { unreachable!() } + fn size(&self) -> usize { + unreachable!() + } fn is_mutable(&self) -> bool { unreachable!() } @@ -57,6 +62,7 @@ impl Ref for ! { pub mod rustc { use rustc_middle::mir::Mutability; use rustc_middle::ty::{self, Ty}; + use std::fmt::{self, Write}; /// A reference in the layout. #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone, Copy)] @@ -65,6 +71,7 @@ pub mod rustc { pub ty: Ty<'tcx>, pub mutability: Mutability, pub align: usize, + pub size: usize, } impl<'tcx> super::Ref for Ref<'tcx> { @@ -72,6 +79,10 @@ pub mod rustc { self.align } + fn size(&self) -> usize { + self.size + } + fn is_mutable(&self) -> bool { match self.mutability { Mutability::Mut => true, @@ -81,6 +92,16 @@ pub mod rustc { } impl<'tcx> Ref<'tcx> {} + impl<'tcx> fmt::Display for Ref<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_char('&')?; + if self.mutability == Mutability::Mut { + f.write_str("mut ")?; + } + self.ty.fmt(f) + } + } + /// A visibility node in the layout. #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)] pub enum Def<'tcx> { diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 71b72828e4cf..c2fc55542ffb 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -372,12 +372,15 @@ pub(crate) mod rustc { } ty::Ref(lifetime, ty, mutability) => { - let align = layout_of(tcx, *ty)?.align(); + let layout = layout_of(tcx, *ty)?; + let align = layout.align(); + let size = layout.size(); Ok(Tree::Ref(Ref { lifetime: *lifetime, ty: *ty, mutability: *mutability, align, + size, })) } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index fefce2640ebd..8f3af491453e 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -23,7 +23,7 @@ pub struct Assume { #[derive(Debug, Hash, Eq, PartialEq, Clone)] pub enum Answer { Yes, - No(Reason), + No(Reason), If(Condition), } @@ -42,7 +42,7 @@ pub enum Condition { /// Answers "why wasn't the source type transmutable into the destination type?" #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone)] -pub enum Reason { +pub enum Reason { /// The layout of the source type is unspecified. SrcIsUnspecified, /// The layout of the destination type is unspecified. @@ -53,6 +53,13 @@ pub enum Reason { DstMayHaveSafetyInvariants, /// `Dst` is larger than `Src`, and the excess bytes were not exclusively uninitialized. DstIsTooBig, + /// A referent of `Dst` is larger than a referent in `Src`. + DstRefIsTooBig { + /// The referent of the source type. + src: T, + /// The too-large referent of the destination type. + dst: T, + }, /// Src should have a stricter alignment than Dst, but it does not. DstHasStricterAlignment { src_min_align: usize, dst_min_align: usize }, /// Can't go from shared pointer to unique pointer diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 0e05aa4d3b2a..e9f425686c4c 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -266,6 +266,11 @@ where src_min_align: src_ref.min_align(), dst_min_align: dst_ref.min_align(), }) + } else if dst_ref.size() > src_ref.size() { + Answer::No(Reason::DstRefIsTooBig { + src: src_ref, + dst: dst_ref, + }) } else { // ...such that `src` is transmutable into `dst`, if // `src_ref` is transmutability into `dst_ref`. diff --git a/tests/ui/transmutability/references/reject_extension.rs b/tests/ui/transmutability/references/reject_extension.rs new file mode 100644 index 000000000000..161da5772e87 --- /dev/null +++ b/tests/ui/transmutability/references/reject_extension.rs @@ -0,0 +1,49 @@ +//@ check-fail + +//! Reject extensions behind references. + +#![crate_type = "lib"] +#![feature(transmutability)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom< + Src, + { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }, + >, + { + } +} + +#[repr(C, packed)] +struct Packed(T); + +fn reject_extension() { + #[repr(C, align(2))] + struct Two(u8); + + #[repr(C, align(4))] + struct Four(u8); + + // These two types differ in the number of trailing padding bytes they have. + type Src = Packed; + type Dst = Packed; + + const _: () = { + use std::mem::size_of; + assert!(size_of::() == 2); + assert!(size_of::() == 4); + }; + + assert::is_transmutable::<&Src, &Dst>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/references/reject_extension.stderr b/tests/ui/transmutability/references/reject_extension.stderr new file mode 100644 index 000000000000..e02ef89c4a03 --- /dev/null +++ b/tests/ui/transmutability/references/reject_extension.stderr @@ -0,0 +1,25 @@ +error[E0277]: `&Packed` cannot be safely transmuted into `&Packed` + --> $DIR/reject_extension.rs:48:37 + | +LL | assert::is_transmutable::<&Src, &Dst>(); + | ^^^^ The referent size of `&Packed` (2 bytes) is smaller than that of `&Packed` (4 bytes) + | +note: required by a bound in `is_transmutable` + --> $DIR/reject_extension.rs:13:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this function +LL | where +LL | Dst: BikeshedIntrinsicFrom< + | ______________^ +LL | | Src, +LL | | { +LL | | Assume { +... | +LL | | }, +LL | | >, + | |_________^ required by this bound in `is_transmutable` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/references/unit-to-u8.stderr b/tests/ui/transmutability/references/unit-to-u8.stderr index e2eb50442caf..7cb45e24e0a4 100644 --- a/tests/ui/transmutability/references/unit-to-u8.stderr +++ b/tests/ui/transmutability/references/unit-to-u8.stderr @@ -1,8 +1,8 @@ -error[E0277]: `Unit` cannot be safely transmuted into `u8` +error[E0277]: `&Unit` cannot be safely transmuted into `&u8` --> $DIR/unit-to-u8.rs:22:52 | LL | assert::is_maybe_transmutable::<&'static Unit, &'static u8>(); - | ^^^^^^^^^^^ The size of `Unit` is smaller than the size of `u8` + | ^^^^^^^^^^^ The referent size of `&Unit` (0 bytes) is smaller than that of `&u8` (1 bytes) | note: required by a bound in `is_maybe_transmutable` --> $DIR/unit-to-u8.rs:9:14 From 026eb3dd6457f223ff1c3a3b40bf59898a25061a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 13 Mar 2024 13:44:00 -0400 Subject: [PATCH 95/99] Delay a bug for stranded opaques --- compiler/rustc_hir_analysis/src/check/check.rs | 8 +++++++- tests/ui/impl-trait/stranded-opaque.rs | 13 +++++++++++++ tests/ui/impl-trait/stranded-opaque.stderr | 9 +++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/ui/impl-trait/stranded-opaque.rs create mode 100644 tests/ui/impl-trait/stranded-opaque.stderr diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1b8174d3d18f..d1fed13ee9fe 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -381,11 +381,17 @@ fn check_opaque_meets_bounds<'tcx>( match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) { Ok(()) => {} Err(ty_err) => { + // Some types may be left "stranded" if they can't be reached + // from an astconv'd bound but they're mentioned in the HIR. This + // will happen, e.g., when a nested opaque is inside of a non- + // existent associated type, like `impl Trait`. + // See . let ty_err = ty_err.to_string(tcx); - tcx.dcx().span_bug( + let guar = tcx.dcx().span_delayed_bug( span, format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"), ); + return Err(guar); } } diff --git a/tests/ui/impl-trait/stranded-opaque.rs b/tests/ui/impl-trait/stranded-opaque.rs new file mode 100644 index 000000000000..c7ab390e1fd0 --- /dev/null +++ b/tests/ui/impl-trait/stranded-opaque.rs @@ -0,0 +1,13 @@ +trait Trait {} + +impl Trait for i32 {} + +// Since `Assoc` doesn't actually exist, it's "stranded", and won't show up in +// the list of opaques that may be defined by the function. Make sure we don't +// ICE in this case. +fn produce() -> impl Trait { + //~^ ERROR associated type `Assoc` not found for `Trait` + 16 +} + +fn main () {} diff --git a/tests/ui/impl-trait/stranded-opaque.stderr b/tests/ui/impl-trait/stranded-opaque.stderr new file mode 100644 index 000000000000..75f5480bc8b8 --- /dev/null +++ b/tests/ui/impl-trait/stranded-opaque.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `Assoc` not found for `Trait` + --> $DIR/stranded-opaque.rs:8:31 + | +LL | fn produce() -> impl Trait { + | ^^^^^ associated type `Assoc` not found + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0220`. From 8f45a9e93d7805bbe5b4c425c774b0a414efb657 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 13 Mar 2024 14:53:04 -0400 Subject: [PATCH 96/99] include 32-bit variant for updated test of miri diagnostics. --- .../static-no-inner-mut.32bit.stderr | 188 ++++++++++++++++-- 1 file changed, 171 insertions(+), 17 deletions(-) diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr b/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr index e8ed6742fab3..85ed6cbd5383 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr @@ -3,42 +3,90 @@ error: encountered mutable pointer in final value of static | LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^^^^ - -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:10:1 | -LL | static REFMUT: &mut i32 = &mut 0; - | ^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered mutable pointer in final value of static --> $DIR/static-no-inner-mut.rs:13:1 | -LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; +LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:13:1 + | +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC0╼ │ ╾──╼ + } error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:14:1 + --> $DIR/static-no-inner-mut.rs:19:1 + | +LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:23:1 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:23:1 + | +LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC1╼ │ ╾──╼ + } error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:29:1 + --> $DIR/static-no-inner-mut.rs:41:1 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:31:1 + --> $DIR/static-no-inner-mut.rs:45:1 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:33:1 + --> $DIR/static-no-inner-mut.rs:49:1 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 warning: skipping const checks | @@ -48,35 +96,141 @@ help: skipping check that does not even have a feature gate LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:10:27 + --> $DIR/static-no-inner-mut.rs:13:27 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:13:56 + --> $DIR/static-no-inner-mut.rs:19:56 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:14:44 + --> $DIR/static-no-inner-mut.rs:23:44 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:29:52 + --> $DIR/static-no-inner-mut.rs:41:52 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:31:51 + --> $DIR/static-no-inner-mut.rs:45:51 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:33:52 + --> $DIR/static-no-inner-mut.rs:49:52 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 9 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:9:1 + | +LL | static REF: &AtomicI32 = &AtomicI32::new(42); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:13:1 + | +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:19:1 + | +LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:23:1 + | +LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:41:1 + | +LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:45:1 + | +LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:49:1 + | +LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From ca9f0630a93a12abb9a4a35f3bb1948c54515c2d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 14 Mar 2024 11:25:05 +0100 Subject: [PATCH 97/99] Rename `ast::StmtKind::Local` into `ast::StmtKind::Let` --- compiler/rustc_ast/src/ast.rs | 2 +- compiler/rustc_ast/src/ast_traits.rs | 8 ++++---- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/block.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_expand/src/build.rs | 2 +- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/unused.rs | 4 ++-- compiler/rustc_parse/src/parser/stmt.rs | 8 ++++---- compiler/rustc_passes/src/hir_stats.rs | 2 +- src/tools/clippy/clippy_utils/src/ast_utils.rs | 2 +- src/tools/rustfmt/src/attr.rs | 2 +- src/tools/rustfmt/src/spanned.rs | 2 +- src/tools/rustfmt/src/stmt.rs | 2 +- src/tools/rustfmt/src/visitor.rs | 2 +- 17 files changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index d522c285e3eb..d0e8b86b71d3 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1021,7 +1021,7 @@ impl Stmt { #[derive(Clone, Encodable, Decodable, Debug)] pub enum StmtKind { /// A local (let) binding. - Local(P), + Let(P), /// An item definition. Item(P), /// Expr without trailing semi-colon. diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 4dc9c30a2c80..a0486227f2af 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -182,7 +182,7 @@ impl HasTokens for Option { impl HasTokens for StmtKind { fn tokens(&self) -> Option<&LazyAttrTokenStream> { match self { - StmtKind::Local(local) => local.tokens.as_ref(), + StmtKind::Let(local) => local.tokens.as_ref(), StmtKind::Item(item) => item.tokens(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens(), StmtKind::Empty => return None, @@ -191,7 +191,7 @@ impl HasTokens for StmtKind { } fn tokens_mut(&mut self) -> Option<&mut Option> { match self { - StmtKind::Local(local) => Some(&mut local.tokens), + StmtKind::Let(local) => Some(&mut local.tokens), StmtKind::Item(item) => item.tokens_mut(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens_mut(), StmtKind::Empty => return None, @@ -355,7 +355,7 @@ impl HasAttrs for StmtKind { fn attrs(&self) -> &[Attribute] { match self { - StmtKind::Local(local) => &local.attrs, + StmtKind::Let(local) => &local.attrs, StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(), StmtKind::Item(item) => item.attrs(), StmtKind::Empty => &[], @@ -365,7 +365,7 @@ impl HasAttrs for StmtKind { fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { match self { - StmtKind::Local(local) => f(&mut local.attrs), + StmtKind::Let(local) => f(&mut local.attrs), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), StmtKind::Item(item) => item.visit_attrs(f), StmtKind::Empty => {} diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 9ec92c9d4edf..83468c5f1012 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1567,7 +1567,7 @@ pub fn noop_flat_map_stmt_kind( vis: &mut T, ) -> SmallVec<[StmtKind; 1]> { match kind { - StmtKind::Local(mut local) => smallvec![StmtKind::Local({ + StmtKind::Let(mut local) => smallvec![StmtKind::Let({ vis.visit_local(&mut local); local })], diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 7296e29301f3..d75ff4565e6f 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -787,7 +787,7 @@ pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::R pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { match &statement.kind { - StmtKind::Local(local) => try_visit!(visitor.visit_local(local)), + StmtKind::Let(local) => try_visit!(visitor.visit_local(local)), StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)), StmtKind::Empty => {} diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 865a56b2c1f1..5f60fbe56707 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -32,7 +32,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut expr = None; while let [s, tail @ ..] = ast_stmts { match &s.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { let hir_id = self.lower_node_id(s.id); let local = self.lower_local(local); self.alias_attrs(hir_id, local.hir_id); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e5d7b8489033..c50878e32a46 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1212,7 +1212,7 @@ impl<'a> State<'a> { fn print_stmt(&mut self, st: &ast::Stmt) { self.maybe_print_comment(st.span.lo()); match &st.kind { - ast::StmtKind::Local(loc) => { + ast::StmtKind::Let(loc) => { self.print_outer_attributes(&loc.attrs); self.space_if_not_bol(); self.ibox(INDENT_UNIT); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 989b7b485c99..e71047f94fa9 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -218,7 +218,7 @@ impl<'a> ExtCtxt<'a> { } pub fn stmt_local(&self, local: P, span: Span) -> ast::Stmt { - ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span } + ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Let(local), span } } pub fn stmt_item(&self, sp: Span, item: P) -> ast::Stmt { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 3544a8f0a8d9..cac1e8f80e32 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1389,7 +1389,7 @@ impl InvocationCollectorNode for ast::Stmt { StmtKind::Item(item) => matches!(item.kind, ItemKind::MacCall(..)), StmtKind::Semi(expr) => matches!(expr.kind, ExprKind::MacCall(..)), StmtKind::Expr(..) => unreachable!(), - StmtKind::Local(..) | StmtKind::Empty => false, + StmtKind::Let(..) | StmtKind::Empty => false, } } fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 595dc08b081e..d1343e3b4bae 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -989,7 +989,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & impl EarlyLintPass for UnusedDocComment { fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) { let kind = match stmt.kind { - ast::StmtKind::Local(..) => "statements", + ast::StmtKind::Let(..) => "statements", // Disabled pending discussion in #78306 ast::StmtKind::Item(..) => return, // expressions will be reported by `check_expr`. diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index f84d1c6c2d0a..3e10879e2411 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -914,7 +914,7 @@ trait UnusedDelimLint { fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { match s.kind { - StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => { + StmtKind::Let(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => { if let Some((init, els)) = local.kind.init_else_opt() { let ctx = match els { None => UnusedDelimsCtx::AssignedValue, @@ -1189,7 +1189,7 @@ impl EarlyLintPass for UnusedParens { } fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { - if let StmtKind::Local(ref local) = s.kind { + if let StmtKind::Let(ref local) = s.kind { self.check_unused_parens_pat(cx, &local.pat, true, false, (true, false)); } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 73f5829adec6..fc907760531f 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -254,7 +254,7 @@ impl<'a> Parser<'a> { let local = this.parse_local(attrs)?; // FIXME - maybe capture semicolon in recovery? Ok(( - this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), TrailingToken::None, )) })?; @@ -278,7 +278,7 @@ impl<'a> Parser<'a> { } else { TrailingToken::None }; - Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), trailing)) + Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) }) } @@ -764,7 +764,7 @@ impl<'a> Parser<'a> { } } StmtKind::Expr(_) | StmtKind::MacCall(_) => {} - StmtKind::Local(local) if let Err(mut e) = self.expect_semi() => { + StmtKind::Let(local) if let Err(mut e) = self.expect_semi() => { // We might be at the `,` in `let x = foo;`. Try to recover. match &mut local.kind { LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => { @@ -820,7 +820,7 @@ impl<'a> Parser<'a> { } eat_semi = false; } - StmtKind::Empty | StmtKind::Item(_) | StmtKind::Local(_) | StmtKind::Semi(_) => { + StmtKind::Empty | StmtKind::Item(_) | StmtKind::Let(_) | StmtKind::Semi(_) => { eat_semi = false } } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index be6ba585d200..61dd02ae7dc8 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -539,7 +539,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_stmt(&mut self, s: &'v ast::Stmt) { record_variants!( (self, s, s.kind, Id::None, ast, Stmt, StmtKind), - [Local, Item, Expr, Semi, Empty, MacCall] + [Let, Item, Expr, Semi, Empty, MacCall] ); ast_visit::walk_stmt(self, s) } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 3b3939da7b6b..3874c1169e48 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -267,7 +267,7 @@ pub fn eq_block(l: &Block, r: &Block) -> bool { pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool { use StmtKind::*; match (&l.kind, &r.kind) { - (Local(l), Local(r)) => { + (Let(l), Let(r)) => { eq_pat(&l.pat, &r.pat) && both(&l.ty, &r.ty, |l, r| eq_ty(l, r)) && eq_local_kind(&l.kind, &r.kind) diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 4d83547d664e..83f59837d442 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -26,7 +26,7 @@ pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { match stmt.kind { - ast::StmtKind::Local(ref local) => local.span, + ast::StmtKind::Let(ref local) => local.span, ast::StmtKind::Item(ref item) => item.span, ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span, ast::StmtKind::MacCall(ref mac_stmt) => mac_stmt.mac.span(), diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 5960b1444994..4aaf7fdb27fb 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -61,7 +61,7 @@ implement_spanned!(ast::Local); impl Spanned for ast::Stmt { fn span(&self) -> Span { match self.kind { - ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), + ast::StmtKind::Let(ref local) => mk_sp(local.span().lo(), self.span.hi()), ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { mk_sp(expr.span().lo(), self.span.hi()) diff --git a/src/tools/rustfmt/src/stmt.rs b/src/tools/rustfmt/src/stmt.rs index e3fe4ebca11f..73a9cce416c1 100644 --- a/src/tools/rustfmt/src/stmt.rs +++ b/src/tools/rustfmt/src/stmt.rs @@ -115,7 +115,7 @@ fn format_stmt( skip_out_of_file_lines_range!(context, stmt.span()); let result = match stmt.kind { - ast::StmtKind::Local(ref local) => local.rewrite(context, shape), + ast::StmtKind::Let(ref local) => local.rewrite(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(context, stmt, is_last_expr) { ";" diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 47f772b485da..6209b37004bf 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -150,7 +150,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_item(item); self.last_pos = stmt.span().hi(); } - ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { + ast::StmtKind::Let(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let attrs = get_attrs_from_stmt(stmt.as_ast_node()); if contains_skip(attrs) { self.push_skipped_with_span( From a4e0e50a3fb8d8658729f2860be54871597078da Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 14 Mar 2024 11:53:38 +0100 Subject: [PATCH 98/99] Rename `hir::StmtKind::Local` into `hir::StmtKind::Let` --- compiler/rustc_ast_lowering/src/block.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 2 +- .../rustc_borrowck/src/diagnostics/conflict_errors.rs | 2 +- .../rustc_borrowck/src/diagnostics/mutability_errors.rs | 4 ++-- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir_analysis/src/check/errs.rs | 2 +- compiler/rustc_hir_analysis/src/check/region.rs | 4 ++-- compiler/rustc_hir_pretty/src/lib.rs | 4 ++-- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 4 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 6 +++--- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_hir_typeck/src/upvar.rs | 2 +- compiler/rustc_infer/src/infer/error_reporting/mod.rs | 2 +- compiler/rustc_infer/src/infer/error_reporting/suggest.rs | 4 ++-- compiler/rustc_middle/src/hir/map/mod.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/block.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_passes/src/hir_stats.rs | 2 +- compiler/rustc_passes/src/liveness.rs | 2 +- compiler/rustc_passes/src/naked_functions.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 2 +- src/tools/clippy/clippy_lints/src/attrs/utils.rs | 2 +- src/tools/clippy/clippy_lints/src/copies.rs | 8 ++++---- src/tools/clippy/clippy_lints/src/default.rs | 2 +- .../clippy/clippy_lints/src/default_numeric_fallback.rs | 2 +- src/tools/clippy/clippy_lints/src/entry.rs | 2 +- src/tools/clippy/clippy_lints/src/explicit_write.rs | 2 +- src/tools/clippy/clippy_lints/src/let_if_seq.rs | 2 +- src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs | 2 +- .../clippy_lints/src/loops/manual_while_let_some.rs | 2 +- src/tools/clippy/clippy_lints/src/loops/never_loop.rs | 2 +- src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs | 2 +- src/tools/clippy/clippy_lints/src/manual_let_else.rs | 2 +- src/tools/clippy/clippy_lints/src/map_unit_fn.rs | 2 +- .../clippy/clippy_lints/src/methods/needless_collect.rs | 2 +- src/tools/clippy/clippy_lints/src/methods/str_splitn.rs | 2 +- .../src/methods/unnecessary_result_map_or_else.rs | 2 +- src/tools/clippy/clippy_lints/src/misc.rs | 2 +- .../clippy_lints/src/mixed_read_write_in_expression.rs | 4 ++-- src/tools/clippy/clippy_lints/src/needless_late_init.rs | 2 +- src/tools/clippy/clippy_lints/src/no_effect.rs | 2 +- .../clippy/clippy_lints/src/pattern_type_mismatch.rs | 2 +- src/tools/clippy/clippy_lints/src/question_mark.rs | 2 +- src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs | 2 +- .../clippy/clippy_lints/src/redundant_closure_call.rs | 2 +- src/tools/clippy/clippy_lints/src/returns.rs | 2 +- .../clippy_lints/src/significant_drop_tightening.rs | 6 +++--- .../clippy/clippy_lints/src/slow_vector_initialization.rs | 2 +- src/tools/clippy/clippy_lints/src/swap.rs | 4 ++-- .../clippy/clippy_lints/src/undocumented_unsafe_blocks.rs | 4 ++-- src/tools/clippy/clippy_lints/src/uninit_vec.rs | 2 +- src/tools/clippy/clippy_lints/src/unused_io_amount.rs | 4 ++-- src/tools/clippy/clippy_lints/src/unused_peekable.rs | 4 ++-- src/tools/clippy/clippy_lints/src/utils/author.rs | 2 +- src/tools/clippy/clippy_utils/src/hir_utils.rs | 4 ++-- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- 58 files changed, 76 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 5f60fbe56707..11a66fe87c9a 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -36,7 +36,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let hir_id = self.lower_node_id(s.id); let local = self.lower_local(local); self.alias_attrs(hir_id, local.hir_id); - let kind = hir::StmtKind::Local(local); + let kind = hir::StmtKind::Let(local); let span = self.lower_span(s.span); stmts.push(hir::Stmt { hir_id, kind, span }); } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 94e1e06a9545..e8ff64a7fd2c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2356,7 +2356,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: self.lower_span(span), ty: None, }; - self.stmt(span, hir::StmtKind::Local(self.arena.alloc(local))) + self.stmt(span, hir::StmtKind::Let(self.arena.alloc(local))) } fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> &'hir hir::Block<'hir> { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 0776f455efd9..5af70937f622 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -616,7 +616,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // FIXME: We make sure that this is a normal top-level binding, // but we could suggest `todo!()` for all uninitalized bindings in the pattern pattern - if let hir::StmtKind::Local(hir::Local { span, ty, init: None, pat, .. }) = + if let hir::StmtKind::Let(hir::Local { span, ty, init: None, pat, .. }) = &ex.kind && let hir::PatKind::Binding(..) = pat.kind && span.contains(self.decl_span) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index ebc9f1d109ee..ee2e3d20fe56 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -558,7 +558,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { hir::intravisit::walk_stmt(self, stmt); let expr = match stmt.kind { hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr) => expr, - hir::StmtKind::Local(hir::Local { init: Some(expr), .. }) => expr, + hir::StmtKind::Let(hir::Local { init: Some(expr), .. }) => expr, _ => { return; } @@ -1305,7 +1305,7 @@ struct BindingFinder { impl<'tcx> Visitor<'tcx> for BindingFinder { type Result = ControlFlow; fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result { - if let hir::StmtKind::Local(local) = s.kind + if let hir::StmtKind::Let(local) = s.kind && local.pat.span == self.span { ControlFlow::Break(local.hir_id) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 866b265c647a..7006c90e17b7 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1209,7 +1209,7 @@ pub struct Stmt<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum StmtKind<'hir> { /// A local (`let`) binding. - Local(&'hir Local<'hir>), + Let(&'hir Local<'hir>), /// An item binding. Item(ItemId), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 32b4bf38fa96..fbbad38d17f1 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -627,7 +627,7 @@ pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) -> pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) -> V::Result { try_visit!(visitor.visit_id(statement.hir_id)); match statement.kind { - StmtKind::Local(ref local) => visitor.visit_local(local), + StmtKind::Let(ref local) => visitor.visit_local(local), StmtKind::Item(item) => visitor.visit_nested_item(item), StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => { visitor.visit_expr(expression) diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index b9dc5cbc4d20..f0c15a070b48 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -27,7 +27,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { /// Check for shared or mutable references of `static mut` inside statement pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { - if let hir::StmtKind::Local(loc) = stmt.kind + if let hir::StmtKind::Let(loc) = stmt.kind && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind && matches!(ba.0, rustc_ast::ByRef::Yes) && let Some(init) = loc.init diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 2a4dd6b0e0ef..3c26729eff8a 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -123,7 +123,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h for (i, statement) in blk.stmts.iter().enumerate() { match statement.kind { - hir::StmtKind::Local(hir::Local { els: Some(els), .. }) => { + hir::StmtKind::Let(hir::Local { els: Some(els), .. }) => { // Let-else has a special lexical structure for variables. // First we take a checkpoint of the current scope context here. let mut prev_cx = visitor.cx; @@ -146,7 +146,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h // From now on, we continue normally. visitor.cx = prev_cx; } - hir::StmtKind::Local(..) => { + hir::StmtKind::Let(..) => { // Each declaration introduces a subscope for bindings // introduced by the declaration; this subscope covers a // suffix of the block. Each subscope in a block has the diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b5bb063c5ed8..7d303d989c79 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -863,7 +863,7 @@ impl<'a> State<'a> { fn print_stmt(&mut self, st: &hir::Stmt<'_>) { self.maybe_print_comment(st.span.lo()); match st.kind { - hir::StmtKind::Local(loc) => { + hir::StmtKind::Let(loc) => { self.print_local(loc.init, loc.els, |this| this.print_local_decl(loc)); } hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)), @@ -2306,7 +2306,7 @@ fn expr_requires_semi_to_be_stmt(e: &hir::Expr<'_>) -> bool { /// seen the semicolon, and thus don't need another. fn stmt_ends_with_semi(stmt: &hir::StmtKind<'_>) -> bool { match *stmt { - hir::StmtKind::Local(_) => true, + hir::StmtKind::Let(_) => true, hir::StmtKind::Item(_) => false, hir::StmtKind::Expr(e) => expr_requires_semi_to_be_stmt(e), hir::StmtKind::Semi(..) => false, diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ba0383d19b92..43e955445943 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -371,11 +371,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn walk_stmt(&mut self, stmt: &hir::Stmt<'_>) { match stmt.kind { - hir::StmtKind::Local(hir::Local { pat, init: Some(expr), els, .. }) => { + hir::StmtKind::Let(hir::Local { pat, init: Some(expr), els, .. }) => { self.walk_local(expr, pat, *els, |_| {}) } - hir::StmtKind::Local(_) => {} + hir::StmtKind::Let(_) => {} hir::StmtKind::Item(_) => { // We don't visit nested items in this visitor, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index a08582a67d94..0bf81f8bae27 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1593,7 +1593,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Don't do all the complex logic below for `DeclItem`. match stmt.kind { hir::StmtKind::Item(..) => return, - hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} + hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} } self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement"); @@ -1602,7 +1602,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let old_diverges = self.diverges.replace(Diverges::Maybe); match stmt.kind { - hir::StmtKind::Local(l) => { + hir::StmtKind::Let(l) => { self.check_decl_local(l); } // Ignore for now. @@ -1765,7 +1765,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [ hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { + hir::StmtKind::Let(hir::Local { source: hir::LocalSource::AssignDesugar(_), .. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5a1c7b056118..3f6f4cccba79 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1599,7 +1599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_local_statement(&self, id: hir::HirId) -> bool { let node = self.tcx.hir_node(id); - matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. })) + matches!(node, Node::Stmt(Stmt { kind: StmtKind::Let(..), .. })) } /// Suggest that `&T` was cloned instead of `T` because `T` does not implement `Clone`, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4c413e4d1c6a..c5bbcc56f86a 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2221,7 +2221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'v> Visitor<'v> for LetVisitor { type Result = ControlFlow>>; fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result { - if let hir::StmtKind::Local(&hir::Local { pat, init, .. }) = ex.kind + if let hir::StmtKind::Let(&hir::Local { pat, init, .. }) = ex.kind && let Binding(_, _, ident, ..) = pat.kind && ident.name == self.ident_name { diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 211109b59417..be14f5bf0d8b 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -217,7 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bug!(); }; for stmt in block.stmts { - let hir::StmtKind::Local(hir::Local { + let hir::StmtKind::Let(hir::Local { init: Some(init), source: hir::LocalSource::AsyncFn, pat, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 222c0a395425..6fb2aa8b1b91 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2139,7 +2139,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // the same span as the error and the type is specified. if let hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { + hir::StmtKind::Let(hir::Local { init: Some(hir::Expr { span: init_span, .. }), ty: Some(array_ty), .. diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 8cdf39b17398..9081fbaa2dc2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -585,7 +585,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result { - if let hir::StmtKind::Local(hir::Local { + if let hir::StmtKind::Let(hir::Local { span, pat: hir::Pat { .. }, ty: None, @@ -824,7 +824,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let hir = self.tcx.hir(); for stmt in blk.stmts.iter().rev() { - let hir::StmtKind::Local(local) = &stmt.kind else { + let hir::StmtKind::Let(local) = &stmt.kind else { continue; }; local.pat.walk(&mut find_compatible_candidates); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index c05da3623585..142988dee747 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -655,7 +655,7 @@ impl<'hir> Map<'hir> { | Node::ForeignItem(_) | Node::TraitItem(_) | Node::ImplItem(_) - | Node::Stmt(Stmt { kind: StmtKind::Local(_), .. }) => break, + | Node::Stmt(Stmt { kind: StmtKind::Let(_), .. }) => break, Node::Expr(expr @ Expr { kind: ExprKind::If(..) | ExprKind::Match(..), .. }) => { return Some(expr); } diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 1e93e126b706..d4a347975dba 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -63,7 +63,7 @@ impl<'tcx> Cx<'tcx> { // ignore for purposes of the MIR None } - hir::StmtKind::Local(local) => { + hir::StmtKind::Let(local) => { let remainder_scope = region::Scope { id: block_id, data: region::ScopeData::Remainder(region::FirstStatementIndex::new( diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 91ab5b30dea3..eb2399f7a64f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2444,7 +2444,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { // When checking statements ignore expressions, they will be checked later. - if let hir::StmtKind::Local(l) = stmt.kind { + if let hir::StmtKind::Let(l) = stmt.kind { self.check_attributes(l.hir_id, stmt.span, Target::Statement, None); } intravisit::walk_stmt(self, stmt) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 61dd02ae7dc8..d742ffc69e45 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -277,7 +277,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) { record_variants!( (self, s, s.kind, Id::Node(s.hir_id), hir, Stmt, StmtKind), - [Local, Item, Expr, Semi] + [Let, Item, Expr, Semi] ); hir_visit::walk_stmt(self, s) } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index e5033e1f51f2..f0c3f7a385d6 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -771,7 +771,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn propagate_through_stmt(&mut self, stmt: &hir::Stmt<'_>, succ: LiveNode) -> LiveNode { match stmt.kind { - hir::StmtKind::Local(local) => { + hir::StmtKind::Let(local) => { // Note: we mark the variable as defined regardless of whether // there is an initializer. Initially I had thought to only mark // the live variable as defined if it was initialized, and then we diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 27c9c1306e6a..bd34b0597e25 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -280,7 +280,7 @@ impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { match stmt.kind { StmtKind::Item(..) => {} - StmtKind::Local(..) => { + StmtKind::Let(..) => { self.items.push((ItemKind::NonAsm, stmt.span)); } StmtKind::Expr(expr) | StmtKind::Semi(expr) => { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1241227a5af3..2924a1865444 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -763,7 +763,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let hir_id = self.tcx.local_def_id_to_hir_id(def_id.as_local()?); match self.tcx.parent_hir_node(hir_id) { - hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. }) => { + hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(local), .. }) => { get_name(err, &local.pat.kind) } // Different to previous arm because one is `&hir::Local` and the other diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs index 9b36cc00444f..91ae19acbf7f 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs @@ -52,7 +52,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_ .as_ref() .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)), |stmt| match &stmt.kind { - StmtKind::Local(_) => true, + StmtKind::Let(_) => true, StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr), StmtKind::Item(_) => false, }, diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index 247048bbc49d..acdcb54be271 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -349,7 +349,7 @@ impl BlockEq { /// If the statement is a local, checks if the bound names match the expected list of names. fn eq_binding_names(s: &Stmt<'_>, names: &[(HirId, Symbol)]) -> bool { - if let StmtKind::Local(l) = s.kind { + if let StmtKind::Let(l) = s.kind { let mut i = 0usize; let mut res = true; l.pat.each_binding_or_first(&mut |_, _, _, name| { @@ -389,7 +389,7 @@ fn eq_stmts( eq: &mut HirEqInterExpr<'_, '_, '_>, moved_bindings: &mut Vec<(HirId, Symbol)>, ) -> bool { - (if let StmtKind::Local(l) = stmt.kind { + (if let StmtKind::Let(l) = stmt.kind { let old_count = moved_bindings.len(); l.pat.each_binding_or_first(&mut |_, id, _, name| { moved_bindings.push((id, name.name)); @@ -432,7 +432,7 @@ fn scan_block_for_eq<'tcx>( .iter() .enumerate() .find(|&(i, stmt)| { - if let StmtKind::Local(l) = stmt.kind + if let StmtKind::Let(l) = stmt.kind && needs_ordered_drop(cx, cx.typeck_results().node_type(l.hir_id)) { local_needs_ordered_drop = true; @@ -509,7 +509,7 @@ fn scan_block_for_eq<'tcx>( // Clear out all locals seen at the end so far. None of them can be moved. let stmts = &blocks[0].stmts; for stmt in &stmts[stmts.len() - init..=stmts.len() - offset] { - if let StmtKind::Local(l) = stmt.kind { + if let StmtKind::Let(l) = stmt.kind { l.pat.each_binding_or_first(&mut |_, id, _, _| { // FIXME(rust/#120456) - is `swap_remove` correct? eq.locals.swap_remove(&id); diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index 8789efcc9944..98a6d9370c34 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { // find all binding statements like `let mut _ = T::default()` where `T::default()` is the // `default` method of the `Default` trait, and store statement index in current block being // checked and the name of the bound variable - let (local, variant, binding_name, binding_type, span) = if let StmtKind::Local(local) = stmt.kind + let (local, variant, binding_name, binding_type, span) = if let StmtKind::Let(local) = stmt.kind // only take `let ...` statements && let Some(expr) = local.init && !any_parent_is_automatically_derived(cx.tcx, expr.hir_id) diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index 59d2df0295fb..1d6c4ce72e18 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { match stmt.kind { // we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric` - StmtKind::Local(local) => self.ty_bounds.push(ExplicitTyBound(local.ty.is_some())), + StmtKind::Let(local) => self.ty_bounds.push(ExplicitTyBound(local.ty.is_some())), _ => self.ty_bounds.push(ExplicitTyBound(false)), } diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index de6073c27236..ebda2ad83870 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -423,7 +423,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { } }, StmtKind::Expr(e) => self.visit_expr(e), - StmtKind::Local(l) => { + StmtKind::Let(l) => { self.visit_pat(l.pat); if let Some(e) = l.init { self.allow_insert_closure &= !self.in_tail_pos; diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index de048fef5f22..2e9bec6a7b08 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) -> &'tcx ExprKind<'hir> { if let ExprKind::Block(block, _label @ None) = kind && let Block { - stmts: [Stmt { kind: StmtKind::Local(local), .. }], + stmts: [Stmt { kind: StmtKind::Let(local), .. }], expr: Some(expr_end_of_block), rules: BlockCheckMode::DefaultBlock, .. diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 270162ae7717..f084d89ccc28 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { let mut it = block.stmts.iter().peekable(); while let Some(stmt) = it.next() { if let Some(expr) = it.peek() - && let hir::StmtKind::Local(local) = stmt.kind + && let hir::StmtKind::Let(local) = stmt.kind && let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind && let hir::StmtKind::Expr(if_) = expr.kind && let hir::ExprKind::If( diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index 18f799e875a0..a7c1d1bd6cd3 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -410,7 +410,7 @@ fn get_assignments<'a, 'tcx>( stmts .iter() .filter_map(move |stmt| match stmt.kind { - StmtKind::Local(..) | StmtKind::Item(..) => None, + StmtKind::Let(..) | StmtKind::Item(..) => None, StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e), }) .chain(*expr) diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs index ca584a454d03..b00a082bb8cf 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs @@ -72,7 +72,7 @@ fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr } fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && is_vec_pop_unwrap(cx, init, is_empty_recv) { diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index 65d922f03df3..6cc79440f39a 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -137,7 +137,7 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t match stmt.kind { StmtKind::Semi(e) | StmtKind::Expr(e) => Some((e, None)), // add the let...else expression (if present) - StmtKind::Local(local) => local.init.map(|init| (init, local.els)), + StmtKind::Let(local) => local.init.map(|init| (init, local.els)), StmtKind::Item(..) => None, } } diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs index 735d704a43ce..93774b897682 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs @@ -11,7 +11,7 @@ use rustc_lint::LateContext; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) { let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) { ([stmt, stmts @ ..], expr) => { - if let StmtKind::Local(&Local { + if let StmtKind::Let(&Local { init: Some(e), els: None, .. diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index fdf8fa4e2771..03e4d668dd8f 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -53,7 +53,7 @@ impl<'tcx> QuestionMark { return; } - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && local.els.is_none() && local.ty.is_none() diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs index 3b82c50a84e6..c9eab7109ebc 100644 --- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs +++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs @@ -138,7 +138,7 @@ fn reduce_unit_expression(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option< // If block only contains statements, // reduce `{ X; }` to `X` or `X;` match inner_stmt.kind { - hir::StmtKind::Local(local) => Some(local.span), + hir::StmtKind::Let(local) => Some(local.span), hir::StmtKind::Expr(e) => Some(e.span), hir::StmtKind::Semi(..) => Some(inner_stmt.span), hir::StmtKind::Item(..) => None, diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 55050ae693e7..78540353005d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -424,7 +424,7 @@ fn get_expr_and_hir_id_from_stmt<'v>(stmt: &'v Stmt<'v>) -> Option<(&'v Expr<'v> match stmt.kind { StmtKind::Expr(expr) | StmtKind::Semi(expr) => Some((expr, None)), StmtKind::Item(..) => None, - StmtKind::Local(Local { init, pat, .. }) => { + StmtKind::Let(Local { init, pat, .. }) => { if let PatKind::Binding(_, hir_id, ..) = pat.kind { init.map(|init_expr| (init_expr, Some(hir_id))) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index 0e7ad8fc996e..55cd1a38ec96 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -198,7 +198,7 @@ fn indirect_usage<'tcx>( binding: HirId, ctxt: SyntaxContext, ) -> Option> { - if let StmtKind::Local(&Local { + if let StmtKind::Let(&Local { pat: Pat { kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None), .. diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs index 7b0cf48ac43b..cdfaa690d5f4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs @@ -27,7 +27,7 @@ fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &E fn get_last_chain_binding_hir_id(mut hir_id: HirId, statements: &[Stmt<'_>]) -> Option { for stmt in statements { - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && let ExprKind::Path(QPath::Resolved(_, path)) = init.kind && let hir::def::Res::Local(local_hir_id) = path.res diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index b9784a58596c..4094d7ded7d8 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if !in_external_macro(cx.tcx.sess, stmt.span) - && let StmtKind::Local(local) = stmt.kind + && let StmtKind::Let(local) = stmt.kind && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind && let Some(init) = local.init // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue. diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index a1f7dc7b38c4..12c7c18afde6 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { match stmt.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { if let Local { init: Some(e), .. } = local { DivergenceVisitor { cx }.visit_expr(e); } @@ -291,7 +291,7 @@ fn check_stmt<'tcx>(vis: &mut ReadVisitor<'_, 'tcx>, stmt: &'tcx Stmt<'_>) -> St StmtKind::Expr(expr) | StmtKind::Semi(expr) => check_expr(vis, expr), // If the declaration is of a local variable, check its initializer // expression if it has one. Otherwise, keep going. - StmtKind::Local(local) => local + StmtKind::Let(local) => local .init .as_ref() .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)), diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 3e63c0a1d36e..4cda4b171e31 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -86,7 +86,7 @@ fn contains_let(cond: &Expr<'_>) -> bool { } fn stmt_needs_ordered_drop(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { - let StmtKind::Local(local) = stmt.kind else { + let StmtKind::Let(local) = stmt.kind else { return false; }; !local.pat.walk_short(|pat| { diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index cac34c8ce06e..43810ec0ec74 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -174,7 +174,7 @@ impl NoEffect { ); return true; } - } else if let StmtKind::Local(local) = stmt.kind { + } else if let StmtKind::Let(local) = stmt.kind { if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) && !matches!(local.source, LocalSource::AsyncFn) && let Some(init) = local.init diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs index 60ced9c12082..fbca4329342a 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -82,7 +82,7 @@ declare_lint_pass!(PatternTypeMismatch => [PATTERN_TYPE_MISMATCH]); impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if let StmtKind::Local(local) = stmt.kind { + if let StmtKind::Let(local) = stmt.kind { if in_external_macro(cx.sess(), local.pat.span) { return; } diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index cf7f730140ce..831c291ed7cc 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -109,7 +109,7 @@ fn find_let_else_ret_expression<'hir>(block: &'hir Block<'hir>) -> Option<&'hir } fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { - if let StmtKind::Local(Local { + if let StmtKind::Let(Local { pat, init: Some(init_expr), els: Some(els), diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs index 650324d4249e..d0b37cd92e00 100644 --- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs +++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { return; } - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Local { pat, init: Some(init), .. } = local diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index f61527cc0a9f..c2673bc409fa 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -262,7 +262,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { } for w in block.stmts.windows(2) { - if let hir::StmtKind::Local(local) = w[0].kind + if let hir::StmtKind::Let(local) = w[0].kind && let Option::Some(t) = local.init && let hir::ExprKind::Closure { .. } = t.kind && let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 2af466d3f51e..196975274674 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { // we need both a let-binding stmt and an expr if let Some(retexpr) = block.expr && let Some(stmt) = block.stmts.iter().last() - && let StmtKind::Local(local) = &stmt.kind + && let StmtKind::Let(local) = &stmt.kind && local.ty.is_none() && cx.tcx.hir().attrs(local.hir_id).is_empty() && let Some(initexpr) = &local.init diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs index 6c99ccda7ea7..f8726aa173a9 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs @@ -236,7 +236,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx fn manage_has_expensive_expr_after_last_attr(&mut self) { let has_expensive_stmt = match self.ap.curr_stmt.kind { hir::StmtKind::Expr(expr) if is_inexpensive_expr(expr) => false, - hir::StmtKind::Local(local) + hir::StmtKind::Let(local) if let Some(expr) = local.init && let hir::ExprKind::Path(_) = expr.kind => { @@ -290,7 +290,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o }; let mut ac = AttrChecker::new(self.cx, self.seen_types, self.type_cache); if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) { - if let hir::StmtKind::Local(local) = self.ap.curr_stmt.kind + if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind && let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind && !self.ap.apas.contains_key(&hir_id) && { @@ -326,7 +326,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o return; }; match self.ap.curr_stmt.kind { - hir::StmtKind::Local(local) => { + hir::StmtKind::Let(local) => { if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { apa.last_bind_ident = ident; } diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index 4837f2858a66..ff8e8fe70217 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` // or `Vec::new()` - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind && let Some(init) = local.init && let Some(size_expr) = Self::as_vec_initializer(cx, init) diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index daa6fe8715ca..be590aede158 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -148,7 +148,7 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { } for [s1, s2, s3] in block.stmts.array_windows::<3>() { - if let StmtKind::Local(tmp) = s1.kind + if let StmtKind::Let(tmp) = s1.kind // let t = foo(); && let Some(tmp_init) = tmp.init && let PatKind::Binding(.., ident, None) = tmp.pat.kind @@ -243,7 +243,7 @@ fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr< if let ExprKind::Assign(lhs, rhs, _) = expr.kind { return Some((ExprOrIdent::Expr(lhs), rhs)); } - } else if let StmtKind::Local(expr) = stmt.kind { + } else if let StmtKind::Let(expr) = stmt.kind { if let Some(rhs) = expr.init { if let PatKind::Binding(_, _, ident_l, _) = expr.pat.kind { return Some((ExprOrIdent::Ident(ident_l), rhs)); diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 559d7ace40ed..0efa65b28e23 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -158,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &hir::Stmt<'tcx>) { - let (hir::StmtKind::Local(&hir::Local { init: Some(expr), .. }) + let (hir::StmtKind::Let(&hir::Local { init: Some(expr), .. }) | hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr)) = stmt.kind else { @@ -358,7 +358,7 @@ fn block_parents_have_safety_comment( }, Node::Stmt(hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { span, hir_id, .. }) + hir::StmtKind::Let(hir::Local { span, hir_id, .. }) | hir::StmtKind::Expr(hir::Expr { span, hir_id, .. }) | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }), .. diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs index fc8519d56283..9ffcfcc0f50c 100644 --- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs +++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs @@ -153,7 +153,7 @@ impl<'tcx> VecLocation<'tcx> { /// or `self` expression for `Vec::reserve()`. fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> Option> { match stmt.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { if let Some(init_expr) = local.init && let PatKind::Binding(_, hir_id, _, None) = local.pat.kind && let Some(init_kind) = get_vec_init_kind(cx, init_expr) diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 6b3ea7700b73..eb64dd633f60 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -61,10 +61,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { /// we need to check them at `check_expr` or `check_block` as they are not stmts /// but we can't check them at `check_expr` because we need the broader context /// because we should do this only for the final expression of the block, and not for - /// `StmtKind::Local` which binds values => the io amount is used. + /// `StmtKind::Let` which binds values => the io amount is used. /// /// To check for unused io amount in stmts, we only consider `StmtKind::Semi`. - /// `StmtKind::Local` is not considered because it binds values => the io amount is used. + /// `StmtKind::Let` is not considered because it binds values => the io amount is used. /// `StmtKind::Expr` is not considered because requires unit type => the io amount is used. /// `StmtKind::Item` is not considered because it's not an expression. /// diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs index ba72b3450b93..f1d0c22b1aec 100644 --- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs +++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable { for (idx, stmt) in block.stmts.iter().enumerate() { if !stmt.span.from_expansion() - && let StmtKind::Local(local) = stmt.kind + && let StmtKind::Let(local) = stmt.kind && let PatKind::Binding(_, binding, ident, _) = local.pat.kind && let Some(init) = local.init && !init.span.from_expansion() @@ -197,7 +197,7 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { }, Node::Stmt(stmt) => { match stmt.kind { - StmtKind::Local(_) | StmtKind::Item(_) => self.found_peek_call = true, + StmtKind::Let(_) | StmtKind::Item(_) => self.found_peek_call = true, StmtKind::Expr(_) | StmtKind::Semi(_) => {}, } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index a0a6382046d0..187bfda129cd 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -724,7 +724,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } match stmt.value.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { bind!(self, local); kind!("Local({local})"); self.option(field!(local.init), "init", |init| { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index f7f5f7ca35ff..106d1d0d77f0 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -108,7 +108,7 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> { impl HirEqInterExpr<'_, '_, '_> { pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool { match (&left.kind, &right.kind) { - (&StmtKind::Local(l), &StmtKind::Local(r)) => { + (&StmtKind::Let(l), &StmtKind::Let(r)) => { // This additional check ensures that the type of the locals are equivalent even if the init // expression or type have some inferred parts. if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results { @@ -1030,7 +1030,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { std::mem::discriminant(&b.kind).hash(&mut self.s); match &b.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { self.hash_pat(local.pat); if let Some(init) = local.init { self.hash_expr(init); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 708037a46555..dc0725730322 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2161,7 +2161,7 @@ pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { Node::Stmt(Stmt { kind: StmtKind::Expr(_) | StmtKind::Semi(_) - | StmtKind::Local(Local { + | StmtKind::Let(Local { pat: Pat { kind: PatKind::Wild, .. From ac1b8575c017b6cc99cf389ceffe853d7b53a694 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 14 Mar 2024 12:00:46 +0100 Subject: [PATCH 99/99] Update `tests/ui/stats/hir-stats.stderr` output --- tests/ui/stats/hir-stats.stderr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index 579a5d5180ef..dc24833c267c 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -17,7 +17,7 @@ ast-stats-1 - Fn 96 ( 1.4%) 1 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 ast-stats-1 FieldDef 160 ( 2.4%) 2 80 ast-stats-1 Stmt 160 ( 2.4%) 5 32 -ast-stats-1 - Local 32 ( 0.5%) 1 +ast-stats-1 - Let 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.4%) 3 ast-stats-1 Param 160 ( 2.4%) 4 40 @@ -75,7 +75,7 @@ ast-stats-2 - DocComment 32 ( 0.4%) 1 ast-stats-2 - Normal 96 ( 1.3%) 3 ast-stats-2 FieldDef 160 ( 2.2%) 2 80 ast-stats-2 Stmt 160 ( 2.2%) 5 32 -ast-stats-2 - Local 32 ( 0.4%) 1 +ast-stats-2 - Let 32 ( 0.4%) 1 ast-stats-2 - Semi 32 ( 0.4%) 1 ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Param 160 ( 2.2%) 4 40 @@ -131,7 +131,7 @@ hir-stats ImplItemRef 72 ( 0.8%) 2 36 hir-stats Arm 80 ( 0.9%) 2 40 hir-stats FieldDef 96 ( 1.1%) 2 48 hir-stats Stmt 96 ( 1.1%) 3 32 -hir-stats - Local 32 ( 0.4%) 1 +hir-stats - Let 32 ( 0.4%) 1 hir-stats - Semi 32 ( 0.4%) 1 hir-stats - Expr 32 ( 0.4%) 1 hir-stats FnDecl 120 ( 1.3%) 3 40