From 249e5b5a0302830eafb914bff5ff80033e065b62 Mon Sep 17 00:00:00 2001 From: Samson <16504129+sagudev@users.noreply.github.com> Date: Tue, 7 Jan 2025 21:29:45 +0100 Subject: [PATCH 001/176] Fix rib example related zulip thread: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Ribs.20in.20name.20resolution --- src/doc/rustc-dev-guide/src/name-resolution.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/name-resolution.md b/src/doc/rustc-dev-guide/src/name-resolution.md index 2727b8142f2a..719ebce85536 100644 --- a/src/doc/rustc-dev-guide/src/name-resolution.md +++ b/src/doc/rustc-dev-guide/src/name-resolution.md @@ -120,9 +120,9 @@ even though they should be visible by ordinary scoping rules. An example: fn do_something(val: T) { // <- New rib in both types and values (1) // `val` is accessible, as is the helper function // `T` is accessible - let helper = || { // New rib on `helper` (2) and another on the block (3) + let helper = || { // New rib on the block (2) // `val` is accessible here - }; // End of (3) + }; // End of (2), new rib on `helper` (3) // `val` is accessible, `helper` variable shadows `helper` function fn helper() { // <- New rib in both types and values (4) // `val` is not accessible here, (4) is not transparent for locals @@ -130,7 +130,7 @@ fn do_something(val: T) { // <- New rib in both types and values (1) } // End of (4) let val = T::default(); // New rib (5) // `val` is the variable, not the parameter here -} // End of (5), (2) and (1) +} // End of (5), (3) and (1) ``` Because the rules for different namespaces are a bit different, each namespace From 7bca1f2675d9f63b09ed9641e9aefe05b8ccc675 Mon Sep 17 00:00:00 2001 From: Sky Date: Tue, 11 Feb 2025 11:49:14 -0500 Subject: [PATCH 002/176] Fix missing const for inherent pointer `replace` methods --- library/core/src/ptr/mut_ptr.rs | 3 ++- library/core/src/ptr/non_null.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index d1b0104c0fa9..c102e21026c8 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1577,8 +1577,9 @@ impl *mut T { /// /// [`ptr::replace`]: crate::ptr::replace() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_inherent_ptr_replace", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] - pub unsafe fn replace(self, src: T) -> T + pub const unsafe fn replace(self, src: T) -> T where T: Sized, { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d93069d384ed..4c7f0817cf38 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1169,7 +1169,8 @@ impl NonNull { /// [`ptr::replace`]: crate::ptr::replace() #[inline(always)] #[stable(feature = "non_null_convenience", since = "1.80.0")] - pub unsafe fn replace(self, src: T) -> T + #[rustc_const_stable(feature = "const_inherent_ptr_replace", since = "CURRENT_RUSTC_VERSION")] + pub const unsafe fn replace(self, src: T) -> T where T: Sized, { From 222adac953d1e745763850f75f4afac69b1d4321 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 5 Mar 2025 01:04:10 +0100 Subject: [PATCH 003/176] Allow optimizing out `panic_bounds_check` in Unicode checks. --- library/core/src/unicode/unicode_data.rs | 73 +++++++++---------- .../src/range_search.rs | 25 ++++--- .../unicode-table-generator/src/skiplist.rs | 20 +++-- 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 4655d35e9c43..e103d09d9ed6 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -55,24 +55,31 @@ fn decode_length(short_offset_run_header: u32) -> usize { (short_offset_run_header >> 21) as usize } +/// # Safety +/// +/// The last element of `short_offset_runs` must be greater than `std::char::MAX`. #[inline(always)] -fn skip_search( - needle: u32, +unsafe fn skip_search( + needle: char, short_offset_runs: &[u32; SOR], offsets: &[u8; OFFSETS], ) -> bool { - // Note that this *cannot* be past the end of the array, as the last - // element is greater than std::char::MAX (the largest possible needle). - // - // So, we cannot have found it (i.e. Ok(idx) + 1 != length) and the correct - // location cannot be past it, so Err(idx) != length either. - // - // This means that we can avoid bounds checking for the accesses below, too. + let needle = needle as u32; + let last_idx = match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) { Ok(idx) => idx + 1, Err(idx) => idx, }; + // SAFETY: `last_idx` *cannot* be past the end of the array, as the last + // element is greater than `std::char::MAX` (the largest possible needle) + // as guaranteed by the caller. + // + // So, we cannot have found it (i.e. `Ok(idx) => idx + 1 != length`) and the + // correct location cannot be past it, so `Err(idx) => idx != length` either. + // + // This means that we can avoid bounds checking for the accesses below, too. + unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; let mut offset_idx = decode_length(short_offset_runs[last_idx]); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { @@ -169,11 +176,9 @@ pub mod alphabetic { 0, 0, 0, 0, 5, 0, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -222,11 +227,9 @@ pub mod case_ignorable { 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -252,11 +255,9 @@ pub mod cased { 8, 0, 10, 1, 20, 6, 6, 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -269,11 +270,9 @@ pub mod cc { 0, 32, 95, 33, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -320,11 +319,9 @@ pub mod grapheme_extend { (c as u32) >= 0x300 && lookup_slow(c) } fn lookup_slow(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -459,11 +456,9 @@ pub mod n { 10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs index 9a51979a2f0d..7376bbdc9aee 100644 --- a/src/tools/unicode-table-generator/src/range_search.rs +++ b/src/tools/unicode-table-generator/src/range_search.rs @@ -53,24 +53,31 @@ fn decode_length(short_offset_run_header: u32) -> usize { (short_offset_run_header >> 21) as usize } +/// # Safety +/// +/// The last element of `short_offset_runs` must be greater than `std::char::MAX`. #[inline(always)] -fn skip_search( - needle: u32, +unsafe fn skip_search( + needle: char, short_offset_runs: &[u32; SOR], offsets: &[u8; OFFSETS], ) -> bool { - // Note that this *cannot* be past the end of the array, as the last - // element is greater than std::char::MAX (the largest possible needle). - // - // So, we cannot have found it (i.e. Ok(idx) + 1 != length) and the correct - // location cannot be past it, so Err(idx) != length either. - // - // This means that we can avoid bounds checking for the accesses below, too. + let needle = needle as u32; + let last_idx = match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) { Ok(idx) => idx + 1, Err(idx) => idx, }; + // SAFETY: `last_idx` *cannot* be past the end of the array, as the last + // element is greater than `std::char::MAX` (the largest possible needle) + // as guaranteed by the caller. + // + // So, we cannot have found it (i.e. `Ok(idx) => idx + 1 != length`) and the + // correct location cannot be past it, so `Err(idx) => idx != length` either. + // + // This means that we can avoid bounds checking for the accesses below, too. + unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; let mut offset_idx = decode_length(short_offset_runs[last_idx]); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index 8ca18ddc91a8..8dd3eeb8735d 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -108,11 +108,21 @@ impl RawEmitter { } else { writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); } - writeln!(&mut self.file, " super::skip_search(",).unwrap(); - writeln!(&mut self.file, " c as u32,").unwrap(); - writeln!(&mut self.file, " &SHORT_OFFSET_RUNS,").unwrap(); - writeln!(&mut self.file, " &OFFSETS,").unwrap(); - writeln!(&mut self.file, " )").unwrap(); + writeln!( + &mut self.file, + " const {{ assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); }}", + ) + .unwrap(); + writeln!( + &mut self.file, + " // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`.", + ) + .unwrap(); + writeln!( + &mut self.file, + " unsafe {{ super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) }}" + ) + .unwrap(); writeln!(&mut self.file, "}}").unwrap(); } } From 3e374043f3ec5d4146fcd350a3e027f359e8ef1c Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 5 Mar 2025 15:47:14 +0100 Subject: [PATCH 004/176] Add test for `escape_debug` without bounds check. --- tests/codegen/char-escape-debug-no-bounds-check.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/codegen/char-escape-debug-no-bounds-check.rs diff --git a/tests/codegen/char-escape-debug-no-bounds-check.rs b/tests/codegen/char-escape-debug-no-bounds-check.rs new file mode 100644 index 000000000000..cfde46045e5a --- /dev/null +++ b/tests/codegen/char-escape-debug-no-bounds-check.rs @@ -0,0 +1,14 @@ +//@ compile-flags: -Copt-level=3 +#![crate_type = "lib"] + +use std::char::EscapeDebug; + +// Make sure no bounds checks are emitted when escaping a character. + +// CHECK-LABEL: @char_escape_debug_no_bounds_check +#[no_mangle] +pub fn char_escape_debug_no_bounds_check(c: char) -> EscapeDebug { + // CHECK-NOT: panic + // CHECK-NOT: panic_bounds_check + c.escape_debug() +} From 34ac75be2830892baaebc81d3d4e13504c362d1a Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 5 Mar 2025 22:38:58 +0100 Subject: [PATCH 005/176] Add second precondition for `skip_search`. --- library/core/src/unicode/unicode_data.rs | 262 ++++++++++++++---- .../src/range_search.rs | 42 ++- .../unicode-table-generator/src/skiplist.rs | 75 +++-- 3 files changed, 294 insertions(+), 85 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index e103d09d9ed6..56f5b7ed8eb1 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -47,27 +47,42 @@ const fn bitset_search< (word & (1 << (needle % 64) as u64)) != 0 } -fn decode_prefix_sum(short_offset_run_header: u32) -> u32 { - short_offset_run_header & ((1 << 21) - 1) -} +#[repr(transparent)] +struct ShortOffsetRunHeader(u32); -fn decode_length(short_offset_run_header: u32) -> usize { - (short_offset_run_header >> 21) as usize +impl ShortOffsetRunHeader { + const fn new(start_index: usize, prefix_sum: u32) -> Self { + assert!(start_index < (1 << 11)); + assert!(prefix_sum < (1 << 21)); + + Self((start_index as u32) << 21 | prefix_sum) + } + + #[inline] + const fn start_index(&self) -> usize { + (self.0 >> 21) as usize + } + + #[inline] + const fn prefix_sum(&self) -> u32 { + self.0 & ((1 << 21) - 1) + } } /// # Safety /// -/// The last element of `short_offset_runs` must be greater than `std::char::MAX`. +/// - The last element of `short_offset_runs` must be greater than `std::char::MAX`. +/// - The start indices of all elements in `short_offset_runs` must be less than `OFFSETS`. #[inline(always)] unsafe fn skip_search( needle: char, - short_offset_runs: &[u32; SOR], + short_offset_runs: &[ShortOffsetRunHeader; SOR], offsets: &[u8; OFFSETS], ) -> bool { let needle = needle as u32; let last_idx = - match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) { + match short_offset_runs.binary_search_by_key(&(needle << 11), |header| (header.0 << 11)) { Ok(idx) => idx + 1, Err(idx) => idx, }; @@ -81,18 +96,23 @@ unsafe fn skip_search( // This means that we can avoid bounds checking for the accesses below, too. unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; - let mut offset_idx = decode_length(short_offset_runs[last_idx]); + let mut offset_idx = short_offset_runs[last_idx].start_index(); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { - decode_length(*next) - offset_idx + (*next).start_index() - offset_idx } else { offsets.len() - offset_idx }; + let prev = - last_idx.checked_sub(1).map(|prev| decode_prefix_sum(short_offset_runs[prev])).unwrap_or(0); + last_idx.checked_sub(1).map(|prev| short_offset_runs[prev].prefix_sum()).unwrap_or(0); let total = needle - prev; let mut prefix_sum = 0; for _ in 0..(length - 1) { + // SAFETY: It is guaranteed that `length <= OFFSETS - offset_idx`, + // so it follows that `length - 1 + offset_idx < OFFSETS`, therefore + // `offset_idx < OFFSETS` is always true in this loop. + unsafe { crate::hint::assert_unchecked(offset_idx < OFFSETS) }; let offset = offsets[offset_idx]; prefix_sum += offset as u32; if prefix_sum > total { @@ -107,15 +127,36 @@ pub const UNICODE_VERSION: (u8, u8, u8) = (16, 0, 0); #[rustfmt::skip] pub mod alphabetic { - static SHORT_OFFSET_RUNS: [u32; 53] = [ - 706, 33559113, 876615277, 956309270, 1166025910, 1314925568, 1319120901, 1398813696, - 1449151936, 1451271309, 1455465997, 1463867300, 1652619520, 1663105646, 1665203518, - 1711342208, 1797326647, 1895898848, 2560697242, 2583768976, 2594255920, 2600551419, - 2608940615, 2613141760, 2615240704, 2619435577, 2621533504, 2652997624, 2688650454, - 2692853744, 2699145507, 2713826044, 2734799872, 2736903168, 2757875366, 2835472128, - 2883707536, 2934039760, 2942429152, 2955013632, 2988568880, 3126984704, 3139610336, - 3141711674, 3145911970, 3154308065, 3158503006, 3162699776, 3164797470, 3166896128, - 3168998219, 3171099568, 3176407984, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 53] = [ + ShortOffsetRunHeader::new(0, 706), ShortOffsetRunHeader::new(16, 4681), + ShortOffsetRunHeader::new(418, 5741), ShortOffsetRunHeader::new(456, 7958), + ShortOffsetRunHeader::new(556, 9398), ShortOffsetRunHeader::new(627, 11264), + ShortOffsetRunHeader::new(629, 12293), ShortOffsetRunHeader::new(667, 13312), + ShortOffsetRunHeader::new(691, 19904), ShortOffsetRunHeader::new(692, 42125), + ShortOffsetRunHeader::new(694, 42509), ShortOffsetRunHeader::new(698, 55204), + ShortOffsetRunHeader::new(788, 63744), ShortOffsetRunHeader::new(793, 64110), + ShortOffsetRunHeader::new(794, 64830), ShortOffsetRunHeader::new(816, 66176), + ShortOffsetRunHeader::new(857, 67383), ShortOffsetRunHeader::new(904, 73440), + ShortOffsetRunHeader::new(1221, 74650), ShortOffsetRunHeader::new(1232, 77712), + ShortOffsetRunHeader::new(1237, 78896), ShortOffsetRunHeader::new(1240, 82939), + ShortOffsetRunHeader::new(1244, 83527), ShortOffsetRunHeader::new(1246, 90368), + ShortOffsetRunHeader::new(1247, 92160), ShortOffsetRunHeader::new(1249, 92729), + ShortOffsetRunHeader::new(1250, 93504), ShortOffsetRunHeader::new(1265, 100344), + ShortOffsetRunHeader::new(1282, 101590), ShortOffsetRunHeader::new(1284, 110576), + ShortOffsetRunHeader::new(1287, 110883), ShortOffsetRunHeader::new(1294, 111356), + ShortOffsetRunHeader::new(1304, 113664), ShortOffsetRunHeader::new(1305, 119808), + ShortOffsetRunHeader::new(1315, 120486), ShortOffsetRunHeader::new(1352, 122624), + ShortOffsetRunHeader::new(1375, 123536), ShortOffsetRunHeader::new(1399, 124112), + ShortOffsetRunHeader::new(1403, 124896), ShortOffsetRunHeader::new(1409, 126464), + ShortOffsetRunHeader::new(1425, 127280), ShortOffsetRunHeader::new(1491, 131072), + ShortOffsetRunHeader::new(1497, 173792), ShortOffsetRunHeader::new(1498, 177978), + ShortOffsetRunHeader::new(1500, 183970), ShortOffsetRunHeader::new(1504, 191457), + ShortOffsetRunHeader::new(1506, 192094), ShortOffsetRunHeader::new(1508, 194560), + ShortOffsetRunHeader::new(1509, 195102), ShortOffsetRunHeader::new(1510, 196608), + ShortOffsetRunHeader::new(1511, 201547), ShortOffsetRunHeader::new(1512, 205744), + ShortOffsetRunHeader::new(1514, 1319856), ]; static OFFSETS: [u8; 1515] = [ 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29, @@ -176,20 +217,44 @@ pub mod alphabetic { 0, 0, 0, 0, 5, 0, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } #[rustfmt::skip] pub mod case_ignorable { - static SHORT_OFFSET_RUNS: [u32; 37] = [ - 688, 44045149, 572528402, 576724925, 807414908, 878718981, 903913493, 929080568, 933275148, - 937491230, 1138818560, 1147208189, 1210124160, 1222707713, 1235291428, 1260457643, - 1277237295, 1537284411, 1545673776, 1604394739, 1667314736, 1692492062, 1700883184, - 1709272384, 1721855823, 1730260976, 1747041437, 1759629056, 1768018279, 1776409088, - 1797382144, 1822548654, 1856103659, 1864493264, 1872884731, 1882062849, 1887371760, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 37] = [ + ShortOffsetRunHeader::new(0, 688), ShortOffsetRunHeader::new(21, 4957), + ShortOffsetRunHeader::new(273, 5906), ShortOffsetRunHeader::new(275, 8125), + ShortOffsetRunHeader::new(385, 11388), ShortOffsetRunHeader::new(419, 12293), + ShortOffsetRunHeader::new(431, 40981), ShortOffsetRunHeader::new(443, 42232), + ShortOffsetRunHeader::new(445, 42508), ShortOffsetRunHeader::new(447, 64286), + ShortOffsetRunHeader::new(543, 65024), ShortOffsetRunHeader::new(547, 66045), + ShortOffsetRunHeader::new(577, 67456), ShortOffsetRunHeader::new(583, 68097), + ShortOffsetRunHeader::new(589, 68900), ShortOffsetRunHeader::new(601, 69291), + ShortOffsetRunHeader::new(609, 71727), ShortOffsetRunHeader::new(733, 71995), + ShortOffsetRunHeader::new(737, 72752), ShortOffsetRunHeader::new(765, 73459), + ShortOffsetRunHeader::new(795, 78896), ShortOffsetRunHeader::new(807, 90398), + ShortOffsetRunHeader::new(811, 92912), ShortOffsetRunHeader::new(815, 93504), + ShortOffsetRunHeader::new(821, 94031), ShortOffsetRunHeader::new(825, 110576), + ShortOffsetRunHeader::new(833, 113821), ShortOffsetRunHeader::new(839, 118528), + ShortOffsetRunHeader::new(843, 119143), ShortOffsetRunHeader::new(847, 121344), + ShortOffsetRunHeader::new(857, 122880), ShortOffsetRunHeader::new(869, 123566), + ShortOffsetRunHeader::new(885, 124139), ShortOffsetRunHeader::new(889, 125136), + ShortOffsetRunHeader::new(893, 127995), ShortOffsetRunHeader::new(897, 917505), + ShortOffsetRunHeader::new(899, 2032112), ]; static OFFSETS: [u8; 905] = [ 39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, @@ -227,18 +292,36 @@ pub mod case_ignorable { 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } #[rustfmt::skip] pub mod cased { - static SHORT_OFFSET_RUNS: [u32; 22] = [ - 4256, 115348384, 136322176, 144711446, 163587254, 320875520, 325101120, 350268208, - 392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 501313088, 505533440, - 509728422, 587325184, 635559984, 648145152, 652341552, 657650058, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 22] = [ + ShortOffsetRunHeader::new(0, 4256), ShortOffsetRunHeader::new(55, 5024), + ShortOffsetRunHeader::new(65, 7296), ShortOffsetRunHeader::new(69, 7958), + ShortOffsetRunHeader::new(78, 9398), ShortOffsetRunHeader::new(153, 11264), + ShortOffsetRunHeader::new(155, 42560), ShortOffsetRunHeader::new(167, 43824), + ShortOffsetRunHeader::new(187, 64256), ShortOffsetRunHeader::new(193, 65313), + ShortOffsetRunHeader::new(197, 66560), ShortOffsetRunHeader::new(201, 67456), + ShortOffsetRunHeader::new(223, 68736), ShortOffsetRunHeader::new(231, 71840), + ShortOffsetRunHeader::new(239, 93760), ShortOffsetRunHeader::new(241, 119808), + ShortOffsetRunHeader::new(243, 120486), ShortOffsetRunHeader::new(280, 122624), + ShortOffsetRunHeader::new(303, 122928), ShortOffsetRunHeader::new(309, 125184), + ShortOffsetRunHeader::new(311, 127280), ShortOffsetRunHeader::new(313, 1241482), ]; static OFFSETS: [u8; 319] = [ 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5, @@ -255,35 +338,67 @@ pub mod cased { 8, 0, 10, 1, 20, 6, 6, 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } #[rustfmt::skip] pub mod cc { - static SHORT_OFFSET_RUNS: [u32; 1] = [ - 1114272, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 1] = [ + ShortOffsetRunHeader::new(0, 1114272), ]; static OFFSETS: [u8; 5] = [ 0, 32, 95, 33, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } #[rustfmt::skip] pub mod grapheme_extend { - static SHORT_OFFSET_RUNS: [u32; 34] = [ - 768, 2098307, 6292881, 10490717, 522196754, 526393356, 723528943, 731918378, 744531567, - 752920578, 769719070, 908131840, 912326558, 920715773, 924912129, 937495844, 962662059, - 971053103, 1256266800, 1323376371, 1386296384, 1407279390, 1415670512, 1424060239, - 1432468637, 1449250560, 1453445477, 1461836288, 1487003648, 1512170158, 1541530860, - 1549920464, 1559101472, 1568604656, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 34] = [ + ShortOffsetRunHeader::new(0, 768), ShortOffsetRunHeader::new(1, 1155), + ShortOffsetRunHeader::new(3, 1425), ShortOffsetRunHeader::new(5, 4957), + ShortOffsetRunHeader::new(249, 5906), ShortOffsetRunHeader::new(251, 8204), + ShortOffsetRunHeader::new(345, 11503), ShortOffsetRunHeader::new(349, 12330), + ShortOffsetRunHeader::new(355, 42607), ShortOffsetRunHeader::new(359, 43010), + ShortOffsetRunHeader::new(367, 64286), ShortOffsetRunHeader::new(433, 65024), + ShortOffsetRunHeader::new(435, 65438), ShortOffsetRunHeader::new(439, 66045), + ShortOffsetRunHeader::new(441, 68097), ShortOffsetRunHeader::new(447, 68900), + ShortOffsetRunHeader::new(459, 69291), ShortOffsetRunHeader::new(463, 71727), + ShortOffsetRunHeader::new(599, 72752), ShortOffsetRunHeader::new(631, 73459), + ShortOffsetRunHeader::new(661, 78912), ShortOffsetRunHeader::new(671, 90398), + ShortOffsetRunHeader::new(675, 92912), ShortOffsetRunHeader::new(679, 94031), + ShortOffsetRunHeader::new(683, 113821), ShortOffsetRunHeader::new(691, 118528), + ShortOffsetRunHeader::new(693, 119141), ShortOffsetRunHeader::new(697, 121344), + ShortOffsetRunHeader::new(709, 122880), ShortOffsetRunHeader::new(721, 123566), + ShortOffsetRunHeader::new(735, 124140), ShortOffsetRunHeader::new(739, 125136), + ShortOffsetRunHeader::new(743, 917536), ShortOffsetRunHeader::new(747, 2032112), ]; static OFFSETS: [u8; 751] = [ 0, 112, 0, 7, 0, 45, 1, 1, 1, 2, 1, 2, 1, 1, 72, 11, 48, 21, 16, 1, 101, 7, 2, 6, 2, 2, 1, @@ -319,8 +434,16 @@ pub mod grapheme_extend { (c as u32) >= 0x300 && lookup_slow(c) } fn lookup_slow(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } @@ -433,13 +556,30 @@ pub mod lowercase { #[rustfmt::skip] pub mod n { - static SHORT_OFFSET_RUNS: [u32; 42] = [ - 1632, 18876774, 31461440, 102765417, 111154926, 115349830, 132128880, 165684320, 186656630, - 195046653, 199241735, 203436434, 216049184, 241215536, 249605104, 274792208, 278987015, - 283181793, 295766104, 320933114, 383848032, 396432464, 438376016, 446765280, 463543280, - 471932752, 488711168, 497115440, 501312096, 505507184, 522284672, 526503152, 530698944, - 534894542, 547479872, 551674608, 555869424, 560064711, 568454257, 576844032, 597818352, - 603126778, + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 42] = [ + ShortOffsetRunHeader::new(0, 1632), ShortOffsetRunHeader::new(9, 2406), + ShortOffsetRunHeader::new(15, 4160), ShortOffsetRunHeader::new(49, 4969), + ShortOffsetRunHeader::new(53, 5870), ShortOffsetRunHeader::new(55, 6470), + ShortOffsetRunHeader::new(63, 8304), ShortOffsetRunHeader::new(79, 9312), + ShortOffsetRunHeader::new(89, 10102), ShortOffsetRunHeader::new(93, 11517), + ShortOffsetRunHeader::new(95, 12295), ShortOffsetRunHeader::new(97, 12690), + ShortOffsetRunHeader::new(103, 42528), ShortOffsetRunHeader::new(115, 43056), + ShortOffsetRunHeader::new(119, 44016), ShortOffsetRunHeader::new(131, 65296), + ShortOffsetRunHeader::new(133, 65799), ShortOffsetRunHeader::new(135, 66273), + ShortOffsetRunHeader::new(141, 67672), ShortOffsetRunHeader::new(153, 68858), + ShortOffsetRunHeader::new(183, 69216), ShortOffsetRunHeader::new(189, 70736), + ShortOffsetRunHeader::new(209, 71248), ShortOffsetRunHeader::new(213, 71904), + ShortOffsetRunHeader::new(221, 72688), ShortOffsetRunHeader::new(225, 73552), + ShortOffsetRunHeader::new(233, 74752), ShortOffsetRunHeader::new(237, 90416), + ShortOffsetRunHeader::new(239, 92768), ShortOffsetRunHeader::new(241, 93552), + ShortOffsetRunHeader::new(249, 93824), ShortOffsetRunHeader::new(251, 118000), + ShortOffsetRunHeader::new(253, 119488), ShortOffsetRunHeader::new(255, 120782), + ShortOffsetRunHeader::new(261, 123200), ShortOffsetRunHeader::new(263, 123632), + ShortOffsetRunHeader::new(265, 124144), ShortOffsetRunHeader::new(267, 125127), + ShortOffsetRunHeader::new(271, 126065), ShortOffsetRunHeader::new(275, 127232), + ShortOffsetRunHeader::new(285, 130032), ShortOffsetRunHeader::new(287, 1244154), ]; static OFFSETS: [u8; 289] = [ 48, 10, 120, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, @@ -456,8 +596,16 @@ pub mod n { 10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, ]; pub fn lookup(c: char) -> bool { - const { assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`. + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } } } diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs index 7376bbdc9aee..09bfe9a86a48 100644 --- a/src/tools/unicode-table-generator/src/range_search.rs +++ b/src/tools/unicode-table-generator/src/range_search.rs @@ -45,27 +45,42 @@ const fn bitset_search< (word & (1 << (needle % 64) as u64)) != 0 } -fn decode_prefix_sum(short_offset_run_header: u32) -> u32 { - short_offset_run_header & ((1 << 21) - 1) -} +#[repr(transparent)] +struct ShortOffsetRunHeader(u32); -fn decode_length(short_offset_run_header: u32) -> usize { - (short_offset_run_header >> 21) as usize +impl ShortOffsetRunHeader { + const fn new(start_index: usize, prefix_sum: u32) -> Self { + assert!(start_index < (1 << 11)); + assert!(prefix_sum < (1 << 21)); + + Self((start_index as u32) << 21 | prefix_sum) + } + + #[inline] + const fn start_index(&self) -> usize { + (self.0 >> 21) as usize + } + + #[inline] + const fn prefix_sum(&self) -> u32 { + self.0 & ((1 << 21) - 1) + } } /// # Safety /// -/// The last element of `short_offset_runs` must be greater than `std::char::MAX`. +/// - The last element of `short_offset_runs` must be greater than `std::char::MAX`. +/// - The start indices of all elements in `short_offset_runs` must be less than `OFFSETS`. #[inline(always)] unsafe fn skip_search( needle: char, - short_offset_runs: &[u32; SOR], + short_offset_runs: &[ShortOffsetRunHeader; SOR], offsets: &[u8; OFFSETS], ) -> bool { let needle = needle as u32; let last_idx = - match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) { + match short_offset_runs.binary_search_by_key(&(needle << 11), |header| (header.0 << 11)) { Ok(idx) => idx + 1, Err(idx) => idx, }; @@ -79,18 +94,23 @@ unsafe fn skip_search( // This means that we can avoid bounds checking for the accesses below, too. unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; - let mut offset_idx = decode_length(short_offset_runs[last_idx]); + let mut offset_idx = short_offset_runs[last_idx].start_index(); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { - decode_length(*next) - offset_idx + (*next).start_index() - offset_idx } else { offsets.len() - offset_idx }; + let prev = - last_idx.checked_sub(1).map(|prev| decode_prefix_sum(short_offset_runs[prev])).unwrap_or(0); + last_idx.checked_sub(1).map(|prev| short_offset_runs[prev].prefix_sum()).unwrap_or(0); let total = needle - prev; let mut prefix_sum = 0; for _ in 0..(length - 1) { + // SAFETY: It is guaranteed that `length <= OFFSETS - offset_idx`, + // so it follows that `length - 1 + offset_idx < OFFSETS`, therefore + // `offset_idx < OFFSETS` is always true in this loop. + unsafe { crate::hint::assert_unchecked(offset_idx < OFFSETS) }; let offset = offsets[offset_idx]; prefix_sum += offset as u32; if prefix_sum > total { diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index 8dd3eeb8735d..c2e44aec8903 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -1,26 +1,23 @@ -use std::fmt::Write as _; +use std::fmt::{self, Write as _}; use std::ops::Range; use crate::fmt_list; use crate::raw_emitter::RawEmitter; /// This will get packed into a single u32 before inserting into the data set. -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] struct ShortOffsetRunHeader { - /// Note, we only allow for 21 bits here. - prefix_sum: u32, - /// Note, we actually only allow for 11 bits here. This should be enough -- /// our largest sets are around ~1400 offsets long. - start_idx: u16, + start_index: u16, + + /// Note, we only allow for 21 bits here. + prefix_sum: u32, } -impl ShortOffsetRunHeader { - fn pack(&self) -> u32 { - assert!(self.start_idx < (1 << 11)); - assert!(self.prefix_sum < (1 << 21)); - - (self.start_idx as u32) << 21 | self.prefix_sum +impl fmt::Debug for ShortOffsetRunHeader { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ShortOffsetRunHeader::new({}, {})", self.start_index, self.prefix_sum) } } @@ -53,7 +50,7 @@ impl RawEmitter { coded_offsets.push(offset); } else { short_offset_runs.push(ShortOffsetRunHeader { - start_idx: start.try_into().unwrap(), + start_index: start.try_into().unwrap(), prefix_sum, }); // This is just needed to maintain indices even/odd @@ -73,9 +70,13 @@ impl RawEmitter { writeln!( &mut self.file, - "static SHORT_OFFSET_RUNS: [u32; {}] = [{}];", + "use super::ShortOffsetRunHeader;\n" + ).unwrap(); + writeln!( + &mut self.file, + "static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; {}] = [{}];", short_offset_runs.len(), - fmt_list(short_offset_runs.iter().map(|v| v.pack())) + fmt_list(short_offset_runs.iter()) ) .unwrap(); self.bytes_used += 4 * short_offset_runs.len(); @@ -110,12 +111,52 @@ impl RawEmitter { } writeln!( &mut self.file, - " const {{ assert!(*SHORT_OFFSET_RUNS.last().unwrap() > (char::MAX as u32)); }}", + " const {{", ) .unwrap(); writeln!( &mut self.file, - " // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`.", + " assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32));", + ) + .unwrap(); + writeln!( + &mut self.file, + " let mut i = 0;", + ) + .unwrap(); + writeln!( + &mut self.file, + " while i < SHORT_OFFSET_RUNS.len() {{", + ) + .unwrap(); + writeln!( + &mut self.file, + " assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len());", + ) + .unwrap(); + writeln!( + &mut self.file, + " i += 1;", + ) + .unwrap(); + writeln!( + &mut self.file, + " }}", + ) + .unwrap(); + writeln!( + &mut self.file, + " }}", + ) + .unwrap(); + writeln!( + &mut self.file, + " // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`", + ) + .unwrap(); + writeln!( + &mut self.file, + " // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`.", ) .unwrap(); writeln!( From 22725588d3156f472b66a19b9ec97fdcc5d0a663 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 7 Mar 2025 20:16:39 +0100 Subject: [PATCH 006/176] Never inline `lookup_slow`. --- library/core/src/unicode/unicode_data.rs | 2 ++ src/tools/unicode-table-generator/src/skiplist.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 56f5b7ed8eb1..f25f443567a8 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -433,6 +433,8 @@ pub mod grapheme_extend { pub fn lookup(c: char) -> bool { (c as u32) >= 0x300 && lookup_slow(c) } + + #[inline(never)] fn lookup_slow(c: char) -> bool { const { assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index c2e44aec8903..e4c3d96546f1 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -105,6 +105,8 @@ impl RawEmitter { writeln!(&mut self.file, " (c as u32) >= {first_code_point:#04x} && lookup_slow(c)") .unwrap(); writeln!(&mut self.file, "}}").unwrap(); + writeln!(&mut self.file).unwrap(); + writeln!(&mut self.file, "#[inline(never)]").unwrap(); writeln!(&mut self.file, "fn lookup_slow(c: char) -> bool {{").unwrap(); } else { writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); From 90ebc246075f9b56cd0a2dee2496698a94c9c033 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 7 Mar 2025 20:19:12 +0100 Subject: [PATCH 007/176] Use `intrinsics::assume` instead of `hint::assert_unchecked`. --- library/core/src/unicode/unicode_data.rs | 10 ++++++++-- src/tools/unicode-table-generator/src/range_search.rs | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index f25f443567a8..63d158114586 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -94,7 +94,10 @@ unsafe fn skip_search( // correct location cannot be past it, so `Err(idx) => idx != length` either. // // This means that we can avoid bounds checking for the accesses below, too. - unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; + // + // We need to use `intrinsics::assume` since the `panic_nounwind` contained + // in `hint::assert_unchecked` may not be optimized out. + unsafe { crate::intrinsics::assume(last_idx < SOR) }; let mut offset_idx = short_offset_runs[last_idx].start_index(); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { @@ -112,7 +115,10 @@ unsafe fn skip_search( // SAFETY: It is guaranteed that `length <= OFFSETS - offset_idx`, // so it follows that `length - 1 + offset_idx < OFFSETS`, therefore // `offset_idx < OFFSETS` is always true in this loop. - unsafe { crate::hint::assert_unchecked(offset_idx < OFFSETS) }; + // + // We need to use `intrinsics::assume` since the `panic_nounwind` contained + // in `hint::assert_unchecked` may not be optimized out. + unsafe { crate::intrinsics::assume(offset_idx < OFFSETS) }; let offset = offsets[offset_idx]; prefix_sum += offset as u32; if prefix_sum > total { diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs index 09bfe9a86a48..02f9cf16d4d3 100644 --- a/src/tools/unicode-table-generator/src/range_search.rs +++ b/src/tools/unicode-table-generator/src/range_search.rs @@ -92,7 +92,10 @@ unsafe fn skip_search( // correct location cannot be past it, so `Err(idx) => idx != length` either. // // This means that we can avoid bounds checking for the accesses below, too. - unsafe { crate::hint::assert_unchecked(last_idx < SOR) }; + // + // We need to use `intrinsics::assume` since the `panic_nounwind` contained + // in `hint::assert_unchecked` may not be optimized out. + unsafe { crate::intrinsics::assume(last_idx < SOR) }; let mut offset_idx = short_offset_runs[last_idx].start_index(); let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { @@ -110,7 +113,10 @@ unsafe fn skip_search( // SAFETY: It is guaranteed that `length <= OFFSETS - offset_idx`, // so it follows that `length - 1 + offset_idx < OFFSETS`, therefore // `offset_idx < OFFSETS` is always true in this loop. - unsafe { crate::hint::assert_unchecked(offset_idx < OFFSETS) }; + // + // We need to use `intrinsics::assume` since the `panic_nounwind` contained + // in `hint::assert_unchecked` may not be optimized out. + unsafe { crate::intrinsics::assume(offset_idx < OFFSETS) }; let offset = offsets[offset_idx]; prefix_sum += offset as u32; if prefix_sum > total { From 224dad154bd055bf3fb792ae51f9c6d91a927f9b Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 8 Mar 2025 12:47:40 +0100 Subject: [PATCH 008/176] Fix formatting. --- .../unicode-table-generator/src/skiplist.rs | 41 ++++--------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index e4c3d96546f1..d3e5c9eded24 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -68,10 +68,7 @@ impl RawEmitter { assert!(inserted); } - writeln!( - &mut self.file, - "use super::ShortOffsetRunHeader;\n" - ).unwrap(); + writeln!(&mut self.file, "use super::ShortOffsetRunHeader;\n").unwrap(); writeln!( &mut self.file, "static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; {}] = [{}];", @@ -111,46 +108,22 @@ impl RawEmitter { } else { writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); } - writeln!( - &mut self.file, - " const {{", - ) - .unwrap(); + writeln!(&mut self.file, " const {{").unwrap(); writeln!( &mut self.file, " assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32));", ) .unwrap(); - writeln!( - &mut self.file, - " let mut i = 0;", - ) - .unwrap(); - writeln!( - &mut self.file, - " while i < SHORT_OFFSET_RUNS.len() {{", - ) - .unwrap(); + writeln!(&mut self.file, " let mut i = 0;").unwrap(); + writeln!(&mut self.file, " while i < SHORT_OFFSET_RUNS.len() {{").unwrap(); writeln!( &mut self.file, " assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len());", ) .unwrap(); - writeln!( - &mut self.file, - " i += 1;", - ) - .unwrap(); - writeln!( - &mut self.file, - " }}", - ) - .unwrap(); - writeln!( - &mut self.file, - " }}", - ) - .unwrap(); + writeln!(&mut self.file, " i += 1;").unwrap(); + writeln!(&mut self.file, " }}").unwrap(); + writeln!(&mut self.file, " }}").unwrap(); writeln!( &mut self.file, " // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`", From 3628a8f326d1f323832aeae742ab3bbd025e4166 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 8 Mar 2025 12:56:00 +0100 Subject: [PATCH 009/176] Remove unneeded parentheses. --- library/core/src/unicode/unicode_data.rs | 12 ++++++------ src/tools/unicode-table-generator/src/skiplist.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 63d158114586..25b9c6e0e0e9 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -224,7 +224,7 @@ pub mod alphabetic { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -299,7 +299,7 @@ pub mod case_ignorable { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -345,7 +345,7 @@ pub mod cased { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -370,7 +370,7 @@ pub mod cc { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -443,7 +443,7 @@ pub mod grapheme_extend { #[inline(never)] fn lookup_slow(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); @@ -605,7 +605,7 @@ pub mod n { ]; pub fn lookup(c: char) -> bool { const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32)); + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; while i < SHORT_OFFSET_RUNS.len() { assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index d3e5c9eded24..34c9802e122f 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -111,7 +111,7 @@ impl RawEmitter { writeln!(&mut self.file, " const {{").unwrap(); writeln!( &mut self.file, - " assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > (char::MAX as u32));", + " assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);", ) .unwrap(); writeln!(&mut self.file, " let mut i = 0;").unwrap(); From 3a6d0ae0086baf30df19390700560c5a346dbe0e Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 11 Mar 2025 15:47:57 -0700 Subject: [PATCH 010/176] Move ByteStr compare and index traits to a separate module This parallels the layout of `core::str`. --- library/core/src/{bstr.rs => bstr/mod.rs} | 280 +--------------------- library/core/src/bstr/traits.rs | 275 +++++++++++++++++++++ 2 files changed, 282 insertions(+), 273 deletions(-) rename library/core/src/{bstr.rs => bstr/mod.rs} (54%) create mode 100644 library/core/src/bstr/traits.rs diff --git a/library/core/src/bstr.rs b/library/core/src/bstr/mod.rs similarity index 54% rename from library/core/src/bstr.rs rename to library/core/src/bstr/mod.rs index ae84fd8adb61..c33dd244ad97 100644 --- a/library/core/src/bstr.rs +++ b/library/core/src/bstr/mod.rs @@ -1,12 +1,13 @@ //! The `ByteStr` type and trait implementations. +mod traits; + +#[unstable(feature = "bstr_internals", issue = "none")] +pub use traits::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord}; + use crate::borrow::{Borrow, BorrowMut}; -use crate::cmp::Ordering; -use crate::ops::{ - Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, - RangeTo, RangeToInclusive, -}; -use crate::{fmt, hash}; +use crate::fmt; +use crate::ops::{Deref, DerefMut, DerefPure}; /// A wrapper for `&[u8]` representing a human-readable string that's conventionally, but not /// always, UTF-8. @@ -295,273 +296,6 @@ impl<'a> Default for &'a mut ByteStr { // } // } -#[unstable(feature = "bstr", issue = "134915")] -impl hash::Hash for ByteStr { - #[inline] - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index for ByteStr { - type Output = u8; - - #[inline] - fn index(&self, idx: usize) -> &u8 { - &self.0[idx] - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, _: RangeFull) -> &ByteStr { - self - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: Range) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeInclusive) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeFrom) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeTo) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeToInclusive) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut for ByteStr { - #[inline] - fn index_mut(&mut self, idx: usize) -> &mut u8 { - &mut self.0[idx] - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut for ByteStr { - #[inline] - fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr { - self - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: Range) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeInclusive) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeFrom) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeTo) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeToInclusive) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Eq for ByteStr {} - -#[unstable(feature = "bstr", issue = "134915")] -impl PartialEq for ByteStr { - #[inline] - fn eq(&self, other: &ByteStr) -> bool { - &self.0 == &other.0 - } -} - -#[doc(hidden)] -#[macro_export] -#[unstable(feature = "bstr_internals", issue = "none")] -macro_rules! impl_partial_eq { - ($lhs:ty, $rhs:ty) => { - #[allow(unused_lifetimes)] - impl<'a> PartialEq<$rhs> for $lhs { - #[inline] - fn eq(&self, other: &$rhs) -> bool { - let other: &[u8] = other.as_ref(); - PartialEq::eq(self.as_bytes(), other) - } - } - - #[allow(unused_lifetimes)] - impl<'a> PartialEq<$lhs> for $rhs { - #[inline] - fn eq(&self, other: &$lhs) -> bool { - let this: &[u8] = self.as_ref(); - PartialEq::eq(this, other.as_bytes()) - } - } - }; -} - -#[doc(hidden)] -#[unstable(feature = "bstr_internals", issue = "none")] -pub use impl_partial_eq; - -#[doc(hidden)] -#[macro_export] -#[unstable(feature = "bstr_internals", issue = "none")] -macro_rules! impl_partial_eq_ord { - ($lhs:ty, $rhs:ty) => { - $crate::bstr::impl_partial_eq!($lhs, $rhs); - - #[allow(unused_lifetimes)] - #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialOrd<$rhs> for $lhs { - #[inline] - fn partial_cmp(&self, other: &$rhs) -> Option { - let other: &[u8] = other.as_ref(); - PartialOrd::partial_cmp(self.as_bytes(), other) - } - } - - #[allow(unused_lifetimes)] - #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialOrd<$lhs> for $rhs { - #[inline] - fn partial_cmp(&self, other: &$lhs) -> Option { - let this: &[u8] = self.as_ref(); - PartialOrd::partial_cmp(this, other.as_bytes()) - } - } - }; -} - -#[doc(hidden)] -#[unstable(feature = "bstr_internals", issue = "none")] -pub use impl_partial_eq_ord; - -#[doc(hidden)] -#[macro_export] -#[unstable(feature = "bstr_internals", issue = "none")] -macro_rules! impl_partial_eq_n { - ($lhs:ty, $rhs:ty) => { - #[allow(unused_lifetimes)] - #[unstable(feature = "bstr", issue = "134915")] - impl PartialEq<$rhs> for $lhs { - #[inline] - fn eq(&self, other: &$rhs) -> bool { - let other: &[u8] = other.as_ref(); - PartialEq::eq(self.as_bytes(), other) - } - } - - #[allow(unused_lifetimes)] - #[unstable(feature = "bstr", issue = "134915")] - impl PartialEq<$lhs> for $rhs { - #[inline] - fn eq(&self, other: &$lhs) -> bool { - let this: &[u8] = self.as_ref(); - PartialEq::eq(this, other.as_bytes()) - } - } - }; -} - -#[doc(hidden)] -#[unstable(feature = "bstr_internals", issue = "none")] -pub use impl_partial_eq_n; - -// PartialOrd with `[u8]` omitted to avoid inference failures -impl_partial_eq!(ByteStr, [u8]); -// PartialOrd with `&[u8]` omitted to avoid inference failures -impl_partial_eq!(ByteStr, &[u8]); -// PartialOrd with `str` omitted to avoid inference failures -impl_partial_eq!(ByteStr, str); -// PartialOrd with `&str` omitted to avoid inference failures -impl_partial_eq!(ByteStr, &str); -// PartialOrd with `[u8; N]` omitted to avoid inference failures -impl_partial_eq_n!(ByteStr, [u8; N]); -// PartialOrd with `[u8; N]` omitted to avoid inference failures -impl_partial_eq_n!(ByteStr, &[u8; N]); - -#[unstable(feature = "bstr", issue = "134915")] -impl Ord for ByteStr { - #[inline] - fn cmp(&self, other: &ByteStr) -> Ordering { - Ord::cmp(&self.0, &other.0) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl PartialOrd for ByteStr { - #[inline] - fn partial_cmp(&self, other: &ByteStr) -> Option { - PartialOrd::partial_cmp(&self.0, &other.0) - } -} - #[unstable(feature = "bstr", issue = "134915")] impl<'a> TryFrom<&'a ByteStr> for &'a str { type Error = crate::str::Utf8Error; diff --git a/library/core/src/bstr/traits.rs b/library/core/src/bstr/traits.rs new file mode 100644 index 000000000000..14b862cbb3cc --- /dev/null +++ b/library/core/src/bstr/traits.rs @@ -0,0 +1,275 @@ +//! Trait implementations for `ByteStr`. + +use crate::bstr::ByteStr; +use crate::cmp::Ordering; +use crate::hash; +use crate::ops::{ + Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, +}; + +#[unstable(feature = "bstr", issue = "134915")] +impl Ord for ByteStr { + #[inline] + fn cmp(&self, other: &ByteStr) -> Ordering { + Ord::cmp(&self.0, &other.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl PartialOrd for ByteStr { + #[inline] + fn partial_cmp(&self, other: &ByteStr) -> Option { + PartialOrd::partial_cmp(&self.0, &other.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl PartialEq for ByteStr { + #[inline] + fn eq(&self, other: &ByteStr) -> bool { + &self.0 == &other.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Eq for ByteStr {} + +#[unstable(feature = "bstr", issue = "134915")] +impl hash::Hash for ByteStr { + #[inline] + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "bstr_internals", issue = "none")] +macro_rules! impl_partial_eq { + ($lhs:ty, $rhs:ty) => { + #[allow(unused_lifetimes)] + impl<'a> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + let other: &[u8] = other.as_ref(); + PartialEq::eq(self.as_bytes(), other) + } + } + + #[allow(unused_lifetimes)] + impl<'a> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + let this: &[u8] = self.as_ref(); + PartialEq::eq(this, other.as_bytes()) + } + } + }; +} + +#[doc(hidden)] +#[unstable(feature = "bstr_internals", issue = "none")] +pub use impl_partial_eq; + +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "bstr_internals", issue = "none")] +macro_rules! impl_partial_eq_ord { + ($lhs:ty, $rhs:ty) => { + $crate::bstr::impl_partial_eq!($lhs, $rhs); + + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option { + let other: &[u8] = other.as_ref(); + PartialOrd::partial_cmp(self.as_bytes(), other) + } + } + + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option { + let this: &[u8] = self.as_ref(); + PartialOrd::partial_cmp(this, other.as_bytes()) + } + } + }; +} + +#[doc(hidden)] +#[unstable(feature = "bstr_internals", issue = "none")] +pub use impl_partial_eq_ord; + +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "bstr_internals", issue = "none")] +macro_rules! impl_partial_eq_n { + ($lhs:ty, $rhs:ty) => { + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + let other: &[u8] = other.as_ref(); + PartialEq::eq(self.as_bytes(), other) + } + } + + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + let this: &[u8] = self.as_ref(); + PartialEq::eq(this, other.as_bytes()) + } + } + }; +} + +#[doc(hidden)] +#[unstable(feature = "bstr_internals", issue = "none")] +pub use impl_partial_eq_n; + +// PartialOrd with `[u8]` omitted to avoid inference failures +impl_partial_eq!(ByteStr, [u8]); +// PartialOrd with `&[u8]` omitted to avoid inference failures +impl_partial_eq!(ByteStr, &[u8]); +// PartialOrd with `str` omitted to avoid inference failures +impl_partial_eq!(ByteStr, str); +// PartialOrd with `&str` omitted to avoid inference failures +impl_partial_eq!(ByteStr, &str); +// PartialOrd with `[u8; N]` omitted to avoid inference failures +impl_partial_eq_n!(ByteStr, [u8; N]); +// PartialOrd with `[u8; N]` omitted to avoid inference failures +impl_partial_eq_n!(ByteStr, &[u8; N]); + +#[unstable(feature = "bstr", issue = "134915")] +impl Index for ByteStr { + type Output = u8; + + #[inline] + fn index(&self, idx: usize) -> &u8 { + &self.0[idx] + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, _: RangeFull) -> &ByteStr { + self + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: Range) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeInclusive) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeFrom) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeTo) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeToInclusive) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut for ByteStr { + #[inline] + fn index_mut(&mut self, idx: usize) -> &mut u8 { + &mut self.0[idx] + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut for ByteStr { + #[inline] + fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr { + self + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: Range) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeInclusive) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeFrom) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeTo) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeToInclusive) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} From 9d379e11a6e9d8b491ce7143600495ae101e8c69 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 11 Mar 2025 17:37:36 -0700 Subject: [PATCH 011/176] Implement SliceIndex for ByteStr --- library/core/src/bstr/mod.rs | 7 + library/core/src/bstr/traits.rs | 244 +++++++++--------- tests/ui/indexing/index-help.stderr | 5 +- .../indexing/indexing-requires-a-uint.stderr | 5 +- tests/ui/integral-indexing.stderr | 40 +-- tests/ui/on-unimplemented/slice-index.stderr | 6 +- tests/ui/str/str-idx.stderr | 21 +- tests/ui/str/str-mut-idx.stderr | 19 +- .../suggest-dereferencing-index.stderr | 7 +- 9 files changed, 191 insertions(+), 163 deletions(-) diff --git a/library/core/src/bstr/mod.rs b/library/core/src/bstr/mod.rs index c33dd244ad97..c8d0c701ba8b 100644 --- a/library/core/src/bstr/mod.rs +++ b/library/core/src/bstr/mod.rs @@ -92,6 +92,13 @@ impl ByteStr { pub fn as_bytes(&self) -> &[u8] { &self.0 } + + #[doc(hidden)] + #[unstable(feature = "bstr_internals", issue = "none")] + #[inline] + pub fn as_bytes_mut(&mut self) -> &mut [u8] { + &mut self.0 + } } #[unstable(feature = "bstr", issue = "134915")] diff --git a/library/core/src/bstr/traits.rs b/library/core/src/bstr/traits.rs index 14b862cbb3cc..ff46bb13ba4e 100644 --- a/library/core/src/bstr/traits.rs +++ b/library/core/src/bstr/traits.rs @@ -2,10 +2,8 @@ use crate::bstr::ByteStr; use crate::cmp::Ordering; -use crate::hash; -use crate::ops::{ - Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, -}; +use crate::slice::SliceIndex; +use crate::{hash, ops, range}; #[unstable(feature = "bstr", issue = "134915")] impl Ord for ByteStr { @@ -149,127 +147,131 @@ impl_partial_eq_n!(ByteStr, [u8; N]); impl_partial_eq_n!(ByteStr, &[u8; N]); #[unstable(feature = "bstr", issue = "134915")] -impl Index for ByteStr { +impl ops::Index for ByteStr +where + I: SliceIndex, +{ + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &I::Output { + index.index(self) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl ops::IndexMut for ByteStr +where + I: SliceIndex, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut I::Output { + index.index_mut(self) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +unsafe impl SliceIndex for ops::RangeFull { + type Output = ByteStr; + #[inline] + fn get(self, slice: &ByteStr) -> Option<&Self::Output> { + Some(slice) + } + #[inline] + fn get_mut(self, slice: &mut ByteStr) -> Option<&mut Self::Output> { + Some(slice) + } + #[inline] + unsafe fn get_unchecked(self, slice: *const ByteStr) -> *const Self::Output { + slice + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut ByteStr) -> *mut Self::Output { + slice + } + #[inline] + fn index(self, slice: &ByteStr) -> &Self::Output { + slice + } + #[inline] + fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output { + slice + } +} + +#[unstable(feature = "bstr", issue = "134915")] +unsafe impl SliceIndex for usize { type Output = u8; - #[inline] - fn index(&self, idx: usize) -> &u8 { - &self.0[idx] + fn get(self, slice: &ByteStr) -> Option<&Self::Output> { + self.get(slice.as_bytes()) + } + #[inline] + fn get_mut(self, slice: &mut ByteStr) -> Option<&mut Self::Output> { + self.get_mut(slice.as_bytes_mut()) + } + #[inline] + unsafe fn get_unchecked(self, slice: *const ByteStr) -> *const Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { self.get_unchecked(slice as *const [u8]) } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut ByteStr) -> *mut Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { self.get_unchecked_mut(slice as *mut [u8]) } + } + #[inline] + fn index(self, slice: &ByteStr) -> &Self::Output { + self.index(slice.as_bytes()) + } + #[inline] + fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output { + self.index_mut(slice.as_bytes_mut()) } } -#[unstable(feature = "bstr", issue = "134915")] -impl Index for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, _: RangeFull) -> &ByteStr { - self - } +macro_rules! impl_slice_index { + ($index:ty) => { + #[unstable(feature = "bstr", issue = "134915")] + unsafe impl SliceIndex for $index { + type Output = ByteStr; + #[inline] + fn get(self, slice: &ByteStr) -> Option<&Self::Output> { + self.get(slice.as_bytes()).map(ByteStr::from_bytes) + } + #[inline] + fn get_mut(self, slice: &mut ByteStr) -> Option<&mut Self::Output> { + self.get_mut(slice.as_bytes_mut()).map(ByteStr::from_bytes_mut) + } + #[inline] + unsafe fn get_unchecked(self, slice: *const ByteStr) -> *const Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { self.get_unchecked(slice as *const [u8]) as *const ByteStr } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut ByteStr) -> *mut Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { self.get_unchecked_mut(slice as *mut [u8]) as *mut ByteStr } + } + #[inline] + fn index(self, slice: &ByteStr) -> &Self::Output { + ByteStr::from_bytes(self.index(slice.as_bytes())) + } + #[inline] + fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output { + ByteStr::from_bytes_mut(self.index_mut(slice.as_bytes_mut())) + } + } + }; } -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: Range) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeInclusive) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeFrom) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeTo) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl Index> for ByteStr { - type Output = ByteStr; - - #[inline] - fn index(&self, r: RangeToInclusive) -> &ByteStr { - ByteStr::from_bytes(&self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut for ByteStr { - #[inline] - fn index_mut(&mut self, idx: usize) -> &mut u8 { - &mut self.0[idx] - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut for ByteStr { - #[inline] - fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr { - self - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: Range) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeInclusive) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeFrom) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeTo) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} - -#[unstable(feature = "bstr", issue = "134915")] -impl IndexMut> for ByteStr { - #[inline] - fn index_mut(&mut self, r: RangeToInclusive) -> &mut ByteStr { - ByteStr::from_bytes_mut(&mut self.0[r]) - } -} +impl_slice_index!(ops::IndexRange); +impl_slice_index!(ops::Range); +impl_slice_index!(range::Range); +impl_slice_index!(ops::RangeTo); +impl_slice_index!(ops::RangeFrom); +impl_slice_index!(range::RangeFrom); +impl_slice_index!(ops::RangeInclusive); +impl_slice_index!(range::RangeInclusive); +impl_slice_index!(ops::RangeToInclusive); +impl_slice_index!((ops::Bound, ops::Bound)); diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr index 1974e13eabce..ac79e3f12bd0 100644 --- a/tests/ui/indexing/index-help.stderr +++ b/tests/ui/indexing/index-help.stderr @@ -5,8 +5,9 @@ LL | x[0i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec<{integer}>` to implement `Index` error: aborting due to 1 previous error diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index 5c60a30946d3..62a1ca3d0573 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -5,8 +5,9 @@ LL | [0][0u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[{integer}]` to implement `Index` = note: 1 redundant requirement hidden = note: required for `[{integer}; 1]` to implement `Index` diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr index e7a45c2c88dd..26253e078cb4 100644 --- a/tests/ui/integral-indexing.stderr +++ b/tests/ui/integral-indexing.stderr @@ -5,8 +5,9 @@ LL | v[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i8` @@ -16,8 +17,9 @@ LL | v[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `u32` @@ -27,8 +29,9 @@ LL | v[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i32` @@ -38,8 +41,9 @@ LL | v[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `Vec` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u8` @@ -49,8 +53,9 @@ LL | s.as_bytes()[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i8` @@ -60,8 +65,9 @@ LL | s.as_bytes()[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i8` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u32` @@ -71,8 +77,9 @@ LL | s.as_bytes()[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `u32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i32` @@ -82,8 +89,9 @@ LL | s.as_bytes()[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[u8]` to implement `Index` error: aborting due to 8 previous errors diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr index 0a9ebe3f088e..e011826bc8f7 100644 --- a/tests/ui/on-unimplemented/slice-index.stderr +++ b/tests/ui/on-unimplemented/slice-index.stderr @@ -5,8 +5,9 @@ LL | x[1i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` - but it is implemented for `usize` - = help: for that trait implementation, expected `usize`, found `i32` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[i32]` to implement `Index` error[E0277]: the type `[i32]` cannot be indexed by `RangeTo` @@ -17,6 +18,7 @@ LL | x[..1i32]; | = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo` = help: the following other types implement trait `SliceIndex`: + `RangeTo` implements `SliceIndex` `RangeTo` implements `SliceIndex<[T]>` `RangeTo` implements `SliceIndex` = note: required for `[i32]` to implement `Index>` diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr index bedbbd9cb502..60cae7e84e37 100644 --- a/tests/ui/str/str-idx.stderr +++ b/tests/ui/str/str-idx.stderr @@ -4,11 +4,12 @@ error[E0277]: the type `str` cannot be indexed by `{integer}` LL | let _: u8 = s[4]; | ^ string indices are ranges of `usize` | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `str` to implement `Index<{integer}>` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -19,11 +20,12 @@ LL | let _ = s.get(4); | | | required by a bound introduced by this call | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` note: required by a bound in `core::str::::get` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -35,11 +37,12 @@ LL | let _ = s.get_unchecked(4); | | | required by a bound introduced by this call | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` note: required by a bound in `core::str::::get_unchecked` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index f09a4c329e5d..4e3fe126ed83 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -31,8 +31,9 @@ LL | s[1usize] = bot(); | ^^^^^^ string indices are ranges of `usize` | = help: the trait `SliceIndex` is not implemented for `usize` - but trait `SliceIndex<[_]>` is implemented for it - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `str` to implement `Index` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -43,11 +44,12 @@ LL | s.get_mut(1); | | | required by a bound introduced by this call | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` note: required by a bound in `core::str::::get_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -59,11 +61,12 @@ LL | s.get_unchecked_mut(1); | | | required by a bound introduced by this call | + = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex` is not implemented for `{integer}` - but trait `SliceIndex<[_]>` is implemented for `usize` - = help: for that trait implementation, expected `[_]`, found `str` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` note: required by a bound in `core::str::::get_unchecked_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index 0335d8eafde4..937f32677a6c 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -4,9 +4,10 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `&usize` LL | let one_item_please: i32 = [1, 2, 3][i]; | ^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&_` - but it is implemented for `_` - = help: for that trait implementation, expected `usize`, found `&usize` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize` + = help: the following other types implement trait `SliceIndex`: + `usize` implements `SliceIndex` + `usize` implements `SliceIndex<[T]>` = note: required for `[{integer}]` to implement `Index<&usize>` = note: 1 redundant requirement hidden = note: required for `[{integer}; 3]` to implement `Index<&usize>` From 2d2307e6163816511790c3bb61e07913d9cb66c1 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Thu, 13 Mar 2025 13:01:53 +0100 Subject: [PATCH 012/176] Dedup `&mut *` reborrow suggestion in loops --- .../src/diagnostics/conflict_errors.rs | 13 ------------- tests/ui/borrowck/mut-borrow-in-loop-2.stderr | 4 ---- 2 files changed, 17 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2694a1eda78d..a2df4e4e47d5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -181,7 +181,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err); let mut is_loop_move = false; - let mut in_pattern = false; let mut seen_spans = FxIndexSet::default(); for move_site in &move_site_vec { @@ -204,7 +203,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_ref_or_clone( mpi, &mut err, - &mut in_pattern, move_spans, moved_place.as_ref(), &mut has_suggest_reborrow, @@ -256,15 +254,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let place = &self.move_data.move_paths[mpi].place; let ty = place.ty(self.body, self.infcx.tcx).ty; - // If we're in pattern, we do nothing in favor of the previous suggestion (#80913). - // Same for if we're in a loop, see #101119. - if is_loop_move & !in_pattern && !matches!(use_spans, UseSpans::ClosureUse { .. }) { - if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() { - // We have a `&mut` ref, we need to reborrow on each iteration (#62112). - self.suggest_reborrow(&mut err, span, moved_place); - } - } - if self.infcx.param_env.caller_bounds().iter().any(|c| { c.as_trait_clause().is_some_and(|pred| { pred.skip_binder().self_ty() == ty && self.infcx.tcx.is_fn_trait(pred.def_id()) @@ -330,7 +319,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { &self, mpi: MovePathIndex, err: &mut Diag<'infcx>, - in_pattern: &mut bool, move_spans: UseSpans<'tcx>, moved_place: PlaceRef<'tcx>, has_suggest_reborrow: &mut bool, @@ -545,7 +533,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && !move_span.is_dummy() && !self.infcx.tcx.sess.source_map().is_imported(move_span) { - *in_pattern = true; let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())]; if let Some(pat) = finder.parent_pat { sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string())); diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr index 4f32df1eb24e..46e06bc91b91 100644 --- a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr +++ b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr @@ -12,10 +12,6 @@ help: consider creating a fresh reborrow of `value` here | LL | Other::handle(&mut *value); | ++++++ -help: consider creating a fresh reborrow of `value` here - | -LL | Other::handle(&mut *value); - | ++++++ error: aborting due to 1 previous error From bacd57a583338b5667046abe474e728a5e881cd0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 16 Mar 2025 14:45:08 +0100 Subject: [PATCH 013/176] Add integer to string formatting tests --- library/alloctests/tests/lib.rs | 1 + library/alloctests/tests/num.rs | 69 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 library/alloctests/tests/num.rs diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 46c11ea150bf..f1f4cc6f93bb 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -63,6 +63,7 @@ mod fmt; mod heap; mod linked_list; mod misc_tests; +mod num; mod rc; mod slice; mod sort; diff --git a/library/alloctests/tests/num.rs b/library/alloctests/tests/num.rs new file mode 100644 index 000000000000..c9c0cd09ff6a --- /dev/null +++ b/library/alloctests/tests/num.rs @@ -0,0 +1,69 @@ +use std::fmt::{Debug, Display}; +use std::str::FromStr; + +fn assert_nb(value: Int) { + let s = value.to_string(); + let s2 = format!("{}", value); + + assert_eq!(s, s2); + let Ok(ret) = Int::from_str(&s) else { + panic!("failed to convert into to string"); + }; + assert_eq!(ret, value); +} + +macro_rules! uint_to_s { + ($($fn_name:ident, $int:ident,)+) => { + $( + #[test] + fn $fn_name() { + assert_nb::<$int>($int::MIN); + assert_nb::<$int>($int::MAX); + assert_nb::<$int>(1); + assert_nb::<$int>($int::MIN / 2); + assert_nb::<$int>($int::MAX / 2); + } + )+ + } +} +macro_rules! int_to_s { + ($($fn_name:ident, $int:ident,)+) => { + $( + #[test] + fn $fn_name() { + assert_nb::<$int>($int::MIN); + assert_nb::<$int>($int::MAX); + assert_nb::<$int>(1); + assert_nb::<$int>(0); + assert_nb::<$int>(-1); + assert_nb::<$int>($int::MIN / 2); + assert_nb::<$int>($int::MAX / 2); + } + )+ + } +} + +int_to_s!( + test_i8_to_string, + i8, + test_i16_to_string, + i16, + test_i32_to_string, + i32, + test_i64_to_string, + i64, + test_i128_to_string, + i128, +); +uint_to_s!( + test_u8_to_string, + u8, + test_u16_to_string, + u16, + test_u32_to_string, + u32, + test_u64_to_string, + u64, + test_u128_to_string, + u128, +); From a4b76e31f8f906e31256b2c8f696e39b2ee36c41 Mon Sep 17 00:00:00 2001 From: Yang Lin Date: Sun, 16 Mar 2025 23:27:10 +0800 Subject: [PATCH 014/176] Adapt to rust-lang/rust#136466: Start removing `rustc_middle::hir::map::Map` Following commit f86f7ad from pull request #136466 in the Rust project (https://github.com/rust-lang/rust), some methods in `Map` were moved to `TyCtxt`. This update reimplements `rustc-drive-example.rs`, `rustc-driver-interacting-with-the-ast.rs`, and `rustc-interface-example.rs` using the new versions of these methods, ensuring compatibility with the nightly-2025-03-08 toolchain. --- src/doc/rustc-dev-guide/examples/rustc-driver-example.rs | 7 +++---- .../examples/rustc-driver-interacting-with-the-ast.rs | 8 +++----- .../rustc-dev-guide/examples/rustc-interface-example.rs | 7 +++---- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 984bd3e37ae3..35dd07dd1365 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-08 #![feature(rustc_private)] @@ -71,9 +71,8 @@ impl rustc_driver::Callbacks for MyCallbacks { fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { // Analyze the program and inspect the types of definitions. - for id in tcx.hir().items() { - let hir = tcx.hir(); - let item = hir.item(id); + for id in tcx.hir_free_items(){ + let item = &tcx.hir_item(id); match item.kind { rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { let name = item.ident; diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index 3270c722e077..2a43ba476e1e 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-08 #![feature(rustc_private)] @@ -70,11 +70,9 @@ impl rustc_driver::Callbacks for MyCallbacks { } fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { - // Every compilation contains a single crate. - let hir_krate = tcx.hir(); // Iterate over the top-level items in the crate, looking for the main function. - for id in hir_krate.items() { - let item = hir_krate.item(id); + for id in tcx.hir_free_items(){ + let item = &tcx.hir_item(id); // Use pattern-matching to find a specific node inside the main function. if let rustc_hir::ItemKind::Fn { body, .. } = item.kind { let expr = &tcx.hir_body(body).value; diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs index 70f27c2a82a9..11125caec704 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-08 #![feature(rustc_private)] @@ -64,9 +64,8 @@ fn main() { println!("{krate:?}"); // Analyze the program and inspect the types of definitions. rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| { - for id in tcx.hir().items() { - let hir = tcx.hir(); - let item = hir.item(id); + for id in tcx.hir_free_items() { + let item = tcx.hir_item(id); match item.kind { rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { let name = item.ident; From 9a2d1fdb141ec2db9be1802316c66722f7b678f8 Mon Sep 17 00:00:00 2001 From: Yang Lin Date: Sun, 16 Mar 2025 23:43:17 +0800 Subject: [PATCH 015/176] Following commit 401dd84 in the Rust project (https://github.com/rust-lang/rust), `ErrorGuaranteed` was replaced by fatal errors. As a result, `tcx.analysis()` now aborts directly instead of returning an error guard. To accommodate this change, this update replaces `tcx.analysis()` with `typeck()` to perform type checking in the example. --- .../examples/rustc-interface-getting-diagnostics.rs | 8 +++++--- .../src/rustc-driver/getting-diagnostics.md | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs index 39b236e1783a..9bb93ab49587 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-08 #![feature(rustc_private)] @@ -86,8 +86,10 @@ fn main() { rustc_interface::run_compiler(config, |compiler| { let krate = rustc_interface::passes::parse(&compiler.sess); rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| { - // Run the analysis phase on the local crate to trigger the type error. - let _ = tcx.analysis(()); + // Iterate all the items defined and perform type checking. + tcx.par_hir_body_owners(|item_def_id| { + tcx.ensure_ok().typeck(item_def_id); + }); }); // If the compiler has encountered errors when this closure returns, it will abort (!) the program. // We avoid this by resetting the error count before returning diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md b/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md index 1043df6ecb65..518cf4e821a7 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md @@ -7,7 +7,7 @@ otherwise be printed to stderr. To get diagnostics from the compiler, configure [`rustc_interface::Config`] to output diagnostic to a buffer, -and run [`TyCtxt.analysis`]. +and run [`rustc_hir_typeck::typeck`] for each item. ```rust {{#include ../../examples/rustc-interface-getting-diagnostics.rs}} @@ -16,3 +16,4 @@ and run [`TyCtxt.analysis`]. [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html [`rustc_interface::Config`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html [`TyCtxt.analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.analysis.html +[`rustc_hir_typeck::typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn.typeck.html From 3e448fd4f5e55b24b943dd4d85287ce0b17105ee Mon Sep 17 00:00:00 2001 From: xizheyin Date: Wed, 5 Mar 2025 13:18:17 +0800 Subject: [PATCH 016/176] Add chapter Remarks on perma-unstable features Signed-off-by: xizheyin --- src/doc/rustc-dev-guide/src/SUMMARY.md | 1 + .../remarks-on-perma-unstable-features.md | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 106db508ebbc..71b58f79daf2 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -124,6 +124,7 @@ - [rustc_driver and rustc_interface](./rustc-driver/intro.md) - [Example: Type checking](./rustc-driver/interacting-with-the-ast.md) - [Example: Getting diagnostics](./rustc-driver/getting-diagnostics.md) + - [Remarks on perma-unstable features](./rustc-driver/remarks-on-perma-unstable-features.md) - [Errors and Lints](diagnostics.md) - [Diagnostic and subdiagnostic structs](./diagnostics/diagnostic-structs.md) - [Translation](./diagnostics/translation.md) diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md new file mode 100644 index 000000000000..c307adc00a00 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md @@ -0,0 +1,55 @@ + +# Remarks on perma unstable features + +## `rustc_private` + +### Overview + +The `rustc_private` feature allows external crates to use compiler internals. + +### Using `rustc-private` with Official Toolchains + +When using the `rustc_private` feature with official Rust toolchains distributed via rustup, you need to install two additional components: + +1. **`rustc-dev`**: Provides compiler libraries +2. **`llvm-tools`**: Provides LLVM libraries required for linking + +#### Installation Steps + +Install both components using rustup: + +```bash +rustup component add rustc-dev llvm-tools +``` + +#### Common Error + +Without the `llvm-tools` component, you'll encounter linking errors like: + +``` +error: linking with `cc` failed: exit status: 1 + | + = note: rust-lld: error: unable to find library -lLLVM-{version} +``` + +### Using `rustc-private` with Custom Toolchains + +For custom-built toolchains or environments not using rustup, additional configuration is typically required: + +#### Requirements + +- LLVM libraries must be available in your system's library search paths +- The LLVM version must match the one used to build your Rust toolchain + +#### Troubleshooting Steps + +1. **Check LLVM installation**: Verify LLVM is installed and accessible +2. **Configure library paths**: You may need to set environment variables: + ```bash + export LD_LIBRARY_PATH=/path/to/llvm/lib:$LD_LIBRARY_PATH + ``` +3. **Check version compatibility**: Ensure your LLVM version is compatible with your Rust toolchain + +### Additional Resources + +- [GitHub Issue #137421](https://github.com/rust-lang/rust/issues/137421): Explains that `rustc_private` linker failures often occur because `llvm-tools` is not installed From 74698d7c2cb9cc6722b9ce5c7b32e3da61e38e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 18 Mar 2025 16:16:28 +0100 Subject: [PATCH 017/176] Add Fuchsia ping group notice --- src/doc/rustc-dev-guide/src/tests/fuchsia.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/tests/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/fuchsia.md index e96290b92152..926803368f08 100644 --- a/src/doc/rustc-dev-guide/src/tests/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/fuchsia.md @@ -4,6 +4,14 @@ million lines of Rust code.[^loc] It has caught a large number of [regressions] in the past and was subsequently included in CI. +## What to do if the Fuchsia job breaks? + +Please contact the `fuchsia` ping group and ask them for help. + +```text +@rustbot ping fuchsia +``` + ## Building Fuchsia in CI Fuchsia builds as part of the suite of bors tests that run before a pull request From 9ff4936afbc57912aed05f822133af6b5da3f0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 18 Mar 2025 16:17:59 +0100 Subject: [PATCH 018/176] Reorder RfL tests page to move the "what if it breaks" section to the top --- .../src/tests/rust-for-linux.md | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md b/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md index c674d1575b78..bdf32ffc398d 100644 --- a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md +++ b/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md @@ -3,26 +3,7 @@ [Rust for Linux](https://rust-for-linux.com/) (RfL) is an effort for adding support for the Rust programming language into the Linux kernel. -## Building Rust for Linux in CI - -Rust for Linux builds as part of the suite of bors tests that run before a pull -request is merged. - -The workflow builds a stage1 sysroot of the Rust compiler, downloads the Linux -kernel, and tries to compile several Rust for Linux drivers and examples using -this sysroot. RfL uses several unstable compiler/language features, therefore -this workflow notifies us if a given compiler change would break it. - -If you are worried that a pull request might break the Rust for Linux builder -and want to test it out before submitting it to the bors queue, simply add this -line to your PR description: - -> try-job: x86_64-rust-for-linux - -Then when you `@bors try` it will pick the job that builds the Rust for Linux -integration. - -## What to do in case of failure +## What to do if the Rust for Linux job breaks? If a PR breaks the Rust for Linux CI job, then: @@ -48,4 +29,23 @@ ping group to ask for help: @rustbot ping rfl ``` +## Building Rust for Linux in CI + +Rust for Linux builds as part of the suite of bors tests that run before a pull +request is merged. + +The workflow builds a stage1 sysroot of the Rust compiler, downloads the Linux +kernel, and tries to compile several Rust for Linux drivers and examples using +this sysroot. RfL uses several unstable compiler/language features, therefore +this workflow notifies us if a given compiler change would break it. + +If you are worried that a pull request might break the Rust for Linux builder +and want to test it out before submitting it to the bors queue, simply add this +line to your PR description: + +> try-job: x86_64-rust-for-linux + +Then when you `@bors try` it will pick the job that builds the Rust for Linux +integration. + [rfl-ping]: ../notification-groups/rust-for-linux.md From c987d34a7e14abf5b7065bfd6c27eb52d2863773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 18 Mar 2025 16:19:55 +0100 Subject: [PATCH 019/176] Add Fuchsia ping group page --- src/doc/rustc-dev-guide/src/SUMMARY.md | 3 ++- .../src/notification-groups/fuchsia.md | 12 ++++++++++++ src/doc/rustc-dev-guide/src/tests/fuchsia.md | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index a090f96f3f80..9e2d0774aab0 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -61,12 +61,13 @@ - [ARM](notification-groups/arm.md) - [Cleanup Crew](notification-groups/cleanup-crew.md) - [Emscripten](notification-groups/emscripten.md) + - [Fuchsia](notification-groups/fuchsia.md) - [LLVM](notification-groups/llvm.md) - [RISC-V](notification-groups/risc-v.md) + - [Rust for Linux](notification-groups/rust-for-linux.md) - [WASI](notification-groups/wasi.md) - [WebAssembly](notification-groups/wasm.md) - [Windows](notification-groups/windows.md) - - [Rust for Linux](notification-groups/rust-for-linux.md) - [Licenses](./licenses.md) - [Editions](guides/editions.md) diff --git a/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md new file mode 100644 index 000000000000..a4658e0d842f --- /dev/null +++ b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md @@ -0,0 +1,12 @@ +# Fuchsia notification group + +**Github Label:** [O-fuchsia]
+**Ping command:** `@rustbot ping fuchsia` + +[O-fuchsia]: https://github.com/rust-lang/rust/labels/O-fuchsia + +This list will be used to notify [Fuchsia][fuchsia] maintainers +when the compiler or the standard library changes in a way that would +break the Fuchsia integration. + +[fuchsia]: ../tests/fuchsia.md diff --git a/src/doc/rustc-dev-guide/src/tests/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/fuchsia.md index 926803368f08..2766c362cc26 100644 --- a/src/doc/rustc-dev-guide/src/tests/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/fuchsia.md @@ -6,7 +6,7 @@ in the past and was subsequently included in CI. ## What to do if the Fuchsia job breaks? -Please contact the `fuchsia` ping group and ask them for help. +Please contact the [fuchsia][fuchsia-ping] ping group and ask them for help. ```text @rustbot ping fuchsia @@ -170,6 +170,7 @@ rustc book][platform-support]. [`public_configs`]: https://gn.googlesource.com/gn/+/main/docs/reference.md#var_public_configs [`//build/config:compiler`]: https://cs.opensource.google/fuchsia/fuchsia/+/main:build/config/BUILD.gn;l=121;drc=c26c473bef93b33117ae417893118907a026fec7 [build system]: https://fuchsia.dev/fuchsia-src/development/build/build_system +[fuchsia-ping]: ../notification-groups/fuchsia.md [^loc]: As of June 2024, Fuchsia had about 2 million lines of first-party Rust code and a roughly equal amount of third-party code, as counted by tokei From 4f053a9ee9f6816cad66c13b0777b22b0d8854bf Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 12:04:47 -0500 Subject: [PATCH 020/176] add new section on the `rustdoc` test suite --- .../src/rustdoc-internals/htmldocck.md | 101 ++++++++++++++++++ src/doc/rustc-dev-guide/src/rustdoc.md | 14 +-- .../rustc-dev-guide/src/tests/compiletest.md | 2 +- 3 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md new file mode 100644 index 000000000000..d69627f46cc5 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md @@ -0,0 +1,101 @@ +# `rustdoc` tests + +This page is specifically about the `rustdoc` test suite, for other test suites used for testing rustdoc, see [Rustdoc § Tests](../rustdoc.md#tests). + +`htmldocck.py` is a custom checker script that uses [XPath] to verify the HTML output of rustdoc. + +[XPath]: https://en.wikipedia.org/wiki/XPath + +## Directives +Directives to htmldocck are similar to those given to `compiletest` in that they take the form of `//@` comments. + +All `PATH`s in directives are relative to the the rustdoc output directory (`build/TARGET/test/rustdoc/TESTNAME`), +so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid writing paths. +To avoid repetion, `-` can be used in any `PATH` argument to re-use the previous `PATH` argument. + +All arguments take the form of quoted strings, +with the exception of `COUNT` and the special `-` form of `PATH`. + +Directives are assertions that place constraints on the generated HTML. + +All directives (except `files`) can be negated by putting a `!` in front of their name. + +Similar to shell commands, +directives can extend across multiple lines if their last char is `\`. +In this case, the start of the next line should be `//`, with no `@`. + +For example, `//@ !has 'foo/struct.Bar.html'` checks that crate `foo` does not have a page for a struct named `Bar` in the crate root. + +### `has` + +Usage 1: `//@ has PATH` +Usage 2: `//@ has PATH XPATH PATTERN` + +In the first form, `has` checks that a given file exists. + +In the second form, `has` is an alias for `matches`, +except `PATTERN` is a whitespace-normalized[^1] string instead of a regex. + +### `matches` + +Usage: `//@ matches PATH XPATH PATTERN` + +Checks that the text of each element selected by `XPATH` in `PATH` matches the python-flavored regex `PATTERN`. + +### `matchesraw` + +Usage: `//@ matchesraw PATH PATTERN` + +Checks that the contents of the file `PATH` matches the regex `PATTERN`. + +### `hasraw` + +Usage: `//@ hasraw PATH PATTERN` + +Same as `matchesraw`, except `PATTERN` is a whitespace-normalized[^1] string instead of a regex. + +### `count` + +Usage: `//@ count PATH XPATH COUNT` + +Checks that there are exactly `COUNT` matches for `XPATH` within the file `PATH`. + +### `snapshot` + +Usage: `//@ snapshot NAME PATH XPATH` + +Creates a snapshot test named NAME. +A snapshot test captures a subtree of the DOM, at the location +determined by the XPath, and compares it to a pre-recorded value +in a file. The file's name is the test's name with the `.rs` extension +replaced with `.NAME.html`, where NAME is the snapshot's name. + +htmldocck supports the `--bless` option to accept the current subtree +as expected, saving it to the file determined by the snapshot's name. +compiletest's `--bless` flag is forwarded to htmldocck. + +### `has-dir` + +Usage: `//@ has-dir PATH` + +Checks for the existance of directory `PATH`. + +### `files` + +Usage: `//@ files PATH ENTRIES` + +Checks that the directory `PATH` contains exactly `ENTRIES`. +`ENTRIES` is a python list of strings inside a quoted string, +as if it were to be parsed by `eval`. +(note that the list is actually parsed by `shlex.split`, +so it cannot contain arbitrary python expressions). + +Example: `//@ files "foo/bar" '["index.html", "sidebar-items.js"]'` + +[^1]: Whitespace normalization means that all spans of consecutive whitespace are replaced with a single space. The files themselves are also whitespace-normalized. + +## Limitations +All `XPATH` arguments must start with `//` due to a flaw in the implemention. + +Only well-formed HTML can be parsed (hopefully rustdoc doesn't output mismatched tags). + diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index 356698148e40..5ac62aa2c376 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -77,27 +77,27 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) `doctest.rs`. * The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting doctests from a given block of Markdown. -* The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`, where - they're handled by the test runner of bootstrap and the supplementary script - `src/etc/htmldocck.py`. * Frontend CSS and JavaScript are stored in `html/static/`. ## Tests -* All paths in this section are relative to `tests` in the rust-lang/rust repository. -* Tests on search engine and index are located in `rustdoc-js` and `rustdoc-js-std`. +* Tests on search engine and index are located in `tests/rustdoc-js` and `tests/rustdoc-js-std`. The format is specified [in the search guide](rustdoc-internals/search.md#testing-the-search-engine). * Tests on the "UI" of rustdoc (the terminal output it produces when run) are in - `rustdoc-ui` + `tests/rustdoc-ui` * Tests on the "GUI" of rustdoc (the HTML, JS, and CSS as rendered in a browser) - are in `rustdoc-gui`. These use a [NodeJS tool called + are in `tests/rustdoc-gui`. These use a [NodeJS tool called browser-UI-test](https://github.com/GuillaumeGomez/browser-UI-test/) that uses puppeteer to run tests in a headless browser and check rendering and interactivity. * Additionally, JavaScript type annotations are written using [TypeScript-flavored JSDoc] comments and an external d.ts file. The code itself is plain, valid JavaScript; we only use tsc as a linter. +* The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`, + where they're handled by the test runner of bootstrap and + the supplementary script `src/etc/htmldocck.py`. + [These tests have several extra directives available to them](./rustdoc-internals/htmldocck.md). [TypeScript-flavored JSDoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 2c35381eadfb..ee66b787bf1b 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -78,7 +78,7 @@ The following test suites are available, with links for more information: ### Rustdoc test suites -See [Rustdoc tests](../rustdoc.md#tests) for more details. +See [Rustdoc § Tests](../rustdoc.md#tests) for more details. | Test suite | Purpose | |------------------|--------------------------------------------------------------------------| From 3668c366621043dce7dc9fddca19a60945526fae Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 12:10:43 -0500 Subject: [PATCH 021/176] add htmldocck.md to SUMMARY.md --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 9e2d0774aab0..fb468777409b 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -95,7 +95,7 @@ - [Parallel Compilation](./parallel-rustc.md) - [Rustdoc internals](./rustdoc-internals.md) - [Search](./rustdoc-internals/search.md) - + - [`rustdoc` tests](./rustdoc-internals/htmldocck.md) # Source Code Representation - [Prologue](./part-3-intro.md) From a172f23df0b108d6d615d1433ae3de51afd292b6 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:10:26 -0500 Subject: [PATCH 022/176] htmldocck: expand limitations and mention compiletest directives --- .../src/rustdoc-internals/htmldocck.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md index d69627f46cc5..b37c1ac3de1b 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md @@ -9,6 +9,10 @@ This page is specifically about the `rustdoc` test suite, for other test suites ## Directives Directives to htmldocck are similar to those given to `compiletest` in that they take the form of `//@` comments. +In addition to the directives listed here, +`rustdoc` tests also support most +[compiletest directives](../tests/directives.html). + All `PATH`s in directives are relative to the the rustdoc output directory (`build/TARGET/test/rustdoc/TESTNAME`), so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid writing paths. To avoid repetion, `-` can be used in any `PATH` argument to re-use the previous `PATH` argument. @@ -95,7 +99,9 @@ Example: `//@ files "foo/bar" '["index.html", "sidebar-items.js"]'` [^1]: Whitespace normalization means that all spans of consecutive whitespace are replaced with a single space. The files themselves are also whitespace-normalized. ## Limitations -All `XPATH` arguments must start with `//` due to a flaw in the implemention. - -Only well-formed HTML can be parsed (hopefully rustdoc doesn't output mismatched tags). +`htmldocck.py` uses the xpath implementation from the standard library. +This leads to several limitations: +* All `XPATH` arguments must start with `//` due to a flaw in the implemention. +* Many XPath features (functions, axies, etc.) are not supported. +* Only well-formed HTML can be parsed (hopefully rustdoc doesn't output mismatched tags). From 6893f0ac7aaf2c02e48c6434f98febe58def1f95 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:19:33 -0500 Subject: [PATCH 023/176] rustdoc test suite: clean up wording and intro --- .../rustc-dev-guide/src/rustdoc-internals/htmldocck.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md index b37c1ac3de1b..97c40c8a8202 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md @@ -1,8 +1,10 @@ -# `rustdoc` tests +# the `rustdoc` test suite This page is specifically about the `rustdoc` test suite, for other test suites used for testing rustdoc, see [Rustdoc § Tests](../rustdoc.md#tests). -`htmldocck.py` is a custom checker script that uses [XPath] to verify the HTML output of rustdoc. +The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. + +This is achived by means of `htmldocck.py`, a custom checker script that leverages [XPath]. [XPath]: https://en.wikipedia.org/wiki/XPath @@ -14,7 +16,8 @@ In addition to the directives listed here, [compiletest directives](../tests/directives.html). All `PATH`s in directives are relative to the the rustdoc output directory (`build/TARGET/test/rustdoc/TESTNAME`), -so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid writing paths. +so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid +having to write a long crate name multiple times. To avoid repetion, `-` can be used in any `PATH` argument to re-use the previous `PATH` argument. All arguments take the form of quoted strings, From 1081d98cf679560b02f6db4b2d72bb3103b92073 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:21:15 -0500 Subject: [PATCH 024/176] rename htmldocck.md -> rustdoc-test-suite.md --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- .../rustdoc-internals/{htmldocck.md => rustdoc-test-suite.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/doc/rustc-dev-guide/src/rustdoc-internals/{htmldocck.md => rustdoc-test-suite.md} (100%) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index fb468777409b..8ea5e86cd63a 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -95,7 +95,7 @@ - [Parallel Compilation](./parallel-rustc.md) - [Rustdoc internals](./rustdoc-internals.md) - [Search](./rustdoc-internals/search.md) - - [`rustdoc` tests](./rustdoc-internals/htmldocck.md) + - [the `rustdoc` test suite](./rustdoc-internals/rustdoc-test-suite.md) # Source Code Representation - [Prologue](./part-3-intro.md) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md similarity index 100% rename from src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md rename to src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md From 40b9be0c456d32cf01441ec1c96fec1523d4737f Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:23:37 -0500 Subject: [PATCH 025/176] clean up wording/grammar and mention double quotes --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- .../src/rustdoc-internals/rustdoc-test-suite.md | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 8ea5e86cd63a..075d5af4c24a 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -95,7 +95,7 @@ - [Parallel Compilation](./parallel-rustc.md) - [Rustdoc internals](./rustdoc-internals.md) - [Search](./rustdoc-internals/search.md) - - [the `rustdoc` test suite](./rustdoc-internals/rustdoc-test-suite.md) + - [The `rustdoc` test suite](./rustdoc-internals/rustdoc-test-suite.md) # Source Code Representation - [Prologue](./part-3-intro.md) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md index 97c40c8a8202..fb4be51c278a 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -1,6 +1,6 @@ -# the `rustdoc` test suite +# The `rustdoc` test suite -This page is specifically about the `rustdoc` test suite, for other test suites used for testing rustdoc, see [Rustdoc § Tests](../rustdoc.md#tests). +This page is specifically about the test suite named `rustdoc`, for other test suites used for testing rustdoc, see [Rustdoc Tests](../rustdoc.md#tests). The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. @@ -20,7 +20,8 @@ so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid having to write a long crate name multiple times. To avoid repetion, `-` can be used in any `PATH` argument to re-use the previous `PATH` argument. -All arguments take the form of quoted strings, +All arguments take the form of quoted strings +(both single and double quotes are supported), with the exception of `COUNT` and the special `-` form of `PATH`. Directives are assertions that place constraints on the generated HTML. From 7f29b47410d62cc1d81c0105add357552a0f1c99 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:25:39 -0500 Subject: [PATCH 026/176] normalize link titles --- .../rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md | 2 +- src/doc/rustc-dev-guide/src/tests/compiletest.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md index fb4be51c278a..c2a2e6495f82 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -1,6 +1,6 @@ # The `rustdoc` test suite -This page is specifically about the test suite named `rustdoc`, for other test suites used for testing rustdoc, see [Rustdoc Tests](../rustdoc.md#tests). +This page is specifically about the test suite named `rustdoc`, for other test suites used for testing rustdoc, see [Rustdoc tests](../rustdoc.md#tests). The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index ee66b787bf1b..2c35381eadfb 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -78,7 +78,7 @@ The following test suites are available, with links for more information: ### Rustdoc test suites -See [Rustdoc § Tests](../rustdoc.md#tests) for more details. +See [Rustdoc tests](../rustdoc.md#tests) for more details. | Test suite | Purpose | |------------------|--------------------------------------------------------------------------| From eeda54f1102d514a9f73c2d5ed92e75b2edfe94e Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:29:14 -0500 Subject: [PATCH 027/176] update filename in link --- src/doc/rustc-dev-guide/src/rustdoc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index 5ac62aa2c376..320dc9d58258 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -97,7 +97,7 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) * The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`, where they're handled by the test runner of bootstrap and the supplementary script `src/etc/htmldocck.py`. - [These tests have several extra directives available to them](./rustdoc-internals/htmldocck.md). + [These tests have several extra directives available to them](./rustdoc-internals/rustdoc-test-suite.md). [TypeScript-flavored JSDoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html From e41cce03a00d29d56f0bb74fb0d5d3e69ee7dfc8 Mon Sep 17 00:00:00 2001 From: Andrei Damian Date: Sun, 2 Mar 2025 21:51:23 +0200 Subject: [PATCH 028/176] fix pthread-based tls on apple targets --- library/std/src/sys/thread_local/mod.rs | 1 + library/std/tests/thread_local/lib.rs | 2 + library/std/tests/thread_local/tests.rs | 21 ++++++++++- tests/run-make/apple-slow-tls/rmake.rs | 37 +++++++++++++++++++ .../apple-slow-tls/tls_test/Cargo.toml | 6 +++ .../apple-slow-tls/tls_test/src/main.rs | 10 +++++ 6 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 tests/run-make/apple-slow-tls/rmake.rs create mode 100644 tests/run-make/apple-slow-tls/tls_test/Cargo.toml create mode 100644 tests/run-make/apple-slow-tls/tls_test/src/main.rs diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index 1ff13154b7b3..b7ce6fcdc05a 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -138,6 +138,7 @@ pub(crate) mod key { not(target_family = "wasm"), target_family = "unix", ), + all(not(target_thread_local), target_vendor = "apple"), target_os = "teeos", all(target_os = "wasi", target_env = "p1", target_feature = "atomics"), ))] { diff --git a/library/std/tests/thread_local/lib.rs b/library/std/tests/thread_local/lib.rs index c52914354253..26af5f1eb0a9 100644 --- a/library/std/tests/thread_local/lib.rs +++ b/library/std/tests/thread_local/lib.rs @@ -1,3 +1,5 @@ +#![feature(cfg_target_thread_local)] + #[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] mod tests; diff --git a/library/std/tests/thread_local/tests.rs b/library/std/tests/thread_local/tests.rs index aa020c2559cc..e8278361d933 100644 --- a/library/std/tests/thread_local/tests.rs +++ b/library/std/tests/thread_local/tests.rs @@ -1,7 +1,7 @@ use std::cell::{Cell, UnsafeCell}; use std::sync::atomic::{AtomicU8, Ordering}; use std::sync::{Arc, Condvar, Mutex}; -use std::thread::{self, Builder, LocalKey}; +use std::thread::{self, LocalKey}; use std::thread_local; #[derive(Clone, Default)] @@ -345,8 +345,27 @@ fn join_orders_after_tls_destructors() { } // Test that thread::current is still available in TLS destructors. +// +// The test won't currently work without target_thread_local, aka with slow tls. +// The runtime tries very hard to drop last the TLS variable that keeps the information about the +// current thread, by using several tricks like deffering the drop to a later round of TLS destruction. +// However, this only seems to work with fast tls. +// +// With slow TLS, it seems that multiple libc implementations will just set the value to null the first +// time they encounter it, regardless of it having a destructor or not. This means that trying to +// retrieve it later in a drop impl of another TLS variable will not work. +// +// ** Apple libc: https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread_tsd.c#L293 +// Sets the variable to null if it has a destructor and the value is not null. However, all variables +// created with pthread_key_create are marked as having a destructor, even if the fn ptr called with +// it is null. +// ** glibc: https://github.com/bminor/glibc/blob/e5893e6349541d871e8a25120bca014551d13ff5/nptl/nptl_deallocate_tsd.c#L59 +// ** musl: https://github.com/kraj/musl/blob/1880359b54ff7dd9f5016002bfdae4b136007dde/src/thread/pthread_key_create.c#L87 +#[cfg(target_thread_local)] #[test] fn thread_current_in_dtor() { + use std::thread::Builder; + // Go through one round of TLS destruction first. struct Defer; impl Drop for Defer { diff --git a/tests/run-make/apple-slow-tls/rmake.rs b/tests/run-make/apple-slow-tls/rmake.rs new file mode 100644 index 000000000000..231e0b1668e9 --- /dev/null +++ b/tests/run-make/apple-slow-tls/rmake.rs @@ -0,0 +1,37 @@ +//! Test if compilation with has-thread-local=false works, and if the output +//! has indeed no fast TLS variables. + +//@ only-apple + +use run_make_support::serde_json::{self, Value}; +use run_make_support::{cargo, llvm_nm, rfs, rustc}; + +fn main() { + let output = + rustc().print("target-spec-json").args(["-Z", "unstable-options"]).run().stdout_utf8(); + + let mut target_json: Value = serde_json::from_str(&output).unwrap(); + let has_thread_local = &mut target_json["has-thread-local"]; + assert!(matches!(has_thread_local, Value::Bool(true)), "{:?}", has_thread_local); + *has_thread_local = Value::Bool(false); + + let out_path = "t.json"; + rfs::write(out_path, serde_json::to_string(&target_json).unwrap()); + + cargo() + .args([ + "b", + "--manifest-path", + "tls_test/Cargo.toml", + "--target", + "t.json", + "-Zbuild-std=std,core,panic_abort", + ]) + .run(); + + // If a binary has any fast TLS variables, it should also contain the symbols + // __tlv_bootstrap and __tlv_atexit. We don't want them. + let output = llvm_nm().arg("tls_test/target/t/debug/tls_test").run().stdout_utf8(); + assert!(!output.contains("_tlv_bootstrap")); + assert!(!output.contains("_tlv_atexit")); +} diff --git a/tests/run-make/apple-slow-tls/tls_test/Cargo.toml b/tests/run-make/apple-slow-tls/tls_test/Cargo.toml new file mode 100644 index 000000000000..c8e5a228eef7 --- /dev/null +++ b/tests/run-make/apple-slow-tls/tls_test/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "tls_test" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/tests/run-make/apple-slow-tls/tls_test/src/main.rs b/tests/run-make/apple-slow-tls/tls_test/src/main.rs new file mode 100644 index 000000000000..d48d22bb3d17 --- /dev/null +++ b/tests/run-make/apple-slow-tls/tls_test/src/main.rs @@ -0,0 +1,10 @@ +use std::cell::RefCell; + +fn main() { + thread_local! { + static S: RefCell = RefCell::default(); + } + + S.with(|x| *x.borrow_mut() = "pika pika".to_string()); + S.with(|x| println!("{}", x.borrow())); +} From 88478aca86706a7b2cc1db4c27add28ee374d376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 19 Mar 2025 09:36:05 +0100 Subject: [PATCH 029/176] Set linkcheck in `ci.yml` --- src/doc/rustc-dev-guide/.github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index 22a4fb1901ab..415d0dc397dc 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -18,6 +18,7 @@ jobs: MDBOOK_LINKCHECK2_VERSION: 0.9.1 MDBOOK_MERMAID_VERSION: 0.12.6 MDBOOK_TOC_VERSION: 0.11.2 + MDBOOK_OUTPUT__LINKCHECK__FOLLOW_WEB_LINKS: ${{ github.event_name != 'pull_request' }} DEPLOY_DIR: book/html BASE_SHA: ${{ github.event.pull_request.base.sha }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 2daaf493815e8b4bfa9862559cecf6f0f2383314 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 19 Mar 2025 18:06:50 +0200 Subject: [PATCH 030/176] use correct code block markers This makes this command pass mdbook test --chapter "Remarks on perma-unstable features" --- .../src/rustc-driver/remarks-on-perma-unstable-features.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md index c307adc00a00..b434cfc9cf14 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md @@ -1,4 +1,3 @@ - # Remarks on perma unstable features ## `rustc_private` @@ -18,7 +17,7 @@ When using the `rustc_private` feature with official Rust toolchains distributed Install both components using rustup: -```bash +```text rustup component add rustc-dev llvm-tools ``` @@ -26,7 +25,7 @@ rustup component add rustc-dev llvm-tools Without the `llvm-tools` component, you'll encounter linking errors like: -``` +```text error: linking with `cc` failed: exit status: 1 | = note: rust-lld: error: unable to find library -lLLVM-{version} @@ -45,7 +44,7 @@ For custom-built toolchains or environments not using rustup, additional configu 1. **Check LLVM installation**: Verify LLVM is installed and accessible 2. **Configure library paths**: You may need to set environment variables: - ```bash + ```text export LD_LIBRARY_PATH=/path/to/llvm/lib:$LD_LIBRARY_PATH ``` 3. **Check version compatibility**: Ensure your LLVM version is compatible with your Rust toolchain From 2de68a1bb180923c753e8d53d5ae913b751b860f Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 20 Mar 2025 17:30:18 +0000 Subject: [PATCH 031/176] Update `ParamEnv` section for `TypingEnv` changes --- src/doc/rustc-dev-guide/src/SUMMARY.md | 5 +- .../src/appendix/code-index.md | 2 +- src/doc/rustc-dev-guide/src/const-eval.md | 2 +- .../src/param_env/param_env_acquisition.md | 43 ---- .../param_env_construction_internals.md | 83 ------- .../src/param_env/param_env_summary.md | 18 -- .../src/param_env/param_env_what_is_it.md | 59 ----- src/doc/rustc-dev-guide/src/traits/caching.md | 2 +- .../rustc-dev-guide/src/traits/resolution.md | 2 +- .../src/typing_parameter_envs.md | 206 ++++++++++++++++++ 10 files changed, 211 insertions(+), 211 deletions(-) delete mode 100644 src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md delete mode 100644 src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md delete mode 100644 src/doc/rustc-dev-guide/src/param_env/param_env_summary.md delete mode 100644 src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md create mode 100644 src/doc/rustc-dev-guide/src/typing_parameter_envs.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 075d5af4c24a..c5d046015d88 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -146,10 +146,7 @@ - [ADTs and Generic Arguments](./ty_module/generic_arguments.md) - [Parameter types/consts/regions](./ty_module/param_ty_const_regions.md) - [`TypeFolder` and `TypeFoldable`](./ty-fold.md) -- [Parameter Environments](./param_env/param_env_summary.md) - - [What is it?](./param_env/param_env_what_is_it.md) - - [How are `ParamEnv`'s constructed internally](./param_env/param_env_construction_internals.md) - - [Which `ParamEnv` do I use?](./param_env/param_env_acquisition.md) +- [Typing/Param Envs](./typing_parameter_envs.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - [Higher-ranked trait bounds](./traits/hrtb.md) diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index b96ede68eab5..65fbf752d792 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -40,5 +40,5 @@ Item | Kind | Short description | Chapter | [Emitting Diagnostics]: ../diagnostics.html [Macro expansion]: ../macro-expansion.html [Name resolution]: ../name-resolution.html -[Parameter Environment]: ../param_env/param_env_summary.html +[Parameter Environment]: ../typing_parameter_envs.html [Trait Solving: Goals and Clauses]: ../traits/goals-and-clauses.html#domain-goals diff --git a/src/doc/rustc-dev-guide/src/const-eval.md b/src/doc/rustc-dev-guide/src/const-eval.md index 69329a3e0851..ca6a35a5e97e 100644 --- a/src/doc/rustc-dev-guide/src/const-eval.md +++ b/src/doc/rustc-dev-guide/src/const-eval.md @@ -35,7 +35,7 @@ They're the wrappers of the `const_eval` query. Statics are special; all other functions do not represent statics correctly and have thus assertions preventing their use on statics. -The `const_eval_*` functions use a [`ParamEnv`](./param_env/param_env_summary.html) of environment +The `const_eval_*` functions use a [`ParamEnv`](./typing_parameter_envs.html) of environment in which the constant is evaluated (e.g. the function within which the constant is used) and a [`GlobalId`]. The `GlobalId` is made up of an `Instance` referring to a constant or static or of an `Instance` of a function and an index into the function's `Promoted` table. diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md b/src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md deleted file mode 100644 index f6cff2d6c63c..000000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md +++ /dev/null @@ -1,43 +0,0 @@ - -# Which `ParamEnv` do I use? - -When needing a [`ParamEnv`][pe] in the compiler there are a few options for obtaining one: -- The correct env is already in scope simply use it (or pass it down the call stack to where you are). -- The [`tcx.param_env(def_id)` query][param_env_query] -- Use [`ParamEnv::new`][param_env_new] to construct an env with an arbitrary set of where clauses. Then call [`traits::normalize_param_env_or_error`][normalize_env_or_error] which will handle normalizing and elaborating all the where clauses in the env for you. -- Creating an empty environment via [`ParamEnv::reveal_all`][env_reveal_all] or [`ParamEnv::empty`][env_empty] - -In the large majority of cases a `ParamEnv` when required already exists somewhere in scope or above in the call stack and should be passed down. A non exhaustive list of places where you might find an existing `ParamEnv`: -- During typeck `FnCtxt` has a [`param_env` field][fnctxt_param_env] -- When writing late lints the `LateContext` has a [`param_env` field][latectxt_param_env] -- During well formedness checking the `WfCheckingCtxt` has a [`param_env` field][wfckctxt_param_env] -- The `TypeChecker` used by Mir Typeck has a [`param_env` field][mirtypeck_param_env] -- In the next-gen trait solver all `Goal`s have a [`param_env` field][goal_param_env] specifying what environment to prove the goal in -- When editing an existing [`TypeRelation`][typerelation] if it implements `PredicateEmittingRelation` then a [`param_env` method][typerelation_param_env] will be available. - -Using the `param_env` query to obtain an env is generally done at the start of some kind of analysis and then passed everywhere that a `ParamEnv` is required. For example the type checker will create a `ParamEnv` for the item it is type checking and then pass it around everywhere. - -Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (i.e. [`compare_method_predicate_entailment`][method_pred_entailment] as mentioned earlier). - -Creating an empty environment via `ParamEnv::empty` is almost always wrong. There are very few places where we actually know that the environment should be empty. One of the only places where we do actually know this is after monomorphization, however the `ParamEnv` there should be constructed via `ParamEnv::reveal_all` instead as at this point we should be able to determine the hidden type of opaque types. Codegen/Post-mono is one of the only places that should be using `ParamEnv::reveal_all`. - -An additional piece of complexity here is specifying the `Reveal` (see linked docs for explanation of what reveal does) used for the `ParamEnv`. When constructing a param env using the `param_env` query it will have `Reveal::UserFacing`, if `Reveal::All` is desired then the [`tcx.param_env_reveal_all_normalized`][env_reveal_all_normalized] query can be used instead. - -The `ParamEnv` type has a method [`ParamEnv::with_reveal_all_normalized`][with_reveal_all] which converts an existing `ParamEnv` into one with `Reveal::All` specified. Where possible the previously mentioned query should be preferred as it is more efficient. - -[param_env_new]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.new -[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html -[fnctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env -[latectxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#structfield.param_env -[wfckctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/wfcheck/struct.WfCheckingCtxt.html#structfield.param_env -[goal_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/canonical/ir/solve/struct.Goal.html#structfield.param_env -[typerelation_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/trait.PredicateEmittingRelation.html#tymethod.param_env -[typerelation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/trait.TypeRelation.html -[mirtypeck_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/struct.TypeChecker.html#structfield.param_env -[env_reveal_all_normalized]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env_reveal_all_normalized -[with_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.with_reveal_all_normalized -[env_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.reveal_all -[env_empty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.empty -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[param_env_query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env -[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md b/src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md deleted file mode 100644 index 69a262a176e0..000000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md +++ /dev/null @@ -1,83 +0,0 @@ - -# How are `ParamEnv`'s constructed internally? - -Creating a [`ParamEnv`][pe] is more complicated than simply using the list of where clauses defined on an item as written by the user. We need to both elaborate supertraits into the env and fully normalize all aliases. This logic is handled by [`traits::normalize_param_env_or_error`][normalize_env_or_error] (even though it does not mention anything about elaboration). - -## Elaborating supertraits - -When we have a function such as `fn foo()` we would like to be able to prove `T: Clone` inside of the function as the `Copy` trait has a `Clone` supertrait. Constructing a `ParamEnv` looks at all of the trait bounds in the env and explicitly adds new where clauses to the `ParamEnv` for any supertraits found on the traits. - -A concrete example would be the following function: -```rust -trait Trait: SuperTrait {} -trait SuperTrait: SuperSuperTrait {} - -// `bar`'s unelaborated `ParamEnv` would be: -// `[T: Sized, T: Copy, T: Trait]` -fn bar(a: T) { - requires_impl(a); -} - -fn requires_impl(a: T) {} -``` - -If we did not elaborate the env then the `requires_impl` call would fail to typecheck as we would not be able to prove `T: Clone` or `T: SuperSuperTrait`. In practice we elaborate the env which means that `bar`'s `ParamEnv` is actually: -`[T: Sized, T: Copy, T: Clone, T: Trait, T: SuperTrait, T: SuperSuperTrait]` -This allows us to prove `T: Clone` and `T: SuperSuperTrait` when type checking `bar`. - -The `Clone` trait has a `Sized` supertrait however we do not end up with two `T: Sized` bounds in the env (one for the supertrait and one for the implicitly added `T: Sized` bound). This is because the elaboration process (implemented via [`util::elaborate`][elaborate]) deduplicates the where clauses to avoid this. - -As a side effect this also means that even if no actual elaboration of supertraits takes place, the existing where clauses in the env are _also_ deduplicated. See the following example: -```rust -trait Trait {} -// The unelaborated `ParamEnv` would be: -// `[T: Sized, T: Trait, T: Trait]` -// but after elaboration it would be: -// `[T: Sized, T: Trait]` -fn foo() {} -``` - -The [next-gen trait solver][next-gen-solver] also requires this elaboration to take place. - -[elaborate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/util/fn.elaborate.html -[next-gen-solver]: ../solve/trait-solving.md - -## Normalizing all bounds - -In the old trait solver the where clauses stored in `ParamEnv` are required to be fully normalized or else the trait solver will not function correctly. A concrete example of needing to normalize the `ParamEnv` is the following: -```rust -trait Trait { - type Assoc; -} - -trait Other { - type Bar; -} - -impl Other for T { - type Bar = u32; -} - -// `foo`'s unnormalized `ParamEnv` would be: -// `[T: Sized, U: Sized, U: Trait]` -fn foo(a: U) -where - U: Trait<::Bar>, -{ - requires_impl(a); -} - -fn requires_impl>(_: U) {} -``` - -As humans we can tell that `::Bar` is equal to `u32` so the trait bound on `U` is equivalent to `U: Trait`. In practice trying to prove `U: Trait` in the old solver in this environment would fail as it is unable to determine that `::Bar` is equal to `u32`. - -To work around this we normalize `ParamEnv`'s after constructing them so that `foo`'s `ParamEnv` is actually: `[T: Sized, U: Sized, U: Trait]` which means the trait solver is now able to use the `U: Trait` in the `ParamEnv` to determine that the trait bound `U: Trait` holds. - -This workaround does not work in all cases as normalizing associated types requires a `ParamEnv` which introduces a bootstrapping problem. We need a normalized `ParamEnv` in order for normalization to give correct results, but we need to normalize to get that `ParamEnv`. Currently we normalize the `ParamEnv` once using the unnormalized param env and it tends to give okay results in practice even though there are some examples where this breaks ([example]). - -In the next-gen trait solver the requirement for all where clauses in the `ParamEnv` to be fully normalized is not present and so we do not normalize when constructing `ParamEnv`s. - -[example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e6933265ea3e84eaa47019465739992c -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_summary.md b/src/doc/rustc-dev-guide/src/param_env/param_env_summary.md deleted file mode 100644 index 0ff6d8fc394e..000000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_summary.md +++ /dev/null @@ -1,18 +0,0 @@ -# The `ParamEnv` type - -## Summary - -The [`ParamEnv`][pe] is used to store information about the environment that we are interacting with the type system from. For example the set of in-scope where-clauses is stored in `ParamEnv` as it differs between each item whereas the list of user written impls is not stored in the `ParamEnv` as this does not change for each item. - -This chapter of the dev guide covers: -- A high level summary of what a `ParamEnv` is and what it is used for -- Technical details about what the process of constructing a `ParamEnv` involves -- Guidance about how to acquire a `ParamEnv` when one is required - -## Bundling - -A useful API on `ParamEnv` is the [`and`][and] method which allows bundling a value with the `ParamEnv`. The `and` method produces a [`ParamEnvAnd`][pea] making it clearer that using the inner value is intended to be done in that specific environment. - -[and]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.and -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[pea]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnvAnd.html \ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md b/src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md deleted file mode 100644 index 5c2f4d594052..000000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md +++ /dev/null @@ -1,59 +0,0 @@ - -# What is a `ParamEnv`? - -The type system relies on information in the environment in order for it to function correctly. This information is stored in the [`ParamEnv`][pe] type and it is important to use the correct `ParamEnv` when interacting with the type system. - -The information represented by `ParamEnv` is a list of in-scope where-clauses, and a `Reveal` (see linked docs for more information). A `ParamEnv` typically corresponds to a specific item's where clauses, some clauses are not explicitly written bounds and instead are implicitly added in [`predicates_of`][predicates_of] such as `ConstArgHasType` or some implied bounds. - -A `ParamEnv` can also be created with arbitrary data that is not derived from a specific item such as in [`compare_method_predicate_entailment`][method_pred_entailment] which creates a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. - -If we have a function such as: -```rust -// `foo` would have a `ParamEnv` of: -// `[T: Sized, T: Trait, ::Assoc: Clone]` -fn foo() -where - ::Assoc: Clone, -{} -``` -If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc. - -A more concrete example: -```rust -// `foo` would have a `ParamEnv` of: -// `[T: Sized, T: Clone]` -fn foo(a: T) { - // when typechecking `foo` we require all the where clauses on `bar` - // to hold in order for it to be legal to call. This means we have to - // prove `T: Clone`. As we are type checking `foo` we use `foo`'s - // environment when trying to check that `T: Clone` holds. - // - // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized, T: Clone]` - // will trivially succeed as bound we want to prove is in our environment. - requires_clone(a); -} -``` - -Or alternatively an example that would not compile: -```rust -// `foo2` would have a `ParamEnv` of: -// `[T: Sized]` -fn foo2(a: T) { - // When typechecking `foo2` we attempt to prove `T: Clone`. - // As we are type checking `foo2` we use `foo2`'s environment - // when trying to prove `T: Clone`. - // - // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized]` will - // fail as there is nothing in the environment telling the trait solver - // that `T` implements `Clone` and there exists no user written impl - // that could apply. - requires_clone(a); -} -``` - -It's very important to use the correct `ParamEnv` when interacting with the type system as otherwise it can lead to ICEs or things compiling when they shouldn't (or vice versa). See [#82159](https://github.com/rust-lang/rust/pull/82159) and [#82067](https://github.com/rust-lang/rust/pull/82067) as examples of PRs that changed rustc to use the correct param env to avoid ICE. Determining how to acquire the correct `ParamEnv` is explained later in this chapter. - -[predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html -[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env diff --git a/src/doc/rustc-dev-guide/src/traits/caching.md b/src/doc/rustc-dev-guide/src/traits/caching.md index a9f20969b574..c44722a1d9a3 100644 --- a/src/doc/rustc-dev-guide/src/traits/caching.md +++ b/src/doc/rustc-dev-guide/src/traits/caching.md @@ -61,7 +61,7 @@ to be pretty clearly safe and also still retains a very high hit rate **TODO**: it looks like `pick_candidate_cache` no longer exists. In general, is this section still accurate at all? -[`ParamEnv`]: ../param_env/param_env_summary.html +[`ParamEnv`]: ../typing_parameter_envs.html [`tcx`]: ../ty.html [#18290]: https://github.com/rust-lang/rust/issues/18290 [#22019]: https://github.com/rust-lang/rust/issues/22019 diff --git a/src/doc/rustc-dev-guide/src/traits/resolution.md b/src/doc/rustc-dev-guide/src/traits/resolution.md index 26eb72458860..c62b0593694f 100644 --- a/src/doc/rustc-dev-guide/src/traits/resolution.md +++ b/src/doc/rustc-dev-guide/src/traits/resolution.md @@ -183,7 +183,7 @@ in that list. If so, it is considered satisfied. More precisely, we want to check whether there is a where-clause obligation that is for the same trait (or some subtrait) and which can match against the obligation. -[parameter environment]: ../param_env/param_env_summary.html +[parameter environment]: ../typing_parameter_envs.html Consider this simple example: diff --git a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md new file mode 100644 index 000000000000..757296d1f652 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md @@ -0,0 +1,206 @@ +# Typing/Parameter Environments + + + +## Typing Environments + +When interacting with the type system there are a few variables to consider that can affect the results of trait solving. The the set of in-scope where clauses, and what phase of the compiler type system operations are being performed in (the [`ParamEnv`][penv] and [`TypingMode`][tmode] structs respectively). + +When an environment to perform type system operations in has not yet been created, the [`TypingEnv`][tenv] can be used to bundle all of the external context required into a single type. + +Once a context to perform type system operations in has been created (e.g. an [`ObligationCtxt`][ocx] or [`FnCtxt`][fnctxt]) a `TypingEnv` is typically not stored anywhere as only the `TypingMode` is a property of the whole environment, whereas different `ParamEnv`s can be used on a per-goal basis. + +[ocx]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/struct.ObligationCtxt.html +[fnctxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html + +## Parameter Environemnts + +### What is a `ParamEnv` + +The [`ParamEnv`][penv] is a list of in-scope where-clauses, it typically corresponds to a specific item's where clauses. Some clauses are not explicitly written but are instead are implicitly added in the [`predicates_of`][predicates_of] query, such as `ConstArgHasType` or (some) implied bounds. + +In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. A `ParamEnv` can also be created with arbitrary sets of clauses that are not derived from a specific item, such as in [`compare_method_predicate_entailment`][method_pred_entailment] where we create a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. + +--- + +If we have a function such as: +```rust +// `foo` would have a `ParamEnv` of: +// `[T: Sized, T: Trait, ::Assoc: Clone]` +fn foo() +where + ::Assoc: Clone, +{} +``` +If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc. + +A more concrete example: +```rust +// `foo` would have a `ParamEnv` of: +// `[T: Sized, T: Clone]` +fn foo(a: T) { + // when typechecking `foo` we require all the where clauses on `requires_clone` + // to hold in order for it to be legal to call. This means we have to + // prove `T: Clone`. As we are type checking `foo` we use `foo`'s + // environment when trying to check that `T: Clone` holds. + // + // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized, T: Clone]` + // will trivially succeed as bound we want to prove is in our environment. + requires_clone(a); +} +``` + +Or alternatively an example that would not compile: +```rust +// `foo2` would have a `ParamEnv` of: +// `[T: Sized]` +fn foo2(a: T) { + // When typechecking `foo2` we attempt to prove `T: Clone`. + // As we are type checking `foo2` we use `foo2`'s environment + // when trying to prove `T: Clone`. + // + // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized]` will + // fail as there is nothing in the environment telling the trait solver + // that `T` implements `Clone` and there exists no user written impl + // that could apply. + requires_clone(a); +} +``` + +[predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html +[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html +[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env + +### Acquiring a `ParamEnv` + +Using the wrong [`ParamEnv`][penv] when interacting with the type system can lead to ICEs, illformed programs compiling, or erroing when we shouldn't. See [#82159](https://github.com/rust-lang/rust/pull/82159) and [#82067](https://github.com/rust-lang/rust/pull/82067) as examples of PRs that modified the compiler to use the correct param env and in the process fixed ICEs. + +In the large majority of cases, when a `ParamEnv` is required it either already exists somewhere in scope, or above in the call stack and should be passed down. A non exhaustive list of places where you might find an existing `ParamEnv`: +- During typeck `FnCtxt` has a [`param_env` field][fnctxt_param_env] +- When writing late lints the `LateContext` has a [`param_env` field][latectxt_param_env] +- During well formedness checking the `WfCheckingCtxt` has a [`param_env` field][wfckctxt_param_env] +- The `TypeChecker` used for MIR Typeck has a [`param_env` field][mirtypeck_param_env] +- In the next-gen trait solver all `Goal`s have a [`param_env` field][goal_param_env] specifying what environment to prove the goal in +- When editing an existing [`TypeRelation`][typerelation] if it implements [`PredicateEmittingRelation`][predicate_emitting_relation] then a [`param_env` method][typerelation_param_env] will be available. + +If you aren't sure if there's a `ParamEnv` in scope somewhere that can be used it can be worth opening a thread in the [`#t-compiler/help`][compiler_help] zulip stream where someone may be able to point out where a `ParamEnv` can be acquired from. + +Manually constructing a `ParamEnv` is typically only needed at the start of some kind of top level analysis (e.g. hir typeck or borrow checking). In such cases there are three ways it can be done: +- Calling the [`tcx.param_env(def_id)` query][param_env_query] which returns the environment associated with a given definition. +- Creating an empty environment with [`ParamEnv::empty`][env_empty]. +- Using [`ParamEnv::new`][param_env_new] to construct an env with an arbitrary set of where clauses. Then calling [`traits::normalize_param_env_or_error`][normalize_env_or_error] to handle normalizing and elaborating all the where clauses in the env. + +Using the `param_env` query is by far the most common way to construct a `ParamEnv` as most of the time the compiler is performing an analysis as part of some specific definition. + +Creating an empty environment with `ParamEnv::empty` is typically only done either in codegen (indirectly via [`TypingEnv::fully_monomorphized`][tenv_mono]), or as part of some analysis that do not expect to ever encounter generic parameters (e.g. various parts of coherence/orphan check). + +Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (e.g. [`compare_method_predicate_entailment`][method_pred_entailment]). + +[param_env_new]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.new +[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html +[fnctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env +[latectxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#structfield.param_env +[wfckctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/wfcheck/struct.WfCheckingCtxt.html#structfield.param_env +[goal_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/canonical/ir/solve/struct.Goal.html#structfield.param_env +[typerelation_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/trait.PredicateEmittingRelation.html#tymethod.param_env +[typerelation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/trait.TypeRelation.html +[mirtypeck_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/struct.TypeChecker.html#structfield.param_env +[env_empty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.empty +[param_env_query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env +[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html +[predicate_emitting_relation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/combine/trait.PredicateEmittingRelation.html +[tenv_mono]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypingEnv.html#method.fully_monomorphized +[compiler_help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp + +### How are `ParamEnv`s constructed + +Creating a [`ParamEnv`][pe] is more complicated than simply using the list of where clauses defined on an item as written by the user. We need to both elaborate supertraits into the env and fully normalize all aliases. This logic is handled by [`traits::normalize_param_env_or_error`][normalize_env_or_error] (even though it does not mention anything about elaboration). + +#### Elaborating supertraits + +When we have a function such as `fn foo()` we would like to be able to prove `T: Clone` inside of the function as the `Copy` trait has a `Clone` supertrait. Constructing a `ParamEnv` looks at all of the trait bounds in the env and explicitly adds new where clauses to the `ParamEnv` for any supertraits found on the traits. + +A concrete example would be the following function: +```rust +trait Trait: SuperTrait {} +trait SuperTrait: SuperSuperTrait {} + +// `bar`'s unelaborated `ParamEnv` would be: +// `[T: Sized, T: Copy, T: Trait]` +fn bar(a: T) { + requires_impl(a); +} + +fn requires_impl(a: T) {} +``` + +If we did not elaborate the env then the `requires_impl` call would fail to typecheck as we would not be able to prove `T: Clone` or `T: SuperSuperTrait`. In practice we elaborate the env which means that `bar`'s `ParamEnv` is actually: +`[T: Sized, T: Copy, T: Clone, T: Trait, T: SuperTrait, T: SuperSuperTrait]` +This allows us to prove `T: Clone` and `T: SuperSuperTrait` when type checking `bar`. + +The `Clone` trait has a `Sized` supertrait however we do not end up with two `T: Sized` bounds in the env (one for the supertrait and one for the implicitly added `T: Sized` bound) as the elaboration process (implemented via [`util::elaborate`][elaborate]) deduplicates where clauses. + +A side effect of this is that even if no actual elaboration of supertraits takes place, the existing where clauses in the env are _also_ deduplicated. See the following example: +```rust +trait Trait {} +// The unelaborated `ParamEnv` would be: +// `[T: Sized, T: Trait, T: Trait]` +// but after elaboration it would be: +// `[T: Sized, T: Trait]` +fn foo() {} +``` + +The [next-gen trait solver][next-gen-solver] also requires this elaboration to take place. + +[elaborate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/util/fn.elaborate.html +[next-gen-solver]: ./solve/trait-solving.md + +#### Normalizing all bounds + +In the old trait solver the where clauses stored in `ParamEnv` are required to be fully normalized as otherwise the trait solver will not function correctly. A concrete example of needing to normalize the `ParamEnv` is the following: +```rust +trait Trait { + type Assoc; +} + +trait Other { + type Bar; +} + +impl Other for T { + type Bar = u32; +} + +// `foo`'s unnormalized `ParamEnv` would be: +// `[T: Sized, U: Sized, U: Trait]` +fn foo(a: U) +where + U: Trait<::Bar>, +{ + requires_impl(a); +} + +fn requires_impl>(_: U) {} +``` + +As humans we can tell that `::Bar` is equal to `u32` so the trait bound on `U` is equivalent to `U: Trait`. In practice trying to prove `U: Trait` in the old solver in this environment would fail as it is unable to determine that `::Bar` is equal to `u32`. + +To work around this we normalize `ParamEnv`'s after constructing them so that `foo`'s `ParamEnv` is actually: `[T: Sized, U: Sized, U: Trait]` which means the trait solver is now able to use the `U: Trait` in the `ParamEnv` to determine that the trait bound `U: Trait` holds. + +This workaround does not work in all cases as normalizing associated types requires a `ParamEnv` which introduces a bootstrapping problem. We need a normalized `ParamEnv` in order for normalization to give correct results, but we need to normalize to get that `ParamEnv`. Currently we normalize the `ParamEnv` once using the unnormalized param env and it tends to give okay results in practice even though there are some examples where this breaks ([example]). + +In the next-gen trait solver the requirement for all where clauses in the `ParamEnv` to be fully normalized is not present and so we do not normalize when constructing `ParamEnv`s. + +[example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e6933265ea3e84eaa47019465739992c +[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html +[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html + +## Typing Modes + +Depending on what context we are performing type system operations in, different behaviour may be required. For example during coherence there are stronger requirements about when we can consider goals to not hold or when we can consider types to be unequal. + +Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tenv] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly. + +[penv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html +[tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/infer_ctxt/enum.TypingMode.html +[tmode]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TypingMode.html From 957aacd036d787e744a221e9a0d42d7811761a6e Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Mar 2025 16:18:43 +0800 Subject: [PATCH 032/176] Move Fuchsia and RfL under `ecosystem-test-jobs/` folder Includes redirects to avoid breaking existing links. --- src/doc/rustc-dev-guide/book.toml | 4 +++- src/doc/rustc-dev-guide/src/SUMMARY.md | 4 ++-- src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md | 2 +- .../src/tests/{ => ecosystem-test-jobs}/fuchsia.md | 4 ++-- .../src/tests/{ => ecosystem-test-jobs}/rust-for-linux.md | 2 +- src/doc/rustc-dev-guide/src/tests/ecosystem.md | 4 ++-- 6 files changed, 11 insertions(+), 9 deletions(-) rename src/doc/rustc-dev-guide/src/tests/{ => ecosystem-test-jobs}/fuchsia.md (98%) rename src/doc/rustc-dev-guide/src/tests/{ => ecosystem-test-jobs}/rust-for-linux.md (97%) diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml index 67069d9930f5..eb2f6806b96f 100644 --- a/src/doc/rustc-dev-guide/book.toml +++ b/src/doc/rustc-dev-guide/book.toml @@ -62,5 +62,7 @@ warning-policy = "error" "/diagnostics/sessiondiagnostic.html" = "diagnostic-structs.html" "/diagnostics/diagnostic-codes.html" = "error-codes.html" "/miri.html" = "const-eval/interpret.html" -"/tests/integration.html" = "ecosystem.html" +"/tests/fuchsia.html" = "ecosystem-test-jobs/fuchsia.html" "/tests/headers.html" = "directives.html" +"/tests/integration.html" = "ecosystem.html" +"/tests/rust-for-linux.html" = "ecosystem-test-jobs/rust-for-linux.html" diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 075d5af4c24a..8fc4fd33e5a3 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -28,8 +28,8 @@ - [Minicore](./tests/minicore.md) - [Ecosystem testing](./tests/ecosystem.md) - [Crater](./tests/crater.md) - - [Fuchsia](./tests/fuchsia.md) - - [Rust for Linux](./tests/rust-for-linux.md) + - [Fuchsia](./tests/ecosystem-test-jobs/fuchsia.md) + - [Rust for Linux](./tests/ecosystem-test-jobs/rust-for-linux.md) - [Performance testing](./tests/perf.md) - [Suggest tests tool](./tests/suggest-tests.md) - [Misc info](./tests/misc.md) diff --git a/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md index a4658e0d842f..e3c1a7148d3c 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md @@ -9,4 +9,4 @@ This list will be used to notify [Fuchsia][fuchsia] maintainers when the compiler or the standard library changes in a way that would break the Fuchsia integration. -[fuchsia]: ../tests/fuchsia.md +[fuchsia]: ../tests/ecosystem-test-jobs/fuchsia.md diff --git a/src/doc/rustc-dev-guide/src/tests/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md similarity index 98% rename from src/doc/rustc-dev-guide/src/tests/fuchsia.md rename to src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index 2766c362cc26..b19d94d6ff73 100644 --- a/src/doc/rustc-dev-guide/src/tests/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -40,7 +40,7 @@ using your local Rust toolchain. src/ci/docker/run.sh x86_64-fuchsia ``` -See the [Testing with Docker](docker.md) chapter for more details on how to run +See the [Testing with Docker](../docker.md) chapter for more details on how to run and debug jobs with Docker. Note that a Fuchsia checkout is *large* – as of this writing, a checkout and @@ -170,7 +170,7 @@ rustc book][platform-support]. [`public_configs`]: https://gn.googlesource.com/gn/+/main/docs/reference.md#var_public_configs [`//build/config:compiler`]: https://cs.opensource.google/fuchsia/fuchsia/+/main:build/config/BUILD.gn;l=121;drc=c26c473bef93b33117ae417893118907a026fec7 [build system]: https://fuchsia.dev/fuchsia-src/development/build/build_system -[fuchsia-ping]: ../notification-groups/fuchsia.md +[fuchsia-ping]: ../../notification-groups/fuchsia.md [^loc]: As of June 2024, Fuchsia had about 2 million lines of first-party Rust code and a roughly equal amount of third-party code, as counted by tokei diff --git a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md similarity index 97% rename from src/doc/rustc-dev-guide/src/tests/rust-for-linux.md rename to src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md index bdf32ffc398d..d549ec6fca52 100644 --- a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md @@ -48,4 +48,4 @@ line to your PR description: Then when you `@bors try` it will pick the job that builds the Rust for Linux integration. -[rfl-ping]: ../notification-groups/rust-for-linux.md +[rfl-ping]: ../../notification-groups/rust-for-linux.md diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem.md b/src/doc/rustc-dev-guide/src/tests/ecosystem.md index 083601404255..f4b93492e005 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem.md @@ -24,5 +24,5 @@ there aren't any significant regressions. We have CI jobs that build large open-source Rust projects that are used as regression tests in CI. Our integration jobs build the following projects: -- [Fuchsia](fuchsia.md) -- [Rust for Linux](rust-for-linux.md) +- [Fuchsia](./ecosystem-test-jobs/fuchsia.md) +- [Rust for Linux](./ecosystem-test-jobs/rust-for-linux.md) From d58ccd86c2353bcf22daee05ed44dc0780121c62 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Mar 2025 16:35:46 +0800 Subject: [PATCH 033/176] Stub out codegen backend test pages --- src/doc/rustc-dev-guide/src/SUMMARY.md | 3 +++ .../src/tests/codegen-backend-tests/cg_clif.md | 3 +++ .../src/tests/codegen-backend-tests/cg_gcc.md | 3 +++ .../src/tests/codegen-backend-tests/intro.md | 13 +++++++++++++ src/doc/rustc-dev-guide/src/tests/intro.md | 8 ++++++-- 5 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md create mode 100644 src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md create mode 100644 src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 8fc4fd33e5a3..29085a6e8533 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -30,6 +30,9 @@ - [Crater](./tests/crater.md) - [Fuchsia](./tests/ecosystem-test-jobs/fuchsia.md) - [Rust for Linux](./tests/ecosystem-test-jobs/rust-for-linux.md) + - [Codegen backend testing](./tests/codegen-backend-tests/intro.md) + - [Cranelift codegen backend](./tests/codegen-backend-tests/cg_clif.md) + - [GCC codegen backend](./tests/codegen-backend-tests/cg_gcc.md) - [Performance testing](./tests/perf.md) - [Suggest tests tool](./tests/suggest-tests.md) - [Misc info](./tests/misc.md) diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md new file mode 100644 index 000000000000..030ddd7dff57 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md @@ -0,0 +1,3 @@ +# Cranelift codegen backend tests + +TODO: please add some more information to this page. diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md new file mode 100644 index 000000000000..4caf4c0e0eef --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md @@ -0,0 +1,3 @@ +# GCC codegen backend tests + +TODO: please add some more information to this page. diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md new file mode 100644 index 000000000000..c4bac26aba2c --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md @@ -0,0 +1,13 @@ +# Codegen backend testing + +See also the [Code generation](../../../src/backend/codegen.md) chapter. + +In addition to the primary LLVM codegen backend, the rust-lang/rust CI also runs tests of the [cranelift][cg_clif] and [GCC][cg_gcc] codegen backends in certain test jobs. + +For more details on the tests involved, see: + +- [Cranelift codegen backend tests](./cg_clif.md) +- [GCC codegen backend tests](./cg_gcc.md) + +[cg_clif]: https://github.com/rust-lang/rustc_codegen_cranelift +[cg_gcc]: https://github.com/rust-lang/rustc_codegen_gcc diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index ba44a969bf95..7bf30b106b43 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -38,7 +38,7 @@ directory, and `x` will essentially run `cargo test` on that package. Examples: | Command | Description | -| ----------------------------------------- | ------------------------------------- | +|-------------------------------------------|---------------------------------------| | `./x test library/std` | Runs tests on `std` only | | `./x test library/core` | Runs tests on `core` only | | `./x test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | @@ -86,7 +86,7 @@ above. Examples: | Command | Description | -| ----------------------- | ------------------------------------------------------------------ | +|-------------------------|--------------------------------------------------------------------| | `./x fmt --check` | Checks formatting and exits with an error if formatting is needed. | | `./x fmt` | Runs rustfmt across the entire codebase. | | `./x test tidy --bless` | First runs rustfmt to format the codebase, then runs tidy checks. | @@ -155,6 +155,10 @@ chapter](ecosystem.md) for more details. A separate infrastructure is used for testing and tracking performance of the compiler. See the [Performance testing chapter](perf.md) for more details. +### Codegen backend testing + +See [Codegen backend testing](./codegen-backend-tests/intro.md). + ## Miscellaneous information There are some other useful testing-related info at [Misc info](misc.md). From ee6a1598268e07cf1fbecc6ad1c2d5a5db593fb4 Mon Sep 17 00:00:00 2001 From: Chiichen Date: Sun, 23 Mar 2025 12:34:41 +0800 Subject: [PATCH 034/176] doc: fix reference to #create-a-configtoml --- src/doc/rustc-dev-guide/src/building/prerequisites.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md index f49f6bb05278..6761cabac1f1 100644 --- a/src/doc/rustc-dev-guide/src/building/prerequisites.md +++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md @@ -38,4 +38,4 @@ incremental compilation ([see here][config]). This will make compilation take longer (especially after a rebase), but will save a ton of space from the incremental caches. -[config]: ./how-to-build-and-run.md#create-a-configtoml +[config]: ./how-to-build-and-run.md#create-a-bootstraptoml From 25900c2768b0b3e3d55a531c9aeb27edaccb92d1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 23 Mar 2025 22:21:41 +0100 Subject: [PATCH 035/176] Tweak integer to string conversion test a bit to be future-proof --- library/alloctests/tests/num.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloctests/tests/num.rs b/library/alloctests/tests/num.rs index c9c0cd09ff6a..3c76e68c6064 100644 --- a/library/alloctests/tests/num.rs +++ b/library/alloctests/tests/num.rs @@ -3,9 +3,9 @@ use std::str::FromStr; fn assert_nb(value: Int) { let s = value.to_string(); - let s2 = format!("{}", value); + let s2 = format!("s: {}.", value); - assert_eq!(s, s2); + assert_eq!(format!("s: {s}."), s2); let Ok(ret) = Int::from_str(&s) else { panic!("failed to convert into to string"); }; From de8b6beac8710f6391e1fe99f774ba99bb0f54ac Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 24 Mar 2025 10:40:03 +0200 Subject: [PATCH 036/176] add needed break --- .../src/rustdoc-internals/rustdoc-test-suite.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md index c2a2e6495f82..471dd29f74fb 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -1,6 +1,7 @@ # The `rustdoc` test suite -This page is specifically about the test suite named `rustdoc`, for other test suites used for testing rustdoc, see [Rustdoc tests](../rustdoc.md#tests). +This page is specifically about the test suite named `rustdoc`. +For other test suites used for testing rustdoc, see [Rustdoc tests](../rustdoc.md#tests). The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. From 62ec34bf5b254a3470fe74042a0ad2a53e56baed Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 24 Mar 2025 10:41:19 +0200 Subject: [PATCH 037/176] typo --- .../rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md index 471dd29f74fb..169b95a7e1ad 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -5,7 +5,7 @@ For other test suites used for testing rustdoc, see [Rustdoc tests](../rustdoc.m The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. -This is achived by means of `htmldocck.py`, a custom checker script that leverages [XPath]. +This is achieved by means of `htmldocck.py`, a custom checker script that leverages [XPath]. [XPath]: https://en.wikipedia.org/wiki/XPath From 328846c6eb650580f93addb687a8f5fd863bd892 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 19 Aug 2024 15:20:02 +0200 Subject: [PATCH 038/176] Rename `is_like_osx` to `is_like_darwin` --- .../rustc_codegen_cranelift/src/abi/mod.rs | 2 +- .../rustc_codegen_cranelift/src/constant.rs | 2 +- .../src/debuginfo/mod.rs | 2 +- compiler/rustc_codegen_gcc/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 6 +++--- compiler/rustc_codegen_llvm/src/mono_item.rs | 2 +- compiler/rustc_codegen_llvm/src/va_arg.rs | 2 +- compiler/rustc_codegen_ssa/src/back/link.rs | 12 +++++------ compiler/rustc_codegen_ssa/src/back/linker.rs | 20 +++++++++---------- .../rustc_codegen_ssa/src/back/metadata.rs | 2 +- compiler/rustc_codegen_ssa/src/back/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/back/rpath.rs | 4 ++-- .../rustc_codegen_ssa/src/back/rpath/tests.rs | 6 +++--- compiler/rustc_codegen_ssa/src/back/write.rs | 4 ++-- .../rustc_codegen_ssa/src/codegen_attrs.rs | 2 +- compiler/rustc_driver_impl/src/lib.rs | 2 +- compiler/rustc_metadata/src/native_libs.rs | 6 +++--- compiler/rustc_target/src/asm/aarch64.rs | 2 +- compiler/rustc_target/src/asm/arm.rs | 2 +- compiler/rustc_target/src/callconv/mod.rs | 2 +- compiler/rustc_target/src/callconv/x86.rs | 2 +- .../rustc_target/src/spec/base/apple/mod.rs | 2 +- compiler/rustc_target/src/spec/json.rs | 4 ++-- compiler/rustc_target/src/spec/mod.rs | 16 +++++++-------- 24 files changed, 54 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index e8076ce77abc..ddd119e0c610 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -641,7 +641,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( .flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()), ); - if fx.tcx.sess.target.is_like_osx && fx.tcx.sess.target.arch == "aarch64" { + if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == "aarch64" { // Add any padding arguments needed for Apple AArch64. // There's no need to pad the argument list unless variadic arguments are actually being // passed. diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index bcc70f4567fb..c8527c3a57df 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -391,7 +391,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant data.set_align(alloc.align.bytes()); if let Some(section_name) = section_name { - let (segment_name, section_name) = if tcx.sess.target.is_like_osx { + let (segment_name, section_name) = if tcx.sess.target.is_like_darwin { // See https://github.com/llvm/llvm-project/blob/main/llvm/lib/MC/MCSectionMachO.cpp let mut parts = section_name.as_str().split(','); let Some(segment_name) = parts.next() else { diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index bba6567774d7..286e02b986b3 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -58,7 +58,7 @@ impl DebugContext { // FIXME this should be configurable // macOS doesn't seem to support DWARF > 3 // 5 version is required for md5 file hash - version: if tcx.sess.target.is_like_osx { + version: if tcx.sess.target.is_like_darwin { 3 } else { // FIXME change to version 5 once the gdb and lldb shipping with the latest debian diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index c514b7a428bc..0dc0a9182988 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -131,7 +131,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // will use load-unaligned instructions instead, and thus avoiding the crash. // // We could remove this hack whenever we decide to drop macOS 10.10 support. - if self.tcx.sess.target.options.is_like_osx { + if self.tcx.sess.target.options.is_like_darwin { // The `inspect` method is okay here because we checked for provenance, and // because we are doing this access to inspect the final interpreter state // (not as part of the interpreter execution). diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index bead4c82a812..bf6138142b64 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -1024,7 +1024,7 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: } pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static CStr { - if cgcx.target_is_like_osx { + if cgcx.target_is_like_darwin { c"__LLVM,__bitcode" } else if cgcx.target_is_like_aix { c".ipa" @@ -1077,7 +1077,7 @@ unsafe fn embed_bitcode( // and COFF we emit the sections using module level inline assembly for that // reason (see issue #90326 for historical background). unsafe { - if cgcx.target_is_like_osx + if cgcx.target_is_like_darwin || cgcx.target_is_like_aix || cgcx.target_arch == "wasm32" || cgcx.target_arch == "wasm64" @@ -1096,7 +1096,7 @@ unsafe fn embed_bitcode( let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline"); llvm::set_initializer(llglobal, llconst); - let section = if cgcx.target_is_like_osx { + let section = if cgcx.target_is_like_darwin { c"__LLVM,__cmdline" } else if cgcx.target_is_like_aix { c".info" diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index a64627eaf598..fdf62a08065c 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -120,7 +120,7 @@ impl CodegenCx<'_, '_> { } // Match clang by only supporting COFF and ELF for now. - if self.tcx.sess.target.is_like_osx { + if self.tcx.sess.target.is_like_darwin { return false; } diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 8baa69cefe1e..c216f0f4a09d 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -399,7 +399,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false) } // macOS / iOS AArch64 - "aarch64" if target.is_like_osx => { + "aarch64" if target.is_like_darwin => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true) } "aarch64" => emit_aapcs_va_arg(bx, addr, target_ty), diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 74597f6263d4..9fa26a33f233 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1012,7 +1012,7 @@ fn link_natively( // On macOS the external `dsymutil` tool is used to create the packed // debug information. Note that this will read debug information from // the objects on the filesystem which we'll clean up later. - SplitDebuginfo::Packed if sess.target.is_like_osx => { + SplitDebuginfo::Packed if sess.target.is_like_darwin => { let prog = Command::new("dsymutil").arg(out_filename).output(); match prog { Ok(prog) => { @@ -1043,7 +1043,7 @@ fn link_natively( let strip = sess.opts.cg.strip; - if sess.target.is_like_osx { + if sess.target.is_like_darwin { let stripcmd = "rust-objcopy"; match (strip, crate_type) { (Strip::Debuginfo, _) => { @@ -1241,7 +1241,7 @@ fn add_sanitizer_libraries( // Everywhere else the runtimes are currently distributed as static // libraries which should be linked to executables only. if matches!(crate_type, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) - && !(sess.target.is_like_osx || sess.target.is_like_msvc) + && !(sess.target.is_like_darwin || sess.target.is_like_msvc) { return; } @@ -1294,7 +1294,7 @@ fn link_sanitizer_runtime( let channel = option_env!("CFG_RELEASE_CHANNEL").map(|channel| format!("-{channel}")).unwrap_or_default(); - if sess.target.is_like_osx { + if sess.target.is_like_darwin { // On Apple platforms, the sanitizer is always built as a dylib, and // LLVM will link to `@rpath/*.dylib`, so we need to specify an // rpath to the library as well (the rpath should be absolute, see @@ -2182,7 +2182,7 @@ fn add_rpath_args( let rpath_config = RPathConfig { libs: &*libs, out_filename: out_filename.to_path_buf(), - is_like_osx: sess.target.is_like_osx, + is_like_darwin: sess.target.is_like_darwin, linker_is_gnu: sess.target.linker_flavor.is_gnu(), }; cmd.link_args(&rpath::get_rpath_linker_args(&rpath_config)); @@ -3044,7 +3044,7 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool /// - The deployment target. /// - The SDK version. fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { - if !sess.target.is_like_osx { + if !sess.target.is_like_darwin { return; } let LinkerFlavor::Darwin(cc, _) = flavor else { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3f5e0c1bce9c..33440361c6f0 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -373,7 +373,7 @@ impl<'a> GccLinker<'a> { // * On OSX they have their own linker, not binutils' // * For WebAssembly the only functional linker is LLD, which doesn't // support hint flags - !self.sess.target.is_like_osx && !self.sess.target.is_like_wasm + !self.sess.target.is_like_darwin && !self.sess.target.is_like_wasm } // Some platforms take hints about whether a library is static or dynamic. @@ -425,7 +425,7 @@ impl<'a> GccLinker<'a> { fn build_dylib(&mut self, crate_type: CrateType, out_filename: &Path) { // On mac we need to tell the linker to let this library be rpathed - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { if self.is_cc() { // `-dynamiclib` makes `cc` pass `-dylib` to the linker. self.cc_arg("-dynamiclib"); @@ -470,7 +470,7 @@ impl<'a> GccLinker<'a> { fn with_as_needed(&mut self, as_needed: bool, f: impl FnOnce(&mut Self)) { if !as_needed { - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { // FIXME(81490): ld64 doesn't support these flags but macOS 11 // has -needed-l{} / -needed_library {} // but we have no way to detect that here. @@ -485,7 +485,7 @@ impl<'a> GccLinker<'a> { f(self); if !as_needed { - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { // See above FIXME comment } else if self.is_gnu && !self.sess.target.is_like_windows { self.link_arg("--as-needed"); @@ -618,7 +618,7 @@ impl<'a> Linker for GccLinker<'a> { let colon = if verbatim && self.is_gnu { ":" } else { "" }; if !whole_archive { self.link_or_cc_arg(format!("-l{colon}{name}")); - } else if self.sess.target.is_like_osx { + } else if self.sess.target.is_like_darwin { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.link_arg("-force_load"); @@ -634,7 +634,7 @@ impl<'a> Linker for GccLinker<'a> { self.hint_static(); if !whole_archive { self.link_or_cc_arg(path); - } else if self.sess.target.is_like_osx { + } else if self.sess.target.is_like_darwin { self.link_arg("-force_load").link_arg(path); } else { self.link_arg("--whole-archive").link_arg(path).link_arg("--no-whole-archive"); @@ -669,7 +669,7 @@ impl<'a> Linker for GccLinker<'a> { // -dead_strip can't be part of the pre_link_args because it's also used // for partial linking when using multiple codegen units (-r). So we // insert it here. - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { self.link_arg("-dead_strip"); // If we're building a dylib, we don't use --gc-sections because LLVM @@ -727,7 +727,7 @@ impl<'a> Linker for GccLinker<'a> { fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) { // MacOS linker doesn't support stripping symbols directly anymore. - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { return; } @@ -794,7 +794,7 @@ impl<'a> Linker for GccLinker<'a> { debug!("EXPORTED SYMBOLS:"); - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { // Write a plain, newline-separated list of symbols let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; @@ -840,7 +840,7 @@ impl<'a> Linker for GccLinker<'a> { } } - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { self.link_arg("-exported_symbols_list").link_arg(path); } else if self.sess.target.is_like_solaris { self.link_arg("-M").link_arg(path); diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 68b453ff4242..83a9ea0603a2 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -214,7 +214,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Cow<'_, str> { - if sess.target.is_like_osx { + if sess.target.is_like_darwin { apple::add_version_to_llvm_target(&sess.target.llvm_target, apple::deployment_target(sess)) .into() } else { diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index d633cc98ac87..7bb8979e8820 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -9,7 +9,7 @@ use tracing::debug; pub(super) struct RPathConfig<'a> { pub libs: &'a [&'a Path], pub out_filename: PathBuf, - pub is_like_osx: bool, + pub is_like_darwin: bool, pub linker_is_gnu: bool, } @@ -63,7 +63,7 @@ fn get_rpaths_relative_to_output(config: &RPathConfig<'_>) -> Vec { fn get_rpath_relative_to_output(config: &RPathConfig<'_>, lib: &Path) -> OsString { // Mac doesn't appear to support $ORIGIN - let prefix = if config.is_like_osx { "@loader_path" } else { "$ORIGIN" }; + let prefix = if config.is_like_darwin { "@loader_path" } else { "$ORIGIN" }; // Strip filenames let lib = lib.parent().unwrap(); diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs index f1a30105c590..ab8fbedb8129 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs @@ -28,7 +28,7 @@ fn test_rpath_relative() { if cfg!(target_os = "macos") { let config = &mut RPathConfig { libs: &[], - is_like_osx: true, + is_like_darwin: true, linker_is_gnu: false, out_filename: PathBuf::from("bin/rustc"), }; @@ -38,7 +38,7 @@ fn test_rpath_relative() { let config = &mut RPathConfig { libs: &[], out_filename: PathBuf::from("bin/rustc"), - is_like_osx: false, + is_like_darwin: false, linker_is_gnu: true, }; let res = get_rpath_relative_to_output(config, Path::new("lib/libstd.so")); @@ -51,7 +51,7 @@ fn test_rpath_relative_issue_119571() { let config = &mut RPathConfig { libs: &[], out_filename: PathBuf::from("rustc"), - is_like_osx: false, + is_like_darwin: false, linker_is_gnu: true, }; // Should not panic when out_filename only contains filename. diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 216a18e72edf..d16ab2798da5 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -352,7 +352,7 @@ pub struct CodegenContext { pub is_pe_coff: bool, pub target_can_use_split_dwarf: bool, pub target_arch: String, - pub target_is_like_osx: bool, + pub target_is_like_darwin: bool, pub target_is_like_aix: bool, pub split_debuginfo: rustc_target::spec::SplitDebuginfo, pub split_dwarf_kind: rustc_session::config::SplitDwarfKind, @@ -1216,7 +1216,7 @@ fn start_executing_work( is_pe_coff: tcx.sess.target.is_like_windows, target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(), target_arch: tcx.sess.target.arch.to_string(), - target_is_like_osx: tcx.sess.target.is_like_osx, + target_is_like_darwin: tcx.sess.target.is_like_darwin, target_is_like_aix: tcx.sess.target.is_like_aix, split_debuginfo: tcx.sess.split_debuginfo(), split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index d16d4ed22838..4a0c3bb170a3 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -213,7 +213,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // somewhat, and is subject to change in the future (which // is a good thing, because this would ideally be a bit // more firmed up). - let is_like_elf = !(tcx.sess.target.is_like_osx + let is_like_elf = !(tcx.sess.target.is_like_darwin || tcx.sess.target.is_like_windows || tcx.sess.target.is_like_wasm); codegen_fn_attrs.flags |= if is_like_elf { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 37755e7d61db..30755a2e86ee 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -779,7 +779,7 @@ fn print_crate_info( } } DeploymentTarget => { - if sess.target.is_like_osx { + if sess.target.is_like_darwin { println_info!( "{}={}", apple::deployment_target_env_var(&sess.target.os), diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 1671b7e06b0a..0249678664a8 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -73,7 +73,7 @@ pub fn walk_native_lib_search_dirs( || sess.target.os == "linux" || sess.target.os == "fuchsia" || sess.target.is_like_aix - || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() + || sess.target.is_like_darwin && !sess.opts.unstable_opts.sanitizer.is_empty() { f(&sess.target_tlib_path.dir, false)?; } @@ -258,7 +258,7 @@ impl<'tcx> Collector<'tcx> { "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => { - if !sess.target.is_like_osx { + if !sess.target.is_like_darwin { sess.dcx().emit_err(errors::LinkFrameworkApple { span }); } NativeLibKind::Framework { as_needed: None } @@ -532,7 +532,7 @@ impl<'tcx> Collector<'tcx> { let mut renames = FxHashSet::default(); for lib in &self.tcx.sess.opts.libs { if let NativeLibKind::Framework { .. } = lib.kind - && !self.tcx.sess.target.is_like_osx + && !self.tcx.sess.target.is_like_darwin { // Cannot check this when parsing options because the target is not yet available. self.tcx.dcx().emit_err(errors::LibFrameworkApple); diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index cdccb3e5d728..43a8d9ca119d 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -78,7 +78,7 @@ pub(crate) fn target_reserves_x18(target: &Target, target_features: &FxIndexSet< target.os == "android" || target.os == "fuchsia" || target.env == "ohos" - || target.is_like_osx + || target.is_like_darwin || target.is_like_windows || target_features.contains(&sym::reserve_x18) } diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index ff0cbddecf78..7fea10ff067b 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -68,7 +68,7 @@ impl ArmInlineAsmRegClass { // This uses the same logic as useR7AsFramePointer in LLVM fn frame_pointer_is_r7(target_features: &FxIndexSet, target: &Target) -> bool { - target.is_like_osx || (!target.is_like_windows && target_features.contains(&sym::thumb_mode)) + target.is_like_darwin || (!target.is_like_windows && target_features.contains(&sym::thumb_mode)) } fn frame_pointer_r11( diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 6d0ee3c7ee58..4a55a25baf42 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -670,7 +670,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { } }, "aarch64" | "arm64ec" => { - let kind = if cx.target_spec().is_like_osx { + let kind = if cx.target_spec().is_like_darwin { aarch64::AbiKind::DarwinPCS } else if cx.target_spec().is_like_windows { aarch64::AbiKind::Win64 diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 6f112b494005..ba3c14062112 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -104,7 +104,7 @@ where let byval_align = if arg.layout.align.abi < align_4 { // (1.) align_4 - } else if t.is_like_osx && contains_vector(cx, arg.layout) { + } else if t.is_like_darwin && contains_vector(cx, arg.layout) { // (3.) align_16 } else { diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 66c85146c294..fd0e47b55aaa 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -115,7 +115,7 @@ pub(crate) fn base( function_sections: false, dynamic_linking: true, families: cvs!["unix"], - is_like_osx: true, + is_like_darwin: true, binary_format: BinaryFormat::MachO, // LLVM notes that macOS 10.11+ and iOS 9+ default // to v4, so we do the same. diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs index 134405f3630e..23b21860c43e 100644 --- a/compiler/rustc_target/src/spec/json.rs +++ b/compiler/rustc_target/src/spec/json.rs @@ -592,7 +592,7 @@ impl Target { key!(families, target_families); key!(abi_return_struct_as_int, bool); key!(is_like_aix, bool); - key!(is_like_osx, bool); + key!(is_like_darwin, bool); key!(is_like_solaris, bool); key!(is_like_windows, bool); key!(is_like_msvc, bool); @@ -770,7 +770,7 @@ impl ToJson for Target { target_option_val!(families, "target-family"); target_option_val!(abi_return_struct_as_int); target_option_val!(is_like_aix); - target_option_val!(is_like_osx); + target_option_val!(is_like_darwin); target_option_val!(is_like_solaris); target_option_val!(is_like_windows); target_option_val!(is_like_msvc); diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 263646d8347b..c7c62cd5a197 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -81,7 +81,7 @@ pub enum Lld { /// of classes that we call "linker flavors". /// /// Technically, it's not even necessary, we can nearly always infer the flavor from linker name -/// and target properties like `is_like_windows`/`is_like_osx`/etc. However, the PRs originally +/// and target properties like `is_like_windows`/`is_like_darwin`/etc. However, the PRs originally /// introducing `-Clinker-flavor` (#40018 and friends) were aiming to reduce this kind of inference /// and provide something certain and explicitly specified instead, and that design goal is still /// relevant now. @@ -2403,7 +2403,7 @@ pub struct TargetOptions { /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. /// Also indicates whether to use Apple-specific ABI changes, such as extending function /// parameters to 32-bits. - pub is_like_osx: bool, + pub is_like_darwin: bool, /// Whether the target toolchain is like Solaris's. /// Only useful for compiling against Illumos/Solaris, /// as they have a different set of linker flags. Defaults to false. @@ -2697,7 +2697,7 @@ fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'stati impl TargetOptions { pub fn supports_comdat(&self) -> bool { // XCOFF and MachO don't support COMDAT. - !self.is_like_aix && !self.is_like_osx + !self.is_like_aix && !self.is_like_darwin } } @@ -2801,7 +2801,7 @@ impl Default for TargetOptions { families: cvs![], abi_return_struct_as_int: false, is_like_aix: false, - is_like_osx: false, + is_like_darwin: false, is_like_solaris: false, is_like_windows: false, is_like_msvc: false, @@ -3067,9 +3067,9 @@ impl Target { } check_eq!( - self.is_like_osx, + self.is_like_darwin, self.vendor == "apple", - "`is_like_osx` must be set if and only if `vendor` is `apple`" + "`is_like_darwin` must be set if and only if `vendor` is `apple`" ); check_eq!( self.is_like_solaris, @@ -3095,9 +3095,9 @@ impl Target { // Check that default linker flavor is compatible with some other key properties. check_eq!( - self.is_like_osx, + self.is_like_darwin, matches!(self.linker_flavor, LinkerFlavor::Darwin(..)), - "`linker_flavor` must be `darwin` if and only if `is_like_osx` is set" + "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set" ); check_eq!( self.is_like_msvc, From d872845eae7f9988995fb8ca35f86d08de999409 Mon Sep 17 00:00:00 2001 From: James Wainwright Date: Wed, 26 Mar 2025 20:45:55 +0000 Subject: [PATCH 039/176] Expose `Unique::from` in const internally --- library/core/src/ptr/unique.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 4810ebe01f9b..d688ce2a07a6 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -100,6 +100,12 @@ impl Unique { } } + /// Create a new `Unique` from a `NonNull` in const context. + #[inline] + pub const fn from_non_null(pointer: NonNull) -> Self { + Unique { pointer, _marker: PhantomData } + } + /// Acquires the underlying `*mut` pointer. #[must_use = "`self` will be dropped if the result is not used"] #[inline] @@ -202,6 +208,6 @@ impl From> for Unique { /// This conversion is infallible since `NonNull` cannot be null. #[inline] fn from(pointer: NonNull) -> Self { - Unique { pointer, _marker: PhantomData } + Unique::from_non_null(pointer) } } From 78e962139020df03174f03da6af91acc5cbb37e3 Mon Sep 17 00:00:00 2001 From: James Wainwright Date: Tue, 25 Mar 2025 21:43:19 +0000 Subject: [PATCH 040/176] Pass `Alignment` for `RawVecInner::new_in` Encodes the safety constraint that `Unique`'s pointer must be non-zero into the API. --- library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec/mod.rs | 9 +++++---- library/alloctests/lib.rs | 1 + library/core/src/alloc/layout.rs | 8 ++++++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f0cdb1e4e0f7..04858667230b 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -135,6 +135,7 @@ #![feature(pattern)] #![feature(pin_coerce_unsized_trait)] #![feature(pointer_like_trait)] +#![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(ptr_metadata)] #![feature(set_ptr_value)] diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 99ebc5c4bfca..83facd9d9321 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -6,7 +6,7 @@ use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; -use core::ptr::{self, NonNull, Unique}; +use core::ptr::{self, Alignment, NonNull, Unique}; use core::{cmp, hint}; #[cfg(not(no_global_oom_handling))] @@ -177,7 +177,7 @@ impl RawVec { /// the returned `RawVec`. #[inline] pub(crate) const fn new_in(alloc: A) -> Self { - Self { inner: RawVecInner::new_in(alloc, align_of::()), _marker: PhantomData } + Self { inner: RawVecInner::new_in(alloc, Alignment::of::()), _marker: PhantomData } } /// Like `with_capacity`, but parameterized over the choice of @@ -409,7 +409,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { impl RawVecInner { #[inline] - const fn new_in(alloc: A, align: usize) -> Self { + const fn new_in(alloc: A, align: Alignment) -> Self { + // SAFETY: `Alignment` is non-zero. let ptr = unsafe { core::mem::transmute(align) }; // `cap: 0` means "unallocated". zero-sized types are ignored. Self { ptr, cap: ZERO_CAP, alloc } @@ -465,7 +466,7 @@ impl RawVecInner { // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. if layout.size() == 0 { - return Ok(Self::new_in(alloc, elem_layout.align())); + return Ok(Self::new_in(alloc, elem_layout.alignment())); } if let Err(err) = alloc_guard(layout.size()) { diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 6ce8a6d9ca17..3241b4b00454 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -28,6 +28,7 @@ #![feature(iter_next_chunk)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(sized_type_properties)] #![feature(slice_iter_mut_as_mut_slice)] diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 1595a3af883d..e8a03aadc339 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -520,6 +520,14 @@ impl Layout { unsafe { Ok(Layout::from_size_align_unchecked(array_size, align.as_usize())) } } } + + /// Perma-unstable access to `align` as `Alignment` type. + #[unstable(issue = "none", feature = "std_internals")] + #[doc(hidden)] + #[inline] + pub const fn alignment(&self) -> Alignment { + self.align + } } #[stable(feature = "alloc_layout", since = "1.28.0")] From aadfd810f62e2e07440672cc20a0540c9904d69b Mon Sep 17 00:00:00 2001 From: James Wainwright Date: Tue, 25 Mar 2025 21:44:54 +0000 Subject: [PATCH 041/176] Swap usize -> ptr transmute for strict_pov API Removes some unsafety and reduces the number of `usize` -> `ptr` transmutes which might be helpful for CHERI-like targets in the future. --- library/alloc/src/raw_vec/mod.rs | 3 +-- library/alloctests/lib.rs | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 83facd9d9321..a989e5b55b3d 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -410,8 +410,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { impl RawVecInner { #[inline] const fn new_in(alloc: A, align: Alignment) -> Self { - // SAFETY: `Alignment` is non-zero. - let ptr = unsafe { core::mem::transmute(align) }; + let ptr = Unique::from_non_null(NonNull::without_provenance(align.as_nonzero())); // `cap: 0` means "unallocated". zero-sized types are ignored. Self { ptr, cap: ZERO_CAP, alloc } } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 3241b4b00454..56e60ed4c844 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -28,6 +28,7 @@ #![feature(iter_next_chunk)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(nonnull_provenance)] #![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(sized_type_properties)] From a9a21bde85b41f19fe46b3cd06601829ed842d8f Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 27 Mar 2025 18:32:48 +0100 Subject: [PATCH 042/176] Delete from_method from rustc_on_unimplemented documentation --- src/doc/rustc-dev-guide/src/diagnostics.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index 972309b5cd34..6f72ea902f5d 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -954,9 +954,6 @@ application of these fields based on a variety of attributes when using `Self="std::iter::Iterator"`. This is needed because `Self` is a keyword which cannot appear in attributes. - `direct`: user-specified rather than derived obligation. - - `from_method`: usable both as boolean (whether the flag is present, like - `crate_local`) or matching against a particular method. Currently used - for `try`. - `from_desugaring`: usable both as boolean (whether the flag is present) or matching against a particular desugaring. The desugaring is identified with its variant name in the `DesugaringKind` enum. From 41b04653f3d2fd9cd6451a586354257d661385e2 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sun, 23 Mar 2025 19:45:27 -0700 Subject: [PATCH 043/176] Trusty: Implement write_vectored for stdio Currently, `write` for stdout and stderr on Trusty is implemented with the semantics of `write_all`. Instead, call the underlying syscall only once in `write` and use the default implementation of `write_all` like other platforms. Also, implement `write_vectored` by adding support for `IoSlice`. Refactor stdin to reuse the unsupported type like #136769. --- library/std/src/sys/io/io_slice/iovec.rs | 2 +- library/std/src/sys/io/mod.rs | 2 +- library/std/src/sys/stdio/trusty.rs | 83 ++++++++++++++---------- 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/library/std/src/sys/io/io_slice/iovec.rs b/library/std/src/sys/io/io_slice/iovec.rs index 072191315f7c..df56358969a3 100644 --- a/library/std/src/sys/io/io_slice/iovec.rs +++ b/library/std/src/sys/io/io_slice/iovec.rs @@ -1,6 +1,6 @@ #[cfg(target_os = "hermit")] use hermit_abi::iovec; -#[cfg(target_family = "unix")] +#[cfg(any(target_family = "unix", target_os = "trusty"))] use libc::iovec; use crate::ffi::c_void; diff --git a/library/std/src/sys/io/mod.rs b/library/std/src/sys/io/mod.rs index e00b479109f3..4d0365d42fd9 100644 --- a/library/std/src/sys/io/mod.rs +++ b/library/std/src/sys/io/mod.rs @@ -2,7 +2,7 @@ mod io_slice { cfg_if::cfg_if! { - if #[cfg(any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3"))] { + if #[cfg(any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty"))] { mod iovec; pub use iovec::*; } else if #[cfg(target_os = "windows")] { diff --git a/library/std/src/sys/stdio/trusty.rs b/library/std/src/sys/stdio/trusty.rs index d393e95394d1..e05461aa44a7 100644 --- a/library/std/src/sys/stdio/trusty.rs +++ b/library/std/src/sys/stdio/trusty.rs @@ -1,21 +1,14 @@ -use crate::io; +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; -pub struct Stdin; +use crate::cmp; +use crate::io::{self, IoSlice}; + +pub type Stdin = unsupported_stdio::Stdin; pub struct Stdout; pub struct Stderr; -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result { - Ok(0) - } -} - impl Stdout { pub const fn new() -> Stdout { Stdout @@ -24,7 +17,16 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { - _write(libc::STDOUT_FILENO, buf) + write(libc::STDOUT_FILENO, buf) + } + + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + write_vectored(libc::STDOUT_FILENO, bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + true } fn flush(&mut self) -> io::Result<()> { @@ -40,7 +42,16 @@ impl Stderr { impl io::Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { - _write(libc::STDERR_FILENO, buf) + write(libc::STDERR_FILENO, buf) + } + + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + write_vectored(libc::STDERR_FILENO, bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + true } fn flush(&mut self) -> io::Result<()> { @@ -48,7 +59,7 @@ impl io::Write for Stderr { } } -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(_err: &io::Error) -> bool { true @@ -58,24 +69,24 @@ pub fn panic_output() -> Option { Some(Stderr) } -fn _write(fd: i32, message: &[u8]) -> io::Result { - let mut iov = libc::iovec { iov_base: message.as_ptr() as *mut _, iov_len: message.len() }; - loop { - // SAFETY: syscall, safe arguments. - let ret = unsafe { libc::writev(fd, &iov, 1) }; - if ret < 0 { - return Err(io::Error::last_os_error()); - } - let ret = ret as usize; - if ret > iov.iov_len { - return Err(io::Error::last_os_error()); - } - if ret == iov.iov_len { - return Ok(message.len()); - } - // SAFETY: ret has been checked to be less than the length of - // the buffer - iov.iov_base = unsafe { iov.iov_base.add(ret) }; - iov.iov_len -= ret; +fn write(fd: i32, buf: &[u8]) -> io::Result { + let iov = libc::iovec { iov_base: buf.as_ptr() as *mut _, iov_len: buf.len() }; + // SAFETY: syscall, safe arguments. + let ret = unsafe { libc::writev(fd, &iov, 1) }; + // This check includes ret < 0, since the length is at most isize::MAX. + if ret as usize > iov.iov_len { + return Err(io::Error::last_os_error()); } + Ok(ret as usize) +} + +fn write_vectored(fd: i32, bufs: &[IoSlice<'_>]) -> io::Result { + let iov = bufs.as_ptr() as *const libc::iovec; + let len = cmp::min(bufs.len(), libc::c_int::MAX as usize) as libc::c_int; + // SAFETY: syscall, safe arguments. + let ret = unsafe { libc::writev(fd, iov, len) }; + if ret < 0 { + return Err(io::Error::last_os_error()); + } + Ok(ret as usize) } From 78768361a0c06adff614515eb651a927c63c91b4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 28 Mar 2025 13:44:55 +1100 Subject: [PATCH 044/176] Remove `rustc_middle::ty::util::ExplicitSelf`. It's an old (2017 or earlier) type that describes a `self` receiver. It's only used in `rustc_hir_analysis` for two error messages, and much of the complexity isn't used. I suspect it used to be used for more things. This commit removes it, and moves a greatly simplified version of the `determine` method into `rustc_hir_analysis`, renamed as `get_self_string`. The big comment on the method is removed because it no longer seems relevant. --- .../src/check/compare_impl_item.rs | 35 ++++++++----- compiler/rustc_middle/src/ty/util.rs | 49 ------------------- 2 files changed, 22 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 84d07c711fa4..a4ed15ba2129 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -12,7 +12,6 @@ use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisi use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::util::ExplicitSelf; use rustc_middle::ty::{ self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, @@ -995,6 +994,26 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { } } +/// Gets the string for an explicit self declaration, e.g. "self", "&self", +/// etc. +fn get_self_string<'tcx, P>(self_arg_ty: Ty<'tcx>, is_self_ty: P) -> String +where + P: Fn(Ty<'tcx>) -> bool, +{ + if is_self_ty(self_arg_ty) { + "self".to_owned() + } else if let ty::Ref(_, ty, mutbl) = self_arg_ty.kind() + && is_self_ty(*ty) + { + match mutbl { + hir::Mutability::Not => "&self".to_owned(), + hir::Mutability::Mut => "&mut self".to_owned(), + } + } else { + format!("self: {self_arg_ty}") + } +} + fn report_trait_method_mismatch<'tcx>( infcx: &InferCtxt<'tcx>, mut cause: ObligationCause<'tcx>, @@ -1020,12 +1039,7 @@ fn report_trait_method_mismatch<'tcx>( if trait_m.fn_has_self_parameter => { let ty = trait_sig.inputs()[0]; - let sugg = match ExplicitSelf::determine(ty, |ty| ty == impl_trait_ref.self_ty()) { - ExplicitSelf::ByValue => "self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), - _ => format!("self: {ty}"), - }; + let sugg = get_self_string(ty, |ty| ty == impl_trait_ref.self_ty()); // When the `impl` receiver is an arbitrary self type, like `self: Box`, the // span points only at the type `Box, but we want to cover the whole @@ -1238,12 +1252,7 @@ fn compare_self_type<'tcx>( .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, method.def_id)); let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty); - match ExplicitSelf::determine(self_arg_ty, can_eq_self) { - ExplicitSelf::ByValue => "self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), - _ => format!("self: {self_arg_ty}"), - } + get_self_string(self_arg_ty, can_eq_self) }; match (trait_m.fn_has_self_parameter, impl_m.fn_has_self_parameter) { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c0d4130336e5..23c5c3488fc6 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1546,55 +1546,6 @@ impl<'tcx> Ty<'tcx> { } } -pub enum ExplicitSelf<'tcx> { - ByValue, - ByReference(ty::Region<'tcx>, hir::Mutability), - ByRawPointer(hir::Mutability), - ByBox, - Other, -} - -impl<'tcx> ExplicitSelf<'tcx> { - /// Categorizes an explicit self declaration like `self: SomeType` - /// into either `self`, `&self`, `&mut self`, `Box`, or - /// `Other`. - /// This is mainly used to require the arbitrary_self_types feature - /// in the case of `Other`, to improve error messages in the common cases, - /// and to make `Other` dyn-incompatible. - /// - /// Examples: - /// - /// ```ignore (illustrative) - /// impl<'a> Foo for &'a T { - /// // Legal declarations: - /// fn method1(self: &&'a T); // ExplicitSelf::ByReference - /// fn method2(self: &'a T); // ExplicitSelf::ByValue - /// fn method3(self: Box<&'a T>); // ExplicitSelf::ByBox - /// fn method4(self: Rc<&'a T>); // ExplicitSelf::Other - /// - /// // Invalid cases will be caught by `check_method_receiver`: - /// fn method_err1(self: &'a mut T); // ExplicitSelf::Other - /// fn method_err2(self: &'static T) // ExplicitSelf::ByValue - /// fn method_err3(self: &&T) // ExplicitSelf::ByReference - /// } - /// ``` - /// - pub fn determine

(self_arg_ty: Ty<'tcx>, is_self_ty: P) -> ExplicitSelf<'tcx> - where - P: Fn(Ty<'tcx>) -> bool, - { - use self::ExplicitSelf::*; - - match *self_arg_ty.kind() { - _ if is_self_ty(self_arg_ty) => ByValue, - ty::Ref(region, ty, mutbl) if is_self_ty(ty) => ByReference(region, mutbl), - ty::RawPtr(ty, mutbl) if is_self_ty(ty) => ByRawPointer(mutbl), - _ if self_arg_ty.boxed_ty().is_some_and(is_self_ty) => ByBox, - _ => Other, - } - } -} - /// Returns a list of types such that the given type needs drop if and only if /// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if /// this type always needs drop. From cdbb219f835ebb3dad05a02c48afa10c33f21f2b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 28 Mar 2025 12:38:32 -0300 Subject: [PATCH 045/176] Fix code generation link --- .../rustc-dev-guide/src/tests/codegen-backend-tests/intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md index c4bac26aba2c..6bf46ddcd21a 100644 --- a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md @@ -1,6 +1,6 @@ # Codegen backend testing -See also the [Code generation](../../../src/backend/codegen.md) chapter. +See also the [Code generation](../../backend/codegen.md) chapter. In addition to the primary LLVM codegen backend, the rust-lang/rust CI also runs tests of the [cranelift][cg_clif] and [GCC][cg_gcc] codegen backends in certain test jobs. From ed35b9be289ba91771d218bd9debc8e30ecd8d83 Mon Sep 17 00:00:00 2001 From: Nikolai Kuklin Date: Fri, 28 Mar 2025 18:12:18 +0100 Subject: [PATCH 046/176] Add `slice::align_to_uninit_mut` --- library/core/src/slice/mod.rs | 53 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5bb7243c4491..058515efdfd7 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -8,7 +8,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::intrinsics::{exact_div, unchecked_sub}; -use crate::mem::{self, SizedTypeProperties}; +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{OneSidedRange, OneSidedRangeBound, Range, RangeBounds, RangeInclusive}; use crate::panic::const_panic; @@ -4589,7 +4589,7 @@ impl [T] { // or generate worse code otherwise. This is also why we need to go // through a raw pointer here. let slice: *mut [T] = self; - let mut arr: mem::MaybeUninit<[&mut I::Output; N]> = mem::MaybeUninit::uninit(); + let mut arr: MaybeUninit<[&mut I::Output; N]> = MaybeUninit::uninit(); let arr_ptr = arr.as_mut_ptr(); // SAFETY: We expect `indices` to contain disjunct values that are @@ -4774,6 +4774,55 @@ impl [T] { } } +impl [MaybeUninit] { + /// Transmutes the mutable uninitialized slice to a mutable uninitialized slice of + /// another type, ensuring alignment of the types is maintained. + /// + /// This is a safe wrapper around [`slice::align_to_mut`], so inherits the same + /// guarantees as that method. + /// + /// # Examples + /// + /// ``` + /// #![feature(align_to_uninit_mut)] + /// use std::mem::MaybeUninit; + /// + /// pub struct BumpAllocator<'scope> { + /// memory: &'scope mut [MaybeUninit], + /// } + /// + /// impl<'scope> BumpAllocator<'scope> { + /// pub fn new(memory: &'scope mut [MaybeUninit]) -> Self { + /// Self { memory } + /// } + /// pub fn try_alloc_uninit(&mut self) -> Option<&'scope mut MaybeUninit> { + /// let first_end = self.memory.as_ptr().align_offset(align_of::()) + size_of::(); + /// let prefix = self.memory.split_off_mut(..first_end)?; + /// Some(&mut prefix.align_to_uninit_mut::().1[0]) + /// } + /// pub fn try_alloc_u32(&mut self, value: u32) -> Option<&'scope mut u32> { + /// let uninit = self.try_alloc_uninit()?; + /// Some(uninit.write(value)) + /// } + /// } + /// + /// let mut memory = [MaybeUninit::::uninit(); 10]; + /// let mut allocator = BumpAllocator::new(&mut memory); + /// let v = allocator.try_alloc_u32(42); + /// assert_eq!(v, Some(&mut 42)); + /// ``` + #[unstable(feature = "align_to_uninit_mut", issue = "139062")] + #[inline] + #[must_use] + pub fn align_to_uninit_mut(&mut self) -> (&mut Self, &mut [MaybeUninit], &mut Self) { + // SAFETY: `MaybeUninit` is transparent. Correct size and alignment are guaranteed by + // `align_to_mut` itself. Therefore the only thing that we have to ensure for a safe + // `transmute` is that the values are valid for the types involved. But for `MaybeUninit` + // any values are valid, so this operation is safe. + unsafe { self.align_to_mut() } + } +} + impl [[T; N]] { /// Takes a `&[[T; N]]`, and flattens it to a `&[T]`. /// From 40b1f4899a9081c0d8edf56072aaeb510b63a415 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 18:32:12 +0100 Subject: [PATCH 047/176] Add the feature gate for the `super let` experiment. --- compiler/rustc_ast_passes/src/feature_gate.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_parse/src/parser/stmt.rs | 15 ++++++++++++++- compiler/rustc_parse/src/parser/token_type.rs | 4 ++++ compiler/rustc_span/src/symbol.rs | 1 + tests/ui/feature-gates/feature-gate-super-let.rs | 4 ++++ .../feature-gates/feature-gate-super-let.stderr | 13 +++++++++++++ 7 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/ui/feature-gates/feature-gate-super-let.rs create mode 100644 tests/ui/feature-gates/feature-gate-super-let.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 31ff102c127a..4f50e21fc7d0 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -505,6 +505,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(contracts, "contracts are incomplete"); gate_all!(contracts_internals, "contract internal machinery is for internal use only"); gate_all!(where_clause_attrs, "attributes in `where` clause are unstable"); + gate_all!(super_let, "`super let` is experimental"); if !visitor.features.never_patterns() { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 72468dd4714d..b4499fb2a6a4 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -630,6 +630,8 @@ declare_features! ( (unstable, strict_provenance_lints, "1.61.0", Some(130351)), /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), + /// Allows `super let` statements. + (unstable, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), /// Allows subtrait items to shadow supertrait items. (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 97cd4d2117f8..2cd09aa8959c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -73,7 +73,20 @@ impl<'a> Parser<'a> { }); } - let stmt = if self.token.is_keyword(kw::Let) { + let stmt = if self.token.is_keyword(kw::Super) && self.is_keyword_ahead(1, &[kw::Let]) { + self.collect_tokens(None, attrs, force_collect, |this, attrs| { + this.expect_keyword(exp!(Super))?; + this.psess.gated_spans.gate(sym::super_let, this.prev_token.span); + this.expect_keyword(exp!(Let))?; + let local = this.parse_local(attrs)?; // FIXME(mara): implement super let + let trailing = Trailing::from(capture_semi && this.token == token::Semi); + Ok(( + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), + trailing, + UsePreAttrPos::No, + )) + })? + } else if self.token.is_keyword(kw::Let) { self.collect_tokens(None, attrs, force_collect, |this, attrs| { this.expect_keyword(exp!(Let))?; let local = this.parse_local(attrs)?; diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs index 886438fd583a..add3c9702019 100644 --- a/compiler/rustc_parse/src/parser/token_type.rs +++ b/compiler/rustc_parse/src/parser/token_type.rs @@ -114,6 +114,7 @@ pub enum TokenType { KwSelfUpper, KwStatic, KwStruct, + KwSuper, KwTrait, KwTry, KwType, @@ -250,6 +251,7 @@ impl TokenType { KwSelfUpper, KwStatic, KwStruct, + KwSuper, KwTrait, KwTry, KwType, @@ -324,6 +326,7 @@ impl TokenType { TokenType::KwSelfUpper => Some(kw::SelfUpper), TokenType::KwStatic => Some(kw::Static), TokenType::KwStruct => Some(kw::Struct), + TokenType::KwSuper => Some(kw::Super), TokenType::KwTrait => Some(kw::Trait), TokenType::KwTry => Some(kw::Try), TokenType::KwType => Some(kw::Type), @@ -549,6 +552,7 @@ macro_rules! exp { (SelfUpper) => { exp!(@kw, SelfUpper, KwSelfUpper) }; (Static) => { exp!(@kw, Static, KwStatic) }; (Struct) => { exp!(@kw, Struct, KwStruct) }; + (Super) => { exp!(@kw, Super, KwSuper) }; (Trait) => { exp!(@kw, Trait, KwTrait) }; (Try) => { exp!(@kw, Try, KwTry) }; (Type) => { exp!(@kw, Type, KwType) }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6807f96e712c..cc1b324eb00d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2036,6 +2036,7 @@ symbols! { sub_assign, sub_with_overflow, suggestion, + super_let, supertrait_item_shadowing, surface_async_drop_in_place, sym, diff --git a/tests/ui/feature-gates/feature-gate-super-let.rs b/tests/ui/feature-gates/feature-gate-super-let.rs new file mode 100644 index 000000000000..cfe92a42669d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-super-let.rs @@ -0,0 +1,4 @@ +fn main() { + super let a = 1; + //~^ ERROR `super let` is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-super-let.stderr b/tests/ui/feature-gates/feature-gate-super-let.stderr new file mode 100644 index 000000000000..a64e1b374f9c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-super-let.stderr @@ -0,0 +1,13 @@ +error[E0658]: `super let` is experimental + --> $DIR/feature-gate-super-let.rs:2:5 + | +LL | super let a = 1; + | ^^^^^ + | + = note: see issue #139076 for more information + = help: add `#![feature(super_let)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 5952f01712521d6700a58eeb0ad8b25db7c8fd68 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 28 Mar 2025 20:10:31 +0100 Subject: [PATCH 048/176] Fix trivial typo of `BoundVariableKind` --- src/doc/rustc-dev-guide/src/ty_module/binders.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/ty_module/binders.md b/src/doc/rustc-dev-guide/src/ty_module/binders.md index defb7cde514a..71157eca9b11 100644 --- a/src/doc/rustc-dev-guide/src/ty_module/binders.md +++ b/src/doc/rustc-dev-guide/src/ty_module/binders.md @@ -40,7 +40,7 @@ We did not always explicitly track the set of bound vars introduced by each `Bin ``` Binder( fn(&'^1_0 &'^1 T/#0), - &[BoundVariarbleKind::Region(...)], + &[BoundVariableKind::Region(...)], ) ``` This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those regions, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase. From 865a5a7e164950cf728439d12efb762e29c46c2c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 29 Mar 2025 20:02:01 +0200 Subject: [PATCH 049/176] mention that know-bug test directive takes arguments --- src/doc/rustc-dev-guide/src/tests/ui.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index c8536b0045cf..728ea3de418a 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -415,6 +415,14 @@ reasons, including: can alert the developer so they know that the associated issue has been fixed and can possibly be closed. +This directive takes comma-separated issue numbers as arguments, or `"unknown"`: + +- `//@ known-bug: #123, #456` (when the issues are on rust-lang/rust) +- `//@ known-bug: rust-lang/chalk#123456` + (allows arbitrary text before the `#`, which is useful when the issue is on another repo) +- `//@ known-bug: unknown` + (when there is no known issue yet; preferrably open one if it does not already exist) + Do not include [error annotations](#error-annotations) in a test with `known-bug`. The test should still include other normal directives and stdout/stderr files. From 1faf7ff9a434de8995e97e7372408489ce87050e Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 29 Mar 2025 23:52:57 +0200 Subject: [PATCH 050/176] update rustc-{driver,interface} examples --- .../rustc-dev-guide/examples/rustc-driver-example.rs | 11 +++++------ .../examples/rustc-driver-interacting-with-the-ast.rs | 4 ++-- .../examples/rustc-interface-example.rs | 8 ++++---- .../examples/rustc-interface-getting-diagnostics.rs | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 35dd07dd1365..fb8b13ad154c 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-03-08 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -20,7 +20,7 @@ use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; -use rustc_driver::{Compilation, run_compiler}; +use rustc_driver::{run_compiler, Compilation}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; @@ -71,13 +71,12 @@ impl rustc_driver::Callbacks for MyCallbacks { fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { // Analyze the program and inspect the types of definitions. - for id in tcx.hir_free_items(){ + for id in tcx.hir_free_items() { let item = &tcx.hir_item(id); match item.kind { - rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { - let name = item.ident; + rustc_hir::ItemKind::Static(ident, ..) | rustc_hir::ItemKind::Fn { ident, .. } => { let ty = tcx.type_of(item.hir_id().owner.def_id); - println!("{name:?}:\t{ty:?}") + println!("{ident:?}:\t{ty:?}") } _ => (), } diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index 2a43ba476e1e..b0c62d5b4bbb 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-03-08 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -71,7 +71,7 @@ impl rustc_driver::Callbacks for MyCallbacks { fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { // Iterate over the top-level items in the crate, looking for the main function. - for id in tcx.hir_free_items(){ + for id in tcx.hir_free_items() { let item = &tcx.hir_item(id); // Use pattern-matching to find a specific node inside the main function. if let rustc_hir::ItemKind::Fn { body, .. } = item.kind { diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs index 11125caec704..360f70c8e865 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-03-08 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -67,10 +67,10 @@ fn main() { for id in tcx.hir_free_items() { let item = tcx.hir_item(id); match item.kind { - rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { - let name = item.ident; + rustc_hir::ItemKind::Static(ident, ..) + | rustc_hir::ItemKind::Fn { ident, .. } => { let ty = tcx.type_of(item.hir_id().owner.def_id); - println!("{name:?}:\t{ty:?}") + println!("{ident:?}:\t{ty:?}") } _ => (), } diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs index 9bb93ab49587..2512ba3c3f92 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-03-08 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] From 471a2a8b87d8b5ba03a43a2c067dd322c1f5e7af Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 30 Mar 2025 00:16:39 +0200 Subject: [PATCH 051/176] example assumes a static exists This was removed, likely by mistake, during a refactor. --- src/doc/rustc-dev-guide/examples/rustc-driver-example.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index fb8b13ad154c..0e3450086ba5 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -34,9 +34,9 @@ impl rustc_span::source_map::FileLoader for MyFileLoader { fn read_file(&self, path: &Path) -> io::Result { if path == Path::new("main.rs") { Ok(r#" +static MESSAGE: &str = "Hello, World!"; fn main() { - let message = "Hello, World!"; - println!("{message}"); + println!("{MESSAGE}"); } "# .to_string()) From 9302f4d94f97750e84a47eaf5ac180feaaaafa3a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 30 Mar 2025 00:31:44 +0200 Subject: [PATCH 052/176] add rustfmt settings file --- .../rustc-dev-guide/ci/date-check/src/main.rs | 155 ++++-------------- .../examples/rustc-driver-example.rs | 2 +- .../rustc-driver-interacting-with-the-ast.rs | 2 +- src/doc/rustc-dev-guide/rustfmt.toml | 7 + 4 files changed, 39 insertions(+), 127 deletions(-) create mode 100644 src/doc/rustc-dev-guide/rustfmt.toml diff --git a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs index 5ab3e6c8b65a..9af69dbbf3f5 100644 --- a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs @@ -1,11 +1,8 @@ -use std::{ - collections::BTreeMap, - convert::TryInto as _, - env, fmt, fs, - path::{Path, PathBuf}, - process, - str::FromStr, -}; +use std::collections::BTreeMap; +use std::convert::TryInto as _; +use std::path::{Path, PathBuf}; +use std::str::FromStr; +use std::{env, fmt, fs, process}; use chrono::{Datelike as _, Month, TimeZone as _, Utc}; use glob::glob; @@ -19,19 +16,13 @@ struct Date { impl Date { fn months_since(self, other: Date) -> Option { - let self_chrono = Utc - .with_ymd_and_hms(self.year.try_into().unwrap(), self.month, 1, 0, 0, 0) - .unwrap(); - let other_chrono = Utc - .with_ymd_and_hms(other.year.try_into().unwrap(), other.month, 1, 0, 0, 0) - .unwrap(); + let self_chrono = + Utc.with_ymd_and_hms(self.year.try_into().unwrap(), self.month, 1, 0, 0, 0).unwrap(); + let other_chrono = + Utc.with_ymd_and_hms(other.year.try_into().unwrap(), other.month, 1, 0, 0, 0).unwrap(); let duration_since = self_chrono.signed_duration_since(other_chrono); let months_since = duration_since.num_days() / 30; - if months_since < 0 { - None - } else { - Some(months_since.try_into().unwrap()) - } + if months_since < 0 { None } else { Some(months_since.try_into().unwrap()) } } } @@ -66,26 +57,18 @@ fn collect_dates_from_file(date_regex: &Regex, text: &str) -> Vec<(usize, Date)> date_regex .captures_iter(text) .filter_map(|cap| { - if let (Some(month), Some(year), None, None) | (None, None, Some(month), Some(year)) = ( - cap.name("m1"), - cap.name("y1"), - cap.name("m2"), - cap.name("y2"), - ) { + if let (Some(month), Some(year), None, None) | (None, None, Some(month), Some(year)) = + (cap.name("m1"), cap.name("y1"), cap.name("m2"), cap.name("y2")) + { let year = year.as_str().parse().expect("year"); - let month = Month::from_str(month.as_str()) - .expect("month") - .number_from_month(); + let month = Month::from_str(month.as_str()).expect("month").number_from_month(); Some((cap.get(0).expect("all").range(), Date { year, month })) } else { None } }) .map(|(byte_range, date)| { - line += text[end_of_last_cap..byte_range.end] - .chars() - .filter(|c| *c == '\n') - .count(); + line += text[end_of_last_cap..byte_range.end].chars().filter(|c| *c == '\n').count(); end_of_last_cap = byte_range.end; (line, date) }) @@ -138,10 +121,7 @@ fn main() { let root_dir_path = Path::new(&root_dir); let glob_pat = format!("{}/**/*.md", root_dir); let today_chrono = Utc::now().date_naive(); - let current_month = Date { - year: today_chrono.year_ce().1, - month: today_chrono.month(), - }; + let current_month = Date { year: today_chrono.year_ce().1, month: today_chrono.month() }; let dates_by_file = collect_dates(glob(&glob_pat).unwrap().map(Result::unwrap)); let dates_by_file: BTreeMap<_, _> = @@ -173,10 +153,7 @@ fn main() { println!(); for (path, dates) in dates_by_file { - println!( - "- {}", - path.strip_prefix(&root_dir_path).unwrap_or(&path).display(), - ); + println!("- {}", path.strip_prefix(&root_dir_path).unwrap_or(&path).display(),); for (line, date) in dates { println!(" - [ ] line {}: {}", line, date); } @@ -191,14 +168,8 @@ mod tests { #[test] fn test_months_since() { - let date1 = Date { - year: 2020, - month: 3, - }; - let date2 = Date { - year: 2021, - month: 1, - }; + let date1 = Date { year: 2020, month: 3 }; + let date2 = Date { year: 2021, month: 1 }; assert_eq!(date2.months_since(date1), Some(10)); } @@ -273,83 +244,17 @@ Test8 assert_eq!( collect_dates_from_file(&make_date_regex(), text), vec![ - ( - 3, - Date { - year: 2021, - month: 1, - } - ), - ( - 6, - Date { - year: 2021, - month: 2, - } - ), - ( - 9, - Date { - year: 2021, - month: 3, - } - ), - ( - 11, - Date { - year: 2021, - month: 4, - } - ), - ( - 17, - Date { - year: 2021, - month: 5, - } - ), - ( - 20, - Date { - year: 2021, - month: 1, - } - ), - ( - 23, - Date { - year: 2021, - month: 2, - } - ), - ( - 26, - Date { - year: 2021, - month: 3, - } - ), - ( - 28, - Date { - year: 2021, - month: 4, - } - ), - ( - 34, - Date { - year: 2021, - month: 5, - } - ), - ( - 38, - Date { - year: 2021, - month: 6, - } - ), + (3, Date { year: 2021, month: 1 }), + (6, Date { year: 2021, month: 2 }), + (9, Date { year: 2021, month: 3 }), + (11, Date { year: 2021, month: 4 }), + (17, Date { year: 2021, month: 5 }), + (20, Date { year: 2021, month: 1 }), + (23, Date { year: 2021, month: 2 }), + (26, Date { year: 2021, month: 3 }), + (28, Date { year: 2021, month: 4 }), + (34, Date { year: 2021, month: 5 }), + (38, Date { year: 2021, month: 6 }), ], ); } diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 0e3450086ba5..db6ac1857854 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -20,7 +20,7 @@ use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; -use rustc_driver::{run_compiler, Compilation}; +use rustc_driver::{Compilation, run_compiler}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index b0c62d5b4bbb..c0d7f977d350 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -20,7 +20,7 @@ use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; -use rustc_driver::{run_compiler, Compilation}; +use rustc_driver::{Compilation, run_compiler}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; diff --git a/src/doc/rustc-dev-guide/rustfmt.toml b/src/doc/rustc-dev-guide/rustfmt.toml new file mode 100644 index 000000000000..b285329c78e6 --- /dev/null +++ b/src/doc/rustc-dev-guide/rustfmt.toml @@ -0,0 +1,7 @@ +# matches that of rust-lang/rust +style_edition = "2024" +use_small_heuristics = "Max" +merge_derives = false +group_imports = "StdExternalCrate" +imports_granularity = "Module" +use_field_init_shorthand = true From ebae4c65a10a593b838d9c2f07f4c13e342ec03e Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 30 Mar 2025 13:21:01 +0100 Subject: [PATCH 053/176] Fix partial clone link --- src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 067e28711184..c3c1c41e3f69 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -63,7 +63,7 @@ cd rust > **NOTE**: A shallow clone limits which `git` commands can be run. > If you intend to work on and contribute to the compiler, it is > generally recommended to fully clone the repository [as shown above](#get-the-source-code), -> or to perform a [partial clone](#shallow-clone-the-repository) instead. +> or to perform a [partial clone](#partial-clone-the-repository) instead. > > For example, `git bisect` and `git blame` require access to the commit history, > so they don't work if the repository was cloned with `--depth 1`. From 59ca7679c7db634465b5f021060f143567824ac4 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Sat, 29 Mar 2025 14:47:09 -0400 Subject: [PATCH 054/176] slice: Remove some uses of unsafe in first/last chunk methods Remove unsafe `split_at_unchecked` and `split_at_mut_unchecked` in some slice `split_first_chunk`/`split_last_chunk` methods. Replace those calls with the safe `split_at` and `split_at_checked` where applicable. Add codegen tests to check for no panics when calculating the last chunk index using `checked_sub` and `split_at` --- library/core/src/slice/mod.rs | 92 ++++++++++++--------------------- tests/codegen/slice-split-at.rs | 24 +++++++++ 2 files changed, 57 insertions(+), 59 deletions(-) create mode 100644 tests/codegen/slice-split-at.rs diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5bb7243c4491..4e8be2064317 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -382,16 +382,11 @@ impl [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_first_chunk(&self) -> Option<(&[T; N], &[T])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (first, tail) = unsafe { self.split_at_unchecked(N) }; + let Some((first, tail)) = self.split_at_checked(N) else { return None }; - // SAFETY: We explicitly check for the correct number of elements, - // and do not let the references outlive the slice. - Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) - } + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) } /// Returns a mutable array reference to the first `N` items in the slice and the remaining @@ -419,17 +414,12 @@ impl [T] { pub const fn split_first_chunk_mut( &mut self, ) -> Option<(&mut [T; N], &mut [T])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (first, tail) = unsafe { self.split_at_mut_unchecked(N) }; + let Some((first, tail)) = self.split_at_mut_checked(N) else { return None }; - // SAFETY: We explicitly check for the correct number of elements, - // do not let the reference outlive the slice, - // and enforce exclusive mutability of the chunk by the split. - Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail)) - } + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and enforce exclusive mutability of the chunk by the split. + Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail)) } /// Returns an array reference to the last `N` items in the slice and the remaining slice. @@ -452,16 +442,12 @@ impl [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_last_chunk(&self) -> Option<(&[T], &[T; N])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (init, last) = unsafe { self.split_at_unchecked(self.len() - N) }; + let Some(index) = self.len().checked_sub(N) else { return None }; + let (init, last) = self.split_at(index); - // SAFETY: We explicitly check for the correct number of elements, - // and do not let the references outlive the slice. - Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) - } + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) } /// Returns a mutable array reference to the last `N` items in the slice and the remaining @@ -489,17 +475,13 @@ impl [T] { pub const fn split_last_chunk_mut( &mut self, ) -> Option<(&mut [T], &mut [T; N])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (init, last) = unsafe { self.split_at_mut_unchecked(self.len() - N) }; + let Some(index) = self.len().checked_sub(N) else { return None }; + let (init, last) = self.split_at_mut(index); - // SAFETY: We explicitly check for the correct number of elements, - // do not let the reference outlive the slice, - // and enforce exclusive mutability of the chunk by the split. - Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) - } + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and enforce exclusive mutability of the chunk by the split. + Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) } /// Returns an array reference to the last `N` items in the slice. @@ -522,17 +504,13 @@ impl [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_last_chunk", since = "1.80.0")] pub const fn last_chunk(&self) -> Option<&[T; N]> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the slice. - // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. - let last = unsafe { self.split_at_unchecked(self.len() - N).1 }; + // FIXME(const-hack): Without const traits, we need this instead of `get`. + let Some(index) = self.len().checked_sub(N) else { return None }; + let (_, last) = self.split_at(index); - // SAFETY: We explicitly check for the correct number of elements, - // and do not let the references outlive the slice. - Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) - } + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) } /// Returns a mutable array reference to the last `N` items in the slice. @@ -556,18 +534,14 @@ impl [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the slice. - // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. - let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 }; + // FIXME(const-hack): Without const traits, we need this instead of `get`. + let Some(index) = self.len().checked_sub(N) else { return None }; + let (_, last) = self.split_at_mut(index); - // SAFETY: We explicitly check for the correct number of elements, - // do not let the reference outlive the slice, - // and require exclusive access to the entire slice to mutate the chunk. - Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }) - } + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and require exclusive access to the entire slice to mutate the chunk. + Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }) } /// Returns a reference to an element or subslice depending on the type of diff --git a/tests/codegen/slice-split-at.rs b/tests/codegen/slice-split-at.rs new file mode 100644 index 000000000000..07018cf9c917 --- /dev/null +++ b/tests/codegen/slice-split-at.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -Copt-level=3 +#![crate_type = "lib"] + +// Check that no panic is generated in `split_at` when calculating the index for +// the tail chunk using `checked_sub`. +// +// Tests written for refactored implementations of: +// `<[T]>::{split_last_chunk, split_last_chunk_mut, last_chunk, last_chunk_mut}` + +// CHECK-LABEL: @split_at_last_chunk +#[no_mangle] +pub fn split_at_last_chunk(s: &[u8], chunk_size: usize) -> Option<(&[u8], &[u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at(index)) +} + +// CHECK-LABEL: @split_at_mut_last_chunk +#[no_mangle] +pub fn split_at_mut_last_chunk(s: &mut [u8], chunk_size: usize) -> Option<(&mut [u8], &mut [u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at_mut(index)) +} From 39a491ada3309f47a0c8bdc41748461d00b4f735 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 23:20:04 +0200 Subject: [PATCH 055/176] unstable book: document import_trait_associated_functions --- .../import-trait-associated-functions.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/import-trait-associated-functions.md diff --git a/src/doc/unstable-book/src/language-features/import-trait-associated-functions.md b/src/doc/unstable-book/src/language-features/import-trait-associated-functions.md new file mode 100644 index 000000000000..0ae5915361e5 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/import-trait-associated-functions.md @@ -0,0 +1,22 @@ +# import_trait_associated_functions + +The tracking issue for this feature is: [#134691] + +[#134691]: https://github.com/rust-lang/rust/issues/134691 + +------------------------ + +This feature allows importing associated functions and constants from traits and then using them like regular items. + +```rust +#![feature(import_trait_associated_functions)] + +use std::ops::Add::add; + +fn main() { + let numbers = vec![1, 2, 3, 4, 5, 6]; + let sum = numbers.into_iter().reduce(add); // instead of `.reduce(Add:add)` + + assert_eq!(sum, Some(21)); +} +``` From 2feb91181882e525e698c4543063f4d0296fcf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Fri, 28 Mar 2025 15:52:15 +0100 Subject: [PATCH 056/176] io: Avoid marking buffer as uninit when copying to `BufWriter` --- library/std/src/io/copy.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 8d733325b3be..15e962924ac7 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -248,8 +248,11 @@ impl BufferedWriterSpec for BufWriter { Err(e) => return Err(e), } } else { + // All the bytes that were already in the buffer are initialized, + // treat them as such when the buffer is flushed. + init += buf.len(); + self.flush_buf()?; - init = 0; } } } From 878786848fdbe29325e9172d0ab86ed964eca7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Fri, 28 Mar 2025 15:52:56 +0100 Subject: [PATCH 057/176] io: Avoid Avoid marking bytes as uninit in `BufReader::peek` --- library/std/src/io/buffered/bufreader/buffer.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index 9fd2472ebdfd..574288e579e0 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -123,7 +123,6 @@ impl Buffer { /// Remove bytes that have already been read from the buffer. pub fn backshift(&mut self) { self.buf.copy_within(self.pos.., 0); - self.initialized -= self.pos; self.filled -= self.pos; self.pos = 0; } From f9ef4563c23d81dff49a3cc4443202358426e3bd Mon Sep 17 00:00:00 2001 From: makai410 Date: Tue, 1 Apr 2025 17:11:53 +0800 Subject: [PATCH 058/176] Implement `associated_items` api. --- compiler/rustc_smir/src/rustc_internal/mod.rs | 8 + compiler/rustc_smir/src/rustc_smir/context.rs | 15 ++ .../rustc_smir/src/rustc_smir/convert/ty.rs | 60 ++++++++ compiler/stable_mir/src/compiler_interface.rs | 7 +- compiler/stable_mir/src/crate_def.rs | 16 +- compiler/stable_mir/src/lib.rs | 7 +- compiler/stable_mir/src/mir/pretty.rs | 12 +- compiler/stable_mir/src/ty.rs | 67 +++++++- .../stable-mir/check_assoc_items.rs | 145 ++++++++++++++++++ 9 files changed, 330 insertions(+), 7 deletions(-) create mode 100644 tests/ui-fulldeps/stable-mir/check_assoc_items.rs diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index ad38ea228bf5..30e9b2e72f73 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -147,6 +147,14 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::CoroutineWitnessDef(self.create_def_id(did)) } + pub fn assoc_def(&mut self, did: DefId) -> stable_mir::ty::AssocDef { + stable_mir::ty::AssocDef(self.create_def_id(did)) + } + + pub fn opaque_def(&mut self, did: DefId) -> stable_mir::ty::OpaqueDef { + stable_mir::ty::OpaqueDef(self.create_def_id(did)) + } + pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov { stable_mir::ty::Prov(self.create_alloc_id(aid)) } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index aa1921fc8e78..322e86147c19 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -822,6 +822,21 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let ty = un_op.internal(&mut *tables, tcx).ty(tcx, arg_internal); ty.stable(&mut *tables) } + + fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let def_id = tables[def_id]; + let assoc_items = if tcx.is_trait_alias(def_id) { + Vec::new() + } else { + tcx.associated_item_def_ids(def_id) + .iter() + .map(|did| tcx.associated_item(*did).stable(&mut *tables)) + .collect() + }; + assoc_items + } } pub(crate) struct TablesWrapper<'tcx>(pub RefCell>); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index aa0eac628dd0..8309809d7b51 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -890,3 +890,63 @@ impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { } } } + +impl<'tcx> Stable<'tcx> for ty::AssocKind { + type T = stable_mir::ty::AssocKind; + + fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { + use stable_mir::ty::AssocKind; + match self { + ty::AssocKind::Const => AssocKind::Const, + ty::AssocKind::Fn => AssocKind::Fn, + ty::AssocKind::Type => AssocKind::Type, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::AssocItemContainer { + type T = stable_mir::ty::AssocItemContainer; + + fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { + use stable_mir::ty::AssocItemContainer; + match self { + ty::AssocItemContainer::Trait => AssocItemContainer::Trait, + ty::AssocItemContainer::Impl => AssocItemContainer::Impl, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::AssocItem { + type T = stable_mir::ty::AssocItem; + + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + stable_mir::ty::AssocItem { + def_id: tables.assoc_def(self.def_id), + name: self.name.to_string(), + kind: self.kind.stable(tables), + container: self.container.stable(tables), + trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)), + fn_has_self_parameter: self.fn_has_self_parameter, + opt_rpitit_info: self.opt_rpitit_info.map(|rpitit| rpitit.stable(tables)), + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { + type T = stable_mir::ty::ImplTraitInTraitData; + + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + use stable_mir::ty::ImplTraitInTraitData; + match self { + ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => { + ImplTraitInTraitData::Trait { + fn_def_id: tables.fn_def(*fn_def_id), + opaque_def_id: tables.opaque_def(*opaque_def_id), + } + } + ty::ImplTraitInTraitData::Impl { fn_def_id } => { + ImplTraitInTraitData::Impl { fn_def_id: tables.fn_def(*fn_def_id) } + } + } + } +} diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index e82c957c34ea..46154da36ca0 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -18,8 +18,8 @@ use crate::ty::{ TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, }; use crate::{ - Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, - Symbol, TraitDecls, mir, + AssocItems, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, + ItemKind, Symbol, TraitDecls, mir, }; /// This trait defines the interface between stable_mir and the Rust compiler. @@ -251,6 +251,9 @@ pub trait Context { /// Get the resulting type of unary operation. fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty; + + /// Get all associated items of a definition. + fn associated_items(&self, def_id: DefId) -> AssocItems; } // A thread local variable that stores a pointer to the tables mapping between TyCtxt diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs index 2577c281ca4f..75228135e4cb 100644 --- a/compiler/stable_mir/src/crate_def.rs +++ b/compiler/stable_mir/src/crate_def.rs @@ -4,7 +4,7 @@ use serde::Serialize; use crate::ty::{GenericArgs, Span, Ty}; -use crate::{Crate, Symbol, with}; +use crate::{AssocItems, Crate, Symbol, with}; /// A unique identification number for each item accessible for the current compilation unit. #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)] @@ -103,6 +103,14 @@ pub trait CrateDefType: CrateDef { } } +/// A trait for retrieving all items from a definition within a crate. +pub trait CrateDefItems: CrateDef { + /// Retrieve all associated items from a definition. + fn associated_items(&self) -> AssocItems { + with(|cx| cx.associated_items(self.def_id())) + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct Attribute { value: String, @@ -158,3 +166,9 @@ macro_rules! crate_def_with_ty { impl CrateDefType for $name {} }; } + +macro_rules! impl_crate_def_items { + ( $name:ident $(;)? ) => { + impl CrateDefItems for $name {} + }; +} diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 70d42dfbfcb9..df90d3e5a084 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -23,11 +23,11 @@ use std::{fmt, io}; use serde::Serialize; use crate::compiler_interface::with; -pub use crate::crate_def::{CrateDef, CrateDefType, DefId}; +pub use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId}; pub use crate::error::*; use crate::mir::mono::StaticDef; use crate::mir::{Body, Mutability}; -use crate::ty::{FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; +use crate::ty::{AssocItem, FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; pub mod abi; #[macro_use] @@ -71,6 +71,9 @@ pub type TraitDecls = Vec; /// A list of impl trait decls. pub type ImplTraitDecls = Vec; +/// A list of associated items. +pub type AssocItems = Vec; + /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug, Serialize)] pub struct Crate { diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 8278afb7a2f1..65d9f20f0a3b 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -9,7 +9,7 @@ use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, Ter use crate::mir::{ Operand, Place, RawPtrKind, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents, }; -use crate::ty::{AdtKind, IndexedVal, MirConst, Ty, TyConst}; +use crate::ty::{AdtKind, AssocKind, IndexedVal, MirConst, Ty, TyConst}; use crate::{Body, CrateDef, Mutability, with}; impl Display for Ty { @@ -18,6 +18,16 @@ impl Display for Ty { } } +impl Display for AssocKind { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + AssocKind::Fn => write!(f, "method"), + AssocKind::Const => write!(f, "associated const"), + AssocKind::Type => write!(f, "associated type"), + } + } +} + impl Debug for Place { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { with(|ctx| write!(f, "{}", ctx.place_pretty(self))) diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index b857a735b725..25ec4a440d6e 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -6,7 +6,7 @@ use serde::Serialize; use super::mir::{Body, Mutability, Safety}; use super::{DefId, Error, Symbol, with}; use crate::abi::{FnAbi, Layout}; -use crate::crate_def::{CrateDef, CrateDefType}; +use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType}; use crate::mir::alloc::{AllocId, read_target_int, read_target_uint}; use crate::mir::mono::StaticDef; use crate::target::MachineInfo; @@ -910,6 +910,10 @@ crate_def! { pub TraitDef; } +impl_crate_def_items! { + TraitDef; +} + impl TraitDef { pub fn declaration(trait_def: &TraitDef) -> TraitDecl { with(|cx| cx.trait_decl(trait_def)) @@ -932,6 +936,10 @@ crate_def! { pub ImplDef; } +impl_crate_def_items! { + ImplDef; +} + impl ImplDef { /// Retrieve information about this implementation. pub fn trait_impl(&self) -> ImplTrait { @@ -1555,3 +1563,60 @@ index_impl!(Span); pub struct VariantIdx(usize); index_impl!(VariantIdx); + +crate_def! { + /// Hold infomation about an Opaque definition, particularly useful in `RPITIT`. + #[derive(Serialize)] + pub OpaqueDef; +} + +crate_def! { + #[derive(Serialize)] + pub AssocDef; +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub struct AssocItem { + pub def_id: AssocDef, + pub name: Symbol, + pub kind: AssocKind, + pub container: AssocItemContainer, + + /// If this is an item in an impl of a trait then this is the `DefId` of + /// the associated item on the trait that this implements. + pub trait_item_def_id: Option, + + /// Whether this is a method with an explicit self + /// as its first parameter, allowing method calls. + pub fn_has_self_parameter: bool, + + /// `Some` if the associated item (an associated type) comes from the + /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData` + /// provides additional information about its source. + pub opt_rpitit_info: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub enum AssocKind { + Const, + Fn, + Type, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub enum AssocItemContainer { + Trait, + Impl, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] +pub enum ImplTraitInTraitData { + Trait { fn_def_id: FnDef, opaque_def_id: OpaqueDef }, + Impl { fn_def_id: FnDef }, +} + +impl AssocItem { + pub fn is_impl_trait_in_trait(&self) -> bool { + self.opt_rpitit_info.is_some() + } +} diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs new file mode 100644 index 000000000000..f6f895588f27 --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs @@ -0,0 +1,145 @@ +//@ run-pass +//! Test that users are able to retrieve all associated items from a definition. +//! definition. + +//@ ignore-stage1 +//@ ignore-cross-compile +//@ ignore-remote +//@ edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] + +extern crate rustc_middle; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate stable_mir; + +use rustc_smir::rustc_internal; +use std::io::Write; +use std::collections::HashSet; +use stable_mir::CrateDef; +use stable_mir::*; +use stable_mir::ty::*; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "crate_assoc_items"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_assoc_items() -> ControlFlow<()> { + let local_crate = stable_mir::local_crate(); + check_items( + &local_crate.fn_defs(), + &[ + "AStruct::new", + "::assoc_fn_no_self", + "::assoc_fn_has_self", + "ATrait::rpitit", + "ATrait::assoc_fn_has_self", + "ATrait::assoc_fn_no_self", + "::rpitit", + ], + ); + + let local_impls = local_crate.trait_impls(); + let local_traits = local_crate.trait_decls(); + + let trait_assoc_item_defs: Vec = local_traits[0].associated_items() + .iter().map(|assoc_item| assoc_item.def_id).collect(); + check_items( + &trait_assoc_item_defs, + &[ + "ATrait::{synthetic#0}", + "ATrait::rpitit", + "ATrait::Assoc", + "ATrait::assoc_fn_no_self", + "ATrait::assoc_fn_has_self", + ] + ); + + let impl_assoc_item_defs: Vec = local_impls[0].associated_items() + .iter().map(|assoc_item| assoc_item.def_id).collect(); + check_items( + &impl_assoc_item_defs, + &[ + "::{synthetic#0}", + "::rpitit", + "::Assoc", + "::assoc_fn_no_self", + "::assoc_fn_has_self", + ] + ); + + ControlFlow::Continue(()) +} + +/// Check if the list of definitions matches the expected list. +/// Note that order doesn't matter. +fn check_items(items: &[T], expected: &[&str]) { + let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect(); + let item_names: HashSet<_> = items.iter().map(|item| item.name()).collect(); + assert_eq!(item_names, expected); +} + +fn main() { + let path = "assoc_items.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, test_assoc_items).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + #![allow(dead_code, unused_variables)] + struct AStruct; + + impl AStruct {{ + const ASSOC_CONST: &str = "Nina"; + + fn new() -> Self {{ + AStruct{{}} + }} + }} + + trait ATrait {{ + type Assoc; + + fn assoc_fn_no_self() {{ + }} + + fn assoc_fn_has_self(&self) {{ + }} + + fn rpitit(&self) -> impl std::fmt::Debug {{ + "ciallo" + }} + }} + + impl ATrait for AStruct {{ + type Assoc = u32; + + fn assoc_fn_no_self() {{ + }} + + fn assoc_fn_has_self(&self) {{ + }} + + fn rpitit(&self) -> impl std::fmt::Debug {{ + "ciallo~" + }} + }} + "# + )?; + Ok(()) +} From 6ce74f78f002d40b98138ee2ba00bbb21af2630d Mon Sep 17 00:00:00 2001 From: Jane Losare-Lusby Date: Tue, 25 Mar 2025 11:56:55 -0700 Subject: [PATCH 059/176] replace extra_filename with strict version hash in metrics file names --- compiler/rustc_driver_impl/src/lib.rs | 13 +++++-------- compiler/rustc_middle/src/ty/context.rs | 5 +++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 6ea14d15c144..981cdf1d1d6e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -60,6 +60,7 @@ use rustc_session::lint::{Lint, LintId}; use rustc_session::output::collect_crate_types; use rustc_session::{EarlyDiagCtxt, Session, config, filesearch}; use rustc_span::FileName; +use rustc_span::def_id::LOCAL_CRATE; use rustc_target::json::ToJson; use rustc_target::spec::{Target, TargetTuple}; use time::OffsetDateTime; @@ -383,14 +384,10 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) } fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) { - let output_filenames = tcxt.output_filenames(()); - let mut metrics_file_name = std::ffi::OsString::from("unstable_feature_usage_metrics-"); - let mut metrics_path = output_filenames.with_directory_and_extension(metrics_dir, "json"); - let metrics_file_stem = - metrics_path.file_name().expect("there should be a valid default output filename"); - metrics_file_name.push(metrics_file_stem); - metrics_path.pop(); - metrics_path.push(metrics_file_name); + let hash = tcxt.crate_hash(LOCAL_CRATE); + let crate_name = tcxt.crate_name(LOCAL_CRATE); + let metrics_file_name = format!("unstable_feature_usage_metrics-{crate_name}-{hash}.json"); + let metrics_path = metrics_dir.join(metrics_file_name); if let Err(error) = tcxt.features().dump_feature_usage_metrics(metrics_path) { // FIXME(yaahc): once metrics can be enabled by default we will want "failure to emit // default metrics" to only produce a warning when metrics are enabled by default and emit diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 86248b495cdc..8b6b2bc2493e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1738,10 +1738,15 @@ impl<'tcx> TyCtxt<'tcx> { // - needs_metadata: for putting into crate metadata. // - instrument_coverage: for putting into coverage data (see // `hash_mir_source`). + // - metrics_dir: metrics use the strict version hash in the filenames + // for dumped metrics files to prevent overwriting distinct metrics + // for similar source builds (may change in the future, this is part + // of the proof of concept impl for the metrics initiative project goal) cfg!(debug_assertions) || self.sess.opts.incremental.is_some() || self.needs_metadata() || self.sess.instrument_coverage() + || self.sess.opts.unstable_opts.metrics_dir.is_some() } #[inline] From a3e6b6947196554227a636095a7fdec0923a20d9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Apr 2025 03:36:40 +0000 Subject: [PATCH 060/176] cache_on_disk_if false is a noop --- compiler/rustc_middle/src/query/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d7ed703f4ae3..9e9b707be0a4 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1602,7 +1602,6 @@ rustc_queries! { /// `Err(AlwaysRequiresDrop)` is returned. query adt_significant_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { desc { |tcx| "computing when `{}` has a significant destructor", tcx.def_path_str(def_id) } - cache_on_disk_if { false } } /// Returns a list of types which (a) have a potentially significant destructor @@ -1624,7 +1623,6 @@ rustc_queries! { /// Otherwise, there is a risk of query cycles. query list_significant_drop_tys(ty: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> &'tcx ty::List> { desc { |tcx| "computing when `{}` has a significant destructor", ty.value } - cache_on_disk_if { false } } /// Computes the layout of a type. Note that this implicitly From 444a7eb5aa9772d2d4363956bdfac8315e47d739 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Apr 2025 03:36:04 +0000 Subject: [PATCH 061/176] Use return_result_from_ensure_ok a bit more --- compiler/rustc_const_eval/src/check_consts/check.rs | 2 +- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 5 +++-- compiler/rustc_mir_build/src/builder/mod.rs | 4 ++-- compiler/rustc_mir_transform/src/lib.rs | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 90002d3f1090..2b74c849f1ae 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -335,7 +335,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { self.tcx.dcx().span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`"); } if let Some(def_id) = def_id.as_local() - && let Err(guar) = self.tcx.at(span).check_well_formed(hir::OwnerId { def_id }) + && let Err(guar) = self.tcx.ensure_ok().check_well_formed(hir::OwnerId { def_id }) { self.error_emitted = Some(guar); } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 93013c8b3f61..747e36b6a1a2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -976,7 +976,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.par_hir_body_owners(|def_id| { if tcx.is_coroutine(def_id.to_def_id()) { tcx.ensure_ok().mir_coroutine_witnesses(def_id); - tcx.ensure_ok().check_coroutine_obligations( + let _ = tcx.ensure_ok().check_coroutine_obligations( tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(), ); // Eagerly check the unsubstituted layout for cycles. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9e9b707be0a4..5315e14b0ff2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -612,6 +612,7 @@ rustc_queries! { query check_coroutine_obligations(key: LocalDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) } + return_result_from_ensure_ok } /// MIR after our optimization passes have run. This is MIR that is ready @@ -1039,7 +1040,7 @@ rustc_queries! { /// Checks well-formedness of tail calls (`become f()`). query check_tail_calls(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { desc { |tcx| "tail-call-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } + return_result_from_ensure_ok } /// Returns the types assumed to be well formed while "inside" of the given item. @@ -1308,7 +1309,7 @@ rustc_queries! { query check_match(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } + return_result_from_ensure_ok } /// Performs part of the privacy check and computes effective visibilities. diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index c8b69a6ec62f..2e409667cdff 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -48,11 +48,11 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>( /// this directly; instead use the cached version via `mir_built`. pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { tcx.ensure_done().thir_abstract_const(def); - if let Err(e) = tcx.check_match(def) { + if let Err(e) = tcx.ensure_ok().check_match(def) { return construct_error(tcx, def, e); } - if let Err(err) = tcx.check_tail_calls(def) { + if let Err(err) = tcx.ensure_ok().check_tail_calls(def) { return construct_error(tcx, def, err); } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 205d388f4fb5..51433d894873 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -528,7 +528,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & | DefKind::Static { .. } | DefKind::Const | DefKind::AssocConst => { - if let Err(guar) = tcx.check_well_formed(root.expect_local()) { + if let Err(guar) = tcx.ensure_ok().check_well_formed(root.expect_local()) { body.tainted_by_errors = Some(guar); } } From 3524e6ab0fd14627bd84b51e00f85e0a8f05f1b9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Apr 2025 03:39:16 +0000 Subject: [PATCH 062/176] ensure_ok().query doesn't need cache_on_disk --- compiler/rustc_middle/src/query/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5315e14b0ff2..fe7ae1f32e2f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1034,7 +1034,6 @@ rustc_queries! { /// Unsafety-check this `LocalDefId`. query check_unsafety(key: LocalDefId) { desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } } /// Checks well-formedness of tail calls (`become f()`). @@ -2511,7 +2510,6 @@ rustc_queries! { /// monomorphized. query check_mono_item(key: ty::Instance<'tcx>) { desc { "monomorphization-time checking" } - cache_on_disk_if { true } } /// Builds the set of functions that should be skipped for the move-size check. From 9d999bb035234f2d3eeff38853e262728f9031c6 Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 24 Mar 2025 16:55:24 +0800 Subject: [PATCH 063/176] Do not use `for_each_assignment_mut` to iterate over assignment statements `for_each_assignment_mut` can skip assignment statements with side effects, which can result in some assignment statements retrieving outdated value. For example, it may skip a dereference assignment statement. --- compiler/rustc_mir_transform/src/gvn.rs | 77 +++++++++---------- compiler/rustc_mir_transform/src/ssa.rs | 38 --------- ..._simplification.hello.GVN.panic-abort.diff | 3 +- ...simplification.hello.GVN.panic-unwind.diff | 3 +- 4 files changed, 41 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 0a54c780f31e..2abb4e8b8ce1 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -3,14 +3,16 @@ //! MIR may contain repeated and/or redundant computations. The objective of this pass is to detect //! such redundancies and re-use the already-computed result when possible. //! -//! In a first pass, we compute a symbolic representation of values that are assigned to SSA -//! locals. This symbolic representation is defined by the `Value` enum. Each produced instance of -//! `Value` is interned as a `VnIndex`, which allows us to cheaply compute identical values. -//! //! From those assignments, we construct a mapping `VnIndex -> Vec<(Local, Location)>` of available //! values, the locals in which they are stored, and the assignment location. //! -//! In a second pass, we traverse all (non SSA) assignments `x = rvalue` and operands. For each +//! We traverse all assignments `x = rvalue` and operands. +//! +//! For each SSA one, we compute a symbolic representation of values that are assigned to SSA +//! locals. This symbolic representation is defined by the `Value` enum. Each produced instance of +//! `Value` is interned as a `VnIndex`, which allows us to cheaply compute identical values. +//! +//! For each non-SSA //! one, we compute the `VnIndex` of the rvalue. If this `VnIndex` is associated to a constant, we //! replace the rvalue/operand by that constant. Otherwise, if there is an SSA local `y` //! associated to this `VnIndex`, and if its definition location strictly dominates the assignment @@ -107,7 +109,7 @@ use rustc_span::def_id::DefId; use smallvec::SmallVec; use tracing::{debug, instrument, trace}; -use crate::ssa::{AssignedValue, SsaLocals}; +use crate::ssa::SsaLocals; pub(super) struct GVN; @@ -126,31 +128,11 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let dominators = body.basic_blocks.dominators().clone(); let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls); - ssa.for_each_assignment_mut( - body.basic_blocks.as_mut_preserves_cfg(), - |local, value, location| { - let value = match value { - // We do not know anything of this assigned value. - AssignedValue::Arg | AssignedValue::Terminator => None, - // Try to get some insight. - AssignedValue::Rvalue(rvalue) => { - let value = state.simplify_rvalue(rvalue, location); - // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark - // `local` as reusable if we have an exact type match. - if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) { - return; - } - value - } - }; - // `next_opaque` is `Some`, so `new_opaque` must return `Some`. - let value = value.or_else(|| state.new_opaque()).unwrap(); - state.assign(local, value); - }, - ); - // Stop creating opaques during replacement as it is useless. - state.next_opaque = None; + for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) { + let opaque = state.new_opaque().unwrap(); + state.assign(local, opaque); + } let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); for bb in reverse_postorder { @@ -250,7 +232,6 @@ struct VnState<'body, 'tcx> { locals: IndexVec>, /// Locals that are assigned that value. // This vector does not hold all the values of `VnIndex` that we create. - // It stops at the largest value created in the first phase of collecting assignments. rev_locals: IndexVec>, values: FxIndexSet>, /// Values evaluated as constants if possible. @@ -345,6 +326,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { /// Record that `local` is assigned `value`. `local` must be SSA. #[instrument(level = "trace", skip(self))] fn assign(&mut self, local: Local, value: VnIndex) { + debug_assert!(self.ssa.is_ssa(local)); self.locals[local] = Some(value); // Only register the value if its type is `Sized`, as we will emit copies of it. @@ -1751,15 +1733,19 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { if let StatementKind::Assign(box (ref mut lhs, ref mut rvalue)) = stmt.kind { self.simplify_place_projection(lhs, location); - // Do not try to simplify a constant, it's already in canonical shape. - if matches!(rvalue, Rvalue::Use(Operand::Constant(_))) { - return; - } - - let value = lhs - .as_local() - .and_then(|local| self.locals[local]) - .or_else(|| self.simplify_rvalue(rvalue, location)); + let value = self.simplify_rvalue(rvalue, location); + let value = if let Some(local) = lhs.as_local() + && self.ssa.is_ssa(local) + // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark + // `local` as reusable if we have an exact type match. + && self.local_decls[local].ty == rvalue.ty(self.local_decls, self.tcx) + { + let value = value.or_else(|| self.new_opaque()).unwrap(); + self.assign(local, value); + Some(value) + } else { + value + }; let Some(value) = value else { return }; if let Some(const_) = self.try_as_constant(value) { @@ -1775,6 +1761,17 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { } self.super_statement(stmt, location); } + + fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { + if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator + && let Some(local) = destination.as_local() + && self.ssa.is_ssa(local) + { + let opaque = self.new_opaque().unwrap(); + self.assign(local, opaque); + } + self.super_terminator(terminator, location); + } } struct StorageRemover<'tcx> { diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 3d512fb064ec..edd0cabca49a 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -32,12 +32,6 @@ pub(super) struct SsaLocals { borrowed_locals: DenseBitSet, } -pub(super) enum AssignedValue<'a, 'tcx> { - Arg, - Rvalue(&'a mut Rvalue<'tcx>), - Terminator, -} - impl SsaLocals { pub(super) fn new<'tcx>( tcx: TyCtxt<'tcx>, @@ -152,38 +146,6 @@ impl SsaLocals { }) } - pub(super) fn for_each_assignment_mut<'tcx>( - &self, - basic_blocks: &mut IndexSlice>, - mut f: impl FnMut(Local, AssignedValue<'_, 'tcx>, Location), - ) { - for &local in &self.assignment_order { - match self.assignments[local] { - Set1::One(DefLocation::Argument) => f( - local, - AssignedValue::Arg, - Location { block: START_BLOCK, statement_index: 0 }, - ), - Set1::One(DefLocation::Assignment(loc)) => { - let bb = &mut basic_blocks[loc.block]; - // `loc` must point to a direct assignment to `local`. - let stmt = &mut bb.statements[loc.statement_index]; - let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { - bug!() - }; - assert_eq!(target.as_local(), Some(local)); - f(local, AssignedValue::Rvalue(rvalue), loc) - } - Set1::One(DefLocation::CallReturn { call, .. }) => { - let bb = &mut basic_blocks[call]; - let loc = Location { block: call, statement_index: bb.statements.len() }; - f(local, AssignedValue::Terminator, loc) - } - _ => {} - } - } - } - /// Compute the equivalence classes for locals, based on copy statements. /// /// The returned vector maps each local to the one it copies. In the following case: diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff index 886f9a68dd9d..417406de39b6 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff @@ -8,8 +8,9 @@ bb0: { StorageLive(_1); - _1 = const ::NEEDS; +- _1 = const ::NEEDS; - switchInt(move _1) -> [0: bb2, otherwise: bb1]; ++ _1 = const false; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff index cc53b213397d..63ba2c6865f0 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff @@ -8,8 +8,9 @@ bb0: { StorageLive(_1); - _1 = const ::NEEDS; +- _1 = const ::NEEDS; - switchInt(move _1) -> [0: bb2, otherwise: bb1]; ++ _1 = const false; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } From 84af55679131e5074b7236fbdd98b12e9012b94e Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 24 Mar 2025 16:55:24 +0800 Subject: [PATCH 064/176] `next_opaque` is no longer an `Option` --- compiler/rustc_mir_transform/src/gvn.rs | 69 ++++++++++++------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 2abb4e8b8ce1..42d736cf5f49 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -130,7 +130,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls); for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) { - let opaque = state.new_opaque().unwrap(); + let opaque = state.new_opaque(); state.assign(local, opaque); } @@ -237,8 +237,7 @@ struct VnState<'body, 'tcx> { /// Values evaluated as constants if possible. evaluated: IndexVec>>, /// Counter to generate different values. - /// This is an option to stop creating opaques during replacement. - next_opaque: Option, + next_opaque: usize, /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop. feature_unsized_locals: bool, ssa: &'body SsaLocals, @@ -270,7 +269,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { rev_locals: IndexVec::with_capacity(num_values), values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()), evaluated: IndexVec::with_capacity(num_values), - next_opaque: Some(1), + next_opaque: 1, feature_unsized_locals: tcx.features().unsized_locals(), ssa, dominators, @@ -291,32 +290,31 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let evaluated = self.eval_to_const(index); let _index = self.evaluated.push(evaluated); debug_assert_eq!(index, _index); - // No need to push to `rev_locals` if we finished listing assignments. - if self.next_opaque.is_some() { - let _index = self.rev_locals.push(SmallVec::new()); - debug_assert_eq!(index, _index); - } + let _index = self.rev_locals.push(SmallVec::new()); + debug_assert_eq!(index, _index); } index } + fn next_opaque(&mut self) -> usize { + let next_opaque = self.next_opaque; + self.next_opaque += 1; + next_opaque + } + /// Create a new `Value` for which we have no information at all, except that it is distinct /// from all the others. #[instrument(level = "trace", skip(self), ret)] - fn new_opaque(&mut self) -> Option { - let next_opaque = self.next_opaque.as_mut()?; - let value = Value::Opaque(*next_opaque); - *next_opaque += 1; - Some(self.insert(value)) + fn new_opaque(&mut self) -> VnIndex { + let value = Value::Opaque(self.next_opaque()); + self.insert(value) } /// Create a new `Value::Address` distinct from all the others. #[instrument(level = "trace", skip(self), ret)] - fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> Option { - let next_opaque = self.next_opaque.as_mut()?; - let value = Value::Address { place, kind, provenance: *next_opaque }; - *next_opaque += 1; - Some(self.insert(value)) + fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> VnIndex { + let value = Value::Address { place, kind, provenance: self.next_opaque() }; + self.insert(value) } fn get(&self, index: VnIndex) -> &Value<'tcx> { @@ -337,21 +335,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } - fn insert_constant(&mut self, value: Const<'tcx>) -> Option { + fn insert_constant(&mut self, value: Const<'tcx>) -> VnIndex { let disambiguator = if value.is_deterministic() { // The constant is deterministic, no need to disambiguate. 0 } else { // Multiple mentions of this constant will yield different values, // so assign a different `disambiguator` to ensure they do not get the same `VnIndex`. - let next_opaque = self.next_opaque.as_mut()?; - let disambiguator = *next_opaque; - *next_opaque += 1; + let disambiguator = self.next_opaque(); // `disambiguator: 0` means deterministic. debug_assert_ne!(disambiguator, 0); disambiguator }; - Some(self.insert(Value::Constant { value, disambiguator })) + self.insert(Value::Constant { value, disambiguator }) } fn insert_bool(&mut self, flag: bool) -> VnIndex { @@ -812,7 +808,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { location: Location, ) -> Option { match *operand { - Operand::Constant(ref constant) => self.insert_constant(constant.const_), + Operand::Constant(ref constant) => Some(self.insert_constant(constant.const_)), Operand::Copy(ref mut place) | Operand::Move(ref mut place) => { let value = self.simplify_place_value(place, location)?; if let Some(const_) = self.try_as_constant(value) { @@ -848,11 +844,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Rvalue::Aggregate(..) => return self.simplify_aggregate(rvalue, location), Rvalue::Ref(_, borrow_kind, ref mut place) => { self.simplify_place_projection(place, location); - return self.new_pointer(*place, AddressKind::Ref(borrow_kind)); + return Some(self.new_pointer(*place, AddressKind::Ref(borrow_kind))); } Rvalue::RawPtr(mutbl, ref mut place) => { self.simplify_place_projection(place, location); - return self.new_pointer(*place, AddressKind::Address(mutbl)); + return Some(self.new_pointer(*place, AddressKind::Address(mutbl))); } Rvalue::WrapUnsafeBinder(ref mut op, ty) => { let value = self.simplify_operand(op, location)?; @@ -1016,7 +1012,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if is_zst { let ty = rvalue.ty(self.local_decls, tcx); - return self.insert_constant(Const::zero_sized(ty)); + return Some(self.insert_constant(Const::zero_sized(ty))); } } @@ -1045,11 +1041,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } }; - let fields: Option> = field_ops + let mut fields: Vec<_> = field_ops .iter_mut() - .map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque())) + .map(|op| self.simplify_operand(op, location).unwrap_or_else(|| self.new_opaque())) .collect(); - let mut fields = fields?; if let AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty } = &mut ty { let mut was_updated = false; @@ -1177,7 +1172,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ) if let ty::Slice(..) = to.builtin_deref(true).unwrap().kind() && let ty::Array(_, len) = from.builtin_deref(true).unwrap().kind() => { - return self.insert_constant(Const::Ty(self.tcx.types.usize, *len)); + return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); } _ => Value::UnaryOp(op, arg_index), }; @@ -1373,7 +1368,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if let CastKind::PointerCoercion(ReifyFnPointer | ClosureFnPointer(_), _) = kind { // Each reification of a generic fn may get a different pointer. // Do not try to merge them. - return self.new_opaque(); + return Some(self.new_opaque()); } let mut was_ever_updated = false; @@ -1489,7 +1484,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Trivial case: we are fetching a statically known length. let place_ty = place.ty(self.local_decls, self.tcx).ty; if let ty::Array(_, len) = place_ty.kind() { - return self.insert_constant(Const::Ty(self.tcx.types.usize, *len)); + return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); } let mut inner = self.simplify_place_value(place, location)?; @@ -1511,7 +1506,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let Some(to) = to.builtin_deref(true) && let ty::Slice(..) = to.kind() { - return self.insert_constant(Const::Ty(self.tcx.types.usize, *len)); + return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); } // Fallback: a symbolic `Len`. @@ -1740,7 +1735,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { // `local` as reusable if we have an exact type match. && self.local_decls[local].ty == rvalue.ty(self.local_decls, self.tcx) { - let value = value.or_else(|| self.new_opaque()).unwrap(); + let value = value.unwrap_or_else(|| self.new_opaque()); self.assign(local, value); Some(value) } else { @@ -1767,7 +1762,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { && let Some(local) = destination.as_local() && self.ssa.is_ssa(local) { - let opaque = self.new_opaque().unwrap(); + let opaque = self.new_opaque(); self.assign(local, opaque); } self.super_terminator(terminator, location); From 7830406df1232c59f82d870c218901b8643701bb Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 24 Mar 2025 16:55:24 +0800 Subject: [PATCH 065/176] Invalidate all dereferences for non-local assignments --- compiler/rustc_data_structures/src/fx.rs | 2 + compiler/rustc_mir_transform/src/gvn.rs | 38 +++++++++++++++---- ..._aggregate_to_copy_miscompile.foo.GVN.diff | 8 ++-- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_data_structures/src/fx.rs b/compiler/rustc_data_structures/src/fx.rs index 80e72250470c..f0db9623b674 100644 --- a/compiler/rustc_data_structures/src/fx.rs +++ b/compiler/rustc_data_structures/src/fx.rs @@ -9,6 +9,8 @@ pub type FxIndexSet = indexmap::IndexSet>; pub type IndexEntry<'a, K, V> = indexmap::map::Entry<'a, K, V>; pub type IndexOccupiedEntry<'a, K, V> = indexmap::map::OccupiedEntry<'a, K, V>; +pub use indexmap::set::MutableValues; + #[macro_export] macro_rules! define_id_collections { ($map_name:ident, $set_name:ident, $entry_name:ident, $key:ty) => { diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 42d736cf5f49..944c21eab407 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -93,7 +93,7 @@ use rustc_const_eval::interpret::{ ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, Scalar, intern_const_alloc_for_constprop, }; -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxIndexSet, MutableValues}; use rustc_data_structures::graph::dominators::Dominators; use rustc_hir::def::DefKind; use rustc_index::bit_set::DenseBitSet; @@ -238,6 +238,8 @@ struct VnState<'body, 'tcx> { evaluated: IndexVec>>, /// Counter to generate different values. next_opaque: usize, + /// Cache the deref values. + derefs: Vec, /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop. feature_unsized_locals: bool, ssa: &'body SsaLocals, @@ -270,6 +272,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()), evaluated: IndexVec::with_capacity(num_values), next_opaque: 1, + derefs: Vec::new(), feature_unsized_locals: tcx.features().unsized_locals(), ssa, dominators, @@ -368,6 +371,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::ZERO, values)) } + fn insert_deref(&mut self, value: VnIndex) -> VnIndex { + let value = self.insert(Value::Projection(value, ProjectionElem::Deref)); + self.derefs.push(value); + value + } + + fn invalidate_derefs(&mut self) { + for deref in std::mem::take(&mut self.derefs) { + let opaque = self.next_opaque(); + *self.values.get_index_mut2(deref.index()).unwrap() = Value::Opaque(opaque); + } + } + #[instrument(level = "trace", skip(self), ret)] fn eval_to_const(&mut self, value: VnIndex) -> Option> { use Value::*; @@ -634,7 +650,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { { // An immutable borrow `_x` always points to the same value for the // lifetime of the borrow, so we can merge all instances of `*_x`. - ProjectionElem::Deref + return Some(self.insert_deref(value)); } else { return None; } @@ -1739,6 +1755,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { self.assign(local, value); Some(value) } else { + // Non-local assignments maybe invalidate deref. + self.invalidate_derefs(); value }; let Some(value) = value else { return }; @@ -1758,12 +1776,16 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { } fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { - if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator - && let Some(local) = destination.as_local() - && self.ssa.is_ssa(local) - { - let opaque = self.new_opaque(); - self.assign(local, opaque); + if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator { + if let Some(local) = destination.as_local() + && self.ssa.is_ssa(local) + { + let opaque = self.new_opaque(); + self.assign(local, opaque); + } + // Function calls maybe invalidate nested deref, and non-local assignments maybe invalidate deref. + // Currently, no distinction is made between these two cases. + self.invalidate_derefs(); } self.super_terminator(terminator, location); } diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff index 22d4277ee451..2efc4ef56044 100644 --- a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff @@ -19,8 +19,7 @@ } bb0: { -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _4 = &_1; @@ -50,13 +49,12 @@ StorageLive(_9); _9 = copy _6; - _0 = Option::::Some(move _9); -+ _0 = copy (*_2); ++ _0 = Option::::Some(copy _6); StorageDead(_9); - StorageDead(_6); + nop; StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); return; } From 7e0463fe93b7fec40e564fb1312296ed608ce837 Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 24 Mar 2025 16:55:24 +0800 Subject: [PATCH 066/176] Revert "comment out the old tests instead of adjusting them" This reverts commit 906f66fb4c22daa8a6f97e5c048e9f6ab3fd9051. --- tests/coverage/closure.cov-map | 18 +++++------ .../const_prop/read_immutable_static.rs | 3 +- tests/mir-opt/const_prop/ref_deref_project.rs | 3 +- tests/mir-opt/const_prop/slice_len.rs | 5 ++- .../gvn.fn_pointers.GVN.panic-abort.diff | 18 +++++------ .../gvn.fn_pointers.GVN.panic-unwind.diff | 18 +++++------ tests/mir-opt/gvn.rs | 31 +++++++++++-------- .../pre-codegen/deref_nested_borrows.rs | 1 - 8 files changed, 48 insertions(+), 49 deletions(-) diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index 2d784ba09b60..640f98956840 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -140,19 +140,17 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) Highest counter ID seen: c1 -Function name: closure::main::{closure#18} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 19, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] +Function name: closure::main::{closure#18} (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 0d, 02, 1c, 00, 02, 1d, 02, 12, 00, 02, 11, 00, 12, 00, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 25, 13) to (start + 2, 28) -- Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) -- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 18) - = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14) -Highest counter ID seen: c1 +- Code(Zero) at (prev + 25, 13) to (start + 2, 28) +- Code(Zero) at (prev + 2, 29) to (start + 2, 18) +- Code(Zero) at (prev + 2, 17) to (start + 0, 18) +- Code(Zero) at (prev + 1, 17) to (start + 1, 14) +Highest counter ID seen: (none) Function name: closure::main::{closure#19} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] diff --git a/tests/mir-opt/const_prop/read_immutable_static.rs b/tests/mir-opt/const_prop/read_immutable_static.rs index 98ba76fb7655..f88e4b3de939 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.rs +++ b/tests/mir-opt/const_prop/read_immutable_static.rs @@ -6,7 +6,6 @@ static FOO: u8 = 2; fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; - // Disabled due to - // COM: CHECK: [[x]] = const 4_u8; + // CHECK-NOT: [[x]] = const 4_u8; let x = FOO + FOO; } diff --git a/tests/mir-opt/const_prop/ref_deref_project.rs b/tests/mir-opt/const_prop/ref_deref_project.rs index 31108e1a57f5..813b4ae47455 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.rs +++ b/tests/mir-opt/const_prop/ref_deref_project.rs @@ -5,7 +5,6 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; - // Disabled due to - // COM: CHECK: [[a]] = const 5_i32; + // CHECK-NOT: [[a]] = const 5_i32; let a = *(&(4, 5).1); } diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index 498e09fbb65c..eb86e28408a3 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -8,8 +8,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; // CHECK: [[slice:_.*]] = copy {{.*}} as &[u32] (PointerCoercion(Unsize, AsCast)); - // Disabled due to - // COM: CHECK: assert(const true, - // COM: CHECK: [[a]] = const 2_u32; + // CHECK-NOT: assert(const true, + // CHECK-NOT: [[a]] = const 2_u32; let a = (&[1u32, 2, 3] as &[u32])[1]; } diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index 7f99b83d937d..3cce35d34e90 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _9: {closure@$DIR/gvn.rs:620:19: 620:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _13: {closure@$DIR/gvn.rs:620:19: 620:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:615:19: 615:21}; + let _7: {closure@$DIR/gvn.rs:620:19: 620:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:615:19: 615:21}; +- _7 = {closure@$DIR/gvn.rs:620:19: 620:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index 06dd0502f30f..d85aca040fe6 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _9: {closure@$DIR/gvn.rs:620:19: 620:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _13: {closure@$DIR/gvn.rs:620:19: 620:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:615:19: 615:21}; + let _7: {closure@$DIR/gvn.rs:620:19: 620:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:615:19: 615:21}; +- _7 = {closure@$DIR/gvn.rs:620:19: 620:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index c895a5792595..be97470ebb17 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -100,17 +100,18 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { opaque((x * y) - y); // We cannot substitute through an immutable reference. - // (Disabled due to ) // CHECK: [[ref:_.*]] = &_3; // CHECK: [[deref:_.*]] = copy (*[[ref]]); - // COM: CHECK: [[addref:_.*]] = Add(copy [[deref]], copy _1); - // COM: CHECK: opaque::(copy [[addref]]) - // COM: CHECK: opaque::(copy [[addref]]) + // CHECK: [[addref:_.*]] = Add(move [[deref]], copy _1); + // CHECK: opaque::(move [[addref]]) + // CHECK: [[deref2:_.*]] = copy (*[[ref]]); + // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); + // CHECK: opaque::(move [[addref2]]) let a = &z; opaque(*a + x); opaque(*a + x); - // And certainly not through a mutable reference or a pointer. + // But not through a mutable reference or a pointer. // CHECK: [[mut:_.*]] = &mut _3; // CHECK: [[addmut:_.*]] = Add( // CHECK: opaque::(move [[addmut]]) @@ -142,9 +143,11 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { // Important: `e` is not `a`! // CHECK: [[ref2:_.*]] = &_3; // CHECK: [[deref2:_.*]] = copy (*[[ref2]]); - // COM: CHECK: [[addref2:_.*]] = Add(copy [[deref2]], copy _1); - // COM: CHECK: opaque::(copy [[addref2]]) - // COM: CHECK: opaque::(copy [[addref2]]) + // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); + // CHECK: opaque::(move [[addref2]]) + // CHECK: [[deref3:_.*]] = copy (*[[ref2]]); + // CHECK: [[addref3:_.*]] = Add(move [[deref3]], copy _1); + // CHECK: opaque::(move [[addref3]]) let e = &z; opaque(*e + x); opaque(*e + x); @@ -499,8 +502,9 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { // Do not reuse dereferences of `&Freeze`. // CHECK: [[ref:_.*]] = &(*_1); // CHECK: [[st7:_.*]] = copy (*[[ref]]); - // COM: CHECK: opaque::(copy [[st7]]) - // COM: CHECK: opaque::(copy [[st7]]) + // CHECK: opaque::(move [[st7]]) + // CHECK: [[st8:_.*]] = copy (*[[ref]]); + // CHECK: opaque::(move [[st8]]) let z = &*t; opaque(*z); opaque(*z); @@ -519,8 +523,9 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { // `*s` is not Copy, but `(*s).0` is, but we still cannot reuse. // CHECK: [[st10:_.*]] = copy ((*_3).0: u32); - // COM: CHECK: opaque::(copy [[st10]]) - // COM: CHECK: opaque::(copy [[st10]]) + // CHECK: opaque::(move [[st10]]) + // CHECK: [[st11:_.*]] = copy ((*_3).0: u32); + // CHECK: opaque::(move [[st11]]) opaque(s.0); opaque(s.0); } @@ -737,7 +742,7 @@ fn borrowed(x: T) { // CHECK: bb1: { // CHECK-NEXT: _0 = opaque::(copy _1) // CHECK: bb2: { - // COM: CHECK-NEXT: _0 = opaque::(copy _1) + // CHECK-NEXT: _0 = opaque::(copy (*_3)) mir! { { let a = x; diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs index 4f70ec36bc92..738cd981ae67 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs @@ -1,4 +1,3 @@ -//! Regression test for // EMIT_MIR_FOR_EACH_PANIC_STRATEGY fn src(x: &&u8) -> bool { From fefb0dba824d7a98bbceba63e434279ff7377a45 Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 24 Mar 2025 16:55:24 +0800 Subject: [PATCH 067/176] Partially revert "Do not unify dereferences in GVN." This reverts commit 917dd826286bd85e26310e4db4a125d4038c277e. --- compiler/rustc_mir_transform/src/gvn.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 944c21eab407..a93fdff5817c 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -642,9 +642,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let proj = match proj { ProjectionElem::Deref => { let ty = place.ty(self.local_decls, self.tcx).ty; - // unsound: https://github.com/rust-lang/rust/issues/130853 - if self.tcx.sess.opts.unstable_opts.unsound_mir_opts - && let Some(Mutability::Not) = ty.ref_mutability() + if let Some(Mutability::Not) = ty.ref_mutability() && let Some(pointee_ty) = ty.builtin_deref(true) && pointee_ty.is_freeze(self.tcx, self.typing_env()) { From 1787789fe5b1eb9f37e72abaff933cd38f68e813 Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 24 Mar 2025 16:55:24 +0800 Subject: [PATCH 068/176] Bless tests --- tests/coverage/closure.cov-map | 18 +- tests/coverage/issue-84561.cov-map | 163 +++++------- .../read_immutable_static.main.GVN.diff | 14 +- .../const_prop/read_immutable_static.rs | 2 +- .../const_prop/ref_deref.main.GVN.diff | 3 +- .../ref_deref_project.main.GVN.diff | 3 +- tests/mir-opt/const_prop/ref_deref_project.rs | 2 +- .../slice_len.main.GVN.32bit.panic-abort.diff | 2 +- ...slice_len.main.GVN.32bit.panic-unwind.diff | 2 +- .../slice_len.main.GVN.64bit.panic-abort.diff | 2 +- ...slice_len.main.GVN.64bit.panic-unwind.diff | 2 +- tests/mir-opt/const_prop/slice_len.rs | 4 +- .../mir-opt/gvn.borrowed.GVN.panic-abort.diff | 3 +- .../gvn.borrowed.GVN.panic-unwind.diff | 3 +- tests/mir-opt/gvn.rs | 2 +- tests/mir-opt/gvn.slices.GVN.panic-abort.diff | 38 +-- .../mir-opt/gvn.slices.GVN.panic-unwind.diff | 38 +-- .../gvn_uninhabited.f.GVN.panic-abort.diff | 15 +- .../gvn_uninhabited.f.GVN.panic-unwind.diff | 15 +- ...variant_a-{closure#0}.PreCodegen.after.mir | 238 ++++++++---------- ...variant_b-{closure#0}.PreCodegen.after.mir | 54 ++-- 21 files changed, 301 insertions(+), 322 deletions(-) diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index 640f98956840..2d784ba09b60 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -140,17 +140,19 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) Highest counter ID seen: c1 -Function name: closure::main::{closure#18} (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 0d, 02, 1c, 00, 02, 1d, 02, 12, 00, 02, 11, 00, 12, 00, 01, 11, 01, 0e] +Function name: closure::main::{closure#18} +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 19, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 -Number of expressions: 0 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Zero) at (prev + 25, 13) to (start + 2, 28) -- Code(Zero) at (prev + 2, 29) to (start + 2, 18) -- Code(Zero) at (prev + 2, 17) to (start + 0, 18) -- Code(Zero) at (prev + 1, 17) to (start + 1, 14) -Highest counter ID seen: (none) +- Code(Counter(0)) at (prev + 25, 13) to (start + 2, 28) +- Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) +- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 18) + = (c0 - c1) +- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14) +Highest counter ID seen: c1 Function name: closure::main::{closure#19} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index 3bd4e7d2a366..47e2922a805a 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -59,109 +59,80 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: issue_84561::test3 -Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 0f, 05, 04, 09, 01, 0f, 09, 02, 05, 04, 0f, 0d, 05, 05, 00, 0f, 11, 01, 05, 00, 0f, 15, 01, 09, 01, 0f, 19, 02, 05, 00, 0f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 02, 0f, 35, 06, 05, 00, 0f, 39, 04, 05, 00, 0f, 3d, 04, 09, 01, 0f, 41, 05, 08, 00, 0f, 45, 01, 09, 00, 13, 1a, 05, 09, 00, 13, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 00, 17, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02] +Raw bytes (279): 0x[01, 01, 0a, 0d, 11, 0d, 15, 0d, 19, 1d, 21, 29, 2d, 25, 29, 25, 29, 25, 29, 27, 31, 29, 2d, 33, 01, 08, 01, 03, 0f, 05, 04, 09, 01, 0f, 09, 02, 05, 04, 0f, 09, 05, 05, 00, 0f, 09, 01, 05, 00, 0f, 09, 01, 09, 01, 0f, 0d, 02, 05, 00, 0f, 0d, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 0d, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 0d, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 0d, 04, 09, 02, 0f, 0d, 06, 05, 00, 0f, 0d, 04, 05, 00, 0f, 0d, 04, 09, 01, 0f, 0d, 05, 08, 00, 0f, 11, 01, 09, 00, 13, 02, 05, 09, 00, 13, 0d, 05, 08, 00, 0f, 15, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 06, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 0d, 03, 05, 00, 0f, 0d, 01, 0c, 00, 13, 19, 01, 0d, 00, 13, 0a, 02, 0d, 00, 13, 1d, 04, 05, 02, 13, 21, 03, 0d, 00, 13, 0e, 02, 0d, 00, 13, 27, 03, 05, 00, 0f, 25, 01, 0c, 00, 13, 29, 01, 0d, 00, 17, 29, 04, 0d, 00, 13, 1e, 02, 0d, 00, 17, 1e, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 1e, 02, 15, 00, 1b, 2d, 04, 0d, 00, 13, 22, 03, 09, 00, 19, 31, 02, 05, 00, 0f, 31, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 27 -- expression 0 operands: lhs = Counter(7), rhs = Counter(8) -- expression 1 operands: lhs = Counter(9), rhs = Counter(10) -- expression 2 operands: lhs = Counter(8), rhs = Counter(9) -- expression 3 operands: lhs = Counter(11), rhs = Counter(12) -- expression 4 operands: lhs = Counter(8), rhs = Expression(5, Add) -- expression 5 operands: lhs = Counter(9), rhs = Counter(11) -- expression 6 operands: lhs = Counter(16), rhs = Counter(17) -- expression 7 operands: lhs = Counter(18), rhs = Counter(19) -- expression 8 operands: lhs = Counter(20), rhs = Counter(21) -- expression 9 operands: lhs = Expression(12, Add), rhs = Counter(20) -- expression 10 operands: lhs = Counter(18), rhs = Counter(19) -- expression 11 operands: lhs = Expression(12, Add), rhs = Expression(13, Add) -- expression 12 operands: lhs = Counter(18), rhs = Counter(19) -- expression 13 operands: lhs = Counter(20), rhs = Counter(22) -- expression 14 operands: lhs = Counter(21), rhs = Counter(22) -- expression 15 operands: lhs = Counter(21), rhs = Counter(22) -- expression 16 operands: lhs = Expression(17, Add), rhs = Counter(23) -- expression 17 operands: lhs = Counter(21), rhs = Counter(22) -- expression 18 operands: lhs = Counter(24), rhs = Counter(25) -- expression 19 operands: lhs = Counter(28), rhs = Counter(29) -- expression 20 operands: lhs = Counter(26), rhs = Counter(27) -- expression 21 operands: lhs = Counter(26), rhs = Counter(27) -- expression 22 operands: lhs = Counter(26), rhs = Counter(27) -- expression 23 operands: lhs = Expression(24, Add), rhs = Counter(30) -- expression 24 operands: lhs = Counter(28), rhs = Counter(29) -- expression 25 operands: lhs = Counter(30), rhs = Counter(31) -- expression 26 operands: lhs = Counter(31), rhs = Counter(32) +Number of expressions: 10 +- expression 0 operands: lhs = Counter(3), rhs = Counter(4) +- expression 1 operands: lhs = Counter(3), rhs = Counter(5) +- expression 2 operands: lhs = Counter(3), rhs = Counter(6) +- expression 3 operands: lhs = Counter(7), rhs = Counter(8) +- expression 4 operands: lhs = Counter(10), rhs = Counter(11) +- expression 5 operands: lhs = Counter(9), rhs = Counter(10) +- expression 6 operands: lhs = Counter(9), rhs = Counter(10) +- expression 7 operands: lhs = Counter(9), rhs = Counter(10) +- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(12) +- expression 9 operands: lhs = Counter(10), rhs = Counter(11) Number of file 0 mappings: 51 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 15) - Code(Counter(1)) at (prev + 4, 9) to (start + 1, 15) - Code(Counter(2)) at (prev + 2, 5) to (start + 4, 15) -- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 15) -- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 15) -- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 15) -- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 15) -- Code(Counter(7)) at (prev + 1, 5) to (start + 0, 15) -- Code(Expression(0, Sub)) at (prev + 0, 32) to (start + 0, 48) +- Code(Counter(2)) at (prev + 5, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 9) to (start + 1, 15) +- Code(Counter(3)) at (prev + 2, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 15) +- Code(Zero) at (prev + 0, 32) to (start + 0, 48) +- Code(Counter(3)) at (prev + 1, 5) to (start + 3, 15) +- Code(Zero) at (prev + 3, 32) to (start + 0, 48) +- Code(Zero) at (prev + 0, 51) to (start + 0, 65) +- Code(Zero) at (prev + 0, 75) to (start + 0, 90) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 15) +- Code(Zero) at (prev + 5, 9) to (start + 3, 16) +- Code(Zero) at (prev + 5, 13) to (start + 0, 27) +- Code(Zero) at (prev + 2, 13) to (start + 0, 28) +- Code(Counter(3)) at (prev + 4, 9) to (start + 2, 15) +- Code(Counter(3)) at (prev + 6, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 4, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 4, 9) to (start + 1, 15) +- Code(Counter(3)) at (prev + 5, 8) to (start + 0, 15) +- Code(Counter(4)) at (prev + 1, 9) to (start + 0, 19) +- Code(Expression(0, Sub)) at (prev + 5, 9) to (start + 0, 19) + = (c3 - c4) +- Code(Counter(3)) at (prev + 5, 8) to (start + 0, 15) +- Code(Counter(5)) at (prev + 1, 9) to (start + 0, 19) +- Code(Zero) at (prev + 3, 13) to (start + 0, 29) +- Code(Expression(1, Sub)) at (prev + 3, 9) to (start + 0, 19) + = (c3 - c5) +- Code(Zero) at (prev + 3, 13) to (start + 0, 29) +- Code(Counter(3)) at (prev + 3, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 1, 12) to (start + 0, 19) +- Code(Counter(6)) at (prev + 1, 13) to (start + 0, 19) +- Code(Expression(2, Sub)) at (prev + 2, 13) to (start + 0, 19) + = (c3 - c6) +- Code(Counter(7)) at (prev + 4, 5) to (start + 2, 19) +- Code(Counter(8)) at (prev + 3, 13) to (start + 0, 19) +- Code(Expression(3, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c7 - c8) -- Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15) -- Code(Counter(9)) at (prev + 3, 32) to (start + 0, 48) -- Code(Counter(10)) at (prev + 0, 51) to (start + 0, 65) -- Code(Expression(1, Sub)) at (prev + 0, 75) to (start + 0, 90) +- Code(Expression(9, Add)) at (prev + 3, 5) to (start + 0, 15) + = (c10 + c11) +- Code(Counter(9)) at (prev + 1, 12) to (start + 0, 19) +- Code(Counter(10)) at (prev + 1, 13) to (start + 0, 23) +- Code(Counter(10)) at (prev + 4, 13) to (start + 0, 19) +- Code(Expression(7, Sub)) at (prev + 2, 13) to (start + 0, 23) + = (c9 - c10) +- Code(Expression(7, Sub)) at (prev + 1, 20) to (start + 0, 27) = (c9 - c10) -- Code(Expression(2, Sub)) at (prev + 1, 5) to (start + 0, 15) - = (c8 - c9) -- Code(Counter(11)) at (prev + 5, 9) to (start + 3, 16) -- Code(Counter(12)) at (prev + 5, 13) to (start + 0, 27) -- Code(Expression(3, Sub)) at (prev + 2, 13) to (start + 0, 28) - = (c11 - c12) -- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 2, 15) - = (c8 - (c9 + c11)) -- Code(Counter(13)) at (prev + 6, 5) to (start + 0, 15) -- Code(Counter(14)) at (prev + 4, 5) to (start + 0, 15) -- Code(Counter(15)) at (prev + 4, 9) to (start + 1, 15) -- Code(Counter(16)) at (prev + 5, 8) to (start + 0, 15) -- Code(Counter(17)) at (prev + 1, 9) to (start + 0, 19) -- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 0, 19) - = (c16 - c17) -- Code(Expression(12, Add)) at (prev + 5, 8) to (start + 0, 15) - = (c18 + c19) -- Code(Counter(20)) at (prev + 1, 9) to (start + 0, 19) -- Code(Expression(8, Sub)) at (prev + 3, 13) to (start + 0, 29) - = (c20 - c21) -- Code(Expression(9, Sub)) at (prev + 3, 9) to (start + 0, 19) - = ((c18 + c19) - c20) -- Code(Expression(11, Sub)) at (prev + 3, 13) to (start + 0, 29) - = ((c18 + c19) - (c20 + c22)) -- Code(Expression(17, Add)) at (prev + 3, 5) to (start + 0, 15) - = (c21 + c22) -- Code(Expression(17, Add)) at (prev + 1, 12) to (start + 0, 19) - = (c21 + c22) -- Code(Counter(23)) at (prev + 1, 13) to (start + 0, 19) -- Code(Expression(16, Sub)) at (prev + 2, 13) to (start + 0, 19) - = ((c21 + c22) - c23) -- Code(Counter(24)) at (prev + 4, 5) to (start + 2, 19) -- Code(Counter(25)) at (prev + 3, 13) to (start + 0, 19) -- Code(Expression(18, Sub)) at (prev + 2, 13) to (start + 0, 19) - = (c24 - c25) -- Code(Expression(24, Add)) at (prev + 3, 5) to (start + 0, 15) - = (c28 + c29) -- Code(Counter(26)) at (prev + 1, 12) to (start + 0, 19) -- Code(Counter(27)) at (prev + 1, 13) to (start + 0, 23) -- Code(Counter(28)) at (prev + 4, 13) to (start + 0, 19) -- Code(Expression(22, Sub)) at (prev + 2, 13) to (start + 0, 23) - = (c26 - c27) -- Code(Expression(22, Sub)) at (prev + 1, 20) to (start + 0, 27) - = (c26 - c27) - Code(Zero) at (prev + 1, 21) to (start + 0, 27) -- Code(Expression(22, Sub)) at (prev + 2, 21) to (start + 0, 27) - = (c26 - c27) -- Code(Counter(29)) at (prev + 4, 13) to (start + 0, 19) -- Code(Expression(23, Sub)) at (prev + 3, 9) to (start + 0, 25) - = ((c28 + c29) - c30) -- Code(Counter(30)) at (prev + 2, 5) to (start + 0, 15) -- Code(Expression(25, Sub)) at (prev + 3, 9) to (start + 0, 34) - = (c30 - c31) -- Code(Counter(31)) at (prev + 2, 5) to (start + 0, 15) -- Code(Expression(26, Sub)) at (prev + 3, 9) to (start + 0, 44) - = (c31 - c32) -- Code(Counter(32)) at (prev + 2, 1) to (start + 0, 2) -Highest counter ID seen: c32 +- Code(Expression(7, Sub)) at (prev + 2, 21) to (start + 0, 27) + = (c9 - c10) +- Code(Counter(11)) at (prev + 4, 13) to (start + 0, 19) +- Code(Expression(8, Sub)) at (prev + 3, 9) to (start + 0, 25) + = ((c10 + c11) - c12) +- Code(Counter(12)) at (prev + 2, 5) to (start + 0, 15) +- Code(Counter(12)) at (prev + 3, 9) to (start + 0, 34) +- Code(Zero) at (prev + 2, 5) to (start + 0, 15) +- Code(Zero) at (prev + 3, 9) to (start + 0, 44) +- Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c12 diff --git a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff index 23928337bf77..8df262b351f1 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff +++ b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff @@ -14,19 +14,23 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); - StorageLive(_3); ++ nop; + nop; _3 = const {ALLOC0: &u8}; - _2 = copy (*_3); +- _2 = copy (*_3); ++ _2 = const 2_u8; StorageLive(_4); StorageLive(_5); _5 = const {ALLOC0: &u8}; - _4 = copy (*_5); -+ _4 = copy (*_3); - _1 = Add(move _2, move _4); +- _1 = Add(move _2, move _4); ++ _4 = const 2_u8; ++ _1 = const 4_u8; StorageDead(_4); - StorageDead(_2); +- StorageDead(_2); ++ nop; StorageDead(_5); - StorageDead(_3); + nop; diff --git a/tests/mir-opt/const_prop/read_immutable_static.rs b/tests/mir-opt/const_prop/read_immutable_static.rs index f88e4b3de939..05fec2f3303b 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.rs +++ b/tests/mir-opt/const_prop/read_immutable_static.rs @@ -6,6 +6,6 @@ static FOO: u8 = 2; fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; - // CHECK-NOT: [[x]] = const 4_u8; + // CHECK: [[x]] = const 4_u8; let x = FOO + FOO; } diff --git a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff index 4477b4b005ba..b9e269266b0b 100644 --- a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff @@ -16,7 +16,8 @@ StorageLive(_2); _4 = const main::promoted[0]; _2 = &(*_4); - _1 = copy (*_2); +- _1 = copy (*_2); ++ _1 = const 4_i32; StorageDead(_2); _0 = const (); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff index bbfd70bea168..dcc13c9251c4 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff @@ -16,7 +16,8 @@ StorageLive(_2); _4 = const main::promoted[0]; _2 = &((*_4).1: i32); - _1 = copy (*_2); +- _1 = copy (*_2); ++ _1 = const 5_i32; StorageDead(_2); _0 = const (); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/ref_deref_project.rs b/tests/mir-opt/const_prop/ref_deref_project.rs index 813b4ae47455..5a48a887f93d 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.rs +++ b/tests/mir-opt/const_prop/ref_deref_project.rs @@ -5,6 +5,6 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; - // CHECK-NOT: [[a]] = const 5_i32; + // CHECK: [[a]] = const 5_i32; let a = *(&(4, 5).1); } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff index 0798b3039295..d6e81debccd8 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff @@ -40,7 +40,7 @@ bb1: { - _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; ++ _1 = const 2_u32; StorageDead(_6); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff index c0b3d4d32190..6713e531892a 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff @@ -40,7 +40,7 @@ bb1: { - _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; ++ _1 = const 2_u32; StorageDead(_6); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff index 0798b3039295..d6e81debccd8 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff @@ -40,7 +40,7 @@ bb1: { - _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; ++ _1 = const 2_u32; StorageDead(_6); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff index c0b3d4d32190..6713e531892a 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff @@ -40,7 +40,7 @@ bb1: { - _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; ++ _1 = const 2_u32; StorageDead(_6); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index eb86e28408a3..ebd3c9e792dc 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -8,7 +8,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; // CHECK: [[slice:_.*]] = copy {{.*}} as &[u32] (PointerCoercion(Unsize, AsCast)); - // CHECK-NOT: assert(const true, - // CHECK-NOT: [[a]] = const 2_u32; + // CHECK: assert(const true, + // CHECK: [[a]] = const 2_u32; let a = (&[1u32, 2, 3] as &[u32])[1]; } diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff index acbea13642c1..b0702696e187 100644 --- a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff @@ -18,7 +18,8 @@ } bb2: { - _0 = opaque::(copy (*_3)) -> [return: bb3, unwind unreachable]; +- _0 = opaque::(copy (*_3)) -> [return: bb3, unwind unreachable]; ++ _0 = opaque::(copy _1) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff index ba080bfdb07a..fe05d4deeede 100644 --- a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff @@ -18,7 +18,8 @@ } bb2: { - _0 = opaque::(copy (*_3)) -> [return: bb3, unwind continue]; +- _0 = opaque::(copy (*_3)) -> [return: bb3, unwind continue]; ++ _0 = opaque::(copy _1) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index be97470ebb17..6ef320c90de1 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -742,7 +742,7 @@ fn borrowed(x: T) { // CHECK: bb1: { // CHECK-NEXT: _0 = opaque::(copy _1) // CHECK: bb2: { - // CHECK-NEXT: _0 = opaque::(copy (*_3)) + // CHECK-NEXT: _0 = opaque::(copy _1) mir! { { let a = x; diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff index 43efcbdfb1e4..e8e99b44e721 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -111,8 +111,9 @@ StorageLive(_7); StorageLive(_8); - StorageLive(_9); +- StorageLive(_10); ++ nop; + nop; - StorageLive(_10); StorageLive(_11); _11 = &(*_1); _10 = core::str::::as_ptr(move _11) -> [return: bb3, unwind unreachable]; @@ -122,8 +123,9 @@ StorageDead(_11); _9 = &_10; - StorageLive(_12); +- StorageLive(_13); ++ nop; + nop; - StorageLive(_13); StorageLive(_14); - _14 = &(*_4); + _14 = &(*_1); @@ -148,11 +150,12 @@ StorageLive(_17); StorageLive(_18); - _18 = copy (*_15); -+ _18 = copy (*_9); ++ _18 = copy _10; StorageLive(_19); - _19 = copy (*_16); -+ _19 = copy (*_12); - _17 = Eq(move _18, move _19); +- _17 = Eq(move _18, move _19); ++ _19 = copy _13; ++ _17 = Eq(copy _10, copy _13); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -163,8 +166,10 @@ StorageDead(_17); StorageDead(_16); StorageDead(_15); - StorageDead(_13); - StorageDead(_10); +- StorageDead(_13); +- StorageDead(_10); ++ nop; ++ nop; StorageDead(_8); StorageDead(_7); - StorageLive(_29); @@ -213,8 +218,9 @@ StorageLive(_33); StorageLive(_34); - StorageLive(_35); +- StorageLive(_36); ++ nop; + nop; - StorageLive(_36); StorageLive(_37); _37 = &(*_1); _36 = core::str::::as_ptr(move _37) -> [return: bb8, unwind unreachable]; @@ -224,8 +230,9 @@ StorageDead(_37); _35 = &_36; - StorageLive(_38); +- StorageLive(_39); ++ nop; + nop; - StorageLive(_39); StorageLive(_40); _40 = &(*_29); _39 = core::slice::::as_ptr(move _40) -> [return: bb9, unwind unreachable]; @@ -249,11 +256,12 @@ StorageLive(_43); StorageLive(_44); - _44 = copy (*_41); -+ _44 = copy (*_35); ++ _44 = copy _36; StorageLive(_45); - _45 = copy (*_42); -+ _45 = copy (*_38); - _43 = Eq(move _44, move _45); +- _43 = Eq(move _44, move _45); ++ _45 = copy _39; ++ _43 = Eq(copy _36, copy _39); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } @@ -264,8 +272,10 @@ StorageDead(_43); StorageDead(_42); StorageDead(_41); - StorageDead(_39); - StorageDead(_36); +- StorageDead(_39); +- StorageDead(_36); ++ nop; ++ nop; StorageDead(_34); StorageDead(_33); _0 = const (); diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff index 8572f538c0ff..4296d4d4a594 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -111,8 +111,9 @@ StorageLive(_7); StorageLive(_8); - StorageLive(_9); +- StorageLive(_10); ++ nop; + nop; - StorageLive(_10); StorageLive(_11); _11 = &(*_1); _10 = core::str::::as_ptr(move _11) -> [return: bb3, unwind continue]; @@ -122,8 +123,9 @@ StorageDead(_11); _9 = &_10; - StorageLive(_12); +- StorageLive(_13); ++ nop; + nop; - StorageLive(_13); StorageLive(_14); - _14 = &(*_4); + _14 = &(*_1); @@ -148,11 +150,12 @@ StorageLive(_17); StorageLive(_18); - _18 = copy (*_15); -+ _18 = copy (*_9); ++ _18 = copy _10; StorageLive(_19); - _19 = copy (*_16); -+ _19 = copy (*_12); - _17 = Eq(move _18, move _19); +- _17 = Eq(move _18, move _19); ++ _19 = copy _13; ++ _17 = Eq(copy _10, copy _13); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -163,8 +166,10 @@ StorageDead(_17); StorageDead(_16); StorageDead(_15); - StorageDead(_13); - StorageDead(_10); +- StorageDead(_13); +- StorageDead(_10); ++ nop; ++ nop; StorageDead(_8); StorageDead(_7); - StorageLive(_29); @@ -213,8 +218,9 @@ StorageLive(_33); StorageLive(_34); - StorageLive(_35); +- StorageLive(_36); ++ nop; + nop; - StorageLive(_36); StorageLive(_37); _37 = &(*_1); _36 = core::str::::as_ptr(move _37) -> [return: bb8, unwind continue]; @@ -224,8 +230,9 @@ StorageDead(_37); _35 = &_36; - StorageLive(_38); +- StorageLive(_39); ++ nop; + nop; - StorageLive(_39); StorageLive(_40); _40 = &(*_29); _39 = core::slice::::as_ptr(move _40) -> [return: bb9, unwind continue]; @@ -249,11 +256,12 @@ StorageLive(_43); StorageLive(_44); - _44 = copy (*_41); -+ _44 = copy (*_35); ++ _44 = copy _36; StorageLive(_45); - _45 = copy (*_42); -+ _45 = copy (*_38); - _43 = Eq(move _44, move _45); +- _43 = Eq(move _44, move _45); ++ _45 = copy _39; ++ _43 = Eq(copy _36, copy _39); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } @@ -264,8 +272,10 @@ StorageDead(_43); StorageDead(_42); StorageDead(_41); - StorageDead(_39); - StorageDead(_36); +- StorageDead(_39); +- StorageDead(_36); ++ nop; ++ nop; StorageDead(_34); StorageDead(_33); _0 = const (); diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff index 881b629803a3..a3e4796d088e 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff @@ -17,15 +17,16 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); - _2 = copy ((*_3).1: E); -- StorageLive(_1); -+ nop; - _1 = copy ((_2 as A).1: u32); +- _2 = copy ((*_3).1: E); ++ _2 = const Scalar(0x00000000): E; + StorageLive(_1); +- _1 = copy ((_2 as A).1: u32); ++ _1 = const 0_u32; StorageDead(_3); StorageDead(_2); - _0 = copy _1; -- StorageDead(_1); -+ nop; +- _0 = copy _1; ++ _0 = const 0_u32; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff index 881b629803a3..a3e4796d088e 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff @@ -17,15 +17,16 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); - _2 = copy ((*_3).1: E); -- StorageLive(_1); -+ nop; - _1 = copy ((_2 as A).1: u32); +- _2 = copy ((*_3).1: E); ++ _2 = const Scalar(0x00000000): E; + StorageLive(_1); +- _1 = copy ((_2 as A).1: u32); ++ _1 = const 0_u32; StorageDead(_3); StorageDead(_2); - _0 = copy _1; -- StorageDead(_1); -+ nop; +- _0 = copy _1; ++ _0 = const 0_u32; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index 5a269717f829..cbdd194afd3a 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -4,70 +4,65 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: &usize; - let mut _5: &(usize, usize, usize, usize); + let _5: &usize; let _6: &usize; - let mut _7: &(usize, usize, usize, usize); - let _8: &usize; - let mut _9: &(usize, usize, usize, usize); - let _10: &usize; - let mut _11: &&usize; - let _12: &usize; - let mut _13: &&usize; - let mut _16: bool; - let mut _17: &&usize; - let _18: &usize; - let mut _19: &&usize; - let mut _22: bool; - let mut _23: &&usize; - let _24: &usize; - let mut _25: &&usize; - let mut _28: bool; - let mut _29: &&usize; - let _30: &usize; - let mut _31: &&usize; + let _7: &usize; + let mut _8: &&usize; + let _9: &usize; + let mut _10: &&usize; + let mut _13: bool; + let mut _14: &&usize; + let _15: &usize; + let mut _16: &&usize; + let mut _19: bool; + let mut _20: &&usize; + let _21: &usize; + let mut _22: &&usize; + let mut _23: bool; + let mut _24: &&usize; + let _25: &usize; + let mut _26: &&usize; scope 1 { debug a => _4; - debug b => _6; - debug c => _8; - debug d => _10; + debug b => _5; + debug c => _6; + debug d => _7; scope 2 (inlined std::cmp::impls::::le) { - debug self => _11; - debug other => _13; + debug self => _8; + debug other => _10; scope 3 (inlined std::cmp::impls::::le) { debug self => _4; - debug other => _8; - let mut _14: usize; - let mut _15: usize; + debug other => _6; + let mut _11: usize; + let mut _12: usize; } } scope 4 (inlined std::cmp::impls::::le) { - debug self => _17; - debug other => _19; + debug self => _14; + debug other => _16; scope 5 (inlined std::cmp::impls::::le) { - debug self => _10; - debug other => _6; - let mut _20: usize; - let mut _21: usize; + debug self => _7; + debug other => _5; + let mut _17: usize; + let mut _18: usize; } } scope 6 (inlined std::cmp::impls::::le) { - debug self => _23; - debug other => _25; + debug self => _20; + debug other => _22; scope 7 (inlined std::cmp::impls::::le) { - debug self => _8; + debug self => _6; debug other => _4; - let mut _26: usize; - let mut _27: usize; } } scope 8 (inlined std::cmp::impls::::le) { - debug self => _29; - debug other => _31; + debug self => _24; + debug other => _26; scope 9 (inlined std::cmp::impls::::le) { - debug self => _6; - debug other => _10; - let mut _32: usize; - let mut _33: usize; + debug self => _5; + debug other => _7; + let mut _27: usize; + let mut _28: usize; } } } @@ -75,129 +70,116 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 bb0: { _3 = copy (*_2); _4 = &((*_3).0: usize); - _5 = copy (*_2); - _6 = &((*_5).1: usize); - _7 = copy (*_2); - _8 = &((*_7).2: usize); - _9 = copy (*_2); - _10 = &((*_9).3: usize); - StorageLive(_16); - StorageLive(_11); - _11 = &_4; + _5 = &((*_3).1: usize); + _6 = &((*_3).2: usize); + _7 = &((*_3).3: usize); StorageLive(_13); - StorageLive(_12); - _12 = copy _8; - _13 = &_12; - StorageLive(_14); - _14 = copy ((*_3).0: usize); - StorageLive(_15); - _15 = copy ((*_7).2: usize); - _16 = Le(move _14, move _15); - StorageDead(_15); - StorageDead(_14); - switchInt(move _16) -> [0: bb1, otherwise: bb2]; + StorageLive(_8); + _8 = &_4; + StorageLive(_10); + StorageLive(_9); + _9 = copy _6; + _10 = &_9; + _11 = copy ((*_3).0: usize); + _12 = copy ((*_3).2: usize); + _13 = Le(copy _11, copy _12); + switchInt(move _13) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageDead(_12); - StorageDead(_13); - StorageDead(_11); + StorageDead(_9); + StorageDead(_10); + StorageDead(_8); goto -> bb4; } bb2: { - StorageDead(_12); - StorageDead(_13); - StorageDead(_11); - StorageLive(_22); - StorageLive(_17); - _17 = &_10; + StorageDead(_9); + StorageDead(_10); + StorageDead(_8); StorageLive(_19); + StorageLive(_14); + _14 = &_7; + StorageLive(_16); + StorageLive(_15); + _15 = copy _5; + _16 = &_15; + StorageLive(_17); + _17 = copy ((*_3).3: usize); StorageLive(_18); - _18 = copy _6; - _19 = &_18; - StorageLive(_20); - _20 = copy ((*_9).3: usize); - StorageLive(_21); - _21 = copy ((*_5).1: usize); - _22 = Le(move _20, move _21); - StorageDead(_21); - StorageDead(_20); - switchInt(move _22) -> [0: bb3, otherwise: bb8]; + _18 = copy ((*_3).1: usize); + _19 = Le(move _17, move _18); + StorageDead(_18); + StorageDead(_17); + switchInt(move _19) -> [0: bb3, otherwise: bb8]; } bb3: { - StorageDead(_18); - StorageDead(_19); - StorageDead(_17); + StorageDead(_15); + StorageDead(_16); + StorageDead(_14); goto -> bb4; } bb4: { - StorageLive(_28); StorageLive(_23); - _23 = &_8; - StorageLive(_25); - StorageLive(_24); - _24 = copy _4; - _25 = &_24; - StorageLive(_26); - _26 = copy ((*_7).2: usize); - StorageLive(_27); - _27 = copy ((*_3).0: usize); - _28 = Le(move _26, move _27); - StorageDead(_27); - StorageDead(_26); - switchInt(move _28) -> [0: bb5, otherwise: bb6]; + StorageLive(_20); + _20 = &_6; + StorageLive(_22); + StorageLive(_21); + _21 = copy _4; + _22 = &_21; + _23 = Le(copy _12, copy _11); + switchInt(move _23) -> [0: bb5, otherwise: bb6]; } bb5: { - StorageDead(_24); - StorageDead(_25); - StorageDead(_23); + StorageDead(_21); + StorageDead(_22); + StorageDead(_20); _0 = const false; goto -> bb7; } bb6: { - StorageDead(_24); + StorageDead(_21); + StorageDead(_22); + StorageDead(_20); + StorageLive(_24); + _24 = &_5; + StorageLive(_26); + StorageLive(_25); + _25 = copy _7; + _26 = &_25; + StorageLive(_27); + _27 = copy ((*_3).1: usize); + StorageLive(_28); + _28 = copy ((*_3).3: usize); + _0 = Le(move _27, move _28); + StorageDead(_28); + StorageDead(_27); StorageDead(_25); - StorageDead(_23); - StorageLive(_29); - _29 = &_6; - StorageLive(_31); - StorageLive(_30); - _30 = copy _10; - _31 = &_30; - StorageLive(_32); - _32 = copy ((*_5).1: usize); - StorageLive(_33); - _33 = copy ((*_9).3: usize); - _0 = Le(move _32, move _33); - StorageDead(_33); - StorageDead(_32); - StorageDead(_30); - StorageDead(_31); - StorageDead(_29); + StorageDead(_26); + StorageDead(_24); goto -> bb7; } bb7: { - StorageDead(_28); + StorageDead(_23); goto -> bb9; } bb8: { - StorageDead(_18); - StorageDead(_19); - StorageDead(_17); + StorageDead(_15); + StorageDead(_16); + StorageDead(_14); _0 = const true; goto -> bb9; } bb9: { - StorageDead(_22); - StorageDead(_16); + StorageDead(_19); + StorageDead(_13); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir index f93f7264dec2..bc7a31d52199 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir @@ -4,46 +4,40 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: usize; - let mut _5: &(usize, usize, usize, usize); + let _5: usize; let _6: usize; - let mut _7: &(usize, usize, usize, usize); - let _8: usize; - let mut _9: &(usize, usize, usize, usize); - let _10: usize; - let mut _11: bool; - let mut _12: bool; - let mut _13: bool; + let _7: usize; + let mut _8: bool; + let mut _9: bool; + let mut _10: bool; scope 1 { debug a => _4; - debug b => _6; - debug c => _8; - debug d => _10; + debug b => _5; + debug c => _6; + debug d => _7; } bb0: { _3 = copy (*_2); _4 = copy ((*_3).0: usize); - _5 = copy (*_2); - _6 = copy ((*_5).1: usize); - _7 = copy (*_2); - _8 = copy ((*_7).2: usize); - _9 = copy (*_2); - _10 = copy ((*_9).3: usize); - StorageLive(_11); - _11 = Le(copy _4, copy _8); - switchInt(move _11) -> [0: bb2, otherwise: bb1]; + _5 = copy ((*_3).1: usize); + _6 = copy ((*_3).2: usize); + _7 = copy ((*_3).3: usize); + StorageLive(_8); + _8 = Le(copy _4, copy _6); + switchInt(move _8) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageLive(_12); - _12 = Le(copy _10, copy _6); - switchInt(move _12) -> [0: bb2, otherwise: bb6]; + StorageLive(_9); + _9 = Le(copy _7, copy _5); + switchInt(move _9) -> [0: bb2, otherwise: bb6]; } bb2: { - StorageLive(_13); - _13 = Le(copy _8, copy _4); - switchInt(move _13) -> [0: bb3, otherwise: bb4]; + StorageLive(_10); + _10 = Le(copy _6, copy _4); + switchInt(move _10) -> [0: bb3, otherwise: bb4]; } bb3: { @@ -52,12 +46,12 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb4: { - _0 = Le(copy _6, copy _10); + _0 = Le(copy _5, copy _7); goto -> bb5; } bb5: { - StorageDead(_13); + StorageDead(_10); goto -> bb7; } @@ -67,8 +61,8 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb7: { - StorageDead(_12); - StorageDead(_11); + StorageDead(_9); + StorageDead(_8); return; } } From 6e6d4a8cc5063dc5ce3e7faa7d21a371bedfc0da Mon Sep 17 00:00:00 2001 From: dianqk Date: Wed, 2 Apr 2025 20:19:43 +0800 Subject: [PATCH 069/176] Update to LLVM 20.1.2 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index acaea3d2bb8f..a9865ceca081 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit acaea3d2bb8f351b740db7ebce7d7a40b9e21488 +Subproject commit a9865ceca08101071e25f3bba97bba8bf0ea9719 From 1d6ddd684305280621b1ea2fb1776828e828e836 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 2 Apr 2025 15:46:05 +0200 Subject: [PATCH 070/176] Remove unused variables generated in merged doctests --- src/librustdoc/doctest/runner.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index f891505d2a60..e34b8a53b073 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -144,7 +144,6 @@ let tests = {{ {ids} tests }}; -let test_marker = std::ffi::OsStr::new(__doctest_mod::RUN_OPTION); let test_args = &[{test_args}]; const ENV_BIN: &'static str = \"RUSTDOC_DOCTEST_BIN_PATH\"; From 05d5fdadbbc5f426f2fe36b05c2b659865f2e4bb Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Wed, 2 Apr 2025 23:26:26 +0800 Subject: [PATCH 071/176] Preparing for merge from rustc --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 6baf43397e88..d7c20d8ce620 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -493c38ba371929579fe136df26eccd9516347c7a +ae9173d7dd4a31806c950c90dcc331f1508b4d17 From 2dd4501610b1a0bc6593cd80141f7e3e7ea40a16 Mon Sep 17 00:00:00 2001 From: nora <48135649+Noratrieb@users.noreply.github.com> Date: Wed, 2 Apr 2025 19:12:26 +0200 Subject: [PATCH 072/176] Put Noratrieb on vacation My review queue has gotten a bit out of hand. I'll work on reviewing those PRs before taking up new ones. --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 59f815974beb..c6d2ab30463e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1125,6 +1125,7 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", "saethlin", + "Noratrieb", ] [[assign.warn_non_default_branch.exceptions]] From 20417a95225a24eb4fc5928166b854ebcc93a281 Mon Sep 17 00:00:00 2001 From: Daniel Bloom Date: Mon, 24 Feb 2025 14:02:13 -0800 Subject: [PATCH 073/176] Make slice iterator constructors unstably const --- library/core/src/slice/iter.rs | 45 +++++----- library/core/src/slice/mod.rs | 48 ++++++---- ...ated_loop.PreCodegen.after.panic-abort.mir | 90 +++++++++---------- ...ted_loop.PreCodegen.after.panic-unwind.mir | 24 +++-- ...ward_loop.PreCodegen.after.panic-abort.mir | 56 ++++++------ ...ard_loop.PreCodegen.after.panic-unwind.mir | 56 ++++++------ ...erse_loop.PreCodegen.after.panic-abort.mir | 26 +++--- ...rse_loop.PreCodegen.after.panic-unwind.mir | 26 +++--- 8 files changed, 190 insertions(+), 181 deletions(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index a687ed7129dc..d48248749c26 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -93,9 +93,9 @@ unsafe impl Send for Iter<'_, T> {} impl<'a, T> Iter<'a, T> { #[inline] - pub(super) fn new(slice: &'a [T]) -> Self { + pub(super) const fn new(slice: &'a [T]) -> Self { let len = slice.len(); - let ptr: NonNull = NonNull::from(slice).cast(); + let ptr: NonNull = NonNull::from_ref(slice).cast(); // SAFETY: Similar to `IterMut::new`. unsafe { let end_or_len = @@ -218,9 +218,9 @@ unsafe impl Send for IterMut<'_, T> {} impl<'a, T> IterMut<'a, T> { #[inline] - pub(super) fn new(slice: &'a mut [T]) -> Self { + pub(super) const fn new(slice: &'a mut [T]) -> Self { let len = slice.len(); - let ptr: NonNull = NonNull::from(slice).cast(); + let ptr: NonNull = NonNull::from_mut(slice).cast(); // SAFETY: There are several things here: // // `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid @@ -1335,7 +1335,7 @@ pub struct Windows<'a, T: 'a> { impl<'a, T: 'a> Windows<'a, T> { #[inline] - pub(super) fn new(slice: &'a [T], size: NonZero) -> Self { + pub(super) const fn new(slice: &'a [T], size: NonZero) -> Self { Self { v: slice, size } } } @@ -1487,7 +1487,7 @@ pub struct Chunks<'a, T: 'a> { impl<'a, T: 'a> Chunks<'a, T> { #[inline] - pub(super) fn new(slice: &'a [T], size: usize) -> Self { + pub(super) const fn new(slice: &'a [T], size: usize) -> Self { Self { v: slice, chunk_size: size } } } @@ -1677,7 +1677,7 @@ pub struct ChunksMut<'a, T: 'a> { impl<'a, T: 'a> ChunksMut<'a, T> { #[inline] - pub(super) fn new(slice: &'a mut [T], size: usize) -> Self { + pub(super) const fn new(slice: &'a mut [T], size: usize) -> Self { Self { v: slice, chunk_size: size, _marker: PhantomData } } } @@ -1863,7 +1863,7 @@ pub struct ChunksExact<'a, T: 'a> { impl<'a, T> ChunksExact<'a, T> { #[inline] - pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self { + pub(super) const fn new(slice: &'a [T], chunk_size: usize) -> Self { let rem = slice.len() % chunk_size; let fst_len = slice.len() - rem; // SAFETY: 0 <= fst_len <= slice.len() by construction above @@ -2043,7 +2043,7 @@ pub struct ChunksExactMut<'a, T: 'a> { impl<'a, T> ChunksExactMut<'a, T> { #[inline] - pub(super) fn new(slice: &'a mut [T], chunk_size: usize) -> Self { + pub(super) const fn new(slice: &'a mut [T], chunk_size: usize) -> Self { let rem = slice.len() % chunk_size; let fst_len = slice.len() - rem; // SAFETY: 0 <= fst_len <= slice.len() by construction above @@ -2210,7 +2210,7 @@ pub struct ArrayWindows<'a, T: 'a, const N: usize> { impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> { #[inline] - pub(super) fn new(slice: &'a [T]) -> Self { + pub(super) const fn new(slice: &'a [T]) -> Self { let num_windows = slice.len().saturating_sub(N - 1); Self { slice_head: slice.as_ptr(), num: num_windows, marker: PhantomData } } @@ -2334,8 +2334,10 @@ pub struct ArrayChunks<'a, T: 'a, const N: usize> { } impl<'a, T, const N: usize> ArrayChunks<'a, T, N> { + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] + // #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] - pub(super) fn new(slice: &'a [T]) -> Self { + pub(super) const fn new(slice: &'a [T]) -> Self { let (array_slice, rem) = slice.as_chunks(); Self { iter: array_slice.iter(), rem } } @@ -2460,8 +2462,9 @@ pub struct ArrayChunksMut<'a, T: 'a, const N: usize> { } impl<'a, T, const N: usize> ArrayChunksMut<'a, T, N> { + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] - pub(super) fn new(slice: &'a mut [T]) -> Self { + pub(super) const fn new(slice: &'a mut [T]) -> Self { let (array_slice, rem) = slice.as_chunks_mut(); Self { iter: array_slice.iter_mut(), rem } } @@ -2579,7 +2582,7 @@ pub struct RChunks<'a, T: 'a> { impl<'a, T: 'a> RChunks<'a, T> { #[inline] - pub(super) fn new(slice: &'a [T], size: usize) -> Self { + pub(super) const fn new(slice: &'a [T], size: usize) -> Self { Self { v: slice, chunk_size: size } } } @@ -2759,7 +2762,7 @@ pub struct RChunksMut<'a, T: 'a> { impl<'a, T: 'a> RChunksMut<'a, T> { #[inline] - pub(super) fn new(slice: &'a mut [T], size: usize) -> Self { + pub(super) const fn new(slice: &'a mut [T], size: usize) -> Self { Self { v: slice, chunk_size: size, _marker: PhantomData } } } @@ -2950,7 +2953,7 @@ pub struct RChunksExact<'a, T: 'a> { impl<'a, T> RChunksExact<'a, T> { #[inline] - pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self { + pub(super) const fn new(slice: &'a [T], chunk_size: usize) -> Self { let rem = slice.len() % chunk_size; // SAFETY: 0 <= rem <= slice.len() by construction above let (fst, snd) = unsafe { slice.split_at_unchecked(rem) }; @@ -2976,7 +2979,8 @@ impl<'a, T> RChunksExact<'a, T> { /// ``` #[must_use] #[stable(feature = "rchunks", since = "1.31.0")] - pub fn remainder(&self) -> &'a [T] { + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] + pub const fn remainder(&self) -> &'a [T] { self.rem } } @@ -3132,7 +3136,7 @@ pub struct RChunksExactMut<'a, T: 'a> { impl<'a, T> RChunksExactMut<'a, T> { #[inline] - pub(super) fn new(slice: &'a mut [T], chunk_size: usize) -> Self { + pub(super) const fn new(slice: &'a mut [T], chunk_size: usize) -> Self { let rem = slice.len() % chunk_size; // SAFETY: 0 <= rem <= slice.len() by construction above let (fst, snd) = unsafe { slice.split_at_mut_unchecked(rem) }; @@ -3144,7 +3148,8 @@ impl<'a, T> RChunksExactMut<'a, T> { /// elements. #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rchunks", since = "1.31.0")] - pub fn into_remainder(self) -> &'a mut [T] { + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] + pub const fn into_remainder(self) -> &'a mut [T] { self.rem } } @@ -3308,7 +3313,7 @@ pub struct ChunkBy<'a, T: 'a, P> { #[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> ChunkBy<'a, T, P> { - pub(super) fn new(slice: &'a [T], predicate: P) -> Self { + pub(super) const fn new(slice: &'a [T], predicate: P) -> Self { ChunkBy { slice, predicate } } } @@ -3395,7 +3400,7 @@ pub struct ChunkByMut<'a, T: 'a, P> { #[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> ChunkByMut<'a, T, P> { - pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { + pub(super) const fn new(slice: &'a mut [T], predicate: P) -> Self { ChunkByMut { slice, predicate } } } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5bb7243c4491..ef8fb694a326 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1043,9 +1043,10 @@ impl [T] { /// assert_eq!(iterator.next(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[rustc_diagnostic_item = "slice_iter"] - pub fn iter(&self) -> Iter<'_, T> { + pub const fn iter(&self) -> Iter<'_, T> { Iter::new(self) } @@ -1062,9 +1063,10 @@ impl [T] { /// } /// assert_eq!(x, &[3, 4, 6]); /// ``` + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn iter_mut(&mut self) -> IterMut<'_, T> { + pub const fn iter_mut(&mut self) -> IterMut<'_, T> { IterMut::new(self) } @@ -1116,9 +1118,10 @@ impl [T] { /// assert_eq!(array, ['s', 't', ' ', '2', '0', '1', '5', 'u', 'R']); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn windows(&self, size: usize) -> Windows<'_, T> { + pub const fn windows(&self, size: usize) -> Windows<'_, T> { let size = NonZero::new(size).expect("window size must be non-zero"); Windows::new(self, size) } @@ -1151,9 +1154,10 @@ impl [T] { /// [`chunks_exact`]: slice::chunks_exact /// [`rchunks`]: slice::rchunks #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> { + pub const fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> { assert!(chunk_size != 0, "chunk size must be non-zero"); Chunks::new(self, chunk_size) } @@ -1190,9 +1194,10 @@ impl [T] { /// [`chunks_exact_mut`]: slice::chunks_exact_mut /// [`rchunks_mut`]: slice::rchunks_mut #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> { + pub const fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> { assert!(chunk_size != 0, "chunk size must be non-zero"); ChunksMut::new(self, chunk_size) } @@ -1228,9 +1233,10 @@ impl [T] { /// [`chunks`]: slice::chunks /// [`rchunks_exact`]: slice::rchunks_exact #[stable(feature = "chunks_exact", since = "1.31.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> { + pub const fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> { assert!(chunk_size != 0, "chunk size must be non-zero"); ChunksExact::new(self, chunk_size) } @@ -1271,9 +1277,10 @@ impl [T] { /// [`chunks_mut`]: slice::chunks_mut /// [`rchunks_exact_mut`]: slice::rchunks_exact_mut #[stable(feature = "chunks_exact", since = "1.31.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> { + pub const fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> { assert!(chunk_size != 0, "chunk size must be non-zero"); ChunksExactMut::new(self, chunk_size) } @@ -1429,9 +1436,10 @@ impl [T] { /// /// [`chunks_exact`]: slice::chunks_exact #[unstable(feature = "array_chunks", issue = "74985")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn array_chunks(&self) -> ArrayChunks<'_, T, N> { + pub const fn array_chunks(&self) -> ArrayChunks<'_, T, N> { assert!(N != 0, "chunk size must be non-zero"); ArrayChunks::new(self) } @@ -1592,9 +1600,10 @@ impl [T] { /// /// [`chunks_exact_mut`]: slice::chunks_exact_mut #[unstable(feature = "array_chunks", issue = "74985")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn array_chunks_mut(&mut self) -> ArrayChunksMut<'_, T, N> { + pub const fn array_chunks_mut(&mut self) -> ArrayChunksMut<'_, T, N> { assert!(N != 0, "chunk size must be non-zero"); ArrayChunksMut::new(self) } @@ -1625,9 +1634,10 @@ impl [T] { /// /// [`windows`]: slice::windows #[unstable(feature = "array_windows", issue = "75027")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn array_windows(&self) -> ArrayWindows<'_, T, N> { + pub const fn array_windows(&self) -> ArrayWindows<'_, T, N> { assert!(N != 0, "window size must be non-zero"); ArrayWindows::new(self) } @@ -1660,9 +1670,10 @@ impl [T] { /// [`rchunks_exact`]: slice::rchunks_exact /// [`chunks`]: slice::chunks #[stable(feature = "rchunks", since = "1.31.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> { + pub const fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> { assert!(chunk_size != 0, "chunk size must be non-zero"); RChunks::new(self, chunk_size) } @@ -1699,9 +1710,10 @@ impl [T] { /// [`rchunks_exact_mut`]: slice::rchunks_exact_mut /// [`chunks_mut`]: slice::chunks_mut #[stable(feature = "rchunks", since = "1.31.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> { + pub const fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> { assert!(chunk_size != 0, "chunk size must be non-zero"); RChunksMut::new(self, chunk_size) } @@ -1739,9 +1751,10 @@ impl [T] { /// [`rchunks`]: slice::rchunks /// [`chunks_exact`]: slice::chunks_exact #[stable(feature = "rchunks", since = "1.31.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> { + pub const fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> { assert!(chunk_size != 0, "chunk size must be non-zero"); RChunksExact::new(self, chunk_size) } @@ -1783,9 +1796,10 @@ impl [T] { /// [`rchunks_mut`]: slice::rchunks_mut /// [`chunks_exact_mut`]: slice::chunks_exact_mut #[stable(feature = "rchunks", since = "1.31.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] #[track_caller] - pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> { + pub const fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> { assert!(chunk_size != 0, "chunk size must be non-zero"); RChunksExactMut::new(self, chunk_size) } @@ -1823,8 +1837,9 @@ impl [T] { /// assert_eq!(iter.next(), None); /// ``` #[stable(feature = "slice_group_by", since = "1.77.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] - pub fn chunk_by(&self, pred: F) -> ChunkBy<'_, T, F> + pub const fn chunk_by(&self, pred: F) -> ChunkBy<'_, T, F> where F: FnMut(&T, &T) -> bool, { @@ -1864,8 +1879,9 @@ impl [T] { /// assert_eq!(iter.next(), None); /// ``` #[stable(feature = "slice_group_by", since = "1.77.0")] + #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] - pub fn chunk_by_mut(&mut self, pred: F) -> ChunkByMut<'_, T, F> + pub const fn chunk_by_mut(&mut self, pred: F) -> ChunkByMut<'_, T, F> where F: FnMut(&T, &T) -> bool, { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 7ef532d222dc..c75edde711e1 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -22,74 +22,74 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug i => _33; debug x => _34; } - scope 19 (inlined > as Iterator>::next) { + scope 18 (inlined > as Iterator>::next) { let mut _27: std::option::Option<&T>; let mut _30: (usize, bool); let mut _31: (usize, &T); - scope 20 { + scope 19 { let _29: usize; - scope 25 { - } - } - scope 21 { - scope 22 { - scope 28 (inlined as FromResidual>>::from_residual) { - } - } - } - scope 23 { scope 24 { } } - scope 26 (inlined as Try>::branch) { - let _28: &T; - scope 27 { + scope 20 { + scope 21 { + scope 27 (inlined as FromResidual>>::from_residual) { + } } } - scope 29 (inlined as Iterator>::next) { + scope 22 { + scope 23 { + } + } + scope 25 (inlined as Try>::branch) { + let _28: &T; + scope 26 { + } + } + scope 28 (inlined as Iterator>::next) { let _14: std::ptr::NonNull; let _16: std::ptr::NonNull; let mut _19: bool; let mut _22: std::ptr::NonNull; let mut _24: usize; let _26: &T; - scope 30 { + scope 29 { let _15: *const T; - scope 31 { + scope 30 { let _23: usize; - scope 32 { - scope 35 (inlined core::num::::unchecked_sub) { - scope 36 (inlined core::ub_checks::check_language_ub) { - scope 37 (inlined core::ub_checks::check_language_ub::runtime) { + scope 31 { + scope 34 (inlined core::num::::unchecked_sub) { + scope 35 (inlined core::ub_checks::check_language_ub) { + scope 36 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 38 (inlined without_provenance_mut::) { + scope 37 (inlined without_provenance_mut::) { } } - scope 33 (inlined std::ptr::const_ptr::::addr) { - scope 34 (inlined std::ptr::const_ptr::::cast::<()>) { + scope 32 (inlined std::ptr::const_ptr::::addr) { + scope 33 (inlined std::ptr::const_ptr::::cast::<()>) { } } - scope 39 (inlined as PartialEq>::eq) { + scope 38 (inlined as PartialEq>::eq) { let mut _17: *mut T; let mut _18: *mut T; + scope 39 (inlined NonNull::::as_ptr) { + } scope 40 (inlined NonNull::::as_ptr) { } - scope 41 (inlined NonNull::::as_ptr) { - } } - scope 42 (inlined NonNull::::add) { + scope 41 (inlined NonNull::::add) { let mut _20: *const T; let mut _21: *const T; - scope 43 (inlined NonNull::::as_ptr) { + scope 42 (inlined NonNull::::as_ptr) { } } - scope 44 (inlined NonNull::::as_ref::<'_>) { + scope 43 (inlined NonNull::::as_ref::<'_>) { let _25: *const T; - scope 45 (inlined NonNull::::as_ptr) { + scope 44 (inlined NonNull::::as_ptr) { } - scope 46 (inlined std::ptr::mut_ptr::::cast_const) { + scope 45 (inlined std::ptr::mut_ptr::::cast_const) { } } } @@ -109,33 +109,31 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let _9: *const T; scope 7 { } - scope 12 (inlined std::ptr::without_provenance::) { - scope 13 (inlined without_provenance_mut::) { + scope 11 (inlined std::ptr::without_provenance::) { + scope 12 (inlined without_provenance_mut::) { } } - scope 14 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 15 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } - scope 8 (inlined as From<&[T]>>::from) { - scope 9 (inlined NonNull::<[T]>::from_ref) { - let mut _4: *const [T]; - } + scope 8 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; } - scope 10 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 11 (inlined NonNull::<[T]>::as_ptr) { + scope 10 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 16 (inlined as Iterator>::enumerate) { - scope 17 (inlined Enumerate::>::new) { + scope 15 (inlined as Iterator>::enumerate) { + scope 16 (inlined Enumerate::>::new) { } } - scope 18 (inlined > as IntoIterator>::into_iter) { + scope 17 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 33dbf04d028d..bc72181b77c4 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -34,33 +34,31 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let _9: *const T; scope 7 { } - scope 12 (inlined std::ptr::without_provenance::) { - scope 13 (inlined without_provenance_mut::) { + scope 11 (inlined std::ptr::without_provenance::) { + scope 12 (inlined without_provenance_mut::) { } } - scope 14 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 15 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } - scope 8 (inlined as From<&[T]>>::from) { - scope 9 (inlined NonNull::<[T]>::from_ref) { - let mut _4: *const [T]; - } + scope 8 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; } - scope 10 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 11 (inlined NonNull::<[T]>::as_ptr) { + scope 10 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 16 (inlined as Iterator>::enumerate) { - scope 17 (inlined Enumerate::>::new) { + scope 15 (inlined as Iterator>::enumerate) { + scope 16 (inlined Enumerate::>::new) { } } - scope 18 (inlined > as IntoIterator>::into_iter) { + scope 17 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 62787f3447ce..38c509d0b534 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -18,50 +18,50 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _27; } - scope 17 (inlined as Iterator>::next) { + scope 16 (inlined as Iterator>::next) { let _13: std::ptr::NonNull; let _15: std::ptr::NonNull; let mut _18: bool; let mut _21: std::ptr::NonNull; let mut _23: usize; let _25: &T; - scope 18 { + scope 17 { let _14: *const T; - scope 19 { + scope 18 { let _22: usize; - scope 20 { - scope 23 (inlined core::num::::unchecked_sub) { - scope 24 (inlined core::ub_checks::check_language_ub) { - scope 25 (inlined core::ub_checks::check_language_ub::runtime) { + scope 19 { + scope 22 (inlined core::num::::unchecked_sub) { + scope 23 (inlined core::ub_checks::check_language_ub) { + scope 24 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 26 (inlined without_provenance_mut::) { + scope 25 (inlined without_provenance_mut::) { } } - scope 21 (inlined std::ptr::const_ptr::::addr) { - scope 22 (inlined std::ptr::const_ptr::::cast::<()>) { + scope 20 (inlined std::ptr::const_ptr::::addr) { + scope 21 (inlined std::ptr::const_ptr::::cast::<()>) { } } - scope 27 (inlined as PartialEq>::eq) { + scope 26 (inlined as PartialEq>::eq) { let mut _16: *mut T; let mut _17: *mut T; + scope 27 (inlined NonNull::::as_ptr) { + } scope 28 (inlined NonNull::::as_ptr) { } - scope 29 (inlined NonNull::::as_ptr) { - } } - scope 30 (inlined NonNull::::add) { + scope 29 (inlined NonNull::::add) { let mut _19: *const T; let mut _20: *const T; - scope 31 (inlined NonNull::::as_ptr) { + scope 30 (inlined NonNull::::as_ptr) { } } - scope 32 (inlined NonNull::::as_ref::<'_>) { + scope 31 (inlined NonNull::::as_ref::<'_>) { let _24: *const T; - scope 33 (inlined NonNull::::as_ptr) { + scope 32 (inlined NonNull::::as_ptr) { } - scope 34 (inlined std::ptr::mut_ptr::::cast_const) { + scope 33 (inlined std::ptr::mut_ptr::::cast_const) { } } } @@ -80,29 +80,27 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _9: *const T; scope 7 { } - scope 12 (inlined std::ptr::without_provenance::) { - scope 13 (inlined without_provenance_mut::) { + scope 11 (inlined std::ptr::without_provenance::) { + scope 12 (inlined without_provenance_mut::) { } } - scope 14 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 15 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } - scope 8 (inlined as From<&[T]>>::from) { - scope 9 (inlined NonNull::<[T]>::from_ref) { - let mut _4: *const [T]; - } + scope 8 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; } - scope 10 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 11 (inlined NonNull::<[T]>::as_ptr) { + scope 10 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 16 (inlined as IntoIterator>::into_iter) { + scope 15 (inlined as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index e5478e279188..158cc284b1ae 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -18,50 +18,50 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _27; } - scope 17 (inlined as Iterator>::next) { + scope 16 (inlined as Iterator>::next) { let _13: std::ptr::NonNull; let _15: std::ptr::NonNull; let mut _18: bool; let mut _21: std::ptr::NonNull; let mut _23: usize; let _25: &T; - scope 18 { + scope 17 { let _14: *const T; - scope 19 { + scope 18 { let _22: usize; - scope 20 { - scope 23 (inlined core::num::::unchecked_sub) { - scope 24 (inlined core::ub_checks::check_language_ub) { - scope 25 (inlined core::ub_checks::check_language_ub::runtime) { + scope 19 { + scope 22 (inlined core::num::::unchecked_sub) { + scope 23 (inlined core::ub_checks::check_language_ub) { + scope 24 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 26 (inlined without_provenance_mut::) { + scope 25 (inlined without_provenance_mut::) { } } - scope 21 (inlined std::ptr::const_ptr::::addr) { - scope 22 (inlined std::ptr::const_ptr::::cast::<()>) { + scope 20 (inlined std::ptr::const_ptr::::addr) { + scope 21 (inlined std::ptr::const_ptr::::cast::<()>) { } } - scope 27 (inlined as PartialEq>::eq) { + scope 26 (inlined as PartialEq>::eq) { let mut _16: *mut T; let mut _17: *mut T; + scope 27 (inlined NonNull::::as_ptr) { + } scope 28 (inlined NonNull::::as_ptr) { } - scope 29 (inlined NonNull::::as_ptr) { - } } - scope 30 (inlined NonNull::::add) { + scope 29 (inlined NonNull::::add) { let mut _19: *const T; let mut _20: *const T; - scope 31 (inlined NonNull::::as_ptr) { + scope 30 (inlined NonNull::::as_ptr) { } } - scope 32 (inlined NonNull::::as_ref::<'_>) { + scope 31 (inlined NonNull::::as_ref::<'_>) { let _24: *const T; - scope 33 (inlined NonNull::::as_ptr) { + scope 32 (inlined NonNull::::as_ptr) { } - scope 34 (inlined std::ptr::mut_ptr::::cast_const) { + scope 33 (inlined std::ptr::mut_ptr::::cast_const) { } } } @@ -80,29 +80,27 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _9: *const T; scope 7 { } - scope 12 (inlined std::ptr::without_provenance::) { - scope 13 (inlined without_provenance_mut::) { + scope 11 (inlined std::ptr::without_provenance::) { + scope 12 (inlined without_provenance_mut::) { } } - scope 14 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 15 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } - scope 8 (inlined as From<&[T]>>::from) { - scope 9 (inlined NonNull::<[T]>::from_ref) { - let mut _4: *const [T]; - } + scope 8 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; } - scope 10 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 11 (inlined NonNull::<[T]>::as_ptr) { + scope 10 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 16 (inlined as IntoIterator>::into_iter) { + scope 15 (inlined as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 4b7ab4516d25..003667621080 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _17; } - scope 19 (inlined > as Iterator>::next) { + scope 18 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; } } @@ -34,33 +34,31 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _9: *const T; scope 7 { } - scope 12 (inlined std::ptr::without_provenance::) { - scope 13 (inlined without_provenance_mut::) { + scope 11 (inlined std::ptr::without_provenance::) { + scope 12 (inlined without_provenance_mut::) { } } - scope 14 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 15 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } - scope 8 (inlined as From<&[T]>>::from) { - scope 9 (inlined NonNull::<[T]>::from_ref) { - let mut _4: *const [T]; - } + scope 8 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; } - scope 10 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 11 (inlined NonNull::<[T]>::as_ptr) { + scope 10 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 16 (inlined as Iterator>::rev) { - scope 17 (inlined Rev::>::new) { + scope 15 (inlined as Iterator>::rev) { + scope 16 (inlined Rev::>::new) { } } - scope 18 (inlined > as IntoIterator>::into_iter) { + scope 17 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index b2c15247cd7b..e1d710fb689c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _17; } - scope 19 (inlined > as Iterator>::next) { + scope 18 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; } } @@ -34,33 +34,31 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _9: *const T; scope 7 { } - scope 12 (inlined std::ptr::without_provenance::) { - scope 13 (inlined without_provenance_mut::) { + scope 11 (inlined std::ptr::without_provenance::) { + scope 12 (inlined without_provenance_mut::) { } } - scope 14 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 15 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } - scope 8 (inlined as From<&[T]>>::from) { - scope 9 (inlined NonNull::<[T]>::from_ref) { - let mut _4: *const [T]; - } + scope 8 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; } - scope 10 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 11 (inlined NonNull::<[T]>::as_ptr) { + scope 10 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 16 (inlined as Iterator>::rev) { - scope 17 (inlined Rev::>::new) { + scope 15 (inlined as Iterator>::rev) { + scope 16 (inlined Rev::>::new) { } } - scope 18 (inlined > as IntoIterator>::into_iter) { + scope 17 (inlined > as IntoIterator>::into_iter) { } bb0: { From 53ef53aed9cb43e6719f6f31aec82e05f236cd57 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 12:39:58 -0500 Subject: [PATCH 074/176] settings.js: begin typechecking migration this also makes `changeSetting` more robust in case it somehow gets called before `main.js` has finished loading. --- src/librustdoc/html/static/js/main.js | 3 --- src/librustdoc/html/static/js/rustdoc.d.ts | 2 ++ src/librustdoc/html/static/js/settings.js | 21 +++++++++++++++++---- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 4150c5609a97..d6f4c2e0fa84 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1101,7 +1101,6 @@ function preLoadCss(cssUrl) { }); }()); - // @ts-expect-error window.rustdoc_add_line_numbers_to_examples = () => { // @ts-expect-error function generateLine(nb) { @@ -1123,7 +1122,6 @@ function preLoadCss(cssUrl) { }); }; - // @ts-expect-error window.rustdoc_remove_line_numbers_from_examples = () => { onEachLazy( document.querySelectorAll(".rustdoc:not(.src) :not(.scraped-example) > .example-wrap"), @@ -1132,7 +1130,6 @@ function preLoadCss(cssUrl) { }; if (getSettingValue("line-numbers") === "true") { - // @ts-expect-error window.rustdoc_add_line_numbers_to_examples(); } diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 91a58fab86ef..0465866e3671 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -78,6 +78,8 @@ declare global { pending_implementors?: rustdoc.Implementors, register_type_impls?: function(rustdoc.TypeImpls): void, pending_type_impls?: rustdoc.TypeImpls, + rustdoc_add_line_numbers_to_examples?: function(), + rustdoc_remove_line_numbers_from_examples?: function(), } interface HTMLElement { /** Used by the popover tooltip code. */ diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 5f1bbd27328c..ff21c828611a 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -4,19 +4,26 @@ /* global MAIN_ID, getVar, getSettingsButton, getHelpButton */ // Eventually fix this. -// @ts-nocheck "use strict"; (function() { const isSettingsPage = window.location.pathname.endsWith("/settings.html"); + /** + * @overload {"theme"|"preferred-dark-theme"|"preferred-light-theme"} + * @param {string} settingName + * @param {string} value + * @returns + * @param {string} settingName + * @param {string|boolean} value + */ function changeSetting(settingName, value) { if (settingName === "theme") { const useSystem = value === "system preference" ? "true" : "false"; updateLocalStorage("use-system-theme", useSystem); } - updateLocalStorage(settingName, value); + updateLocalStorage(settingName, "" + value); switch (settingName) { case "theme": @@ -27,9 +34,15 @@ break; case "line-numbers": if (value === true) { - window.rustdoc_add_line_numbers_to_examples(); + const f = window.rustdoc_add_line_numbers_to_examples; + if (f !== undefined) { + f(); + } } else { - window.rustdoc_remove_line_numbers_from_examples(); + const f = window.rustdoc_remove_line_numbers_from_examples; + if (f !== undefined) { + f(); + } } break; case "hide-sidebar": From 6ca7bd041b2da04274d019f4dd001f5cfc51e78a Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 13:06:17 -0500 Subject: [PATCH 075/176] settings.js: add new rustdoc.Setting interface --- src/librustdoc/html/static/js/rustdoc.d.ts | 10 +++++ src/librustdoc/html/static/js/settings.js | 43 +++++++++++++--------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 0465866e3671..1b28fcb19def 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -479,4 +479,14 @@ declare namespace rustdoc { * is a tuple of (filename, subdirs, filenames). */ type Dir = [string, rustdoc.Dir[], string[]] + + /** + * Indivitual setting object, used in `settings.js` + */ + interface Setting { + js_name: string, + name: string, + options?: string[], + default: string | boolean, + } } diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index ff21c828611a..694a26cdac20 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -102,6 +102,9 @@ } } + /** + * @param {HTMLElement} settingsElement + */ function setEvents(settingsElement) { updateLightAndDark(); onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"), toggle => { @@ -114,23 +117,27 @@ changeSetting(toggle.id, toggle.checked); }; }); - onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"), elem => { - const settingId = elem.name; - let settingValue = getSettingValue(settingId); - if (settingId === "theme") { - const useSystem = getSettingValue("use-system-theme"); - if (useSystem === "true" || settingValue === null) { - // "light" is the default theme - settingValue = useSystem === "false" ? "light" : "system preference"; + onEachLazy( + settingsElement.querySelectorAll("input[type=\"radio\"]"), + /** @param {HTMLInputElement} elem */ + elem => { + const settingId = elem.name; + let settingValue = getSettingValue(settingId); + if (settingId === "theme") { + const useSystem = getSettingValue("use-system-theme"); + if (useSystem === "true" || settingValue === null) { + // "light" is the default theme + settingValue = useSystem === "false" ? "light" : "system preference"; + } } + if (settingValue !== null && settingValue !== "null") { + elem.checked = settingValue === elem.value; + } + elem.addEventListener("change", ev => { + changeSetting(elem.name, elem.value); + }); } - if (settingValue !== null && settingValue !== "null") { - elem.checked = settingValue === elem.value; - } - elem.addEventListener("change", ev => { - changeSetting(ev.target.name, ev.target.value); - }); - }); + ); } /** @@ -138,7 +145,7 @@ * as argument which describes each setting and how to render it. It returns a string * representing the raw HTML. * - * @param {Array} settings + * @param {Array} settings * * @return {string} */ @@ -195,7 +202,9 @@ * @return {HTMLElement} */ function buildSettingsPage() { - const theme_names = getVar("themes").split(",").filter(t => t); + const theme_list = getVar("themes") + const theme_names = (theme_list === null ? "" : theme_list) + .split(",").filter(t => t); theme_names.push("light", "dark", "ayu"); const settings = [ From f05683639d64dc26e51f63d97a0ba3cd812dc374 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 13:08:05 -0500 Subject: [PATCH 076/176] settings.js: remove dead code for adding
to settings page --- src/librustdoc/html/static/js/settings.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 694a26cdac20..5e706e284928 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -153,11 +153,6 @@ let output = ""; for (const setting of settings) { - if (setting === "hr") { - output += "
"; - continue; - } - const js_data_name = setting["js_name"]; const setting_name = setting["name"]; From 9f8d3d0bc9057ecc9de715a5cf65d97dc67da766 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 13:09:49 -0500 Subject: [PATCH 077/176] settings.js: refactor settingsBlurHandler changes: * Add type signature * Add null checks * getHelpButton and getSettingsButton are only called once, which should marginally improve performance due to less queries. unfortunatly 2 @ts-expect-error was needed, as typescript is unaware the EventTarget is likely an Element. --- src/librustdoc/html/static/js/settings.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 5e706e284928..f61673c9088e 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -310,12 +310,21 @@ }); } + /** + * @param {MouseEvent} event + */ function settingsBlurHandler(event) { - if (!getHelpButton().contains(document.activeElement) && - !getHelpButton().contains(event.relatedTarget) && - !getSettingsButton().contains(document.activeElement) && - !getSettingsButton().contains(event.relatedTarget) - ) { + const helpBtn = getHelpButton(); + const settingsBtn = getSettingsButton(); + const helpUnfocused = helpBtn === null || + (!helpBtn.contains(document.activeElement) && + // @ts-expect-error + !helpBtn.contains(event.relatedTarget)); + const settingsUnfocused = settingsBtn === null || + (!settingsBtn.contains(document.activeElement) && + // @ts-expect-error + !settingsBtn.contains(event.relatedTarget)); + if (helpUnfocused && settingsUnfocused) { window.hidePopoverMenus(); } } From 072aa9e66f7c5e398d3030c8d41dc89079a4aed2 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 2 Apr 2025 18:15:50 +0000 Subject: [PATCH 078/176] Apply requested API changes to `cell_update` Do the following: * Switch to `impl FnOnce` rather than a generic `F`. * Change `update` to return nothing. This was discussed at a libs-api meeting [1]. Tracking issue: https://github.com/rust-lang/rust/issues/50186 [1]: https://github.com/rust-lang/rust/pull/134446#issuecomment-2770842949 --- library/core/src/cell.rs | 15 ++++----------- library/coretests/tests/cell.rs | 4 ++-- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index e789601a409a..09117e4968db 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -544,7 +544,7 @@ impl Cell { unsafe { *self.value.get() } } - /// Updates the contained value using a function and returns the new value. + /// Updates the contained value using a function. /// /// # Examples /// @@ -554,21 +554,14 @@ impl Cell { /// use std::cell::Cell; /// /// let c = Cell::new(5); - /// let new = c.update(|x| x + 1); - /// - /// assert_eq!(new, 6); + /// c.update(|x| x + 1); /// assert_eq!(c.get(), 6); /// ``` #[inline] #[unstable(feature = "cell_update", issue = "50186")] - pub fn update(&self, f: F) -> T - where - F: FnOnce(T) -> T, - { + pub fn update(&self, f: impl FnOnce(T) -> T) { let old = self.get(); - let new = f(old); - self.set(new); - new + self.set(f(old)); } } diff --git a/library/coretests/tests/cell.rs b/library/coretests/tests/cell.rs index d6a401c2b4d9..781a46c3744f 100644 --- a/library/coretests/tests/cell.rs +++ b/library/coretests/tests/cell.rs @@ -50,10 +50,10 @@ fn smoketest_cell() { fn cell_update() { let x = Cell::new(10); - assert_eq!(x.update(|x| x + 5), 15); + x.update(|x| x + 5); assert_eq!(x.get(), 15); - assert_eq!(x.update(|x| x / 3), 5); + x.update(|x| x / 3); assert_eq!(x.get(), 5); } From d2ff26bbe696e3aa8f6c92de787d8de4c68d7a5e Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 13:24:55 -0500 Subject: [PATCH 079/176] settings.js: add some null checks to buildSettingsPage --- src/librustdoc/html/static/js/settings.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index f61673c9088e..ea02e01dccf7 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -289,10 +289,16 @@ el.innerHTML = innerHTML; if (isSettingsPage) { - document.getElementById(MAIN_ID).appendChild(el); + const mainElem = document.getElementById(MAIN_ID); + if (mainElem !== null) { + mainElem.appendChild(el); + } } else { el.setAttribute("tabindex", "-1"); - getSettingsButton().appendChild(el); + const settingsBtn = getSettingsButton(); + if (settingsBtn !== null) { + settingsBtn.appendChild(el); + } } return el; } From a805f5253e96dd1746cd929fd172a3e8391c6517 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 13:45:35 -0500 Subject: [PATCH 080/176] settings.js: make top-level code typecheck With this, almost the entire file is fully typechecked, the only exception being the Element.contains(EventTarget) pattern that is used several times, those are annotated with @ts-expect-error --- src/librustdoc/html/static/js/main.js | 2 +- src/librustdoc/html/static/js/rustdoc.d.ts | 2 ++ src/librustdoc/html/static/js/settings.js | 18 ++++++++++-------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index d6f4c2e0fa84..754eb90b4723 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1,6 +1,6 @@ // Local js definitions: /* global addClass, getSettingValue, hasClass, updateLocalStorage */ -/* global onEachLazy, removeClass, getVar */ +/* global onEachLazy, removeClass, getVar, nonnull */ "use strict"; diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 1b28fcb19def..0d2e19e019f3 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -30,6 +30,8 @@ declare global { currentCrate: string|null; /** * Hide popovers, tooltips, or the mobile sidebar. + * + * Pass `true` to reset focus for tooltip popovers. */ hideAllModals: function(boolean), /** diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index ea02e01dccf7..4facb45ae38e 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -1,9 +1,7 @@ // Local js definitions: /* global getSettingValue, updateLocalStorage, updateTheme */ /* global addClass, removeClass, onEach, onEachLazy */ -/* global MAIN_ID, getVar, getSettingsButton, getHelpButton */ - -// Eventually fix this. +/* global MAIN_ID, getVar, getSettingsButton, getHelpButton, nonnull */ "use strict"; @@ -317,7 +315,7 @@ } /** - * @param {MouseEvent} event + * @param {FocusEvent} event */ function settingsBlurHandler(event) { const helpBtn = getHelpButton(); @@ -337,22 +335,26 @@ if (!isSettingsPage) { // We replace the existing "onclick" callback. - const settingsButton = getSettingsButton(); - const settingsMenu = document.getElementById("settings"); + // These elements must exist, as (outside of the settings page) + // `settings.js` is only loaded after the settings button is clicked. + const settingsButton = nonnull(getSettingsButton()); + const settingsMenu = nonnull(document.getElementById("settings")); settingsButton.onclick = event => { + // @ts-expect-error if (settingsMenu.contains(event.target)) { return; } event.preventDefault(); const shouldDisplaySettings = settingsMenu.style.display === "none"; - window.hideAllModals(); + window.hideAllModals(false); if (shouldDisplaySettings) { displaySettings(); } }; settingsButton.onblur = settingsBlurHandler; - settingsButton.querySelector("a").onblur = settingsBlurHandler; + // the settings button should always have a link in it + nonnull(settingsButton.querySelector("a")).onblur = settingsBlurHandler; onEachLazy(settingsMenu.querySelectorAll("input"), el => { el.onblur = settingsBlurHandler; }); From 8a341298ec1c6a029bda1cc9f0ec696e9444caa9 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 13:48:05 -0500 Subject: [PATCH 081/176] main.js: make hideAllModals docs clearer "true" looks like a string value, `true` makes it more clear that we are talking about the actual boolean value. --- src/librustdoc/html/static/js/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 754eb90b4723..9902918fe5e7 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1593,7 +1593,7 @@ function preLoadCss(cssUrl) { /** * Hide popover menus, clickable tooltips, and the sidebar (if applicable). * - * Pass "true" to reset focus for tooltip popovers. + * Pass `true` to reset focus for tooltip popovers. */ window.hideAllModals = switchFocus => { hideSidebar(); From 9f54910f4ba9d1183c5246ec16f0a35183772db2 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 13:56:31 -0500 Subject: [PATCH 082/176] settings.js: add elemContainsTarget utility function this allows us to eliminate the last 3 @ts-expect-error in this file. --- src/librustdoc/html/static/js/settings.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 4facb45ae38e..d82f5f546334 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -8,6 +8,18 @@ (function() { const isSettingsPage = window.location.pathname.endsWith("/settings.html"); + /** + * @param {Element} elem + * @param {EventTarget|null} target + */ + function elemContainsTarget(elem, target) { + if (target instanceof Node) { + return elem.contains(target); + } else { + return false; + } + } + /** * @overload {"theme"|"preferred-dark-theme"|"preferred-light-theme"} * @param {string} settingName @@ -322,12 +334,10 @@ const settingsBtn = getSettingsButton(); const helpUnfocused = helpBtn === null || (!helpBtn.contains(document.activeElement) && - // @ts-expect-error - !helpBtn.contains(event.relatedTarget)); + !elemContainsTarget(helpBtn, event.relatedTarget)); const settingsUnfocused = settingsBtn === null || (!settingsBtn.contains(document.activeElement) && - // @ts-expect-error - !settingsBtn.contains(event.relatedTarget)); + !elemContainsTarget(settingsBtn, event.relatedTarget)); if (helpUnfocused && settingsUnfocused) { window.hidePopoverMenus(); } @@ -340,8 +350,7 @@ const settingsButton = nonnull(getSettingsButton()); const settingsMenu = nonnull(document.getElementById("settings")); settingsButton.onclick = event => { - // @ts-expect-error - if (settingsMenu.contains(event.target)) { + if (elemContainsTarget(settingsMenu, event.target)) { return; } event.preventDefault(); From 6a1f57d095d3f6236b737655182cffb34cbf1ae2 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 1 Mar 2025 22:21:26 +0100 Subject: [PATCH 083/176] Demote i686-pc-windows-gnu to Tier 2 In accordance with RFC 3771. I also added a stub doc page for the target and renamed the windows-gnullvm page for consistency. --- .../src/spec/targets/i686_pc_windows_gnu.rs | 2 +- src/bootstrap/mk/Makefile.in | 4 --- .../docker/host-x86_64/mingw-check/Dockerfile | 2 +- .../x86_64-gnu-tools/checktools.sh | 1 - src/ci/github-actions/jobs.yml | 27 +--------------- src/doc/rustc/src/SUMMARY.md | 3 +- src/doc/rustc/src/platform-support.md | 10 +++--- .../rustc/src/platform-support/windows-gnu.md | 32 +++++++++++++++++++ ...-windows-gnullvm.md => windows-gnullvm.md} | 8 ++--- 9 files changed, 46 insertions(+), 43 deletions(-) create mode 100644 src/doc/rustc/src/platform-support/windows-gnu.md rename src/doc/rustc/src/platform-support/{pc-windows-gnullvm.md => windows-gnullvm.md} (88%) diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs index 2a26323e5147..e775c8fc524c 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs @@ -20,7 +20,7 @@ pub(crate) fn target() -> Target { llvm_target: "i686-pc-windows-gnu".into(), metadata: TargetMetadata { description: Some("32-bit MinGW (Windows 10+)".into()), - tier: Some(1), + tier: Some(2), host_tools: Some(true), std: Some(true), }, diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 6cb0b19d7632..605f54d1d7fc 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -120,10 +120,6 @@ ci-msvc: ci-msvc-py ci-msvc-ps1 # Set of tests that should represent half of the time of the test suite. # Used to split tests across multiple CI runners. # Test both x and bootstrap entrypoints. -ci-mingw-x-1: - $(Q)$(CFG_SRC_DIR)/x test --stage 2 $(SKIP_COMPILER) $(TEST_SET2) -ci-mingw-x-2: - $(Q)$(CFG_SRC_DIR)/x test --stage 2 $(SKIP_SRC) $(TEST_SET2) ci-mingw-x: $(Q)$(CFG_SRC_DIR)/x test --stage 2 $(TEST_SET1) ci-mingw-bootstrap: diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index b32fa6c8e4ee..8bb7116c3ec5 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -47,7 +47,7 @@ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ ENV SCRIPT \ python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ /scripts/check-default-config-profiles.sh && \ - python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ + python3 ../x.py check --target=x86_64-pc-windows-gnu --host=x86_64-pc-windows-gnu && \ python3 ../x.py clippy ci && \ python3 ../x.py build --stage 0 src/tools/build-manifest && \ python3 ../x.py test --stage 0 src/tools/compiletest && \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index 8324d1ec5862..28c035daa5d5 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -62,7 +62,6 @@ case $HOST_TARGET in # See # For now, these tests are moved to `x86_64-msvc-ext2` in `src/ci/github-actions/jobs.yml`. #python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass - #python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass ;; *) echo "FATAL: unexpected host $HOST_TARGET" diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index f62ed23d038c..26ff17e423b5 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -501,7 +501,7 @@ auto: env: SCRIPT: > python x.py test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass && - python x.py test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass && + python x.py test --stage 2 src/tools/miri --target x86_64-pc-windows-gnu --test-args pass && python x.py miri --stage 2 library/core --test-args notest && python x.py miri --stage 2 library/alloc --test-args notest && python x.py miri --stage 2 library/std --test-args notest @@ -533,31 +533,6 @@ auto: # came from the mingw-w64 SourceForge download site. Unfortunately # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - # i686-mingw is split into three jobs to run tests in parallel. - - name: i686-mingw-1 - env: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-mingw-x-1 - # There is no dist-i686-mingw-alt, so there is no prebuilt LLVM with assertions - NO_DOWNLOAD_CI_LLVM: 1 - <<: *job-windows-25 - - - name: i686-mingw-2 - env: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-mingw-x-2 - # There is no dist-i686-mingw-alt, so there is no prebuilt LLVM with assertions - NO_DOWNLOAD_CI_LLVM: 1 - <<: *job-windows-25 - - - name: i686-mingw-3 - env: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-mingw-bootstrap - # There is no dist-i686-mingw-alt, so there is no prebuilt LLVM with assertions - NO_DOWNLOAD_CI_LLVM: 1 - <<: *job-windows-25 - # x86_64-mingw is split into two jobs to run tests in parallel. - name: x86_64-mingw-1 env: diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index e1ba27c07dae..9bb64adfa786 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -103,7 +103,6 @@ - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [solaris](platform-support/solaris.md) - - [\*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) - [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) - [\*-unknown-hermit](platform-support/hermit.md) @@ -122,6 +121,8 @@ - [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md) - [wasm32v1-none](platform-support/wasm32v1-none.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) + - [windows-gnu](platform-support/windows-gnu.md) + - [windows-gnullvm](platform-support/windows-gnullvm.md) - [\*-win7-windows-gnu](platform-support/win7-windows-gnu.md) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index bc97568f85c9..4149b4cb9202 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -34,11 +34,10 @@ target | notes -------|------- [`aarch64-apple-darwin`](platform-support/apple-darwin.md) | ARM64 macOS (11.0+, Big Sur+) `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) -`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI] `i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI] `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+, Pentium 4) [^x86_32-floats-return-ABI] [`x86_64-apple-darwin`](platform-support/apple-darwin.md) | 64-bit macOS (10.12+, Sierra+) -`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 10+, Windows Server 2016+) +[`x86_64-pc-windows-gnu`](platform-support/windows-gnu.md) | 64-bit MinGW (Windows 10+, Windows Server 2016+) `x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 10+, Windows Server 2016+) `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+) @@ -96,6 +95,7 @@ target | notes [`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | Armv7-A OpenHarmony [`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36) [`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, musl 1.2.5) +[`i686-pc-windows-gnu`](platform-support/windows-gnu.md) | 32-bit MinGW (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI] `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17) `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17) [`powerpc64le-unknown-linux-gnu`](platform-support/powerpc64le-unknown-linux-gnu.md) | PPC64LE Linux (kernel 3.10, glibc 2.17) @@ -143,7 +143,7 @@ target | std | notes [`aarch64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | Mac Catalyst on ARM64 [`aarch64-apple-ios-sim`](platform-support/apple-ios.md) | ✓ | Apple iOS Simulator on ARM64 [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android -[`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ARM64 MinGW (Windows 10+), LLVM ABI +[`aarch64-pc-windows-gnullvm`](platform-support/windows-gnullvm.md) | ✓ | ARM64 MinGW (Windows 10+), LLVM ABI [`aarch64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | ARM64 Fuchsia `aarch64-unknown-none` | * | Bare ARM64, hardfloat `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat @@ -166,7 +166,7 @@ target | std | notes `i586-unknown-linux-gnu` | ✓ | 32-bit Linux (kernel 3.2, glibc 2.17, original Pentium) [^x86_32-floats-x87] `i586-unknown-linux-musl` | ✓ | 32-bit Linux (musl 1.2.3, original Pentium) [^x86_32-floats-x87] [`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android ([Pentium 4 plus various extensions](https://developer.android.com/ndk/guides/abis.html#x86)) [^x86_32-floats-return-ABI] -[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 32-bit x86 MinGW (Windows 10+, Pentium 4), LLVM ABI [^x86_32-floats-return-ABI] +[`i686-pc-windows-gnullvm`](platform-support/windows-gnullvm.md) | ✓ | 32-bit x86 MinGW (Windows 10+, Pentium 4), LLVM ABI [^x86_32-floats-return-ABI] [`i686-unknown-freebsd`](platform-support/freebsd.md) | ✓ | 32-bit x86 FreeBSD (Pentium 4) [^x86_32-floats-return-ABI] `i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 (Pentium 4) [^x86_32-floats-return-ABI] [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | ? | 32-bit UEFI (Pentium 4, softfloat) @@ -202,7 +202,7 @@ target | std | notes [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android [`x86_64-pc-solaris`](platform-support/solaris.md) | ✓ | 64-bit x86 Solaris 11.4 -[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 64-bit x86 MinGW (Windows 10+), LLVM ABI +[`x86_64-pc-windows-gnullvm`](platform-support/windows-gnullvm.md) | ✓ | 64-bit x86 MinGW (Windows 10+), LLVM ABI [`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat diff --git a/src/doc/rustc/src/platform-support/windows-gnu.md b/src/doc/rustc/src/platform-support/windows-gnu.md new file mode 100644 index 000000000000..a867ebcfe253 --- /dev/null +++ b/src/doc/rustc/src/platform-support/windows-gnu.md @@ -0,0 +1,32 @@ +# \*-windows-gnu + +**⚠️ This documentation page is a stub, you can help improving it by sending a PR. ⚠️** + +**Tier: 1/2 (with host tools)** + +Target triples available: +- `i686-pc-windows-gnu`: Tier 2 +- `x86_64-pc-windows-gnu`: Tier 1 + +## Target maintainers + +**⚠️ These targets do not have any maintainers and are not properly maintained. ⚠️** + +If you are using this target, consider signing up to become a target maintainer. +See the target tier policy for details. +Without maintainers, these targets may be demoted in the future. + +## Requirements + +These targets support std and host tools. + +Unlike their MSVC counterparts, windows-gnu targets support cross-compilation and are free of all MSVC licensing implications. + +They follow Windows calling convention for `extern "C"`. + +Like with any other Windows target, created binaries are in PE format. + +## Building Rust programs + +Rust does ship a pre-compiled std library for those targets. +That means one can easily compile and cross-compile for those targets from other hosts if C proper toolchain is installed. diff --git a/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md b/src/doc/rustc/src/platform-support/windows-gnullvm.md similarity index 88% rename from src/doc/rustc/src/platform-support/pc-windows-gnullvm.md rename to src/doc/rustc/src/platform-support/windows-gnullvm.md index f14fe7df4228..1ff559fe9600 100644 --- a/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md +++ b/src/doc/rustc/src/platform-support/windows-gnullvm.md @@ -1,8 +1,8 @@ -# \*-pc-windows-gnullvm +# \*-windows-gnullvm **Tier: 2 (without host tools)** -Windows targets similar to `*-pc-windows-gnu` but using UCRT as the runtime and various LLVM tools/libraries instead of GCC/Binutils. +Windows targets similar to `*-windows-gnu` but using UCRT as the runtime and various LLVM tools/libraries instead of GCC/Binutils. Target triples available so far: - `aarch64-pc-windows-gnullvm` @@ -17,9 +17,9 @@ Target triples available so far: ## Requirements The easiest way to obtain these targets is cross-compilation, but native build from `x86_64-pc-windows-gnu` is possible with few hacks which I don't recommend. -Std support is expected to be on par with `*-pc-windows-gnu`. +Std support is expected to be on par with `*-windows-gnu`. -Binaries for this target should be at least on par with `*-pc-windows-gnu` in terms of requirements and functionality. +Binaries for this target should be at least on par with `*-windows-gnu` in terms of requirements and functionality. Those targets follow Windows calling convention for `extern "C"`. From ef1827b97452f697c28d028f94148463606b2fd8 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 15:24:38 -0500 Subject: [PATCH 084/176] settings.js: fix whitespace --- src/librustdoc/html/static/js/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index d82f5f546334..2c051d0025cb 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -19,7 +19,7 @@ return false; } } - + /** * @overload {"theme"|"preferred-dark-theme"|"preferred-light-theme"} * @param {string} settingName From fef3cf0d071e5b771734be4380bdccebfee60990 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 2 Apr 2025 23:56:09 +0300 Subject: [PATCH 085/176] hygiene: Avoid recursion in syntax context decoding --- compiler/rustc_metadata/src/rmeta/mod.rs | 4 +- .../rustc_middle/src/query/on_disk_cache.rs | 3 +- compiler/rustc_middle/src/ty/parameterized.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 161 +++++++----------- 4 files changed, 67 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index b1bc4b43ab44..96a1f65eeb0f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -36,7 +36,9 @@ use rustc_serialize::opaque::FileEncoder; use rustc_session::config::{SymbolManglingVersion, TargetModifier}; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_span::edition::Edition; -use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData}; +use rustc_span::hygiene::{ + ExpnIndex, MacroKind, SyntaxContextDataNonRecursive as SyntaxContextData, +}; use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol}; use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 14e3ce8bef6b..c6ecc679b7b3 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -16,7 +16,8 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_span::hygiene::{ - ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData, + ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, + SyntaxContextDataNonRecursive as SyntaxContextData, }; use rustc_span::source_map::Spanned; use rustc_span::{ diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 61b35b33a096..b56e08626920 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -113,7 +113,7 @@ trivially_parameterized_over_tcx! { rustc_span::Span, rustc_span::Symbol, rustc_span::def_id::DefPathHash, - rustc_span::hygiene::SyntaxContextData, + rustc_span::hygiene::SyntaxContextDataNonRecursive, rustc_span::Ident, rustc_type_ir::Variance, rustc_hir::Attribute, diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 9959e98e3dd7..9be16f8ce0c9 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -24,9 +24,6 @@ // because getting it wrong can lead to nested `HygieneData::with` calls that // trigger runtime aborts. (Fortunately these are obvious and easy to fix.) -use std::cell::RefCell; -use std::collections::hash_map::Entry; -use std::collections::hash_set::Entry as SetEntry; use std::hash::Hash; use std::sync::Arc; use std::{fmt, iter, mem}; @@ -34,7 +31,7 @@ use std::{fmt, iter, mem}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; -use rustc_data_structures::sync::{Lock, WorkerLocal}; +use rustc_data_structures::sync::Lock; use rustc_data_structures::unhash::UnhashMap; use rustc_hashes::Hash64; use rustc_index::IndexVec; @@ -61,8 +58,8 @@ impl !PartialOrd for SyntaxContext {} /// The other fields are only for caching. type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); -#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable)] -pub struct SyntaxContextData { +#[derive(Clone, Copy, Debug)] +struct SyntaxContextData { outer_expn: ExpnId, outer_transparency: Transparency, parent: SyntaxContext, @@ -74,6 +71,17 @@ pub struct SyntaxContextData { dollar_crate_name: Symbol, } +/// Same as `SyntaxContextData`, but `opaque(_and_semitransparent)` cannot be recursive +/// and use `None` if they need to refer to self. Used for encoding and decoding metadata. +#[derive(Encodable, Decodable)] +pub struct SyntaxContextDataNonRecursive { + outer_expn: ExpnId, + outer_transparency: Transparency, + parent: SyntaxContext, + opaque: Option, + opaque_and_semitransparent: Option, +} + impl SyntaxContextData { fn new( (parent, outer_expn, outer_transparency): SyntaxContextKey, @@ -114,6 +122,19 @@ impl SyntaxContextData { } } +impl SyntaxContextDataNonRecursive { + fn recursive(&self, ctxt: SyntaxContext) -> SyntaxContextData { + SyntaxContextData { + outer_expn: self.outer_expn, + outer_transparency: self.outer_transparency, + parent: self.parent, + opaque: self.opaque.unwrap_or(ctxt), + opaque_and_semitransparent: self.opaque_and_semitransparent.unwrap_or(ctxt), + dollar_crate_name: kw::DollarCrate, + } + } +} + rustc_index::newtype_index! { /// A unique ID associated with a macro invocation and expansion. #[orderable] @@ -637,6 +658,19 @@ impl HygieneData { SyntaxContextData::new(key, opaque, opaque_and_semitransparent); ctxt } + + fn non_recursive_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContextDataNonRecursive { + debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); + let data = &self.syntax_context_data[ctxt.0 as usize]; + SyntaxContextDataNonRecursive { + outer_expn: data.outer_expn, + outer_transparency: data.outer_transparency, + parent: data.parent, + opaque: (data.opaque != ctxt).then_some(data.opaque), + opaque_and_semitransparent: (data.opaque_and_semitransparent != ctxt) + .then_some(data.opaque_and_semitransparent), + } + } } pub fn walk_chain(span: Span, to: SyntaxContext) -> Span { @@ -1266,7 +1300,7 @@ impl HygieneEncodeContext { pub fn encode( &self, encoder: &mut T, - mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData), + mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextDataNonRecursive), mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash), ) { // When we serialize a `SyntaxContextData`, we may end up serializing @@ -1315,18 +1349,12 @@ struct HygieneDecodeContextInner { // so that multiple occurrences of the same serialized id are decoded to the same // `SyntaxContext`. This only stores `SyntaxContext`s which are completely decoded. remapped_ctxts: Vec>, - - /// Maps serialized `SyntaxContext` ids that are currently being decoded to a `SyntaxContext`. - decoding: FxHashMap, } #[derive(Default)] /// Additional information used to assist in decoding hygiene data pub struct HygieneDecodeContext { inner: Lock, - - /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread. - local_in_progress: WorkerLocal>>, } /// Register an expansion which has been decoded from the on-disk-cache for the local crate. @@ -1397,7 +1425,10 @@ pub fn decode_expn_id( // to track which `SyntaxContext`s we have already decoded. // The provided closure will be invoked to deserialize a `SyntaxContextData` // if we haven't already seen the id of the `SyntaxContext` we are deserializing. -pub fn decode_syntax_context SyntaxContextData>( +pub fn decode_syntax_context< + D: Decoder, + F: FnOnce(&mut D, u32) -> SyntaxContextDataNonRecursive, +>( d: &mut D, context: &HygieneDecodeContext, decode_data: F, @@ -1409,113 +1440,43 @@ pub fn decode_syntax_context SyntaxContext return SyntaxContext::root(); } - let pending_ctxt = { - let mut inner = context.inner.lock(); - - // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between - // raw ids from different crate metadatas. - if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() { - // This has already been decoded. - return ctxt; - } - - match inner.decoding.entry(raw_id) { - Entry::Occupied(ctxt_entry) => { - let pending_ctxt = *ctxt_entry.get(); - match context.local_in_progress.borrow_mut().entry(raw_id) { - // We're decoding this already on the current thread. Return here and let the - // function higher up the stack finish decoding to handle recursive cases. - // Hopefully having a `SyntaxContext` that refers to an incorrect data is ok - // during reminder of the decoding process, it's certainly not ok after the - // top level decoding function returns. - SetEntry::Occupied(..) => return pending_ctxt, - // Some other thread is currently decoding this. - // Race with it (alternatively we could wait here). - // We cannot return this value, unlike in the recursive case above, because it - // may expose a `SyntaxContext` pointing to incorrect data to arbitrary code. - SetEntry::Vacant(entry) => { - entry.insert(); - pending_ctxt - } - } - } - Entry::Vacant(entry) => { - // We are the first thread to start decoding. Mark the current thread as being - // progress. - context.local_in_progress.borrow_mut().insert(raw_id); - - // Allocate and store SyntaxContext id *before* calling the decoder function, - // as the SyntaxContextData may reference itself. - let new_ctxt = HygieneData::with(|hygiene_data| { - // Push a dummy SyntaxContextData to ensure that nobody else can get the - // same ID as us. This will be overwritten after call `decode_data`. - hygiene_data.syntax_context_data.push(SyntaxContextData::decode_placeholder()); - SyntaxContext::from_usize(hygiene_data.syntax_context_data.len() - 1) - }); - entry.insert(new_ctxt); - new_ctxt - } - } - }; + // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between + // raw ids from different crate metadatas. + if let Some(ctxt) = context.inner.lock().remapped_ctxts.get(raw_id as usize).copied().flatten() + { + // This has already been decoded. + return ctxt; + } // Don't try to decode data while holding the lock, since we need to // be able to recursively decode a SyntaxContext let ctxt_data = decode_data(d, raw_id); - let ctxt_key = ctxt_data.key(); let ctxt = HygieneData::with(|hygiene_data| { - match hygiene_data.syntax_context_map.get(&ctxt_key) { - // Ensure that syntax contexts are unique. - // If syntax contexts with the given key already exists, reuse it instead of - // using `pending_ctxt`. - // `pending_ctxt` will leave an unused hole in the vector of syntax contexts. - // Hopefully its value isn't stored anywhere during decoding and its dummy data - // is never accessed later. The `is_decode_placeholder` asserts on all - // accesses to syntax context data attempt to ensure it. - Some(&ctxt) => ctxt, - // This is a completely new context. - // Overwrite its placeholder data with our decoded data. - None => { - let ctxt_data_ref = - &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize]; - let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data); - // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`. - // We don't care what the encoding crate set this to - we want to resolve it - // from the perspective of the current compilation session. - ctxt_data_ref.dollar_crate_name = kw::DollarCrate; - // Make sure nothing weird happened while `decode_data` was running. - if !prev_ctxt_data.is_decode_placeholder() { - // Another thread may have already inserted the decoded data, - // but the decoded data should match. - assert_eq!(prev_ctxt_data, *ctxt_data_ref); - } - hygiene_data.syntax_context_map.insert(ctxt_key, pending_ctxt); - pending_ctxt - } - } + let ctxt_key = (ctxt_data.parent, ctxt_data.outer_expn, ctxt_data.outer_transparency); + *hygiene_data.syntax_context_map.entry(ctxt_key).or_insert_with(|| { + let ctxt = SyntaxContext::from_usize(hygiene_data.syntax_context_data.len()); + hygiene_data.syntax_context_data.push(ctxt_data.recursive(ctxt)); + ctxt + }) }); - // Mark the context as completed - context.local_in_progress.borrow_mut().remove(&raw_id); - let mut inner = context.inner.lock(); let new_len = raw_id as usize + 1; if inner.remapped_ctxts.len() < new_len { inner.remapped_ctxts.resize(new_len, None); } inner.remapped_ctxts[raw_id as usize] = Some(ctxt); - inner.decoding.remove(&raw_id); ctxt } -fn for_all_ctxts_in( +fn for_all_ctxts_in( ctxts: impl Iterator, mut f: F, ) { - let all_data: Vec<_> = HygieneData::with(|data| { - ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect() - }); + let all_data: Vec<_> = + HygieneData::with(|data| ctxts.map(|ctxt| (ctxt, data.non_recursive_ctxt(ctxt))).collect()); for (ctxt, data) in all_data.into_iter() { f(ctxt.0, ctxt, &data); } From f798c46dadc160fe6f1eeb8aef584ab2a535870d Mon Sep 17 00:00:00 2001 From: Ross Smyth <18294397+RossSmyth@users.noreply.github.com> Date: Mon, 3 Mar 2025 22:12:51 -0500 Subject: [PATCH 086/176] Map myself --- .mailmap | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index a791daa681d4..606e3d6b68ce 100644 --- a/.mailmap +++ b/.mailmap @@ -276,7 +276,7 @@ Jacob Greenfield Jacob Pratt Jacob Pratt Jake Goulding -Jake Goulding +Jake Goulding Jake Goulding Jake Vossen Jakob Degen @@ -565,6 +565,9 @@ Robert Habermeier Robert Millar Roc Yu Rohit Joshi Rohit Joshi +Ross Smyth <18294397+RossSmyth@users.noreply.github.com> +Ross Smyth <18294397+RossSmyth@users.noreply.github.com> +Ross Smyth <18294397+RossSmyth@users.noreply.github.com> Roxane Fruytier Rui Russell Johnston From 33c1ff057983e1b32b7fe9b2eaf0253ddf9bef04 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 16:25:29 -0500 Subject: [PATCH 087/176] rustdoc: make settings checkboxes always square --- src/librustdoc/html/static/css/rustdoc.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 0ea4d8f1e391..aa8df35258df 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1446,6 +1446,9 @@ so that we can apply CSS-filters to change the arrow color in themes */ align-items: center; cursor: pointer; } +.setting-check input { + flex-shrink: 0, +} .setting-radio input:checked { box-shadow: inset 0 0 0 3px var(--main-background-color); From 4435c999db7a4affa81662d1d90a75595da94b78 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 2 Apr 2025 16:36:08 -0500 Subject: [PATCH 088/176] rustdoc js: satisfy eslint --- src/librustdoc/html/static/js/main.js | 2 +- src/librustdoc/html/static/js/settings.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 9902918fe5e7..a7ce2bf9048b 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1,6 +1,6 @@ // Local js definitions: /* global addClass, getSettingValue, hasClass, updateLocalStorage */ -/* global onEachLazy, removeClass, getVar, nonnull */ +/* global onEachLazy, removeClass, getVar */ "use strict"; diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 2c051d0025cb..2430b5829b2b 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -143,10 +143,10 @@ if (settingValue !== null && settingValue !== "null") { elem.checked = settingValue === elem.value; } - elem.addEventListener("change", ev => { + elem.addEventListener("change", () => { changeSetting(elem.name, elem.value); }); - } + }, ); } @@ -207,7 +207,7 @@ * @return {HTMLElement} */ function buildSettingsPage() { - const theme_list = getVar("themes") + const theme_list = getVar("themes"); const theme_names = (theme_list === null ? "" : theme_list) .split(",").filter(t => t); theme_names.push("light", "dark", "ayu"); From 14e6a964f214e9a974a07e337e0668238d11a26c Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 2 Apr 2025 23:43:41 +0200 Subject: [PATCH 089/176] Mark super_let feature as incomplete. Co-authored-by: Travis Cross --- compiler/rustc_feature/src/unstable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index b4499fb2a6a4..0bb793e67ee2 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -631,7 +631,7 @@ declare_features! ( /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), /// Allows `super let` statements. - (unstable, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), + (incomplete, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), /// Allows subtrait items to shadow supertrait items. (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)), /// Allows using `#[thread_local]` on `static` items. From 5c2a32296dea18b3e295b351c8375cd83d6d5643 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 3 Apr 2025 01:07:55 +0200 Subject: [PATCH 090/176] use lower case to match other error messages --- compiler/rustc_session/src/config.rs | 4 ++-- compiler/rustc_target/src/spec/mod.rs | 2 +- tests/run-make/target-specs/rmake.rs | 2 +- tests/ui/errors/wrong-target-spec.rs | 2 +- tests/ui/errors/wrong-target-spec.stderr | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ed336cc55961..3e2579b3f1dc 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1424,8 +1424,8 @@ pub fn build_target_config( target } Err(e) => early_dcx.early_fatal(format!( - "Error loading target specification: {e}. \ - Run `rustc --print target-list` for a list of built-in targets" + "error loading target specification: {e}; \ + run `rustc --print target-list` for a list of built-in targets" )), } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 7234d1dc63ee..296ec50366f4 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3516,7 +3516,7 @@ impl Target { Err("the `i586-pc-windows-msvc` target has been removed. Use the `i686-pc-windows-msvc` target instead.\n\ Windows 10 (the minimum required OS version) requires a CPU baseline of at least i686 so you can safely switch".into()) } else { - Err(format!("Could not find specification for target {target_tuple:?}")) + Err(format!("could not find specification for target {target_tuple:?}")) } } TargetTuple::TargetJson { ref contents, .. } => { diff --git a/tests/run-make/target-specs/rmake.rs b/tests/run-make/target-specs/rmake.rs index f36a5784c893..9184e5f772f7 100644 --- a/tests/run-make/target-specs/rmake.rs +++ b/tests/run-make/target-specs/rmake.rs @@ -14,7 +14,7 @@ fn main() { .input("foo.rs") .target("my-invalid-platform.json") .run_fail() - .assert_stderr_contains("Error loading target specification"); + .assert_stderr_contains("error loading target specification"); rustc() .input("foo.rs") .target("my-incomplete-platform.json") diff --git a/tests/ui/errors/wrong-target-spec.rs b/tests/ui/errors/wrong-target-spec.rs index 9b31c943e3e9..a3a0e05d8266 100644 --- a/tests/ui/errors/wrong-target-spec.rs +++ b/tests/ui/errors/wrong-target-spec.rs @@ -7,4 +7,4 @@ fn main() {} -//~? ERROR Error loading target specification: Could not find specification for target "x86_64_unknown-linux-musl" +//~? ERROR error loading target specification: could not find specification for target "x86_64_unknown-linux-musl" diff --git a/tests/ui/errors/wrong-target-spec.stderr b/tests/ui/errors/wrong-target-spec.stderr index 8b06f404078d..35850a4adf22 100644 --- a/tests/ui/errors/wrong-target-spec.stderr +++ b/tests/ui/errors/wrong-target-spec.stderr @@ -1,2 +1,2 @@ -error: Error loading target specification: Could not find specification for target "x86_64_unknown-linux-musl". Run `rustc --print target-list` for a list of built-in targets +error: error loading target specification: could not find specification for target "x86_64_unknown-linux-musl"; run `rustc --print target-list` for a list of built-in targets From 076cccd412ab7c40fcf83750a17c11417d5f65cd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 19 Dec 2024 15:16:24 +1100 Subject: [PATCH 091/176] Remove `Op` type. First, move the `lang_item_for_op` call from the top of `lookup_op_method`'s body to its callsites. It makes those callsites a little more verbose, but also means `lookup_op_method` no longer cares whether it's handling a binop or unop. This lets us remove `Op` and split `lang_item_for_op` into `lang_item_for_{bin,un}op`, which is a little simpler. This change is a prerequisite for adding the `ast::AssignOpKind` type in a subsequent commit. --- compiler/rustc_hir_typeck/src/op.rs | 86 +++++++++++++++-------------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index a473e14b2444..24becc535698 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -4,15 +4,15 @@ use rustc_data_structures::packed::Pu128; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; use rustc_infer::traits::ObligationCauseCode; +use rustc_middle::bug; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::{bug, span_bug}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Ident, Span, Symbol, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{FulfillmentError, Obligation, ObligationCtxt}; use tracing::debug; @@ -49,7 +49,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs, lhs_deref_ty), Some((rhs, rhs_ty)), - Op::Binary(op, IsAssign::Yes), + lang_item_for_binop(self.tcx, op, IsAssign::Yes), + op.span, expected, ) .is_ok() @@ -60,7 +61,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs, lhs_ty), Some((rhs, rhs_ty)), - Op::Binary(op, IsAssign::Yes), + lang_item_for_binop(self.tcx, op, IsAssign::Yes), + op.span, expected, ) .is_err() @@ -242,7 +244,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let result = self.lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty_var)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op, is_assign), + op.span, expected, ); @@ -301,8 +304,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ty::new_misc_error(self.tcx) } Err(errors) => { - let (_, trait_def_id) = - lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span); + let (_, trait_def_id) = lang_item_for_binop(self.tcx, op, is_assign); let missing_trait = trait_def_id .map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id))); let mut path = None; @@ -409,7 +411,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_deref_ty), Some((rhs_expr, rhs_ty)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op, is_assign), + op.span, expected, ) .is_ok() @@ -442,7 +445,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_adjusted_ty), Some((rhs_expr, rhs_adjusted_ty)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op, is_assign), + op.span, expected, ) .is_ok() @@ -499,7 +503,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op, is_assign), + op.span, expected, ) .is_ok() @@ -592,7 +597,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op, is_assign), + op.span, expected, ) .unwrap_err(); @@ -799,7 +805,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Ty<'tcx> { assert!(op.is_by_value()); - match self.lookup_op_method((ex, operand_ty), None, Op::Unary(op, ex.span), expected) { + match self.lookup_op_method( + (ex, operand_ty), + None, + lang_item_for_unop(self.tcx, op), + ex.span, + expected, + ) { Ok(method) => { self.write_method_call_and_enforce_effects(ex.hir_id, ex.span, method); method.sig.output() @@ -898,21 +910,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, (lhs_expr, lhs_ty): (&'tcx hir::Expr<'tcx>, Ty<'tcx>), opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>, - op: Op, + (opname, trait_did): (Symbol, Option), + span: Span, expected: Expectation<'tcx>, ) -> Result, Vec>> { - let span = match op { - Op::Binary(op, _) => op.span, - Op::Unary(_, span) => span, - }; - let (opname, Some(trait_did)) = lang_item_for_op(self.tcx, op, span) else { + let Some(trait_did) = trait_did else { // Bail if the operator trait is not defined. return Err(vec![]); }; debug!( - "lookup_op_method(lhs_ty={:?}, op={:?}, opname={:?}, trait_did={:?})", - lhs_ty, op, opname, trait_did + "lookup_op_method(lhs_ty={:?}, opname={:?}, trait_did={:?})", + lhs_ty, opname, trait_did ); let opname = Ident::with_dummy_span(opname); @@ -980,13 +989,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -fn lang_item_for_op( +fn lang_item_for_binop( tcx: TyCtxt<'_>, - op: Op, - span: Span, -) -> (rustc_span::Symbol, Option) { + op: hir::BinOp, + is_assign: IsAssign, +) -> (Symbol, Option) { let lang = tcx.lang_items(); - if let Op::Binary(op, IsAssign::Yes) = op { + if is_assign == IsAssign::Yes { match op.node { hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()), hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()), @@ -1006,10 +1015,10 @@ fn lang_item_for_op( | hir::BinOpKind::Ne | hir::BinOpKind::And | hir::BinOpKind::Or => { - span_bug!(span, "impossible assignment operation: {}=", op.node.as_str()) + bug!("impossible assignment operation: {}=", op.node.as_str()) } } - } else if let Op::Binary(op, IsAssign::No) = op { + } else { match op.node { hir::BinOpKind::Add => (sym::add, lang.add_trait()), hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()), @@ -1028,15 +1037,18 @@ fn lang_item_for_op( hir::BinOpKind::Eq => (sym::eq, lang.eq_trait()), hir::BinOpKind::Ne => (sym::ne, lang.eq_trait()), hir::BinOpKind::And | hir::BinOpKind::Or => { - span_bug!(span, "&& and || are not overloadable") + bug!("&& and || are not overloadable") } } - } else if let Op::Unary(hir::UnOp::Not, _) = op { - (sym::not, lang.not_trait()) - } else if let Op::Unary(hir::UnOp::Neg, _) = op { - (sym::neg, lang.neg_trait()) - } else { - bug!("lookup_op_method: op not supported: {:?}", op) + } +} + +fn lang_item_for_unop(tcx: TyCtxt<'_>, op: hir::UnOp) -> (Symbol, Option) { + let lang = tcx.lang_items(); + match op { + hir::UnOp::Not => (sym::not, lang.not_trait()), + hir::UnOp::Neg => (sym::neg, lang.neg_trait()), + hir::UnOp::Deref => bug!("Deref is not overloadable"), } } @@ -1097,12 +1109,6 @@ enum IsAssign { Yes, } -#[derive(Clone, Copy, Debug)] -enum Op { - Binary(hir::BinOp, IsAssign), - Unary(hir::UnOp, Span), -} - /// Dereferences a single level of immutable referencing. fn deref_ty_if_possible(ty: Ty<'_>) -> Ty<'_> { match ty.kind() { From ac8ccf09b491a0eb2bc5ce1b8059e04d194fea6a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Dec 2024 08:33:43 +1100 Subject: [PATCH 092/176] Use `BinOpKind` instead of `BinOp` for function args where possible. Because it's nice to avoid passing in unnecessary data. --- .../rustc_ast_pretty/src/pprust/state/expr.rs | 12 ++-- compiler/rustc_hir_pretty/src/lib.rs | 12 ++-- .../src/fn_ctxt/suggestions.rs | 4 +- compiler/rustc_hir_typeck/src/op.rs | 56 ++++++++++--------- compiler/rustc_lint/src/types.rs | 45 +++++++-------- .../src/missing_asserts_for_indexing.rs | 8 +-- src/tools/clippy/clippy_utils/src/consts.rs | 18 +++--- 7 files changed, 77 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 7d9dc89bd756..4c301a5c6fb5 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -274,22 +274,22 @@ impl<'a> State<'a> { fn print_expr_binary( &mut self, - op: ast::BinOp, + op: ast::BinOpKind, lhs: &ast::Expr, rhs: &ast::Expr, fixup: FixupContext, ) { - let binop_prec = op.node.precedence(); + let binop_prec = op.precedence(); let left_prec = lhs.precedence(); let right_prec = rhs.precedence(); - let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() { + let (mut left_needs_paren, right_needs_paren) = match op.fixity() { Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), }; - match (&lhs.kind, op.node) { + match (&lhs.kind, op) { // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // of `(x as i32) < ...`. We need to convince it _not_ to do that. @@ -312,7 +312,7 @@ impl<'a> State<'a> { self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression()); self.space(); - self.word_space(op.node.as_str()); + self.word_space(op.as_str()); self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression()); } @@ -410,7 +410,7 @@ impl<'a> State<'a> { self.print_expr_method_call(seg, receiver, args, fixup); } ast::ExprKind::Binary(op, lhs, rhs) => { - self.print_expr_binary(*op, lhs, rhs, fixup); + self.print_expr_binary(op.node, lhs, rhs, fixup); } ast::ExprKind::Unary(op, expr) => { self.print_expr_unary(*op, expr, fixup); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1c23761b2e5b..2b4e04c79567 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1271,18 +1271,18 @@ impl<'a> State<'a> { self.print_call_post(base_args) } - fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { - let binop_prec = op.node.precedence(); + fn print_expr_binary(&mut self, op: hir::BinOpKind, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { + let binop_prec = op.precedence(); let left_prec = lhs.precedence(); let right_prec = rhs.precedence(); - let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() { + let (mut left_needs_paren, right_needs_paren) = match op.fixity() { Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), }; - match (&lhs.kind, op.node) { + match (&lhs.kind, op) { // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // of `(x as i32) < ...`. We need to convince it _not_ to do that. @@ -1297,7 +1297,7 @@ impl<'a> State<'a> { self.print_expr_cond_paren(lhs, left_needs_paren); self.space(); - self.word_space(op.node.as_str()); + self.word_space(op.as_str()); self.print_expr_cond_paren(rhs, right_needs_paren); } @@ -1451,7 +1451,7 @@ impl<'a> State<'a> { self.word(".use"); } hir::ExprKind::Binary(op, lhs, rhs) => { - self.print_expr_binary(op, lhs, rhs); + self.print_expr_binary(op.node, lhs, rhs); } hir::ExprKind::Unary(op, expr) => { self.print_expr_unary(op, expr); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 0097b6ea1231..3acf73d3d0e4 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -3477,9 +3477,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty: Ty<'tcx>, rhs_expr: &'tcx hir::Expr<'tcx>, lhs_expr: &'tcx hir::Expr<'tcx>, - op: hir::BinOp, + op: hir::BinOpKind, ) { - match op.node { + match op { hir::BinOpKind::Eq => { if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait() && self diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 24becc535698..a90c5da20b53 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -35,13 +35,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (lhs_ty, rhs_ty, return_ty) = self.check_overloaded_binop(expr, lhs, rhs, op, IsAssign::Yes, expected); - let ty = - if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { - self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, op); - self.tcx.types.unit - } else { - return_ty - }; + let ty = if !lhs_ty.is_ty_var() + && !rhs_ty.is_ty_var() + && is_builtin_binop(lhs_ty, rhs_ty, op.node) + { + self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, op.node); + self.tcx.types.unit + } else { + return_ty + }; self.check_lhs_assignable(lhs, E0067, op.span, |err| { if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) { @@ -49,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs, lhs_deref_ty), Some((rhs, rhs_ty)), - lang_item_for_binop(self.tcx, op, IsAssign::Yes), + lang_item_for_binop(self.tcx, op.node, IsAssign::Yes), op.span, expected, ) @@ -61,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs, lhs_ty), Some((rhs, rhs_ty)), - lang_item_for_binop(self.tcx, op, IsAssign::Yes), + lang_item_for_binop(self.tcx, op.node, IsAssign::Yes), op.span, expected, ) @@ -100,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.hir_id, expr, op, lhs_expr, rhs_expr ); - match BinOpCategory::from(op) { + match BinOpCategory::from(op.node) { BinOpCategory::Shortcircuit => { // && and || are a simple case. self.check_expr_coercible_to_type(lhs_expr, tcx.types.bool, None); @@ -139,14 +141,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // can't pin this down to a specific impl. if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() - && is_builtin_binop(lhs_ty, rhs_ty, op) + && is_builtin_binop(lhs_ty, rhs_ty, op.node) { let builtin_return_ty = self.enforce_builtin_binop_types( lhs_expr.span, lhs_ty, rhs_expr.span, rhs_ty, - op, + op.node, ); self.demand_eqtype(expr.span, builtin_return_ty, return_ty); builtin_return_ty @@ -163,7 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty: Ty<'tcx>, rhs_span: Span, rhs_ty: Ty<'tcx>, - op: hir::BinOp, + op: hir::BinOpKind, ) -> Ty<'tcx> { debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op)); @@ -244,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let result = self.lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty_var)), - lang_item_for_binop(self.tcx, op, is_assign), + lang_item_for_binop(self.tcx, op.node, is_assign), op.span, expected, ); @@ -255,7 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_ty_var, Some(lhs_expr), |err, ty| { - self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr, op); + self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr, op.node); }, ); let rhs_ty = self.resolve_vars_with_obligations(rhs_ty); @@ -304,7 +306,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ty::new_misc_error(self.tcx) } Err(errors) => { - let (_, trait_def_id) = lang_item_for_binop(self.tcx, op, is_assign); + let (_, trait_def_id) = lang_item_for_binop(self.tcx, op.node, is_assign); let missing_trait = trait_def_id .map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id))); let mut path = None; @@ -411,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_deref_ty), Some((rhs_expr, rhs_ty)), - lang_item_for_binop(self.tcx, op, is_assign), + lang_item_for_binop(self.tcx, op.node, is_assign), op.span, expected, ) @@ -445,7 +447,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_adjusted_ty), Some((rhs_expr, rhs_adjusted_ty)), - lang_item_for_binop(self.tcx, op, is_assign), + lang_item_for_binop(self.tcx, op.node, is_assign), op.span, expected, ) @@ -503,7 +505,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty)), - lang_item_for_binop(self.tcx, op, is_assign), + lang_item_for_binop(self.tcx, op.node, is_assign), op.span, expected, ) @@ -597,7 +599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty)), - lang_item_for_binop(self.tcx, op, is_assign), + lang_item_for_binop(self.tcx, op.node, is_assign), op.span, expected, ) @@ -991,12 +993,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn lang_item_for_binop( tcx: TyCtxt<'_>, - op: hir::BinOp, + op: hir::BinOpKind, is_assign: IsAssign, ) -> (Symbol, Option) { let lang = tcx.lang_items(); if is_assign == IsAssign::Yes { - match op.node { + match op { hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()), hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()), hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()), @@ -1015,11 +1017,11 @@ fn lang_item_for_binop( | hir::BinOpKind::Ne | hir::BinOpKind::And | hir::BinOpKind::Or => { - bug!("impossible assignment operation: {}=", op.node.as_str()) + bug!("impossible assignment operation: {}=", op.as_str()) } } } else { - match op.node { + match op { hir::BinOpKind::Add => (sym::add, lang.add_trait()), hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()), hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()), @@ -1076,8 +1078,8 @@ enum BinOpCategory { } impl BinOpCategory { - fn from(op: hir::BinOp) -> BinOpCategory { - match op.node { + fn from(op: hir::BinOpKind) -> BinOpCategory { + match op { hir::BinOpKind::Shl | hir::BinOpKind::Shr => BinOpCategory::Shift, hir::BinOpKind::Add @@ -1133,7 +1135,7 @@ fn deref_ty_if_possible(ty: Ty<'_>) -> Ty<'_> { /// Reason #2 is the killer. I tried for a while to always use /// overloaded logic and just check the types in constants/codegen after /// the fact, and it worked fine, except for SIMD types. -nmatsakis -fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool { +fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOpKind) -> bool { // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. // (See https://github.com/rust-lang/rust/issues/57447.) let (lhs, rhs) = (deref_ty_if_possible(lhs), deref_ty_if_possible(rhs)); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fec5db64bf28..a6c82f574a1c 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{ }; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, Symbol, source_map, sym}; +use rustc_span::{Span, Symbol, sym}; use tracing::debug; use {rustc_ast as ast, rustc_hir as hir}; @@ -223,7 +223,7 @@ impl TypeLimits { fn lint_nan<'tcx>( cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>, - binop: hir::BinOp, + binop: hir::BinOpKind, l: &'tcx hir::Expr<'tcx>, r: &'tcx hir::Expr<'tcx>, ) { @@ -262,19 +262,19 @@ fn lint_nan<'tcx>( InvalidNanComparisons::EqNe { suggestion } } - let lint = match binop.node { + let lint = match binop { hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, l) => { eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful { nan_plus_binop: l_span.until(r_span), float: r_span.shrink_to_hi(), - neg: (binop.node == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()), + neg: (binop == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()), }) } hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, r) => { eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful { nan_plus_binop: l_span.shrink_to_hi().to(r_span), float: l_span.shrink_to_hi(), - neg: (binop.node == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()), + neg: (binop == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()), }) } hir::BinOpKind::Lt | hir::BinOpKind::Le | hir::BinOpKind::Gt | hir::BinOpKind::Ge @@ -560,11 +560,11 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { } } hir::ExprKind::Binary(binop, ref l, ref r) => { - if is_comparison(binop) { - if !check_limits(cx, binop, l, r) { + if is_comparison(binop.node) { + if !check_limits(cx, binop.node, l, r) { cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons); } else { - lint_nan(cx, e, binop, l, r); + lint_nan(cx, e, binop.node, l, r); let cmpop = ComparisonOp::BinOp(binop.node); lint_wide_pointer(cx, e, cmpop, l, r); lint_fn_pointer(cx, e, cmpop, l, r); @@ -591,8 +591,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { _ => {} }; - fn is_valid(binop: hir::BinOp, v: T, min: T, max: T) -> bool { - match binop.node { + fn is_valid(binop: hir::BinOpKind, v: T, min: T, max: T) -> bool { + match binop { hir::BinOpKind::Lt => v > min && v <= max, hir::BinOpKind::Le => v >= min && v < max, hir::BinOpKind::Gt => v >= min && v < max, @@ -602,22 +602,19 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { } } - fn rev_binop(binop: hir::BinOp) -> hir::BinOp { - source_map::respan( - binop.span, - match binop.node { - hir::BinOpKind::Lt => hir::BinOpKind::Gt, - hir::BinOpKind::Le => hir::BinOpKind::Ge, - hir::BinOpKind::Gt => hir::BinOpKind::Lt, - hir::BinOpKind::Ge => hir::BinOpKind::Le, - _ => return binop, - }, - ) + fn rev_binop(binop: hir::BinOpKind) -> hir::BinOpKind { + match binop { + hir::BinOpKind::Lt => hir::BinOpKind::Gt, + hir::BinOpKind::Le => hir::BinOpKind::Ge, + hir::BinOpKind::Gt => hir::BinOpKind::Lt, + hir::BinOpKind::Ge => hir::BinOpKind::Le, + _ => binop, + } } fn check_limits( cx: &LateContext<'_>, - binop: hir::BinOp, + binop: hir::BinOpKind, l: &hir::Expr<'_>, r: &hir::Expr<'_>, ) -> bool { @@ -659,9 +656,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { } } - fn is_comparison(binop: hir::BinOp) -> bool { + fn is_comparison(binop: hir::BinOpKind) -> bool { matches!( - binop.node, + binop, hir::BinOpKind::Eq | hir::BinOpKind::Lt | hir::BinOpKind::Le diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index d78299fe08be..cdd6f4e5b033 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -10,7 +10,7 @@ use rustc_ast::{LitKind, RangeLimits}; use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnindexMap; use rustc_errors::{Applicability, Diag}; -use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp}; +use rustc_hir::{BinOpKind, Block, Body, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; @@ -97,7 +97,7 @@ enum LengthComparison { /// /// E.g. for `v.len() > 5` this returns `Some((LengthComparison::IntLessThanLength, 5, v.len()))` fn len_comparison<'hir>( - bin_op: BinOp, + bin_op: BinOpKind, left: &'hir Expr<'hir>, right: &'hir Expr<'hir>, ) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> { @@ -112,7 +112,7 @@ fn len_comparison<'hir>( // normalize comparison, `v.len() > 4` becomes `4 < v.len()` // this simplifies the logic a bit - let (op, left, right) = normalize_comparison(bin_op.node, left, right)?; + let (op, left, right) = normalize_comparison(bin_op, left, right)?; match (op, left.kind, right.kind) { (Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, left as usize, right)), (Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, right as usize, left)), @@ -138,7 +138,7 @@ fn assert_len_expr<'hir>( && let ExprKind::Unary(UnOp::Not, condition) = &cond.kind && let ExprKind::Binary(bin_op, left, right) = &condition.kind - && let Some((cmp, asserted_len, slice_len)) = len_comparison(*bin_op, left, right) + && let Some((cmp, asserted_len, slice_len)) = len_comparison(bin_op.node, left, right) && let ExprKind::MethodCall(method, recv, [], _) = &slice_len.kind && cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice() && method.ident.name == sym::len diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index dd149c4a29b9..17751e824c02 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -15,7 +15,7 @@ use rustc_apfloat::ieee::{Half, Quad}; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ - BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, PatExpr, PatExprKind, QPath, UnOp, + BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, PatExpr, PatExprKind, QPath, UnOp, }; use rustc_lexer::tokenize; use rustc_lint::LateContext; @@ -506,7 +506,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { UnOp::Deref => Some(if let Constant::Ref(r) = o { *r } else { o }), }), ExprKind::If(cond, then, ref otherwise) => self.ifthenelse(cond, then, *otherwise), - ExprKind::Binary(op, left, right) => self.binop(op, left, right), + ExprKind::Binary(op, left, right) => self.binop(op.node, left, right), ExprKind::Call(callee, []) => { // We only handle a few const functions for now. if let ExprKind::Path(qpath) = &callee.kind @@ -744,7 +744,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { } } - fn binop(&self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option> { + fn binop(&self, op: BinOpKind, left: &Expr<'_>, right: &Expr<'_>) -> Option> { let l = self.expr(left)?; let r = self.expr(right); match (l, r) { @@ -757,7 +757,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { // Using / or %, where the left-hand argument is the smallest integer of a signed integer type and // the right-hand argument is -1 always panics, even with overflow-checks disabled - if let BinOpKind::Div | BinOpKind::Rem = op.node + if let BinOpKind::Div | BinOpKind::Rem = op && l == ty_min_value && r == -1 { @@ -765,7 +765,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { } let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); - match op.node { + match op { // When +, * or binary - create a value greater than the maximum value, or less than // the minimum value that can be stored, it panics. BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(zext), @@ -792,7 +792,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { ty::Uint(ity) => { let bits = ity.bits(); - match op.node { + match op { BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), BinOpKind::Sub => l.checked_sub(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), BinOpKind::Mul => l.checked_mul(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), @@ -815,7 +815,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { _ => None, }, // FIXME(f16_f128): add these types when binary operations are available on all platforms - (Constant::F32(l), Some(Constant::F32(r))) => match op.node { + (Constant::F32(l), Some(Constant::F32(r))) => match op { BinOpKind::Add => Some(Constant::F32(l + r)), BinOpKind::Sub => Some(Constant::F32(l - r)), BinOpKind::Mul => Some(Constant::F32(l * r)), @@ -829,7 +829,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { BinOpKind::Gt => Some(Constant::Bool(l > r)), _ => None, }, - (Constant::F64(l), Some(Constant::F64(r))) => match op.node { + (Constant::F64(l), Some(Constant::F64(r))) => match op { BinOpKind::Add => Some(Constant::F64(l + r)), BinOpKind::Sub => Some(Constant::F64(l - r)), BinOpKind::Mul => Some(Constant::F64(l * r)), @@ -843,7 +843,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { BinOpKind::Gt => Some(Constant::Bool(l > r)), _ => None, }, - (l, r) => match (op.node, l, r) { + (l, r) => match (op, l, r) { (BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)), (BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)), (BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => { From ddcb370bc6c2de76c2a2f8b6cfb46a7b6ec553e6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Dec 2024 10:15:05 +1100 Subject: [PATCH 093/176] Tighten up assignment operator representations. In the AST, currently we use `BinOpKind` within `ExprKind::AssignOp` and `AssocOp::AssignOp`, even though this allows some nonsensical combinations. E.g. there is no `&&=` operator. Likewise for HIR and THIR. This commit introduces `AssignOpKind` which only includes the ten assignable operators, and uses it in `ExprKind::AssignOp` and `AssocOp::AssignOp`. (And does similar things for `hir::ExprKind` and `thir::ExprKind`.) This avoids the possibility of nonsensical combinations, as seen by the removal of the `bug!` case in `lang_item_for_binop`. The commit is mostly plumbing, including: - Adds an `impl From for BinOpKind` (AST) and `impl From for BinOp` (MIR/THIR). - `BinOpCategory` can now be created from both `BinOpKind` and `AssignOpKind`. - Replaces the `IsAssign` type with `Op`, which has more information and a few methods. - `suggest_swapping_lhs_and_rhs`: moves the condition to the call site, it's easier that way. - `check_expr_inner`: had to factor out some code into a separate method. I'm on the fence about whether avoiding the nonsensical combinations is worth the extra code. --- compiler/rustc_ast/src/ast.rs | 71 ++++- compiler/rustc_ast/src/util/parser.rs | 24 +- compiler/rustc_ast_lowering/src/expr.rs | 6 +- .../rustc_ast_pretty/src/pprust/state/expr.rs | 3 +- compiler/rustc_hir/src/hir.rs | 8 +- compiler/rustc_hir_pretty/src/lib.rs | 3 +- compiler/rustc_hir_typeck/src/expr.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 38 +-- compiler/rustc_hir_typeck/src/op.rs | 283 +++++++++--------- compiler/rustc_hir_typeck/src/writeback.rs | 38 +-- compiler/rustc_middle/src/mir/syntax.rs | 36 +++ compiler/rustc_middle/src/thir.rs | 4 +- .../rustc_mir_build/src/builder/expr/stmt.rs | 10 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 19 +- compiler/rustc_parse/src/parser/expr.rs | 14 +- .../clippy_lints/src/format_push_string.rs | 4 +- .../src/implicit_saturating_add.rs | 4 +- .../src/implicit_saturating_sub.rs | 4 +- .../clippy/clippy_lints/src/loops/utils.rs | 6 +- .../src/mixed_read_write_in_expression.rs | 5 +- .../src/operators/arithmetic_side_effects.rs | 5 +- .../clippy/clippy_lints/src/operators/mod.rs | 7 +- .../clippy_lints/src/suspicious_trait_impl.rs | 28 +- src/tools/clippy/clippy_lints/src/swap.rs | 4 +- src/tools/clippy/clippy_utils/src/sugg.rs | 2 +- src/tools/rustfmt/src/expr.rs | 2 +- 26 files changed, 391 insertions(+), 239 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 33c20602dfd2..97e6879c33e9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -981,6 +981,75 @@ impl BinOpKind { pub type BinOp = Spanned; +// Sometimes `BinOpKind` and `AssignOpKind` need the same treatment. The +// operations covered by `AssignOpKind` are a subset of those covered by +// `BinOpKind`, so it makes sense to convert `AssignOpKind` to `BinOpKind`. +impl From for BinOpKind { + fn from(op: AssignOpKind) -> BinOpKind { + match op { + AssignOpKind::AddAssign => BinOpKind::Add, + AssignOpKind::SubAssign => BinOpKind::Sub, + AssignOpKind::MulAssign => BinOpKind::Mul, + AssignOpKind::DivAssign => BinOpKind::Div, + AssignOpKind::RemAssign => BinOpKind::Rem, + AssignOpKind::BitXorAssign => BinOpKind::BitXor, + AssignOpKind::BitAndAssign => BinOpKind::BitAnd, + AssignOpKind::BitOrAssign => BinOpKind::BitOr, + AssignOpKind::ShlAssign => BinOpKind::Shl, + AssignOpKind::ShrAssign => BinOpKind::Shr, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] +pub enum AssignOpKind { + /// The `+=` operator (addition) + AddAssign, + /// The `-=` operator (subtraction) + SubAssign, + /// The `*=` operator (multiplication) + MulAssign, + /// The `/=` operator (division) + DivAssign, + /// The `%=` operator (modulus) + RemAssign, + /// The `^=` operator (bitwise xor) + BitXorAssign, + /// The `&=` operator (bitwise and) + BitAndAssign, + /// The `|=` operator (bitwise or) + BitOrAssign, + /// The `<<=` operator (shift left) + ShlAssign, + /// The `>>=` operator (shift right) + ShrAssign, +} + +impl AssignOpKind { + pub fn as_str(&self) -> &'static str { + use AssignOpKind::*; + match self { + AddAssign => "+=", + SubAssign => "-=", + MulAssign => "*=", + DivAssign => "/=", + RemAssign => "%=", + BitXorAssign => "^=", + BitAndAssign => "&=", + BitOrAssign => "|=", + ShlAssign => "<<=", + ShrAssign => ">>=", + } + } + + /// AssignOps are always by value. + pub fn is_by_value(self) -> bool { + true + } +} + +pub type AssignOp = Spanned; + /// Unary operator. /// /// Note that `&data` is not an operator, it's an `AddrOf` expression. @@ -1593,7 +1662,7 @@ pub enum ExprKind { /// An assignment with an operator. /// /// E.g., `a += 1`. - AssignOp(BinOp, P, P), + AssignOp(AssignOp, P, P), /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field. Field(P, Ident), /// An indexing operation (e.g., `foo[2]`). diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 98b1fc52ed74..1e5f414fae1c 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -1,6 +1,6 @@ use rustc_span::kw; -use crate::ast::{self, BinOpKind, RangeLimits}; +use crate::ast::{self, AssignOpKind, BinOpKind, RangeLimits}; use crate::token::{self, Token}; /// Associative operator. @@ -9,7 +9,7 @@ pub enum AssocOp { /// A binary op. Binary(BinOpKind), /// `?=` where ? is one of the assignable BinOps - AssignOp(BinOpKind), + AssignOp(AssignOpKind), /// `=` Assign, /// `as` @@ -44,16 +44,16 @@ impl AssocOp { token::Or => Some(Binary(BinOpKind::BitOr)), token::Shl => Some(Binary(BinOpKind::Shl)), token::Shr => Some(Binary(BinOpKind::Shr)), - token::PlusEq => Some(AssignOp(BinOpKind::Add)), - token::MinusEq => Some(AssignOp(BinOpKind::Sub)), - token::StarEq => Some(AssignOp(BinOpKind::Mul)), - token::SlashEq => Some(AssignOp(BinOpKind::Div)), - token::PercentEq => Some(AssignOp(BinOpKind::Rem)), - token::CaretEq => Some(AssignOp(BinOpKind::BitXor)), - token::AndEq => Some(AssignOp(BinOpKind::BitAnd)), - token::OrEq => Some(AssignOp(BinOpKind::BitOr)), - token::ShlEq => Some(AssignOp(BinOpKind::Shl)), - token::ShrEq => Some(AssignOp(BinOpKind::Shr)), + token::PlusEq => Some(AssignOp(AssignOpKind::AddAssign)), + token::MinusEq => Some(AssignOp(AssignOpKind::SubAssign)), + token::StarEq => Some(AssignOp(AssignOpKind::MulAssign)), + token::SlashEq => Some(AssignOp(AssignOpKind::DivAssign)), + token::PercentEq => Some(AssignOp(AssignOpKind::RemAssign)), + token::CaretEq => Some(AssignOp(AssignOpKind::BitXorAssign)), + token::AndEq => Some(AssignOp(AssignOpKind::BitAndAssign)), + token::OrEq => Some(AssignOp(AssignOpKind::BitOrAssign)), + token::ShlEq => Some(AssignOp(AssignOpKind::ShlAssign)), + token::ShrEq => Some(AssignOp(AssignOpKind::ShrAssign)), token::Lt => Some(Binary(BinOpKind::Lt)), token::Le => Some(Binary(BinOpKind::Le)), token::Ge => Some(Binary(BinOpKind::Ge)), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 52291fdfb302..80bb1e8fc414 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -274,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span), ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp( - self.lower_binop(*op), + self.lower_assign_op(*op), self.lower_expr(el), self.lower_expr(er), ), @@ -443,6 +443,10 @@ impl<'hir> LoweringContext<'_, 'hir> { Spanned { node: b.node, span: self.lower_span(b.span) } } + fn lower_assign_op(&mut self, a: AssignOp) -> AssignOp { + Spanned { node: a.node, span: self.lower_span(a.span) } + } + fn lower_legacy_const_generics( &mut self, mut f: Expr, diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 4c301a5c6fb5..df848a26d390 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -605,8 +605,7 @@ impl<'a> State<'a> { fixup.leftmost_subexpression(), ); self.space(); - self.word(op.node.as_str()); - self.word_space("="); + self.word_space(op.node.as_str()); self.print_expr_cond_paren( rhs, rhs.precedence() < ExprPrecedence::Assign, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f8af1b81ca9b..1a6c15b66a45 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -10,9 +10,9 @@ use rustc_ast::{ LitKind, TraitObjectSyntax, UintTy, UnsafeBinderCastKind, }; pub use rustc_ast::{ - AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, - ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto, MetaItemInner, MetaItemLit, Movability, - Mutability, UnOp, + AssignOp, AssignOpKind, AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind, + BoundConstness, BoundPolarity, ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto, + MetaItemInner, MetaItemLit, Movability, Mutability, UnOp, }; use rustc_attr_data_structures::AttributeKind; use rustc_data_structures::fingerprint::Fingerprint; @@ -2648,7 +2648,7 @@ pub enum ExprKind<'hir> { /// An assignment with an operator. /// /// E.g., `a += 1`. - AssignOp(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>), + AssignOp(AssignOp, &'hir Expr<'hir>, &'hir Expr<'hir>), /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct or tuple field. Field(&'hir Expr<'hir>, Ident), /// An indexing operation (`foo[2]`). diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 2b4e04c79567..8c0c17f7a7d6 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1572,8 +1572,7 @@ impl<'a> State<'a> { hir::ExprKind::AssignOp(op, lhs, rhs) => { self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); self.space(); - self.word(op.node.as_str()); - self.word_space("="); + self.word_space(op.node.as_str()); self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); } hir::ExprKind::Field(expr, ident) => { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a882ea27af6b..45ab8e03db57 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -512,7 +512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_assign(expr, expected, lhs, rhs, span) } ExprKind::AssignOp(op, lhs, rhs) => { - self.check_expr_binop_assign(expr, op, lhs, rhs, expected) + self.check_expr_assign_op(expr, op, lhs, rhs, expected) } ExprKind::Unary(unop, oprnd) => self.check_expr_unop(unop, oprnd, expected, expr), ExprKind::AddrOf(kind, mutbl, oprnd) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3acf73d3d0e4..912098c4e2d6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -3477,30 +3477,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty: Ty<'tcx>, rhs_expr: &'tcx hir::Expr<'tcx>, lhs_expr: &'tcx hir::Expr<'tcx>, - op: hir::BinOpKind, ) { - match op { - hir::BinOpKind::Eq => { - if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait() - && self - .infcx - .type_implements_trait(partial_eq_def_id, [rhs_ty, lhs_ty], self.param_env) - .must_apply_modulo_regions() - { - let sm = self.tcx.sess.source_map(); - if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_expr.span) - && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_expr.span) - { - err.note(format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`")); - err.multipart_suggestion( - "consider swapping the equality", - vec![(lhs_expr.span, rhs_snippet), (rhs_expr.span, lhs_snippet)], - Applicability::MaybeIncorrect, - ); - } - } + if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait() + && self + .infcx + .type_implements_trait(partial_eq_def_id, [rhs_ty, lhs_ty], self.param_env) + .must_apply_modulo_regions() + { + let sm = self.tcx.sess.source_map(); + if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_expr.span) + && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_expr.span) + { + err.note(format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`")); + err.multipart_suggestion( + "consider swapping the equality", + vec![(lhs_expr.span, rhs_snippet), (rhs_expr.span, lhs_snippet)], + Applicability::MaybeIncorrect, + ); } - _ => {} } } } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index a90c5da20b53..93f77b8409f0 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -24,22 +24,23 @@ use crate::Expectation; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks a `a = b` - pub(crate) fn check_expr_binop_assign( + pub(crate) fn check_expr_assign_op( &self, expr: &'tcx hir::Expr<'tcx>, - op: hir::BinOp, + op: hir::AssignOp, lhs: &'tcx hir::Expr<'tcx>, rhs: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { let (lhs_ty, rhs_ty, return_ty) = - self.check_overloaded_binop(expr, lhs, rhs, op, IsAssign::Yes, expected); + self.check_overloaded_binop(expr, lhs, rhs, Op::AssignOp(op), expected); + let category = BinOpCategory::from(op.node); let ty = if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() - && is_builtin_binop(lhs_ty, rhs_ty, op.node) + && is_builtin_binop(lhs_ty, rhs_ty, category) { - self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, op.node); + self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, category); self.tcx.types.unit } else { return_ty @@ -51,7 +52,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs, lhs_deref_ty), Some((rhs, rhs_ty)), - lang_item_for_binop(self.tcx, op.node, IsAssign::Yes), + lang_item_for_binop(self.tcx, Op::AssignOp(op)), op.span, expected, ) @@ -63,7 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs, lhs_ty), Some((rhs, rhs_ty)), - lang_item_for_binop(self.tcx, op.node, IsAssign::Yes), + lang_item_for_binop(self.tcx, Op::AssignOp(op)), op.span, expected, ) @@ -118,14 +119,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Otherwise, we always treat operators as if they are // overloaded. This is the way to be most flexible w/r/t // types that get inferred. - let (lhs_ty, rhs_ty, return_ty) = self.check_overloaded_binop( - expr, - lhs_expr, - rhs_expr, - op, - IsAssign::No, - expected, - ); + let (lhs_ty, rhs_ty, return_ty) = + self.check_overloaded_binop(expr, lhs_expr, rhs_expr, Op::BinOp(op), expected); // Supply type inference hints if relevant. Probably these // hints should be enforced during select as part of the @@ -139,16 +134,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // deduce that the result type should be `u32`, even // though we don't know yet what type 2 has and hence // can't pin this down to a specific impl. + let category = BinOpCategory::from(op.node); if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() - && is_builtin_binop(lhs_ty, rhs_ty, op.node) + && is_builtin_binop(lhs_ty, rhs_ty, category) { let builtin_return_ty = self.enforce_builtin_binop_types( lhs_expr.span, lhs_ty, rhs_expr.span, rhs_ty, - op.node, + category, ); self.demand_eqtype(expr.span, builtin_return_ty, return_ty); builtin_return_ty @@ -165,16 +161,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty: Ty<'tcx>, rhs_span: Span, rhs_ty: Ty<'tcx>, - op: hir::BinOpKind, + category: BinOpCategory, ) -> Ty<'tcx> { - debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op)); + debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, category)); // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. // (See https://github.com/rust-lang/rust/issues/57447.) let (lhs_ty, rhs_ty) = (deref_ty_if_possible(lhs_ty), deref_ty_if_possible(rhs_ty)); let tcx = self.tcx; - match BinOpCategory::from(op) { + match category { BinOpCategory::Shortcircuit => { self.demand_suptype(lhs_span, tcx.types.bool, lhs_ty); self.demand_suptype(rhs_span, tcx.types.bool, rhs_ty); @@ -205,17 +201,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, lhs_expr: &'tcx hir::Expr<'tcx>, rhs_expr: &'tcx hir::Expr<'tcx>, - op: hir::BinOp, - is_assign: IsAssign, + op: Op, expected: Expectation<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) { - debug!( - "check_overloaded_binop(expr.hir_id={}, op={:?}, is_assign={:?})", - expr.hir_id, op, is_assign - ); + debug!("check_overloaded_binop(expr.hir_id={}, op={:?})", expr.hir_id, op); - let lhs_ty = match is_assign { - IsAssign::No => { + let lhs_ty = match op { + Op::BinOp(_) => { // Find a suitable supertype of the LHS expression's type, by coercing to // a type variable, to pass as the `Self` to the trait, avoiding invariant // trait matching creating lifetime constraints that are too strict. @@ -225,7 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fresh_var = self.next_ty_var(lhs_expr.span); self.demand_coerce(lhs_expr, lhs_ty, fresh_var, Some(rhs_expr), AllowTwoPhase::No) } - IsAssign::Yes => { + Op::AssignOp(_) => { // rust-lang/rust#52126: We have to use strict // equivalence on the LHS of an assign-op like `+=`; // overwritten or mutably-borrowed places cannot be @@ -246,8 +238,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let result = self.lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty_var)), - lang_item_for_binop(self.tcx, op.node, is_assign), - op.span, + lang_item_for_binop(self.tcx, op), + op.span(), expected, ); @@ -257,15 +249,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_ty_var, Some(lhs_expr), |err, ty| { - self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr, op.node); + if let Op::BinOp(binop) = op + && binop.node == hir::BinOpKind::Eq + { + self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr); + } }, ); let rhs_ty = self.resolve_vars_with_obligations(rhs_ty); let return_ty = match result { Ok(method) => { - let by_ref_binop = !op.node.is_by_value(); - if is_assign == IsAssign::Yes || by_ref_binop { + let by_ref_binop = !op.is_by_value(); + if matches!(op, Op::AssignOp(_)) || by_ref_binop { if let ty::Ref(_, _, mutbl) = method.sig.inputs()[0].kind() { let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::Yes); let autoref = Adjustment { @@ -306,31 +302,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ty::new_misc_error(self.tcx) } Err(errors) => { - let (_, trait_def_id) = lang_item_for_binop(self.tcx, op.node, is_assign); + let (_, trait_def_id) = lang_item_for_binop(self.tcx, op); let missing_trait = trait_def_id .map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id))); let mut path = None; let lhs_ty_str = self.tcx.short_string(lhs_ty, &mut path); let rhs_ty_str = self.tcx.short_string(rhs_ty, &mut path); - let (mut err, output_def_id) = match is_assign { - IsAssign::Yes => { + let (mut err, output_def_id) = match op { + Op::AssignOp(assign_op) => { + let s = assign_op.node.as_str(); let mut err = struct_span_code_err!( self.dcx(), expr.span, E0368, - "binary assignment operation `{}=` cannot be applied to type `{}`", - op.node.as_str(), + "binary assignment operation `{}` cannot be applied to type `{}`", + s, lhs_ty_str, ); err.span_label( lhs_expr.span, - format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty_str), + format!("cannot use `{}` on type `{}`", s, lhs_ty_str), ); self.note_unmet_impls_on_type(&mut err, errors, false); (err, None) } - IsAssign::No => { - let message = match op.node { + Op::BinOp(bin_op) => { + let message = match bin_op.node { hir::BinOpKind::Add => { format!("cannot add `{rhs_ty_str}` to `{lhs_ty_str}`") } @@ -366,8 +363,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => format!( "binary operation `{}` cannot be applied to type `{}`", - op.node.as_str(), - lhs_ty_str, + bin_op.node.as_str(), + lhs_ty_str ), }; let output_def_id = trait_def_id.and_then(|def_id| { @@ -380,7 +377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .cloned() }); let mut err = - struct_span_code_err!(self.dcx(), op.span, E0369, "{message}"); + struct_span_code_err!(self.dcx(), bin_op.span, E0369, "{message}"); if !lhs_expr.span.eq(&rhs_expr.span) { err.span_label(lhs_expr.span, lhs_ty_str.clone()); err.span_label(rhs_expr.span, rhs_ty_str); @@ -413,19 +410,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_deref_ty), Some((rhs_expr, rhs_ty)), - lang_item_for_binop(self.tcx, op.node, is_assign), - op.span, + lang_item_for_binop(self.tcx, op), + op.span(), expected, ) .is_ok() { let msg = format!( - "`{}{}` can be used on `{}` if you dereference the left-hand side", - op.node.as_str(), - match is_assign { - IsAssign::Yes => "=", - IsAssign::No => "", - }, + "`{}` can be used on `{}` if you dereference the left-hand side", + op.as_str(), self.tcx.short_string(lhs_deref_ty, err.long_ty_path()), ); err.span_suggestion_verbose( @@ -447,15 +440,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_adjusted_ty), Some((rhs_expr, rhs_adjusted_ty)), - lang_item_for_binop(self.tcx, op.node, is_assign), - op.span, + lang_item_for_binop(self.tcx, op), + op.span(), expected, ) .is_ok() { let lhs = self.tcx.short_string(lhs_adjusted_ty, err.long_ty_path()); let rhs = self.tcx.short_string(rhs_adjusted_ty, err.long_ty_path()); - let op = op.node.as_str(); + let op = op.as_str(); err.note(format!("an implementation for `{lhs} {op} {rhs}` exists")); if let Some(lhs_new_mutbl) = lhs_new_mutbl @@ -505,8 +498,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty)), - lang_item_for_binop(self.tcx, op.node, is_assign), - op.span, + lang_item_for_binop(self.tcx, op), + op.span(), expected, ) .is_ok() @@ -518,13 +511,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We should suggest `a + b` => `*a + b` if `a` is copy, and suggest // `a += b` => `*a += b` if a is a mut ref. - if !op.span.can_be_used_for_suggestions() { + if !op.span().can_be_used_for_suggestions() { // Suppress suggestions when lhs and rhs are not in the same span as the error - } else if is_assign == IsAssign::Yes + } else if let Op::AssignOp(_) = op && let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) { suggest_deref_binop(&mut err, lhs_deref_ty); - } else if is_assign == IsAssign::No + } else if let Op::BinOp(_) = op && let ty::Ref(region, lhs_deref_ty, mutbl) = lhs_ty.kind() { if self.type_is_copy_modulo_regions(self.param_env, *lhs_deref_ty) { @@ -579,10 +572,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(missing_trait) = missing_trait { - if op.node == hir::BinOpKind::Add - && self.check_str_addition( - lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, is_assign, op, - ) + if matches!( + op, + Op::BinOp(Spanned { node: hir::BinOpKind::Add, .. }) + | Op::AssignOp(Spanned { node: hir::AssignOpKind::AddAssign, .. }) + ) && self + .check_str_addition(lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, op) { // This has nothing here because it means we did string // concatenation (e.g., "Hello " + "World!"). This means @@ -599,8 +594,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty)), - lang_item_for_binop(self.tcx, op.node, is_assign), - op.span, + lang_item_for_binop(self.tcx, op), + op.span(), expected, ) .unwrap_err(); @@ -650,9 +645,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Suggest using `add`, `offset` or `offset_from` for pointer - {integer}, // pointer + {integer} or pointer - pointer. - if op.span.can_be_used_for_suggestions() { - match op.node { - hir::BinOpKind::Add if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() => { + if op.span().can_be_used_for_suggestions() { + match op { + Op::BinOp(Spanned { node: hir::BinOpKind::Add, .. }) + if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() => + { err.multipart_suggestion( "consider using `wrapping_add` or `add` for pointer + {integer}", vec![ @@ -665,7 +662,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } - hir::BinOpKind::Sub => { + Op::BinOp(Spanned { node: hir::BinOpKind::Sub, .. }) => { if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() { err.multipart_suggestion( "consider using `wrapping_sub` or `sub` for \ @@ -721,8 +718,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>, err: &mut Diag<'_>, - is_assign: IsAssign, - op: hir::BinOp, + op: Op, ) -> bool { let str_concat_note = "string concatenation requires an owned `String` on the left"; let rm_borrow_msg = "remove the borrow to obtain an owned `String`"; @@ -741,8 +737,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { r_ty.kind(), ty::Ref(_, inner_ty, _) if *inner_ty.kind() == ty::Str )) => { - if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str` - err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings"); + if let Op::BinOp(_) = op { // Do not supply this message if `&str += &str` + err.span_label( + op.span(), + "`+` cannot be used to concatenate two `&str` strings" + ); err.note(str_concat_note); if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { err.span_suggestion_verbose( @@ -766,11 +765,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if (*l_ty.kind() == ty::Str || is_std_string(l_ty)) && is_std_string(rhs_ty) => { err.span_label( - op.span, + op.span(), "`+` cannot be used to concatenate a `&str` with a `String`", ); - match is_assign { - IsAssign::No => { + match op { + Op::BinOp(_) => { let sugg_msg; let lhs_sugg = if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { sugg_msg = "remove the borrow on the left and add one on the right"; @@ -789,7 +788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - IsAssign::Yes => { + Op::AssignOp(_) => { err.note(str_concat_note); } } @@ -991,37 +990,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -fn lang_item_for_binop( - tcx: TyCtxt<'_>, - op: hir::BinOpKind, - is_assign: IsAssign, -) -> (Symbol, Option) { +fn lang_item_for_binop(tcx: TyCtxt<'_>, op: Op) -> (Symbol, Option) { let lang = tcx.lang_items(); - if is_assign == IsAssign::Yes { - match op { - hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()), - hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()), - hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()), - hir::BinOpKind::Div => (sym::div_assign, lang.div_assign_trait()), - hir::BinOpKind::Rem => (sym::rem_assign, lang.rem_assign_trait()), - hir::BinOpKind::BitXor => (sym::bitxor_assign, lang.bitxor_assign_trait()), - hir::BinOpKind::BitAnd => (sym::bitand_assign, lang.bitand_assign_trait()), - hir::BinOpKind::BitOr => (sym::bitor_assign, lang.bitor_assign_trait()), - hir::BinOpKind::Shl => (sym::shl_assign, lang.shl_assign_trait()), - hir::BinOpKind::Shr => (sym::shr_assign, lang.shr_assign_trait()), - hir::BinOpKind::Lt - | hir::BinOpKind::Le - | hir::BinOpKind::Ge - | hir::BinOpKind::Gt - | hir::BinOpKind::Eq - | hir::BinOpKind::Ne - | hir::BinOpKind::And - | hir::BinOpKind::Or => { - bug!("impossible assignment operation: {}=", op.as_str()) - } - } - } else { - match op { + match op { + Op::AssignOp(op) => match op.node { + hir::AssignOpKind::AddAssign => (sym::add_assign, lang.add_assign_trait()), + hir::AssignOpKind::SubAssign => (sym::sub_assign, lang.sub_assign_trait()), + hir::AssignOpKind::MulAssign => (sym::mul_assign, lang.mul_assign_trait()), + hir::AssignOpKind::DivAssign => (sym::div_assign, lang.div_assign_trait()), + hir::AssignOpKind::RemAssign => (sym::rem_assign, lang.rem_assign_trait()), + hir::AssignOpKind::BitXorAssign => (sym::bitxor_assign, lang.bitxor_assign_trait()), + hir::AssignOpKind::BitAndAssign => (sym::bitand_assign, lang.bitand_assign_trait()), + hir::AssignOpKind::BitOrAssign => (sym::bitor_assign, lang.bitor_assign_trait()), + hir::AssignOpKind::ShlAssign => (sym::shl_assign, lang.shl_assign_trait()), + hir::AssignOpKind::ShrAssign => (sym::shr_assign, lang.shr_assign_trait()), + }, + Op::BinOp(op) => match op.node { hir::BinOpKind::Add => (sym::add, lang.add_trait()), hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()), hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()), @@ -1041,7 +1025,7 @@ fn lang_item_for_binop( hir::BinOpKind::And | hir::BinOpKind::Or => { bug!("&& and || are not overloadable") } - } + }, } } @@ -1056,6 +1040,7 @@ fn lang_item_for_unop(tcx: TyCtxt<'_>, op: hir::UnOp) -> (Symbol, Option for BinOpCategory { fn from(op: hir::BinOpKind) -> BinOpCategory { + use hir::BinOpKind::*; match op { - hir::BinOpKind::Shl | hir::BinOpKind::Shr => BinOpCategory::Shift, - - hir::BinOpKind::Add - | hir::BinOpKind::Sub - | hir::BinOpKind::Mul - | hir::BinOpKind::Div - | hir::BinOpKind::Rem => BinOpCategory::Math, - - hir::BinOpKind::BitXor | hir::BinOpKind::BitAnd | hir::BinOpKind::BitOr => { - BinOpCategory::Bitwise - } - - hir::BinOpKind::Eq - | hir::BinOpKind::Ne - | hir::BinOpKind::Lt - | hir::BinOpKind::Le - | hir::BinOpKind::Ge - | hir::BinOpKind::Gt => BinOpCategory::Comparison, - - hir::BinOpKind::And | hir::BinOpKind::Or => BinOpCategory::Shortcircuit, + Shl | Shr => BinOpCategory::Shift, + Add | Sub | Mul | Div | Rem => BinOpCategory::Math, + BitXor | BitAnd | BitOr => BinOpCategory::Bitwise, + Eq | Ne | Lt | Le | Ge | Gt => BinOpCategory::Comparison, + And | Or => BinOpCategory::Shortcircuit, } } } -/// Whether the binary operation is an assignment (`a += b`), or not (`a + b`) +impl From for BinOpCategory { + fn from(op: hir::AssignOpKind) -> BinOpCategory { + use hir::AssignOpKind::*; + match op { + ShlAssign | ShrAssign => BinOpCategory::Shift, + AddAssign | SubAssign | MulAssign | DivAssign | RemAssign => BinOpCategory::Math, + BitXorAssign | BitAndAssign | BitOrAssign => BinOpCategory::Bitwise, + } + } +} + +/// An assignment op (e.g. `a += b`), or a binary op (e.g. `a + b`). #[derive(Clone, Copy, Debug, PartialEq)] -enum IsAssign { - No, - Yes, +enum Op { + BinOp(hir::BinOp), + AssignOp(hir::AssignOp), +} + +impl Op { + fn span(&self) -> Span { + match self { + Op::BinOp(op) => op.span, + Op::AssignOp(op) => op.span, + } + } + + fn as_str(&self) -> &'static str { + match self { + Op::BinOp(op) => op.node.as_str(), + Op::AssignOp(op) => op.node.as_str(), + } + } + + fn is_by_value(&self) -> bool { + match self { + Op::BinOp(op) => op.node.is_by_value(), + Op::AssignOp(op) => op.node.is_by_value(), + } + } } /// Dereferences a single level of immutable referencing. @@ -1135,27 +1140,24 @@ fn deref_ty_if_possible(ty: Ty<'_>) -> Ty<'_> { /// Reason #2 is the killer. I tried for a while to always use /// overloaded logic and just check the types in constants/codegen after /// the fact, and it worked fine, except for SIMD types. -nmatsakis -fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOpKind) -> bool { +fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, category: BinOpCategory) -> bool { // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. // (See https://github.com/rust-lang/rust/issues/57447.) let (lhs, rhs) = (deref_ty_if_possible(lhs), deref_ty_if_possible(rhs)); - match BinOpCategory::from(op) { + match category.into() { BinOpCategory::Shortcircuit => true, - BinOpCategory::Shift => { lhs.references_error() || rhs.references_error() || lhs.is_integral() && rhs.is_integral() } - BinOpCategory::Math => { lhs.references_error() || rhs.references_error() || lhs.is_integral() && rhs.is_integral() || lhs.is_floating_point() && rhs.is_floating_point() } - BinOpCategory::Bitwise => { lhs.references_error() || rhs.references_error() @@ -1163,7 +1165,6 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOpKind) -> b || lhs.is_floating_point() && rhs.is_floating_point() || lhs.is_bool() && rhs.is_bool() } - BinOpCategory::Comparison => { lhs.references_error() || rhs.references_error() || lhs.is_scalar() && rhs.is_scalar() } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index d457133c703f..06f82b361b0d 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -160,7 +160,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.typeck_results.node_args_mut().remove(e.hir_id); } } - hir::ExprKind::Binary(ref op, lhs, rhs) | hir::ExprKind::AssignOp(ref op, lhs, rhs) => { + hir::ExprKind::Binary(ref op, lhs, rhs) => { let lhs_ty = self.typeck_results.node_type(lhs.hir_id); let rhs_ty = self.typeck_results.node_type(rhs.hir_id); @@ -168,25 +168,27 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.typeck_results.type_dependent_defs_mut().remove(e.hir_id); self.typeck_results.node_args_mut().remove(e.hir_id); - match e.kind { - hir::ExprKind::Binary(..) => { - if !op.node.is_by_value() { - let mut adjustments = self.typeck_results.adjustments_mut(); - if let Some(a) = adjustments.get_mut(lhs.hir_id) { - a.pop(); - } - if let Some(a) = adjustments.get_mut(rhs.hir_id) { - a.pop(); - } - } - } - hir::ExprKind::AssignOp(..) - if let Some(a) = - self.typeck_results.adjustments_mut().get_mut(lhs.hir_id) => - { + if !op.node.is_by_value() { + let mut adjustments = self.typeck_results.adjustments_mut(); + if let Some(a) = adjustments.get_mut(lhs.hir_id) { a.pop(); } - _ => {} + if let Some(a) = adjustments.get_mut(rhs.hir_id) { + a.pop(); + } + } + } + } + hir::ExprKind::AssignOp(_, lhs, rhs) => { + let lhs_ty = self.typeck_results.node_type(lhs.hir_id); + let rhs_ty = self.typeck_results.node_type(rhs.hir_id); + + if lhs_ty.is_scalar() && rhs_ty.is_scalar() { + self.typeck_results.type_dependent_defs_mut().remove(e.hir_id); + self.typeck_results.node_args_mut().remove(e.hir_id); + + if let Some(a) = self.typeck_results.adjustments_mut().get_mut(lhs.hir_id) { + a.pop(); } } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 6d6e6a1f185b..707c8d04d557 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1668,6 +1668,42 @@ pub enum BinOp { Offset, } +// Assignment operators, e.g. `+=`. See comments on the corresponding variants +// in `BinOp` for details. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +pub enum AssignOp { + AddAssign, + SubAssign, + MulAssign, + DivAssign, + RemAssign, + BitXorAssign, + BitAndAssign, + BitOrAssign, + ShlAssign, + ShrAssign, +} + +// Sometimes `BinOp` and `AssignOp` need the same treatment. The operations +// covered by `AssignOp` are a subset of those covered by `BinOp`, so it makes +// sense to convert `AssignOp` to `BinOp`. +impl From for BinOp { + fn from(op: AssignOp) -> BinOp { + match op { + AssignOp::AddAssign => BinOp::Add, + AssignOp::SubAssign => BinOp::Sub, + AssignOp::MulAssign => BinOp::Mul, + AssignOp::DivAssign => BinOp::Div, + AssignOp::RemAssign => BinOp::Rem, + AssignOp::BitXorAssign => BinOp::BitXor, + AssignOp::BitAndAssign => BinOp::BitAnd, + AssignOp::BitOrAssign => BinOp::BitOr, + AssignOp::ShlAssign => BinOp::Shl, + AssignOp::ShrAssign => BinOp::Shr, + } + } +} + // Some nodes are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 6783bbf8bf42..8d373cb3b309 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -27,7 +27,7 @@ use tracing::instrument; use crate::middle::region; use crate::mir::interpret::AllocId; -use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; +use crate::mir::{self, AssignOp, BinOp, BorrowKind, FakeReadCause, UnOp}; use crate::thir::visit::for_each_immediate_subpat; use crate::ty::adjustment::PointerCoercion; use crate::ty::layout::IntegerExt; @@ -403,7 +403,7 @@ pub enum ExprKind<'tcx> { }, /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`. AssignOp { - op: BinOp, + op: AssignOp, lhs: ExprId, rhs: ExprId, }, diff --git a/compiler/rustc_mir_build/src/builder/expr/stmt.rs b/compiler/rustc_mir_build/src/builder/expr/stmt.rs index 7f8a0a34c312..2dff26f02f3a 100644 --- a/compiler/rustc_mir_build/src/builder/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/builder/expr/stmt.rs @@ -78,8 +78,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // because AssignOp is only legal for Copy types // (overloaded ops should be desugared into a call). let result = unpack!( - block = - this.build_binary_op(block, op, expr_span, lhs_ty, Operand::Copy(lhs), rhs) + block = this.build_binary_op( + block, + op.into(), + expr_span, + lhs_ty, + Operand::Copy(lhs), + rhs + ) ); this.cfg.push_assign(block, source_info, lhs, result); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index b8af77245f25..31e22e69111b 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -9,7 +9,7 @@ use rustc_middle::hir::place::{ Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind, }; use rustc_middle::middle::region; -use rustc_middle::mir::{self, BinOp, BorrowKind, UnOp}; +use rustc_middle::mir::{self, AssignOp, BinOp, BorrowKind, UnOp}; use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion, @@ -489,7 +489,7 @@ impl<'tcx> ThirBuildCx<'tcx> { self.overloaded_operator(expr, Box::new([lhs, rhs])) } else { ExprKind::AssignOp { - op: bin_op(op.node), + op: assign_op(op.node), lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs), } @@ -1347,3 +1347,18 @@ fn bin_op(op: hir::BinOpKind) -> BinOp { _ => bug!("no equivalent for ast binop {:?}", op), } } + +fn assign_op(op: hir::AssignOpKind) -> AssignOp { + match op { + hir::AssignOpKind::AddAssign => AssignOp::AddAssign, + hir::AssignOpKind::SubAssign => AssignOp::SubAssign, + hir::AssignOpKind::MulAssign => AssignOp::MulAssign, + hir::AssignOpKind::DivAssign => AssignOp::DivAssign, + hir::AssignOpKind::RemAssign => AssignOp::RemAssign, + hir::AssignOpKind::BitXorAssign => AssignOp::BitXorAssign, + hir::AssignOpKind::BitAndAssign => AssignOp::BitAndAssign, + hir::AssignOpKind::BitOrAssign => AssignOp::BitOrAssign, + hir::AssignOpKind::ShlAssign => AssignOp::ShlAssign, + hir::AssignOpKind::ShrAssign => AssignOp::ShrAssign, + } +} diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e1e6b93abf35..841d967d934b 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -14,10 +14,10 @@ use rustc_ast::util::classify; use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par}; use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::{ - self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, - ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall, - MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, - YieldKind, + self as ast, AnonConst, Arm, AssignOp, AssignOpKind, AttrStyle, AttrVec, BinOp, BinOpKind, + BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, + FnRetTy, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, + UnOp, UnsafeBinderCastKind, YieldKind, }; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; @@ -359,7 +359,7 @@ impl<'a> Parser<'a> { ( Some( AssocOp::Binary(BinOpKind::Shr | BinOpKind::Gt | BinOpKind::Ge) - | AssocOp::AssignOp(BinOpKind::Shr), + | AssocOp::AssignOp(AssignOpKind::ShrAssign), ), _, ) if self.restrictions.contains(Restrictions::CONST_EXPR) => { @@ -3914,8 +3914,8 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::LeftArrowOperator { span }); } - fn mk_assign_op(&self, binop: BinOp, lhs: P, rhs: P) -> ExprKind { - ExprKind::AssignOp(binop, lhs, rhs) + fn mk_assign_op(&self, assign_op: AssignOp, lhs: P, rhs: P) -> ExprKind { + ExprKind::AssignOp(assign_op, lhs, rhs) } fn mk_range( diff --git a/src/tools/clippy/clippy_lints/src/format_push_string.rs b/src/tools/clippy/clippy_lints/src/format_push_string.rs index 68cc50f39391..b64d608c0c70 100644 --- a/src/tools/clippy/clippy_lints/src/format_push_string.rs +++ b/src/tools/clippy/clippy_lints/src/format_push_string.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher; use clippy_utils::ty::is_type_lang_item; -use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource}; +use rustc_hir::{AssignOpKind, Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString { return; } }, - ExprKind::AssignOp(op, left, arg) if op.node == BinOpKind::Add && is_string(cx, left) => arg, + ExprKind::AssignOp(op, left, arg) if op.node == AssignOpKind::AddAssign && is_string(cx, left) => arg, _ => return, }; if is_format(cx, arg) { diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs index 41d2b18803d9..185fc2aa2d4a 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs @@ -5,7 +5,7 @@ use clippy_utils::source::snippet_with_context; use rustc_ast::ast::{LitIntType, LitKind}; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind}; +use rustc_hir::{AssignOpKind, BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{IntTy, Ty, UintTy}; use rustc_session::declare_lint_pass; @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd { && ex.span.ctxt() == ctxt && expr1.span.ctxt() == ctxt && clippy_utils::SpanlessEq::new(cx).eq_expr(l, target) - && BinOpKind::Add == op1.node + && AssignOpKind::AddAssign == op1.node && let ExprKind::Lit(lit) = value.kind && let LitKind::Int(Pu128(1), LitIntType::Unsuffixed) = lit.node && block.expr.is_none() diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index cbc3e2ccd5b8..5d7d3ae3f24b 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -8,7 +8,7 @@ use clippy_utils::{ use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath}; +use rustc_hir::{AssignOpKind, BinOp, BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -366,7 +366,7 @@ fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a Exp match peel_blocks_with_stmt(expr).kind { ExprKind::AssignOp(ref op1, target, value) => { // Check if literal being subtracted is one - (BinOpKind::Sub == op1.node && is_integer_literal(value, 1)).then_some(target) + (AssignOpKind::SubAssign == op1.node && is_integer_literal(value, 1)).then_some(target) }, ExprKind::Assign(target, value, _) => { if let ExprKind::Binary(ref op1, left1, right1) = value.kind diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index a5185d38e7c3..3c6fbef2bda8 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -3,7 +3,9 @@ use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_loc use rustc_ast::ast::{LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_expr, walk_local}; -use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, LetStmt, Mutability, PatKind}; +use rustc_hir::{ + AssignOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, LetStmt, Mutability, PatKind +}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty}; @@ -58,7 +60,7 @@ impl<'tcx> Visitor<'tcx> for IncrementVisitor<'_, 'tcx> { match parent.kind { ExprKind::AssignOp(op, lhs, rhs) => { if lhs.hir_id == expr.hir_id { - *state = if op.node == BinOpKind::Add + *state = if op.node == AssignOpKind::AddAssign && is_integer_const(self.cx, rhs, 1) && *state == IncrementVisitorVarState::Initial && self.depth == 0 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 be728e6c8b74..fbd287f52854 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 @@ -261,10 +261,11 @@ fn check_expr<'tcx>(vis: &mut ReadVisitor<'_, 'tcx>, expr: &'tcx Expr<'_>) -> St | ExprKind::Assign(..) | ExprKind::Index(..) | ExprKind::Repeat(_, _) - | ExprKind::Struct(_, _, _) => { + | ExprKind::Struct(_, _, _) + | ExprKind::AssignOp(_, _, _) => { walk_expr(vis, expr); }, - ExprKind::Binary(op, _, _) | ExprKind::AssignOp(op, _, _) => { + ExprKind::Binary(op, _, _) => { if op.node == BinOpKind::And || op.node == BinOpKind::Or { // x && y and x || y always evaluate x first, so these are // strictly sequenced. diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index 08fcd17e5555..a78a342d4fe3 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -335,9 +335,12 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects { return; } match &expr.kind { - hir::ExprKind::AssignOp(op, lhs, rhs) | hir::ExprKind::Binary(op, lhs, rhs) => { + hir::ExprKind::Binary(op, lhs, rhs) => { self.manage_bin_ops(cx, expr, op.node, lhs, rhs); }, + hir::ExprKind::AssignOp(op, lhs, rhs) => { + self.manage_bin_ops(cx, expr, op.node.into(), lhs, rhs); + }, hir::ExprKind::MethodCall(ps, receiver, args, _) => { self.manage_method_call(args, cx, expr, ps, receiver); }, diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index f758d08d3663..d32c062cf56a 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -913,9 +913,10 @@ impl<'tcx> LateLintPass<'tcx> for Operators { ); }, ExprKind::AssignOp(op, lhs, rhs) => { - self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs); - misrefactored_assign_op::check(cx, e, op.node, lhs, rhs); - modulo_arithmetic::check(cx, e, op.node, lhs, rhs, false); + let bin_op = op.node.into(); + self.arithmetic_context.check_binary(cx, e, bin_op, lhs, rhs); + misrefactored_assign_op::check(cx, e, bin_op, lhs, rhs); + modulo_arithmetic::check(cx, e, bin_op, lhs, rhs, false); }, ExprKind::Assign(lhs, rhs, _) => { assign_op_pattern::check(cx, e, lhs, rhs); diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs index fb426e91bf01..56bd8fefdb45 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs @@ -5,6 +5,7 @@ use core::ops::ControlFlow; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does @@ -56,8 +57,27 @@ declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind - && let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node) + match expr.kind { + hir::ExprKind::Binary(op, _, _) => { + self.check_expr_inner(cx, expr, op.node, op.span); + } + hir::ExprKind::AssignOp(op, _, _) => { + self.check_expr_inner(cx, expr, op.node.into(), op.span); + } + _ => {} + } + } +} + +impl<'tcx> SuspiciousImpl { + fn check_expr_inner( + &mut self, + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + binop: hir::BinOpKind, + span: Span, + ) { + if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop) && let Some(binop_trait_id) = cx.tcx.lang_items().get(binop_trait_lang) && let Some(op_assign_trait_id) = cx.tcx.lang_items().get(op_assign_trait_lang) @@ -82,10 +102,10 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { span_lint( cx, lint, - binop.span, + span, format!( "suspicious use of `{}` in `{}` impl", - binop.node.as_str(), + binop.as_str(), cx.tcx.item_name(trait_id) ), ); diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index 7176d533b616..0337b74b4b12 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -10,7 +10,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, LetStmt, PatKind, QPath, Stmt, StmtKind}; +use rustc_hir::{AssignOpKind, Block, Expr, ExprKind, LetStmt, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; use rustc_session::declare_lint_pass; @@ -307,7 +307,7 @@ fn extract_sides_of_xor_assign<'a, 'hir>( if let StmtKind::Semi(expr) = stmt.kind && let ExprKind::AssignOp( Spanned { - node: BinOpKind::BitXor, + node: AssignOpKind::BitXorAssign, .. }, lhs, diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 065d48119a24..e92c0c79b255 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -357,7 +357,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { match op { AssocOp::Binary(op) => format!("{lhs} {} {rhs}", op.as_str()), AssocOp::Assign => format!("{lhs} = {rhs}"), - AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()), + AssocOp::AssignOp(op) => format!("{lhs} {} {rhs}", op.as_str()), AssocOp::Cast => format!("{lhs} as {rhs}"), AssocOp::Range(limits) => format!("{lhs}{}{rhs}", limits.as_str()), } diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 65120770edd6..be6b483bfff1 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -2058,7 +2058,7 @@ fn rewrite_assignment( context: &RewriteContext<'_>, lhs: &ast::Expr, rhs: &ast::Expr, - op: Option<&ast::BinOp>, + op: Option<&ast::AssignOp>, shape: Shape, ) -> RewriteResult { let operator_str = match op { From 60b742d832b08d63e9c2bae0989c13e32ae4e73c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Apr 2025 23:35:03 +0000 Subject: [PATCH 094/176] Monomorphize region resolver --- compiler/rustc_type_ir/src/fold.rs | 53 +++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 0bc8b94bbf4c..e58f25f4ce78 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -54,7 +54,7 @@ use tracing::{debug, instrument}; use crate::inherent::*; use crate::visit::{TypeVisitable, TypeVisitableExt as _}; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, TypeFlags}; #[cfg(feature = "nightly")] type Never = !; @@ -438,12 +438,12 @@ where pub fn fold_regions( cx: I, value: T, - mut f: impl FnMut(I::Region, ty::DebruijnIndex) -> I::Region, + f: impl FnMut(I::Region, ty::DebruijnIndex) -> I::Region, ) -> T where T: TypeFoldable, { - value.fold_with(&mut RegionFolder::new(cx, &mut f)) + value.fold_with(&mut RegionFolder::new(cx, f)) } /// Folds over the substructure of a type, visiting its component @@ -453,7 +453,7 @@ where /// new bound regions which are not visited by this visitors as /// they are not free; only regions that occur free will be /// visited by `fld_r`. -pub struct RegionFolder<'a, I: Interner> { +pub struct RegionFolder { cx: I, /// Stores the index of a binder *just outside* the stuff we have @@ -464,20 +464,21 @@ pub struct RegionFolder<'a, I: Interner> { /// Callback invokes for each free region. The `DebruijnIndex` /// points to the binder *just outside* the ones we have passed /// through. - fold_region_fn: &'a mut (dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region + 'a), + fold_region_fn: F, } -impl<'a, I: Interner> RegionFolder<'a, I> { +impl RegionFolder { #[inline] - pub fn new( - cx: I, - fold_region_fn: &'a mut dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region, - ) -> RegionFolder<'a, I> { + pub fn new(cx: I, fold_region_fn: F) -> RegionFolder { RegionFolder { cx, current_index: ty::INNERMOST, fold_region_fn } } } -impl<'a, I: Interner> TypeFolder for RegionFolder<'a, I> { +impl TypeFolder for RegionFolder +where + I: Interner, + F: FnMut(I::Region, ty::DebruijnIndex) -> I::Region, +{ fn cx(&self) -> I { self.cx } @@ -502,4 +503,34 @@ impl<'a, I: Interner> TypeFolder for RegionFolder<'a, I> { } } } + + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + if t.has_type_flags( + TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_RE_BOUND | TypeFlags::HAS_RE_ERASED, + ) { + t.super_fold_with(self) + } else { + t + } + } + + fn fold_const(&mut self, ct: I::Const) -> I::Const { + if ct.has_type_flags( + TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_RE_BOUND | TypeFlags::HAS_RE_ERASED, + ) { + ct.super_fold_with(self) + } else { + ct + } + } + + fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { + if p.has_type_flags( + TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_RE_BOUND | TypeFlags::HAS_RE_ERASED, + ) { + p.super_fold_with(self) + } else { + p + } + } } From 842da5c1ae4225b39958912e136ee6e708f3c6c6 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 3 Apr 2025 01:43:06 +0200 Subject: [PATCH 095/176] structure the message --- compiler/rustc_session/src/config.rs | 10 ++++++---- tests/ui/errors/wrong-target-spec.stderr | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 3e2579b3f1dc..120fabf37351 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1423,10 +1423,12 @@ pub fn build_target_config( } target } - Err(e) => early_dcx.early_fatal(format!( - "error loading target specification: {e}; \ - run `rustc --print target-list` for a list of built-in targets" - )), + Err(e) => { + let mut err = + early_dcx.early_struct_fatal(format!("error loading target specification: {e}")); + err.help("run `rustc --print target-list` for a list of built-in targets"); + err.emit(); + } } } diff --git a/tests/ui/errors/wrong-target-spec.stderr b/tests/ui/errors/wrong-target-spec.stderr index 35850a4adf22..98b03ae00cb3 100644 --- a/tests/ui/errors/wrong-target-spec.stderr +++ b/tests/ui/errors/wrong-target-spec.stderr @@ -1,2 +1,4 @@ -error: error loading target specification: could not find specification for target "x86_64_unknown-linux-musl"; run `rustc --print target-list` for a list of built-in targets +error: error loading target specification: could not find specification for target "x86_64_unknown-linux-musl" + | + = help: run `rustc --print target-list` for a list of built-in targets From 9434486312b33633d265b19804c3e9b76535527c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Apr 2025 23:38:27 +0000 Subject: [PATCH 096/176] Micro-optimize RegionEraserVisitor --- compiler/rustc_middle/src/ty/erase_regions.rs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index f25c48cf42ab..8bddb5c0fd77 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -44,7 +44,13 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.has_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) } + if !ty.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) { + ty + } else if ty.has_infer() { + ty.super_fold_with(self) + } else { + self.tcx.erase_regions_ty(ty) + } } fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> @@ -64,4 +70,20 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { _ => self.tcx.lifetimes.re_erased, } } + + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + if ct.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) { + ct.super_fold_with(self) + } else { + ct + } + } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if p.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) { + p.super_fold_with(self) + } else { + p + } + } } From 62fcb9d585723f0ab6646ba0e7dbaa72867bf8a8 Mon Sep 17 00:00:00 2001 From: beetrees Date: Thu, 3 Apr 2025 01:08:41 +0100 Subject: [PATCH 097/176] Fix the `f16`/`f128` feature gate on integer literals --- compiler/rustc_ast_passes/src/feature_gate.rs | 22 ++++++++++--------- .../feature-gate-f128.e2015.stderr | 16 +++++++++++--- .../feature-gate-f128.e2018.stderr | 16 +++++++++++--- tests/ui/feature-gates/feature-gate-f128.rs | 1 + .../feature-gate-f16.e2015.stderr | 16 +++++++++++--- .../feature-gate-f16.e2018.stderr | 16 +++++++++++--- tests/ui/feature-gates/feature-gate-f16.rs | 1 + 7 files changed, 66 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index ea60e083c4ce..5745a52df71b 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -332,17 +332,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ExprKind::TryBlock(_) => { gate!(&self, try_blocks, e.span, "`try` expression is experimental"); } - ast::ExprKind::Lit(token::Lit { kind: token::LitKind::Float, suffix, .. }) => { - match suffix { - Some(sym::f16) => { - gate!(&self, f16, e.span, "the type `f16` is unstable") - } - Some(sym::f128) => { - gate!(&self, f128, e.span, "the type `f128` is unstable") - } - _ => (), + ast::ExprKind::Lit(token::Lit { + kind: token::LitKind::Float | token::LitKind::Integer, + suffix, + .. + }) => match suffix { + Some(sym::f16) => { + gate!(&self, f16, e.span, "the type `f16` is unstable") } - } + Some(sym::f128) => { + gate!(&self, f128, e.span, "the type `f128` is unstable") + } + _ => (), + }, _ => {} } visit::walk_expr(self, e) diff --git a/tests/ui/feature-gates/feature-gate-f128.e2015.stderr b/tests/ui/feature-gates/feature-gate-f128.e2015.stderr index 771aee79dce1..7e8ea5e948dc 100644 --- a/tests/ui/feature-gates/feature-gate-f128.e2015.stderr +++ b/tests/ui/feature-gates/feature-gate-f128.e2015.stderr @@ -19,7 +19,7 @@ LL | let a: f128 = 100.0; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f128` is unstable - --> $DIR/feature-gate-f128.rs:15:11 + --> $DIR/feature-gate-f128.rs:16:11 | LL | fn foo(a: f128) {} | ^^^^ @@ -29,7 +29,7 @@ LL | fn foo(a: f128) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f128` is unstable - --> $DIR/feature-gate-f128.rs:18:8 + --> $DIR/feature-gate-f128.rs:19:8 | LL | a: f128, | ^^^^ @@ -48,6 +48,16 @@ LL | let b = 0.0f128; = help: add `#![feature(f128)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error[E0658]: the type `f128` is unstable + --> $DIR/feature-gate-f128.rs:12:13 + | +LL | let c = 0f128; + | ^^^^^ + | + = note: see issue #116909 for more information + = help: add `#![feature(f128)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f128.e2018.stderr b/tests/ui/feature-gates/feature-gate-f128.e2018.stderr index 771aee79dce1..7e8ea5e948dc 100644 --- a/tests/ui/feature-gates/feature-gate-f128.e2018.stderr +++ b/tests/ui/feature-gates/feature-gate-f128.e2018.stderr @@ -19,7 +19,7 @@ LL | let a: f128 = 100.0; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f128` is unstable - --> $DIR/feature-gate-f128.rs:15:11 + --> $DIR/feature-gate-f128.rs:16:11 | LL | fn foo(a: f128) {} | ^^^^ @@ -29,7 +29,7 @@ LL | fn foo(a: f128) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f128` is unstable - --> $DIR/feature-gate-f128.rs:18:8 + --> $DIR/feature-gate-f128.rs:19:8 | LL | a: f128, | ^^^^ @@ -48,6 +48,16 @@ LL | let b = 0.0f128; = help: add `#![feature(f128)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error[E0658]: the type `f128` is unstable + --> $DIR/feature-gate-f128.rs:12:13 + | +LL | let c = 0f128; + | ^^^^^ + | + = note: see issue #116909 for more information + = help: add `#![feature(f128)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f128.rs b/tests/ui/feature-gates/feature-gate-f128.rs index d25b6dde4ee4..dcbe60e934ae 100644 --- a/tests/ui/feature-gates/feature-gate-f128.rs +++ b/tests/ui/feature-gates/feature-gate-f128.rs @@ -9,6 +9,7 @@ const A: f128 = 10.0; //~ ERROR the type `f128` is unstable pub fn main() { let a: f128 = 100.0; //~ ERROR the type `f128` is unstable let b = 0.0f128; //~ ERROR the type `f128` is unstable + let c = 0f128; //~ ERROR the type `f128` is unstable foo(1.23); } diff --git a/tests/ui/feature-gates/feature-gate-f16.e2015.stderr b/tests/ui/feature-gates/feature-gate-f16.e2015.stderr index 2bb3b59465a0..5d1ca8f6d047 100644 --- a/tests/ui/feature-gates/feature-gate-f16.e2015.stderr +++ b/tests/ui/feature-gates/feature-gate-f16.e2015.stderr @@ -19,7 +19,7 @@ LL | let a: f16 = 100.0; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f16` is unstable - --> $DIR/feature-gate-f16.rs:15:11 + --> $DIR/feature-gate-f16.rs:16:11 | LL | fn foo(a: f16) {} | ^^^ @@ -29,7 +29,7 @@ LL | fn foo(a: f16) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f16` is unstable - --> $DIR/feature-gate-f16.rs:18:8 + --> $DIR/feature-gate-f16.rs:19:8 | LL | a: f16, | ^^^ @@ -48,6 +48,16 @@ LL | let b = 0.0f16; = help: add `#![feature(f16)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error[E0658]: the type `f16` is unstable + --> $DIR/feature-gate-f16.rs:12:13 + | +LL | let c = 0f16; + | ^^^^ + | + = note: see issue #116909 for more information + = help: add `#![feature(f16)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f16.e2018.stderr b/tests/ui/feature-gates/feature-gate-f16.e2018.stderr index 2bb3b59465a0..5d1ca8f6d047 100644 --- a/tests/ui/feature-gates/feature-gate-f16.e2018.stderr +++ b/tests/ui/feature-gates/feature-gate-f16.e2018.stderr @@ -19,7 +19,7 @@ LL | let a: f16 = 100.0; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f16` is unstable - --> $DIR/feature-gate-f16.rs:15:11 + --> $DIR/feature-gate-f16.rs:16:11 | LL | fn foo(a: f16) {} | ^^^ @@ -29,7 +29,7 @@ LL | fn foo(a: f16) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f16` is unstable - --> $DIR/feature-gate-f16.rs:18:8 + --> $DIR/feature-gate-f16.rs:19:8 | LL | a: f16, | ^^^ @@ -48,6 +48,16 @@ LL | let b = 0.0f16; = help: add `#![feature(f16)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error[E0658]: the type `f16` is unstable + --> $DIR/feature-gate-f16.rs:12:13 + | +LL | let c = 0f16; + | ^^^^ + | + = note: see issue #116909 for more information + = help: add `#![feature(f16)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f16.rs b/tests/ui/feature-gates/feature-gate-f16.rs index af906d71f5fe..f748c603efe9 100644 --- a/tests/ui/feature-gates/feature-gate-f16.rs +++ b/tests/ui/feature-gates/feature-gate-f16.rs @@ -9,6 +9,7 @@ const A: f16 = 10.0; //~ ERROR the type `f16` is unstable pub fn main() { let a: f16 = 100.0; //~ ERROR the type `f16` is unstable let b = 0.0f16; //~ ERROR the type `f16` is unstable + let c = 0f16; //~ ERROR the type `f16` is unstable foo(1.23); } From 0d8c33f6f14c2a2e0ce03d82b313006e84b7a9c2 Mon Sep 17 00:00:00 2001 From: Jake Wharton Date: Wed, 2 Apr 2025 23:03:55 -0400 Subject: [PATCH 098/176] Remove creation of duplicate AnonPipe The File is unwrapped to a Handle into an AnonPipe, and then that AnonPipe was unwrapped to a Handle into another AnonPipe. The second operation is entirely redundant. --- library/std/src/sys/pal/windows/pipe.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs index c78524649226..7fd623396195 100644 --- a/library/std/src/sys/pal/windows/pipe.rs +++ b/library/std/src/sys/pal/windows/pipe.rs @@ -143,7 +143,6 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res }; opts.security_attributes(&mut sa); let theirs = File::open(Path::new(&name), &opts)?; - let theirs = AnonPipe { inner: theirs.into_inner() }; Ok(Pipes { ours: AnonPipe { inner: ours }, From 4d649906900cd833b0680f53b8c197b087711a4a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 29 Mar 2025 02:41:32 +0300 Subject: [PATCH 099/176] compiletest: Require `//~` annotations even if `error-pattern` is specified --- src/doc/rustc-dev-guide/src/tests/ui.md | 3 ++ src/tools/compiletest/src/runtest/ui.rs | 16 ++++------ tests/rustdoc-ui/doctest/no-run-flag-error.rs | 3 +- tests/rustdoc-ui/invalid-theme-name.rs | 3 +- tests/rustdoc-ui/issues/issue-91713.rs | 3 +- .../lints/no-crate-level-doc-lint.rs | 3 +- .../lints/no-crate-level-doc-lint.stderr | 2 +- tests/rustdoc-ui/track-diagnostics.rs | 2 +- .../ui-fulldeps/missing-rustc-driver-error.rs | 2 +- tests/ui/abi/fixed_x18.rs | 2 ++ .../shadow-call-stack-without-fixed-x18.rs | 3 +- tests/ui/allocator/two-allocators2.rs | 3 +- tests/ui/allocator/two-allocators3.rs | 4 +-- tests/ui/amdgpu-require-explicit-cpu.rs | 3 +- tests/ui/associated-types/issue-36499.rs | 2 +- tests/ui/attributes/attr-bad-crate-attr.rs | 3 +- .../ui/attributes/attr-bad-crate-attr.stderr | 2 +- tests/ui/attributes/z-crate-attr/garbage.rs | 5 +++- tests/ui/attributes/z-crate-attr/injection.rs | 4 ++- .../ui/attributes/z-crate-attr/inner-attr.rs | 3 +- tests/ui/attributes/z-crate-attr/multiple.rs | 4 ++- .../z-crate-attr/unbalanced-paren.rs | 4 ++- tests/ui/binop/binop-bitxor-str.rs | 3 +- tests/ui/binop/binop-bitxor-str.stderr | 2 +- tests/ui/binop/binop-mul-bool.rs | 4 +-- tests/ui/binop/binop-mul-bool.stderr | 2 +- tests/ui/c-variadic/issue-86053-1.rs | 14 ++++++--- tests/ui/c-variadic/issue-86053-1.stderr | 8 ++--- tests/ui/capture1.rs | 4 +-- tests/ui/capture1.stderr | 2 +- tests/ui/cast/cast-from-nil.rs | 3 +- tests/ui/cast/cast-from-nil.stderr | 2 +- tests/ui/cast/cast-to-nil.rs | 3 +- tests/ui/cast/cast-to-nil.stderr | 2 +- tests/ui/cfg/cfg_false_no_std-2.rs | 4 ++- tests/ui/codegen/mismatched-data-layouts.rs | 3 +- .../cfg-arg-invalid-3.rs | 4 ++- .../cfg-arg-invalid-5.rs | 4 ++- .../conditional-compilation/cfg-attr-cfg-2.rs | 3 +- .../cfg-attr-cfg-2.stderr | 2 +- .../conditional-compilation/cfg-in-crate-1.rs | 4 +-- .../cfg-in-crate-1.stderr | 2 +- tests/ui/const-ptr/out_of_bounds_read.rs | 5 ++-- tests/ui/const-ptr/out_of_bounds_read.stderr | 4 +-- tests/ui/consts/const-size_of-cycle.rs | 3 +- tests/ui/consts/const-size_of-cycle.stderr | 6 ++-- tests/ui/consts/miri_unleashed/drop.rs | 4 ++- tests/ui/consts/timeout.rs | 3 +- tests/ui/consts/timeout.stderr | 2 +- tests/ui/crate_type_flag.rs | 3 +- .../debuginfo-type-name-layout-ice-94961-1.rs | 2 +- .../debuginfo-type-name-layout-ice-94961-2.rs | 2 +- tests/ui/debuginfo/dwarf-versions.rs | 6 ++-- .../windows_gnu_split_debuginfo_packed.rs | 3 +- .../windows_gnu_split_debuginfo_unpacked.rs | 3 +- tests/ui/deprecation/deprecation-lint-2.rs | 3 +- .../ui/deprecation/deprecation-lint-2.stderr | 4 +-- tests/ui/deprecation/deprecation-lint-3.rs | 2 +- .../ui/deprecation/deprecation-lint-3.stderr | 4 +-- tests/ui/duplicate/dupe-symbols-4.rs | 4 +-- tests/ui/duplicate/dupe-symbols-4.stderr | 2 +- tests/ui/duplicate/dupe-symbols-7.rs | 5 +--- tests/ui/duplicate/dupe-symbols-7.stderr | 2 +- tests/ui/duplicate/dupe-symbols-8.rs | 3 +- tests/ui/duplicate/dupe-symbols-8.stderr | 2 +- tests/ui/elided-test.rs | 4 +-- tests/ui/elided-test.stderr | 2 +- tests/ui/error-codes/E0602.rs | 5 +++- ...emap-path-prefix-reverse.local-self.stderr | 2 +- ...p-path-prefix-reverse.remapped-self.stderr | 2 +- tests/ui/errors/remap-path-prefix-reverse.rs | 3 +- tests/ui/errors/remap-path-prefix-sysroot.rs | 4 ++- .../ui/errors/remap-path-prefix.normal.stderr | 2 +- tests/ui/errors/remap-path-prefix.rs | 9 +++--- ...p-path-prefix.with-diagnostic-scope.stderr | 2 +- ...ath-prefix.without-diagnostic-scope.stderr | 2 +- tests/ui/expr/if/if-typeck.rs | 3 +- tests/ui/expr/if/if-typeck.stderr | 2 +- tests/ui/ext-nonexistent.rs | 2 +- tests/ui/ext-nonexistent.stderr | 2 +- tests/ui/extern-flag/empty-extern-arg.rs | 5 +++- .../extern-flag/invalid-crate-name-dashed.rs | 3 +- .../invalid-crate-name-non-ascii.rs | 3 +- tests/ui/extern-flag/invalid-crate-name.rs | 3 +- tests/ui/extern-flag/no-force-extern.rs | 6 ++-- tests/ui/fn/fn-bad-block-type.rs | 4 +-- tests/ui/fn/fn-bad-block-type.stderr | 2 +- tests/ui/imports/import-loop-2.rs | 4 +-- tests/ui/imports/import-loop-2.stderr | 2 +- tests/ui/imports/import-loop.rs | 4 +-- tests/ui/imports/import-loop.stderr | 2 +- tests/ui/imports/import3.rs | 3 +- tests/ui/imports/import3.stderr | 2 +- tests/ui/imports/import4.rs | 5 +--- tests/ui/imports/import4.stderr | 2 +- ...te-instantiation-struct-tail-ice-114484.rs | 17 +++++++++-- ...nstantiation-struct-tail-ice-114484.stderr | 8 ++--- .../instrument-xray/flags-always-never-1.rs | 3 +- tests/ui/instrument-xray/flags-dupe-always.rs | 3 +- .../flags-dupe-ignore-loops.rs | 3 +- .../instrument-xray/target-not-supported.rs | 3 +- .../ui/internal/internal-unstable-noallow.rs | 10 +++---- .../internal/internal-unstable-noallow.stderr | 8 ++--- .../invalid-compile-flags/crate-type-flag.rs | 7 +++-- .../function-return/requires-x86-or-x86_64.rs | 3 +- ...nk-extern-requires-non-large-code-model.rs | 3 +- .../reg-struct-return/requires-x86.rs | 5 ++-- .../regparm/regparm-valid-values.rs | 3 +- .../regparm/requires-x86.rs | 5 ++-- .../invalid/issue-114435-layout-type-err.rs | 3 +- .../non-ice-error-on-worker-io-fail.rs | 4 +-- tests/ui/issues/issue-37131.rs | 1 + tests/ui/lang-items/lang-item-missing.rs | 4 +-- tests/ui/lang-items/lang-item-missing.stderr | 2 +- .../missing-copy-lang-item-issue-19660.rs | 4 +-- .../missing-copy-lang-item-issue-19660.stderr | 2 +- tests/ui/layout/size-of-val-raw-too-big.rs | 3 +- .../layout/unknown-when-no-type-parameter.rs | 3 +- .../unknown-when-no-type-parameter.stderr | 2 +- tests/ui/limits/issue-17913.rs | 3 +- tests/ui/limits/issue-55878.rs | 2 +- tests/ui/limits/issue-55878.stderr | 2 +- tests/ui/link-native-libs/empty-kind-1.rs | 3 +- tests/ui/link-native-libs/empty-kind-2.rs | 3 +- tests/ui/link-native-libs/link-arg-error.rs | 3 +- .../link-native-libs/manual-link-bad-form.rs | 3 +- .../link-native-libs/manual-link-bad-kind.rs | 3 +- .../manual-link-bad-search-path.rs | 3 +- .../link-native-libs/manual-link-framework.rs | 3 +- .../manual-link-unsupported-kind.rs | 3 +- .../link-native-libs/modifiers-override-3.rs | 3 +- .../suggest-libname-only-1.rs | 5 ++-- .../suggest-libname-only-1.stderr | 2 +- .../suggest-libname-only-2.rs | 5 ++-- .../suggest-libname-only-2.stderr | 2 +- tests/ui/linkage-attr/incompatible-flavor.rs | 3 +- tests/ui/linkage-attr/issue-10755.rs | 3 +- .../raw-dylib/elf/multiple-libraries.rs | 2 ++ .../raw-dylib/elf/single-symbol.rs | 2 ++ .../ui/linkage-attr/raw-dylib/elf/verbatim.rs | 2 ++ tests/ui/linkage-attr/unstable-flavor.rs | 5 ++-- tests/ui/lint/bad-lint-cap.rs | 3 +- tests/ui/lint/cli-unknown-force-warn.rs | 5 +++- ...command-line-register-unknown-lint-tool.rs | 5 +++- .../ui/lint/force-warn/warnings-lint-group.rs | 5 +++- tests/ui/lint/issue-104897.rs | 5 +--- tests/ui/lint/issue-104897.stderr | 2 +- .../lint/lint-pre-expansion-extern-module.rs | 4 ++- tests/ui/lint/lint-removed-cmdline-deny.rs | 7 +++-- .../ui/lint/lint-removed-cmdline-deny.stderr | 4 +-- tests/ui/lint/lint-removed-cmdline.rs | 7 +++-- tests/ui/lint/lint-removed-cmdline.stderr | 4 +-- tests/ui/lint/lint-renamed-cmdline-deny.rs | 8 +++-- .../ui/lint/lint-renamed-cmdline-deny.stderr | 4 +-- tests/ui/lint/lint-renamed-cmdline.rs | 8 +++-- tests/ui/lint/lint-renamed-cmdline.stderr | 4 +-- tests/ui/lint/lint-stability2.rs | 3 +- tests/ui/lint/lint-stability2.stderr | 4 +-- tests/ui/lint/lint-stability3.rs | 2 +- tests/ui/lint/lint-stability3.stderr | 4 +-- .../ui/lint/lint-unknown-lint-cmdline-deny.rs | 8 ++++- tests/ui/lint/lint-unknown-lint-cmdline.rs | 9 ++++-- .../lint/unused_parens_multibyte_recovery.rs | 7 ++--- .../unused_parens_multibyte_recovery.stderr | 2 +- tests/ui/lto/issue-11154.rs | 4 +-- tests/ui/lto/lto-duplicate-symbols.rs | 4 ++- tests/ui/macros/not-utf8.rs | 2 +- tests/ui/macros/not-utf8.stderr | 2 +- .../unreachable-arg.edition_2021.stderr | 2 +- tests/ui/macros/unreachable-arg.rs | 3 +- ...nreachable-format-args.edition_2015.stderr | 2 +- tests/ui/macros/unreachable-format-args.rs | 2 +- ...ue-107423-unused-delim-only-one-no-pair.rs | 5 +--- ...07423-unused-delim-only-one-no-pair.stderr | 2 +- tests/ui/minus-string.rs | 4 +-- tests/ui/minus-string.stderr | 2 +- tests/ui/mir/enable_passes_validation.rs | 11 +++---- tests/ui/mir/lint/assignment-overlap.rs | 2 +- tests/ui/mir/lint/call-overlap.rs | 2 +- tests/ui/mir/lint/no-storage.rs | 2 +- tests/ui/mir/lint/storage-live.rs | 2 +- tests/ui/mir/lint/storage-return.rs | 2 +- tests/ui/mir/validate/noncleanup-cleanup.rs | 6 ++-- tests/ui/mir/validate/noncleanup-resume.rs | 4 +-- tests/ui/mir/validate/noncleanup-terminate.rs | 4 +-- tests/ui/missing/missing-main.rs | 3 +- tests/ui/missing/missing-main.stderr | 2 +- tests/ui/missing/missing-return.rs | 2 +- tests/ui/nested-ty-params.rs | 2 ++ tests/ui/no-capture-arc.rs | 4 +-- tests/ui/no-capture-arc.stderr | 2 +- tests/ui/no_std/no-std-no-start-binary.rs | 2 ++ tests/ui/no_std/no-std-unwind-binary.rs | 3 +- .../packed/packed-struct-generic-transmute.rs | 1 + tests/ui/packed/packed-struct-transmute.rs | 1 + .../ui/panic-handler/panic-handler-missing.rs | 3 +- tests/ui/panic-handler/panic-handler-std.rs | 3 +- .../ui/panic-handler/panic-handler-std.stderr | 2 +- tests/ui/panic-handler/weak-lang-item.rs | 7 +++-- tests/ui/panic-handler/weak-lang-item.stderr | 2 +- .../abort-link-to-unwind-dylib.rs | 3 +- tests/ui/panic-runtime/bad-panic-flag1.rs | 3 +- tests/ui/panic-runtime/bad-panic-flag2.rs | 3 +- .../ui/panic-runtime/need-abort-got-unwind.rs | 3 +- .../ui/panic-runtime/need-unwind-got-abort.rs | 3 +- .../runtime-depend-on-needs-runtime.rs | 3 +- .../panic-runtime/transitive-link-a-bunch.rs | 5 +++- tests/ui/panic-runtime/two-panic-runtimes.rs | 3 +- .../ui/panic-runtime/want-abort-got-unwind.rs | 5 +++- .../panic-runtime/want-abort-got-unwind2.rs | 5 +++- .../ui/panic-runtime/want-unwind-got-abort.rs | 3 +- .../panic-runtime/want-unwind-got-abort2.rs | 4 ++- tests/ui/panics/default-backtrace-ice.rs | 2 +- .../parser/attribute/attr-dangling-in-fn.rs | 4 +-- .../attribute/attr-dangling-in-fn.stderr | 2 +- .../parser/attribute/attr-dangling-in-mod.rs | 4 +-- .../attribute/attr-dangling-in-mod.stderr | 2 +- tests/ui/parser/circular_modules_main.rs | 4 +-- tests/ui/parser/class-implements-bad-trait.rs | 3 +- .../parser/class-implements-bad-trait.stderr | 2 +- tests/ui/parser/import-from-path.rs | 3 +- tests/ui/parser/import-from-path.stderr | 2 +- tests/ui/parser/import-from-rename.rs | 4 +-- tests/ui/parser/import-from-rename.stderr | 2 +- tests/ui/parser/import-glob-path.rs | 3 +- tests/ui/parser/import-glob-path.stderr | 2 +- tests/ui/parser/import-glob-rename.rs | 4 +-- tests/ui/parser/import-glob-rename.stderr | 2 +- ...lar-module-with-doc-comment-issue-97589.rs | 3 +- tests/ui/parser/issues/issue-21146.rs | 3 +- tests/ui/parser/issues/issue-66473.rs | Bin 129 -> 287 bytes tests/ui/parser/issues/issue-66473.stderr | 13 ++++---- tests/ui/parser/issues/issue-68629.rs | Bin 131 -> 258 bytes tests/ui/parser/issues/issue-68629.stderr | 10 +++---- tests/ui/parser/issues/issue-68730.rs | Bin 177 -> 305 bytes tests/ui/parser/issues/issue-68730.stderr | 10 +++---- tests/ui/parser/shebang/shebang-split.rs | 3 +- tests/ui/parser/utf16-be-without-bom.rs | Bin 162 -> 202 bytes tests/ui/parser/utf16-be-without-bom.stderr | 28 +++++++++--------- tests/ui/parser/utf16-le-without-bom.rs | Bin 163 -> 203 bytes tests/ui/parser/utf16-le-without-bom.stderr | 28 +++++++++--------- tests/ui/print-request/print-lints-help.rs | 3 +- tests/ui/print-request/stability.rs | 9 +++--- tests/ui/privacy/private-inferred-type-3.rs | 15 +++++----- .../ui/privacy/private-inferred-type-3.stderr | 14 ++++----- tests/ui/proc-macro/export-macro.rs | 4 +-- tests/ui/proc-macro/export-macro.stderr | 2 +- .../issue-59191-replace-root-with-fn.rs | 4 ++- tests/ui/proc-macro/panic-abort.rs | 3 +- tests/ui/proc-macro/two-crate-types-1.rs | 4 +-- tests/ui/proc-macro/two-crate-types-2.rs | 3 +- tests/ui/reachable/unreachable-code-ret.rs | 4 +-- .../ui/reachable/unreachable-code-ret.stderr | 4 +-- tests/ui/resolve/bad-env-capture.rs | 4 ++- tests/ui/resolve/bad-env-capture.stderr | 6 ++-- tests/ui/resolve/bad-env-capture2.rs | 4 ++- tests/ui/resolve/bad-env-capture2.stderr | 6 ++-- tests/ui/resolve/bad-env-capture3.rs | 4 ++- tests/ui/resolve/bad-env-capture3.stderr | 6 ++-- tests/ui/return/ret-non-nil.rs | 4 +-- tests/ui/return/ret-non-nil.stderr | 2 +- .../rfc-1717-dllimport/missing-link-attr.rs | 3 +- .../rfc-1717-dllimport/multiple-renames.rs | 3 +- .../rfc-1717-dllimport/rename-modifiers.rs | 2 +- .../rename-modifiers.stderr | 2 +- .../rfc-1717-dllimport/rename-to-empty.rs | 3 +- tests/ui/rmeta/rmeta_bin.rs | 3 +- tests/ui/rmeta/rmeta_lib.rs | 3 +- tests/ui/sanitizer/incompatible.rs | 3 +- tests/ui/sanitizer/unsupported-target.rs | 4 ++- tests/ui/simd/monomorphize-too-long.rs | 3 +- tests/ui/simd/monomorphize-zero-length.rs | 3 +- .../type-generic-monomorphisation-empty.rs | 4 +-- ...-generic-monomorphisation-non-primitive.rs | 4 +-- ...type-generic-monomorphisation-oversized.rs | 4 +-- .../type-generic-monomorphisation-wide-ptr.rs | 4 +-- .../ui/simd/type-generic-monomorphisation.rs | 5 ++-- tests/ui/simd/type-wide-ptr.rs | 4 +-- tests/ui/tail-typeck.rs | 4 +-- tests/ui/tail-typeck.stderr | 2 +- ...oat-target-feature-flag-disable-implied.rs | 4 ++- ...dfloat-target-feature-flag-disable-neon.rs | 4 ++- ...n-hardfloat-target-feature-flag-disable.rs | 5 +++- ...forbidden-hardfloat-target-feature-flag.rs | 5 +++- .../forbidden-target-feature-flag-disable.rs | 2 ++ .../forbidden-target-feature-flag.rs | 4 ++- ...arget-cpu-lacks-required-target-feature.rs | 3 +- .../tied-features-no-implication.pacg.stderr | 4 +-- .../tied-features-no-implication.rs | 8 ++--- .../test-attrs/test-panic-abort-disabled.rs | 3 +- tests/ui/track-diagnostics/track.rs | 3 ++ tests/ui/track-diagnostics/track2.rs | 2 +- tests/ui/track-diagnostics/track3.rs | 2 ++ tests/ui/track-diagnostics/track4.rs | 2 +- tests/ui/track-diagnostics/track5.rs | 2 +- tests/ui/track-diagnostics/track6.rs | 2 +- .../solver-cycles/129541-recursive-struct.rs | 3 +- .../panic-causes-oom-112708.rs | 2 +- tests/ui/treat-err-as-bug/span_delayed_bug.rs | 2 +- tests/ui/type/issue-91268.rs | 3 +- tests/ui/type/issue-91268.stderr | 2 +- tests/ui/type/type-arg-out-of-scope.rs | 3 +- tests/ui/type/type-arg-out-of-scope.stderr | 4 +-- tests/ui/typeck/issue-91334.rs | 4 +-- tests/ui/typeck/output-type-mismatch.rs | 4 +-- tests/ui/typeck/output-type-mismatch.stderr | 2 +- tests/ui/typeck/while-type-error.rs | 4 +-- tests/ui/typeck/while-type-error.stderr | 2 +- tests/ui/typeck/wrong-ret-type.rs | 3 +- tests/ui/typeck/wrong-ret-type.stderr | 2 +- .../deny-unstable-lint-command-line.rs | 2 +- ...warn-unknown-unstable-lint-command-line.rs | 2 +- tests/ui/use/use-meta-mismatch.rs | 4 +-- tests/ui/use/use-meta-mismatch.stderr | 2 +- .../windows-subsystem-invalid.rs | 4 +-- 315 files changed, 656 insertions(+), 530 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 1190c2646af1..6f412a7a60e4 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -335,6 +335,9 @@ But for strict testing, try to use the `ERROR` annotation as much as possible, including `//~?` annotations for diagnostics without span. For compile time diagnostics `error-pattern` should very rarely be necessary. +Per-line annotations (`//~`) are still checked in tests using `error-pattern`, +to opt out of these checks in exceptional cases use `//@ compile-flags: --error-format=human`. + ### Error levels The error levels that you can have are: diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index 9b5b8b56b600..974e5170465e 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -169,16 +169,9 @@ impl TestCx<'_> { self.props.error_patterns ); - let check_patterns = should_run == WillExecute::No - && (!self.props.error_patterns.is_empty() - || !self.props.regex_error_patterns.is_empty()); if !explicit && self.config.compare_mode.is_none() { - let check_annotations = !check_patterns || !expected_errors.is_empty(); - - if check_annotations { - // "//~ERROR comments" - self.check_expected_errors(expected_errors, &proc_res); - } + // "//~ERROR comments" + self.check_expected_errors(expected_errors, &proc_res); } else if explicit && !expected_errors.is_empty() { let msg = format!( "line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead", @@ -188,7 +181,10 @@ impl TestCx<'_> { self.fatal(&msg); } let output_to_check = self.get_output(&proc_res); - if check_patterns { + if should_run == WillExecute::No + && (!self.props.error_patterns.is_empty() + || !self.props.regex_error_patterns.is_empty()) + { // "// error-pattern" comments self.check_all_error_patterns(&output_to_check, &proc_res, pm); } diff --git a/tests/rustdoc-ui/doctest/no-run-flag-error.rs b/tests/rustdoc-ui/doctest/no-run-flag-error.rs index 896d7729b8df..3f9016b23db4 100644 --- a/tests/rustdoc-ui/doctest/no-run-flag-error.rs +++ b/tests/rustdoc-ui/doctest/no-run-flag-error.rs @@ -1,6 +1,7 @@ // test the behavior of the --no-run flag without the --test flag //@ compile-flags:-Z unstable-options --no-run --test-args=--test-threads=1 -//@ error-pattern: the `--test` flag must be passed pub fn f() {} + +//~? ERROR the `--test` flag must be passed to enable `--no-run` diff --git a/tests/rustdoc-ui/invalid-theme-name.rs b/tests/rustdoc-ui/invalid-theme-name.rs index d632a08ebc80..7f1d191c89de 100644 --- a/tests/rustdoc-ui/invalid-theme-name.rs +++ b/tests/rustdoc-ui/invalid-theme-name.rs @@ -1,3 +1,4 @@ //@ compile-flags:--theme {{src-base}}/invalid-theme-name.rs -//@ error-pattern: invalid argument //@ error-pattern: must have a .css extension + +//~? ERROR invalid argument: "$DIR/invalid-theme-name.rs" diff --git a/tests/rustdoc-ui/issues/issue-91713.rs b/tests/rustdoc-ui/issues/issue-91713.rs index 9875b5d4ad69..682407260070 100644 --- a/tests/rustdoc-ui/issues/issue-91713.rs +++ b/tests/rustdoc-ui/issues/issue-91713.rs @@ -1,3 +1,4 @@ //@ check-pass //@ compile-flags: --passes list -//@ error-pattern: the `passes` flag no longer functions + +//~? WARN the `passes` flag no longer functions diff --git a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs index 6e631061e8ac..5e7dc377f5d5 100644 --- a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs +++ b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs @@ -1,6 +1,7 @@ -//@ error-pattern: no documentation found //@ normalize-stderr: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL" #![deny(rustdoc::missing_crate_level_docs)] //^~ NOTE defined here pub fn foo() {} + +//~? ERROR no documentation found for this crate's top-level module diff --git a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr index 3a748335ea8e..721d3662c93b 100644 --- a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr +++ b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr @@ -3,7 +3,7 @@ error: no documentation found for this crate's top-level module = help: The following guide may be of use: https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html note: the lint level is defined here - --> $DIR/no-crate-level-doc-lint.rs:3:9 + --> $DIR/no-crate-level-doc-lint.rs:2:9 | LL | #![deny(rustdoc::missing_crate_level_docs)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/rustdoc-ui/track-diagnostics.rs b/tests/rustdoc-ui/track-diagnostics.rs index 27781f47e0dd..d18d26bf7943 100644 --- a/tests/rustdoc-ui/track-diagnostics.rs +++ b/tests/rustdoc-ui/track-diagnostics.rs @@ -8,4 +8,4 @@ struct A; struct B; -pub const S: A = B; +pub const S: A = B; //~ ERROR mismatched types diff --git a/tests/ui-fulldeps/missing-rustc-driver-error.rs b/tests/ui-fulldeps/missing-rustc-driver-error.rs index 03ab5ce7b253..d582efada908 100644 --- a/tests/ui-fulldeps/missing-rustc-driver-error.rs +++ b/tests/ui-fulldeps/missing-rustc-driver-error.rs @@ -1,6 +1,6 @@ // Test that we get the following hint when trying to use a compiler crate without rustc_driver. //@ error-pattern: try adding `extern crate rustc_driver;` at the top level of this crate -//@ compile-flags: --emit link +//@ compile-flags: --emit link --error-format=human //@ normalize-stderr: ".*crate .* required.*\n\n" -> "" //@ normalize-stderr: "aborting due to [0-9]+" -> "aborting due to NUMBER" diff --git a/tests/ui/abi/fixed_x18.rs b/tests/ui/abi/fixed_x18.rs index f1ff3e1d5341..d373468f68fe 100644 --- a/tests/ui/abi/fixed_x18.rs +++ b/tests/ui/abi/fixed_x18.rs @@ -23,3 +23,5 @@ #[lang = "sized"] trait Sized {} + +//~? ERROR the `-Zfixed-x18` flag is not supported on the ` diff --git a/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs b/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs index d758c903087b..74882fb5c55c 100644 --- a/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs +++ b/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs @@ -1,5 +1,4 @@ //@ compile-flags: --target aarch64-unknown-none -Zsanitizer=shadow-call-stack -//@ error-pattern: shadow-call-stack sanitizer is not supported for this target //@ dont-check-compiler-stderr //@ needs-llvm-components: aarch64 @@ -13,3 +12,5 @@ trait Sized {} #[no_mangle] pub fn foo() {} + +//~? ERROR shadow-call-stack sanitizer is not supported for this target diff --git a/tests/ui/allocator/two-allocators2.rs b/tests/ui/allocator/two-allocators2.rs index b3bb4598c778..6efb297054bc 100644 --- a/tests/ui/allocator/two-allocators2.rs +++ b/tests/ui/allocator/two-allocators2.rs @@ -1,6 +1,5 @@ //@ aux-build:system-allocator.rs //@ no-prefer-dynamic -//@ error-pattern: the `#[global_allocator]` in extern crate system_allocator; @@ -10,3 +9,5 @@ use std::alloc::System; static A: System = System; fn main() {} + +//~? ERROR the `#[global_allocator]` in this crate conflicts with global allocator in: system_allocator diff --git a/tests/ui/allocator/two-allocators3.rs b/tests/ui/allocator/two-allocators3.rs index 0cb3879666da..3aba96068de9 100644 --- a/tests/ui/allocator/two-allocators3.rs +++ b/tests/ui/allocator/two-allocators3.rs @@ -1,10 +1,10 @@ //@ aux-build:system-allocator.rs //@ aux-build:system-allocator2.rs //@ no-prefer-dynamic -//@ error-pattern: the `#[global_allocator]` in - extern crate system_allocator; extern crate system_allocator2; fn main() {} + +//~? ERROR the `#[global_allocator]` in system_allocator conflicts with global allocator in: system_allocator2 diff --git a/tests/ui/amdgpu-require-explicit-cpu.rs b/tests/ui/amdgpu-require-explicit-cpu.rs index 46778a1094fa..d40cb97977d9 100644 --- a/tests/ui/amdgpu-require-explicit-cpu.rs +++ b/tests/ui/amdgpu-require-explicit-cpu.rs @@ -3,7 +3,6 @@ //@ compile-flags: --crate-type=cdylib --target=amdgcn-amd-amdhsa //@ needs-llvm-components: amdgpu //@ needs-rust-lld -//@[nocpu] error-pattern: target requires explicitly specifying a cpu //@[nocpu] build-fail //@[cpu] compile-flags: -Ctarget-cpu=gfx900 //@[cpu] build-pass @@ -15,3 +14,5 @@ trait Sized {} pub fn foo() {} + +//[nocpu]~? ERROR target requires explicitly specifying a cpu with `-C target-cpu` diff --git a/tests/ui/associated-types/issue-36499.rs b/tests/ui/associated-types/issue-36499.rs index 25f4060fa6f5..606918b40b70 100644 --- a/tests/ui/associated-types/issue-36499.rs +++ b/tests/ui/associated-types/issue-36499.rs @@ -1,5 +1,5 @@ //@ error-pattern: aborting due to 1 previous error fn main() { - 2 + +2; + 2 + +2; //~ ERROR leading `+` is not supported } diff --git a/tests/ui/attributes/attr-bad-crate-attr.rs b/tests/ui/attributes/attr-bad-crate-attr.rs index 9de0abca9a75..d37d349026a0 100644 --- a/tests/ui/attributes/attr-bad-crate-attr.rs +++ b/tests/ui/attributes/attr-bad-crate-attr.rs @@ -3,7 +3,6 @@ //! //! See . -//@ error-pattern: expected item - #![attr = "val"] #[attr = "val"] // Unterminated +//~^ ERROR expected item after attributes diff --git a/tests/ui/attributes/attr-bad-crate-attr.stderr b/tests/ui/attributes/attr-bad-crate-attr.stderr index 69eabd32230f..22522896bd1a 100644 --- a/tests/ui/attributes/attr-bad-crate-attr.stderr +++ b/tests/ui/attributes/attr-bad-crate-attr.stderr @@ -1,5 +1,5 @@ error: expected item after attributes - --> $DIR/attr-bad-crate-attr.rs:9:1 + --> $DIR/attr-bad-crate-attr.rs:7:1 | LL | #[attr = "val"] // Unterminated | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/attributes/z-crate-attr/garbage.rs b/tests/ui/attributes/z-crate-attr/garbage.rs index ec81dd1bcaa0..69444e1935a2 100644 --- a/tests/ui/attributes/z-crate-attr/garbage.rs +++ b/tests/ui/attributes/z-crate-attr/garbage.rs @@ -1,4 +1,7 @@ // Show diagnostics for invalid tokens //@ compile-flags: -Zcrate-attr=`%~@$# -//@ error-pattern:unknown start of token + fn main() {} + +//~? ERROR unknown start of token: ` +//~? ERROR expected identifier, found `%` diff --git a/tests/ui/attributes/z-crate-attr/injection.rs b/tests/ui/attributes/z-crate-attr/injection.rs index 0c5c81ca71a9..a91f9d2886e3 100644 --- a/tests/ui/attributes/z-crate-attr/injection.rs +++ b/tests/ui/attributes/z-crate-attr/injection.rs @@ -1,3 +1,5 @@ //@ compile-flags: '-Zcrate-attr=feature(yeet_expr)]fn main(){}#[inline' -//@ error-pattern:unexpected closing delimiter + fn foo() {} + +//~? ERROR unexpected closing delimiter: `]` diff --git a/tests/ui/attributes/z-crate-attr/inner-attr.rs b/tests/ui/attributes/z-crate-attr/inner-attr.rs index 522c906dcd81..47ecad700624 100644 --- a/tests/ui/attributes/z-crate-attr/inner-attr.rs +++ b/tests/ui/attributes/z-crate-attr/inner-attr.rs @@ -1,4 +1,5 @@ //@ compile-flags: -Zcrate-attr=#![feature(foo)] -//@ error-pattern:expected identifier fn main() {} + +//~? ERROR expected identifier, found `#` diff --git a/tests/ui/attributes/z-crate-attr/multiple.rs b/tests/ui/attributes/z-crate-attr/multiple.rs index ee13253f6255..47d35d2c3fdf 100644 --- a/tests/ui/attributes/z-crate-attr/multiple.rs +++ b/tests/ui/attributes/z-crate-attr/multiple.rs @@ -1,3 +1,5 @@ //@ compile-flags: -Zcrate-attr=feature(foo),feature(bar) -//@ error-pattern:invalid crate attr + fn main() {} + +//~? ERROR invalid crate attribute diff --git a/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs index fc1d7f39a597..77d5d698f659 100644 --- a/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs +++ b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs @@ -1,4 +1,6 @@ // Show diagnostics for unbalanced parens. //@ compile-flags: -Zcrate-attr=( -//@ error-pattern:unclosed delimiter + fn main() {} + +//~? ERROR this file contains an unclosed delimiter diff --git a/tests/ui/binop/binop-bitxor-str.rs b/tests/ui/binop/binop-bitxor-str.rs index d59e46167fe0..3072fa6ae90d 100644 --- a/tests/ui/binop/binop-bitxor-str.rs +++ b/tests/ui/binop/binop-bitxor-str.rs @@ -1,3 +1,2 @@ -//@ error-pattern:no implementation for `String ^ String` - fn main() { let x = "a".to_string() ^ "b".to_string(); } +//~^ ERROR no implementation for `String ^ String` diff --git a/tests/ui/binop/binop-bitxor-str.stderr b/tests/ui/binop/binop-bitxor-str.stderr index 9d9ec6c5af6b..d4bb0c17bfa7 100644 --- a/tests/ui/binop/binop-bitxor-str.stderr +++ b/tests/ui/binop/binop-bitxor-str.stderr @@ -1,5 +1,5 @@ error[E0369]: no implementation for `String ^ String` - --> $DIR/binop-bitxor-str.rs:3:37 + --> $DIR/binop-bitxor-str.rs:1:37 | LL | fn main() { let x = "a".to_string() ^ "b".to_string(); } | --------------- ^ --------------- String diff --git a/tests/ui/binop/binop-mul-bool.rs b/tests/ui/binop/binop-mul-bool.rs index 0b4ed21a12d0..706195d215cc 100644 --- a/tests/ui/binop/binop-mul-bool.rs +++ b/tests/ui/binop/binop-mul-bool.rs @@ -1,3 +1 @@ -//@ error-pattern:cannot multiply `bool` by `bool` - -fn main() { let x = true * false; } +fn main() { let x = true * false; } //~ ERROR cannot multiply `bool` by `bool` diff --git a/tests/ui/binop/binop-mul-bool.stderr b/tests/ui/binop/binop-mul-bool.stderr index 82d066f45a4e..7fa70f65f56a 100644 --- a/tests/ui/binop/binop-mul-bool.stderr +++ b/tests/ui/binop/binop-mul-bool.stderr @@ -1,5 +1,5 @@ error[E0369]: cannot multiply `bool` by `bool` - --> $DIR/binop-mul-bool.rs:3:26 + --> $DIR/binop-mul-bool.rs:1:26 | LL | fn main() { let x = true * false; } | ---- ^ ----- bool diff --git a/tests/ui/c-variadic/issue-86053-1.rs b/tests/ui/c-variadic/issue-86053-1.rs index f952235be981..8eeb99a4cc19 100644 --- a/tests/ui/c-variadic/issue-86053-1.rs +++ b/tests/ui/c-variadic/issue-86053-1.rs @@ -1,12 +1,18 @@ // Regression test for the ICE described in issue #86053. -//@ error-pattern:unexpected `self` parameter in function -//@ error-pattern:`...` must be the last argument of a C-variadic function -//@ error-pattern:cannot find type `F` in this scope - #![feature(c_variadic)] #![crate_type="lib"] fn ordering4 < 'a , 'b > ( a : , self , self , self , + //~^ ERROR expected type, found `,` + //~| ERROR unexpected `self` parameter in function + //~| ERROR unexpected `self` parameter in function + //~| ERROR unexpected `self` parameter in function self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + //~^ ERROR unexpected `self` parameter in function + //~| ERROR unexpected `self` parameter in function + //~| ERROR unexpected `self` parameter in function + //~| ERROR `...` must be the last argument of a C-variadic function + //~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~| ERROR cannot find type `F` in this scope } diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr index ce31f0d300f1..dc323f9a234d 100644 --- a/tests/ui/c-variadic/issue-86053-1.stderr +++ b/tests/ui/c-variadic/issue-86053-1.stderr @@ -1,23 +1,23 @@ error: expected type, found `,` - --> $DIR/issue-86053-1.rs:10:47 + --> $DIR/issue-86053-1.rs:6:47 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , | ^ expected type error: unexpected `self` parameter in function - --> $DIR/issue-86053-1.rs:10:51 + --> $DIR/issue-86053-1.rs:6:51 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/issue-86053-1.rs:10:58 + --> $DIR/issue-86053-1.rs:6:58 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/issue-86053-1.rs:10:67 + --> $DIR/issue-86053-1.rs:6:67 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , | ^^^^ must be the first parameter of an associated function diff --git a/tests/ui/capture1.rs b/tests/ui/capture1.rs index 9bf6532a7d38..4f8c04e3fa9d 100644 --- a/tests/ui/capture1.rs +++ b/tests/ui/capture1.rs @@ -1,6 +1,4 @@ -//@ error-pattern: can't capture dynamic environment in a fn item - fn main() { let bar: isize = 5; - fn foo() -> isize { return bar; } + fn foo() -> isize { return bar; } //~ ERROR can't capture dynamic environment in a fn item } diff --git a/tests/ui/capture1.stderr b/tests/ui/capture1.stderr index 067b85ba6191..8027430de522 100644 --- a/tests/ui/capture1.stderr +++ b/tests/ui/capture1.stderr @@ -1,5 +1,5 @@ error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/capture1.rs:5:32 + --> $DIR/capture1.rs:3:32 | LL | fn foo() -> isize { return bar; } | ^^^ diff --git a/tests/ui/cast/cast-from-nil.rs b/tests/ui/cast/cast-from-nil.rs index 8a677603aa9f..65e1eb31b21b 100644 --- a/tests/ui/cast/cast-from-nil.rs +++ b/tests/ui/cast/cast-from-nil.rs @@ -1,2 +1 @@ -//@ error-pattern: non-primitive cast: `()` as `u32` -fn main() { let u = (assert!(true) as u32); } +fn main() { let u = (assert!(true) as u32); } //~ ERROR non-primitive cast: `()` as `u32` diff --git a/tests/ui/cast/cast-from-nil.stderr b/tests/ui/cast/cast-from-nil.stderr index 991ff93a8bd0..82c53d71e78a 100644 --- a/tests/ui/cast/cast-from-nil.stderr +++ b/tests/ui/cast/cast-from-nil.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `()` as `u32` - --> $DIR/cast-from-nil.rs:2:21 + --> $DIR/cast-from-nil.rs:1:21 | LL | fn main() { let u = (assert!(true) as u32); } | ^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/tests/ui/cast/cast-to-nil.rs b/tests/ui/cast/cast-to-nil.rs index d91f9a16a07f..7cd864471dde 100644 --- a/tests/ui/cast/cast-to-nil.rs +++ b/tests/ui/cast/cast-to-nil.rs @@ -1,2 +1 @@ -//@ error-pattern: non-primitive cast: `u32` as `()` -fn main() { let u = 0u32 as (); } +fn main() { let u = 0u32 as (); } //~ ERROR non-primitive cast: `u32` as `()` diff --git a/tests/ui/cast/cast-to-nil.stderr b/tests/ui/cast/cast-to-nil.stderr index 14c75983b94c..d7121a7adba7 100644 --- a/tests/ui/cast/cast-to-nil.stderr +++ b/tests/ui/cast/cast-to-nil.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `u32` as `()` - --> $DIR/cast-to-nil.rs:2:21 + --> $DIR/cast-to-nil.rs:1:21 | LL | fn main() { let u = 0u32 as (); } | ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/tests/ui/cfg/cfg_false_no_std-2.rs b/tests/ui/cfg/cfg_false_no_std-2.rs index cd3375658721..fa6042f5892c 100644 --- a/tests/ui/cfg/cfg_false_no_std-2.rs +++ b/tests/ui/cfg/cfg_false_no_std-2.rs @@ -1,7 +1,6 @@ // Error, the linked empty library is `no_std` and doesn't provide a panic handler. //@ dont-check-compiler-stderr -//@ error-pattern: `#[panic_handler]` function required, but not found //@ aux-build: cfg_false_lib_no_std_before.rs #![no_std] @@ -9,3 +8,6 @@ extern crate cfg_false_lib_no_std_before as _; fn main() {} + +//~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/codegen/mismatched-data-layouts.rs b/tests/ui/codegen/mismatched-data-layouts.rs index 955f917ee332..194bcaa307f2 100644 --- a/tests/ui/codegen/mismatched-data-layouts.rs +++ b/tests/ui/codegen/mismatched-data-layouts.rs @@ -3,7 +3,6 @@ //@ build-fail //@ needs-llvm-components: x86 //@ compile-flags: --crate-type=lib --target={{src-base}}/codegen/mismatched-data-layout.json -Z unstable-options -//@ error-pattern: differs from LLVM target's //@ normalize-stderr: "`, `[A-Za-z0-9-:]*`" -> "`, `normalized data layout`" //@ normalize-stderr: "layout, `[A-Za-z0-9-:]*`" -> "layout, `normalized data layout`" @@ -12,3 +11,5 @@ #[lang = "sized"] trait Sized {} + +//~? ERROR differs from LLVM target's diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs index c086b8d8c3f4..ba55b1c08b1e 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs @@ -1,3 +1,5 @@ //@ compile-flags: --cfg a::b -//@ error-pattern: invalid `--cfg` argument: `a::b` (argument key must be an identifier) + fn main() {} + +//~? ERROR invalid `--cfg` argument: `a::b` (argument key must be an identifier) diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs index 6f0bf8cf5fee..d64aeead79cb 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs @@ -1,3 +1,5 @@ //@ compile-flags: --cfg a=10 -//@ error-pattern: invalid `--cfg` argument: `a=10` (argument value must be a string) + fn main() {} + +//~? ERROR invalid `--cfg` argument: `a=10` (argument value must be a string) diff --git a/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs b/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs index c801bbccedd6..80735990015c 100644 --- a/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs +++ b/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs @@ -1,8 +1,7 @@ -//@ error-pattern: `main` function not found //@ compile-flags: --cfg foo --check-cfg=cfg(foo,bar) // main is conditionally compiled, but the conditional compilation // is conditional too! #[cfg_attr(foo, cfg(bar))] -fn main() { } +fn main() { } //~ ERROR `main` function not found in crate `cfg_attr_cfg_2` diff --git a/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr index 64595241dc72..1febb4308633 100644 --- a/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr @@ -1,5 +1,5 @@ error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` - --> $DIR/cfg-attr-cfg-2.rs:8:14 + --> $DIR/cfg-attr-cfg-2.rs:7:14 | LL | fn main() { } | ^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.rs b/tests/ui/conditional-compilation/cfg-in-crate-1.rs index ecd3722bf4c5..a1faa2397a33 100644 --- a/tests/ui/conditional-compilation/cfg-in-crate-1.rs +++ b/tests/ui/conditional-compilation/cfg-in-crate-1.rs @@ -1,3 +1 @@ -//@ error-pattern: `main` function not found - -#![cfg(FALSE)] +#![cfg(FALSE)] //~ ERROR `main` function not found in crate `cfg_in_crate_1` diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr index 6067a3a921cb..126e10cf0402 100644 --- a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr +++ b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr @@ -1,5 +1,5 @@ error[E0601]: `main` function not found in crate `cfg_in_crate_1` - --> $DIR/cfg-in-crate-1.rs:3:15 + --> $DIR/cfg-in-crate-1.rs:1:15 | LL | #![cfg(FALSE)] | ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` diff --git a/tests/ui/const-ptr/out_of_bounds_read.rs b/tests/ui/const-ptr/out_of_bounds_read.rs index 312b53432b47..ccf45bf324a0 100644 --- a/tests/ui/const-ptr/out_of_bounds_read.rs +++ b/tests/ui/const-ptr/out_of_bounds_read.rs @@ -1,5 +1,3 @@ -//@ error-pattern: evaluation of constant value failed - fn main() { use std::ptr; @@ -8,6 +6,9 @@ fn main() { const PAST_END_PTR: *const u32 = unsafe { DATA.as_ptr().add(1) }; const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; + //~^ ERROR evaluation of constant value failed const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; + //~^ ERROR evaluation of constant value failed const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; + //~^ ERROR evaluation of constant value failed } diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr index 899e151c9b81..b396fc4d71bc 100644 --- a/tests/ui/const-ptr/out_of_bounds_read.stderr +++ b/tests/ui/const-ptr/out_of_bounds_read.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/out_of_bounds_read.rs:10:33 + --> $DIR/out_of_bounds_read.rs:8:33 | LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; | ^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes @@ -8,7 +8,7 @@ note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL error[E0080]: evaluation of constant value failed - --> $DIR/out_of_bounds_read.rs:11:39 + --> $DIR/out_of_bounds_read.rs:10:39 | LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; | ^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes diff --git a/tests/ui/consts/const-size_of-cycle.rs b/tests/ui/consts/const-size_of-cycle.rs index cfb2294c4459..f45d96d43f80 100644 --- a/tests/ui/consts/const-size_of-cycle.rs +++ b/tests/ui/consts/const-size_of-cycle.rs @@ -1,7 +1,6 @@ -//@ error-pattern: cycle detected - struct Foo { bytes: [u8; std::mem::size_of::()] + //~^ ERROR cycle detected when evaluating type-level constant } fn main() {} diff --git a/tests/ui/consts/const-size_of-cycle.stderr b/tests/ui/consts/const-size_of-cycle.stderr index cd0ea5564254..bf17d76a092b 100644 --- a/tests/ui/consts/const-size_of-cycle.stderr +++ b/tests/ui/consts/const-size_of-cycle.stderr @@ -1,11 +1,11 @@ error[E0391]: cycle detected when evaluating type-level constant - --> $DIR/const-size_of-cycle.rs:4:17 + --> $DIR/const-size_of-cycle.rs:2:17 | LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... - --> $DIR/const-size_of-cycle.rs:4:17 + --> $DIR/const-size_of-cycle.rs:2:17 | LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | bytes: [u8; std::mem::size_of::()] = note: ...which requires normalizing `[u8; std::mem::size_of::()]`... = note: ...which again requires evaluating type-level constant, completing the cycle note: cycle used when checking that `Foo` is well-formed - --> $DIR/const-size_of-cycle.rs:3:1 + --> $DIR/const-size_of-cycle.rs:1:1 | LL | struct Foo { | ^^^^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/drop.rs b/tests/ui/consts/miri_unleashed/drop.rs index 45ade4906b82..17d089222d96 100644 --- a/tests/ui/consts/miri_unleashed/drop.rs +++ b/tests/ui/consts/miri_unleashed/drop.rs @@ -14,4 +14,6 @@ static TEST_OK: () = { // The actual error is tested by the error-pattern above. static TEST_BAD: () = { let _v: Vec = Vec::new(); -}; +}; //~ ERROR could not evaluate static initializer + +//~? WARN skipping const checks diff --git a/tests/ui/consts/timeout.rs b/tests/ui/consts/timeout.rs index c4fb8bab6636..8dab87ac8e18 100644 --- a/tests/ui/consts/timeout.rs +++ b/tests/ui/consts/timeout.rs @@ -3,7 +3,6 @@ //! ICE. //@ compile-flags: --crate-type=lib -Ztiny-const-eval-limit -//@ error-pattern: constant evaluation is taking a long time static ROOK_ATTACKS_TABLE: () = { 0_u64.count_ones(); @@ -23,3 +22,5 @@ static ROOK_ATTACKS_TABLE: () = { 0_u64.count_ones(); 0_u64.count_ones(); }; + +//~? ERROR constant evaluation is taking a long time diff --git a/tests/ui/consts/timeout.stderr b/tests/ui/consts/timeout.stderr index 6bfa06d86d11..ecefeff76e96 100644 --- a/tests/ui/consts/timeout.stderr +++ b/tests/ui/consts/timeout.stderr @@ -4,7 +4,7 @@ error: constant evaluation is taking a long time = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. If your compilation actually takes a long time, you can safely allow the lint. help: the constant being evaluated - --> $DIR/timeout.rs:8:1 + --> $DIR/timeout.rs:7:1 | LL | static ROOK_ATTACKS_TABLE: () = { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/crate_type_flag.rs b/tests/ui/crate_type_flag.rs index 4f3cfbae45d6..03bea3638e1a 100644 --- a/tests/ui/crate_type_flag.rs +++ b/tests/ui/crate_type_flag.rs @@ -1,4 +1,5 @@ //@ compile-flags: --crate-type dynlib -//@ error-pattern: unknown crate type: `dynlib`, expected one of: `lib`, `rlib`, `staticlib`, `dylib`, `cdylib`, `bin`, `proc-macro` fn main() {} + +//~? ERROR unknown crate type: `dynlib` diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs index 3bff44716985..7f85cbf227ae 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs @@ -1,9 +1,9 @@ +//~ ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture // Make sure the compiler does not ICE when trying to generate the debuginfo name of a type that // causes a layout error. See https://github.com/rust-lang/rust/issues/94961. //@ compile-flags:-C debuginfo=2 //@ build-fail -//@ error-pattern: too big for the target architecture #![crate_type = "rlib"] diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs index 6a3f8f4c249c..e9b021e4f484 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs @@ -1,3 +1,4 @@ +//~ ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture // Make sure the compiler does not ICE when trying to generate the debuginfo name of a type that // causes a layout error. // This version of the test already ICE'd before the commit that introduce the ICE described in @@ -5,7 +6,6 @@ //@ compile-flags:-C debuginfo=2 //@ build-fail -//@ error-pattern: too big for the target architecture #![crate_type = "rlib"] diff --git a/tests/ui/debuginfo/dwarf-versions.rs b/tests/ui/debuginfo/dwarf-versions.rs index 806ade51a997..6030b2fcf3cd 100644 --- a/tests/ui/debuginfo/dwarf-versions.rs +++ b/tests/ui/debuginfo/dwarf-versions.rs @@ -4,7 +4,6 @@ //@ revisions: zero one two three four five six //@[zero] compile-flags: -Zdwarf-version=0 -//@[zero] error-pattern: requested DWARF version 0 is not supported //@[one] compile-flags: -Zdwarf-version=1 //@[one] error-pattern: requested DWARF version 1 is not supported @@ -22,7 +21,6 @@ //@[five] check-pass //@[six] compile-flags: -Zdwarf-version=6 -//@[six] error-pattern: requested DWARF version 6 is not supported //@ compile-flags: -g --target x86_64-unknown-linux-gnu --crate-type cdylib //@ needs-llvm-components: x86 @@ -36,3 +34,7 @@ pub trait Sized {} pub fn foo() {} + +//[zero]~? ERROR requested DWARF version 0 is not supported +//[one]~? ERROR requested DWARF version 1 is not supported +//[six]~? ERROR requested DWARF version 6 is not supported diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs index 896bbac7d8e1..75b8141cc385 100644 --- a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs @@ -1,6 +1,5 @@ //@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g //@ compile-flags: --crate-type cdylib -Csplit-debuginfo=packed -//@ error-pattern: error: `-Csplit-debuginfo=packed` is unstable on this platform //@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm //@[aarch64_gl] needs-llvm-components: aarch64 @@ -27,3 +26,5 @@ #![no_core] #![no_std] + +//~? ERROR `-Csplit-debuginfo=packed` is unstable on this platform diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs index 54a88c912173..3f4da555aadf 100644 --- a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs @@ -1,6 +1,5 @@ //@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g //@ compile-flags: --crate-type cdylib -Csplit-debuginfo=unpacked -//@ error-pattern: error: `-Csplit-debuginfo=unpacked` is unstable on this platform //@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm //@[aarch64_gl] needs-llvm-components: aarch64 @@ -27,3 +26,5 @@ #![no_core] #![no_std] + +//~? ERROR `-Csplit-debuginfo=unpacked` is unstable on this platform diff --git a/tests/ui/deprecation/deprecation-lint-2.rs b/tests/ui/deprecation/deprecation-lint-2.rs index 553b1afe45ca..f22eebb53a02 100644 --- a/tests/ui/deprecation/deprecation-lint-2.rs +++ b/tests/ui/deprecation/deprecation-lint-2.rs @@ -1,5 +1,4 @@ //@ aux-build:deprecation-lint.rs -//@ error-pattern: use of deprecated function #![deny(deprecated)] @@ -9,5 +8,5 @@ extern crate deprecation_lint; use deprecation_lint::*; fn main() { - macro_test!(); + macro_test!(); //~ ERROR use of deprecated function `deprecation_lint::deprecated`: text } diff --git a/tests/ui/deprecation/deprecation-lint-2.stderr b/tests/ui/deprecation/deprecation-lint-2.stderr index 7d411c00445c..ebc760bfe7bf 100644 --- a/tests/ui/deprecation/deprecation-lint-2.stderr +++ b/tests/ui/deprecation/deprecation-lint-2.stderr @@ -1,11 +1,11 @@ error: use of deprecated function `deprecation_lint::deprecated`: text - --> $DIR/deprecation-lint-2.rs:12:5 + --> $DIR/deprecation-lint-2.rs:11:5 | LL | macro_test!(); | ^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/deprecation-lint-2.rs:4:9 + --> $DIR/deprecation-lint-2.rs:3:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ diff --git a/tests/ui/deprecation/deprecation-lint-3.rs b/tests/ui/deprecation/deprecation-lint-3.rs index f01fc9244570..5a9ca9a2d0a6 100644 --- a/tests/ui/deprecation/deprecation-lint-3.rs +++ b/tests/ui/deprecation/deprecation-lint-3.rs @@ -1,5 +1,4 @@ //@ aux-build:deprecation-lint.rs -//@ error-pattern: use of deprecated function #![deny(deprecated)] #![allow(warnings)] @@ -11,4 +10,5 @@ use deprecation_lint::*; fn main() { macro_test_arg_nested!(deprecated_text); + //~^ ERROR use of deprecated function `deprecation_lint::deprecated_text`: text } diff --git a/tests/ui/deprecation/deprecation-lint-3.stderr b/tests/ui/deprecation/deprecation-lint-3.stderr index 1723b7bbd053..8bfe08cf6d50 100644 --- a/tests/ui/deprecation/deprecation-lint-3.stderr +++ b/tests/ui/deprecation/deprecation-lint-3.stderr @@ -1,11 +1,11 @@ error: use of deprecated function `deprecation_lint::deprecated_text`: text - --> $DIR/deprecation-lint-3.rs:13:28 + --> $DIR/deprecation-lint-3.rs:12:28 | LL | macro_test_arg_nested!(deprecated_text); | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/deprecation-lint-3.rs:4:9 + --> $DIR/deprecation-lint-3.rs:3:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ diff --git a/tests/ui/duplicate/dupe-symbols-4.rs b/tests/ui/duplicate/dupe-symbols-4.rs index a9b7d689ad42..d961ba10e72f 100644 --- a/tests/ui/duplicate/dupe-symbols-4.rs +++ b/tests/ui/duplicate/dupe-symbols-4.rs @@ -1,7 +1,5 @@ //@ build-fail -// -//@ error-pattern: symbol `fail` is already defined #![crate_type="rlib"] #![allow(warnings)] @@ -20,5 +18,5 @@ impl A for B { impl A for C { #[no_mangle] - fn fail(self) {} + fn fail(self) {} //~ ERROR symbol `fail` is already defined } diff --git a/tests/ui/duplicate/dupe-symbols-4.stderr b/tests/ui/duplicate/dupe-symbols-4.stderr index 4c5f1e7867f5..e85d3f2b0634 100644 --- a/tests/ui/duplicate/dupe-symbols-4.stderr +++ b/tests/ui/duplicate/dupe-symbols-4.stderr @@ -1,5 +1,5 @@ error: symbol `fail` is already defined - --> $DIR/dupe-symbols-4.rs:23:5 + --> $DIR/dupe-symbols-4.rs:21:5 | LL | fn fail(self) {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/duplicate/dupe-symbols-7.rs b/tests/ui/duplicate/dupe-symbols-7.rs index 162c3c40446d..ea17942493cd 100644 --- a/tests/ui/duplicate/dupe-symbols-7.rs +++ b/tests/ui/duplicate/dupe-symbols-7.rs @@ -1,10 +1,7 @@ //@ build-fail //@ ignore-wasi wasi does different things with the `main` symbol -// -//@ error-pattern: entry symbol `main` declared multiple times - #![allow(warnings)] #[no_mangle] -fn main(){} +fn main(){} //~ ERROR entry symbol `main` declared multiple times diff --git a/tests/ui/duplicate/dupe-symbols-7.stderr b/tests/ui/duplicate/dupe-symbols-7.stderr index aa6213af2e4f..d75038569397 100644 --- a/tests/ui/duplicate/dupe-symbols-7.stderr +++ b/tests/ui/duplicate/dupe-symbols-7.stderr @@ -1,5 +1,5 @@ error: entry symbol `main` declared multiple times - --> $DIR/dupe-symbols-7.rs:10:1 + --> $DIR/dupe-symbols-7.rs:7:1 | LL | fn main(){} | ^^^^^^^^^ diff --git a/tests/ui/duplicate/dupe-symbols-8.rs b/tests/ui/duplicate/dupe-symbols-8.rs index 258e91fa8c87..b3c635f38ed6 100644 --- a/tests/ui/duplicate/dupe-symbols-8.rs +++ b/tests/ui/duplicate/dupe-symbols-8.rs @@ -1,11 +1,10 @@ //@ build-fail -//@ error-pattern: entry symbol `main` declared multiple times //@ ignore-wasi wasi does different things with the `main` symbol // // See #67946. #![allow(warnings)] -fn main() { +fn main() { //~ ERROR entry symbol `main` declared multiple times extern "Rust" { fn main(); } diff --git a/tests/ui/duplicate/dupe-symbols-8.stderr b/tests/ui/duplicate/dupe-symbols-8.stderr index 0f47d3683b5a..494fdcca327b 100644 --- a/tests/ui/duplicate/dupe-symbols-8.stderr +++ b/tests/ui/duplicate/dupe-symbols-8.stderr @@ -1,5 +1,5 @@ error: entry symbol `main` declared multiple times - --> $DIR/dupe-symbols-8.rs:8:1 + --> $DIR/dupe-symbols-8.rs:7:1 | LL | fn main() { | ^^^^^^^^^ diff --git a/tests/ui/elided-test.rs b/tests/ui/elided-test.rs index 025b75c1b5c8..2bedc25e17bb 100644 --- a/tests/ui/elided-test.rs +++ b/tests/ui/elided-test.rs @@ -1,7 +1,5 @@ -//@ error-pattern: `main` function not found - // Since we're not compiling a test runner this function should be elided // and the build will fail because main doesn't exist #[test] fn main() { -} +} //~ ERROR `main` function not found in crate `elided_test` diff --git a/tests/ui/elided-test.stderr b/tests/ui/elided-test.stderr index e323b8ba7ead..7aebe5d8264d 100644 --- a/tests/ui/elided-test.stderr +++ b/tests/ui/elided-test.stderr @@ -1,5 +1,5 @@ error[E0601]: `main` function not found in crate `elided_test` - --> $DIR/elided-test.rs:7:2 + --> $DIR/elided-test.rs:5:2 | LL | } | ^ consider adding a `main` function to `$DIR/elided-test.rs` diff --git a/tests/ui/error-codes/E0602.rs b/tests/ui/error-codes/E0602.rs index 1849fd2d895c..cba15bb92d45 100644 --- a/tests/ui/error-codes/E0602.rs +++ b/tests/ui/error-codes/E0602.rs @@ -1,8 +1,11 @@ //@ compile-flags:-D bogus //@ check-pass -//@ error-pattern:E0602 //@ error-pattern:requested on the command line with `-D bogus` //@ error-pattern:`#[warn(unknown_lints)]` on by default fn main() {} + +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `bogus` diff --git a/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr index 7aa66be0d097..b4f83f6bfc0a 100644 --- a/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr +++ b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr @@ -1,7 +1,7 @@ error[E0423]: expected value, found struct `remapped_dep::SomeStruct` --> $DIR/remap-path-prefix-reverse.rs:16:13 | -LL | let _ = remapped_dep::SomeStruct; // ~ERROR E0423 +LL | let _ = remapped_dep::SomeStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `remapped_dep::SomeStruct {}` | ::: remapped-aux/remapped_dep.rs:4:1 diff --git a/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr index 7aa66be0d097..b4f83f6bfc0a 100644 --- a/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr +++ b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr @@ -1,7 +1,7 @@ error[E0423]: expected value, found struct `remapped_dep::SomeStruct` --> $DIR/remap-path-prefix-reverse.rs:16:13 | -LL | let _ = remapped_dep::SomeStruct; // ~ERROR E0423 +LL | let _ = remapped_dep::SomeStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `remapped_dep::SomeStruct {}` | ::: remapped-aux/remapped_dep.rs:4:1 diff --git a/tests/ui/errors/remap-path-prefix-reverse.rs b/tests/ui/errors/remap-path-prefix-reverse.rs index 7743e38f50f0..28fdabb8f4df 100644 --- a/tests/ui/errors/remap-path-prefix-reverse.rs +++ b/tests/ui/errors/remap-path-prefix-reverse.rs @@ -13,5 +13,6 @@ extern crate remapped_dep; fn main() { // The actual error is irrelevant. The important part it that is should show // a snippet of the dependency's source. - let _ = remapped_dep::SomeStruct; // ~ERROR E0423 + let _ = remapped_dep::SomeStruct; + //~^ ERROR expected value, found struct `remapped_dep::SomeStruct` } diff --git a/tests/ui/errors/remap-path-prefix-sysroot.rs b/tests/ui/errors/remap-path-prefix-sysroot.rs index 7281e6da0944..5e2e4fab51de 100644 --- a/tests/ui/errors/remap-path-prefix-sysroot.rs +++ b/tests/ui/errors/remap-path-prefix-sysroot.rs @@ -3,7 +3,6 @@ //@ [with-remap]compile-flags: --remap-path-prefix={{rust-src-base}}=remapped //@ [with-remap]compile-flags: --remap-path-prefix={{src-base}}=remapped-tests-ui //@ [without-remap]compile-flags: -//@ error-pattern: E0507 // The $SRC_DIR*.rs:LL:COL normalisation doesn't kick in automatically // as the remapped revision will not begin with $SRC_DIR_REAL, @@ -18,7 +17,10 @@ struct Worker { impl Drop for Worker { fn drop(&mut self) { self.thread.join().unwrap(); + //[without-remap]~^ ERROR cannot move out of `self.thread` which is behind a mutable reference } } pub fn main(){} + +//[with-remap]~? ERROR cannot move out of `self.thread` which is behind a mutable reference diff --git a/tests/ui/errors/remap-path-prefix.normal.stderr b/tests/ui/errors/remap-path-prefix.normal.stderr index 46d33d26052c..5a125a7024a9 100644 --- a/tests/ui/errors/remap-path-prefix.normal.stderr +++ b/tests/ui/errors/remap-path-prefix.normal.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `ferris` in this scope - --> remapped/errors/remap-path-prefix.rs:19:5 + --> remapped/errors/remap-path-prefix.rs:15:5 | LL | ferris | ^^^^^^ not found in this scope diff --git a/tests/ui/errors/remap-path-prefix.rs b/tests/ui/errors/remap-path-prefix.rs index 8809caa4d4f1..7e38e16280f5 100644 --- a/tests/ui/errors/remap-path-prefix.rs +++ b/tests/ui/errors/remap-path-prefix.rs @@ -7,14 +7,13 @@ // The remapped paths are not normalized by compiletest. //@ normalize-stderr: "\\(errors)" -> "/$1" -// The remapped paths aren't recognized by compiletest, so we -// cannot use line-specific patterns. -//@ error-pattern: E0425 - fn main() { // We cannot actually put an ERROR marker here because // the file name in the error message is not what the // test framework expects (since the filename gets remapped). // We still test the expected error in the stderr file. - ferris + ferris //[without-diagnostic-scope]~ ERROR cannot find value `ferris` in this scope } + +//[normal]~? ERROR cannot find value `ferris` in this scope +//[with-diagnostic-scope]~? ERROR cannot find value `ferris` in this scope diff --git a/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr b/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr index 46d33d26052c..5a125a7024a9 100644 --- a/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr +++ b/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `ferris` in this scope - --> remapped/errors/remap-path-prefix.rs:19:5 + --> remapped/errors/remap-path-prefix.rs:15:5 | LL | ferris | ^^^^^^ not found in this scope diff --git a/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr b/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr index 0badea6e27bf..b6332685dbf0 100644 --- a/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr +++ b/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `ferris` in this scope - --> $DIR/remap-path-prefix.rs:19:5 + --> $DIR/remap-path-prefix.rs:15:5 | LL | ferris | ^^^^^^ not found in this scope diff --git a/tests/ui/expr/if/if-typeck.rs b/tests/ui/expr/if/if-typeck.rs index ba828f11e79b..0985598f0f75 100644 --- a/tests/ui/expr/if/if-typeck.rs +++ b/tests/ui/expr/if/if-typeck.rs @@ -1,4 +1,3 @@ -//@ error-pattern:mismatched types // issue #513 fn f() { } @@ -6,5 +5,5 @@ fn f() { } fn main() { // f is not a bool - if f { } + if f { } //~ ERROR mismatched types } diff --git a/tests/ui/expr/if/if-typeck.stderr b/tests/ui/expr/if/if-typeck.stderr index 1be43a20105f..bca00f890cbe 100644 --- a/tests/ui/expr/if/if-typeck.stderr +++ b/tests/ui/expr/if/if-typeck.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/if-typeck.rs:9:8 + --> $DIR/if-typeck.rs:8:8 | LL | if f { } | ^ expected `bool`, found fn item diff --git a/tests/ui/ext-nonexistent.rs b/tests/ui/ext-nonexistent.rs index a66407953a99..1293324b67eb 100644 --- a/tests/ui/ext-nonexistent.rs +++ b/tests/ui/ext-nonexistent.rs @@ -1,2 +1,2 @@ -//@ error-pattern:cannot find macro fn main() { iamnotanextensionthatexists!(""); } +//~^ ERROR cannot find macro `iamnotanextensionthatexists` in this scope diff --git a/tests/ui/ext-nonexistent.stderr b/tests/ui/ext-nonexistent.stderr index 8891e823e4af..edb59bba6e5d 100644 --- a/tests/ui/ext-nonexistent.stderr +++ b/tests/ui/ext-nonexistent.stderr @@ -1,5 +1,5 @@ error: cannot find macro `iamnotanextensionthatexists` in this scope - --> $DIR/ext-nonexistent.rs:2:13 + --> $DIR/ext-nonexistent.rs:1:13 | LL | fn main() { iamnotanextensionthatexists!(""); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/extern-flag/empty-extern-arg.rs b/tests/ui/extern-flag/empty-extern-arg.rs index dea68b5b1ad4..2dee721ed03c 100644 --- a/tests/ui/extern-flag/empty-extern-arg.rs +++ b/tests/ui/extern-flag/empty-extern-arg.rs @@ -1,6 +1,9 @@ +//~ ERROR extern location for std does not exist //@ compile-flags: --extern std= -//@ error-pattern: extern location for std does not exist //@ needs-unwind since it affects the error output //@ ignore-emscripten missing eh_catch_typeinfo lang item fn main() {} + +//~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/extern-flag/invalid-crate-name-dashed.rs b/tests/ui/extern-flag/invalid-crate-name-dashed.rs index b846214175e1..b336cc84569e 100644 --- a/tests/ui/extern-flag/invalid-crate-name-dashed.rs +++ b/tests/ui/extern-flag/invalid-crate-name-dashed.rs @@ -1,5 +1,4 @@ //@ compile-flags: --extern=my-awesome-library=libawesome.rlib -//@ error-pattern: crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier //@ error-pattern: consider replacing the dashes with underscores: `my_awesome_library` // In a sense, this is a regression test for issue #113035. We no longer suggest @@ -8,3 +7,5 @@ pub use my_awesome_library::*; fn main() {} + +//~? ERROR crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier diff --git a/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs b/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs index 5231503820fa..718189382838 100644 --- a/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs +++ b/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs @@ -1,4 +1,5 @@ //@ compile-flags: --extern čɍαţē=libnon_ascii.rlib -//@ error-pattern: crate name `čɍαţē` passed to `--extern` is not a valid ASCII identifier fn main() {} + +//~? ERROR crate name `čɍαţē` passed to `--extern` is not a valid ASCII identifier diff --git a/tests/ui/extern-flag/invalid-crate-name.rs b/tests/ui/extern-flag/invalid-crate-name.rs index c7b5b637217a..5d73e1196736 100644 --- a/tests/ui/extern-flag/invalid-crate-name.rs +++ b/tests/ui/extern-flag/invalid-crate-name.rs @@ -1,4 +1,5 @@ //@ compile-flags: --extern=?#1%$ -//@ error-pattern: crate name `?#1%$` passed to `--extern` is not a valid ASCII identifier fn main() {} + +//~? ERROR crate name `?#1%$` passed to `--extern` is not a valid ASCII identifier diff --git a/tests/ui/extern-flag/no-force-extern.rs b/tests/ui/extern-flag/no-force-extern.rs index 11d2f91c7bbf..c9317abe292c 100644 --- a/tests/ui/extern-flag/no-force-extern.rs +++ b/tests/ui/extern-flag/no-force-extern.rs @@ -1,10 +1,12 @@ //@ aux-crate:panic_handler=panic_handler.rs //@ ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header) // compile_flags: -Zunstable-options --crate-type dylib -//@ error-pattern: `#[panic_handler]` function required, but not found //@ dont-check-compiler-stderr //@ edition: 2018 #![no_std] -fn foo() {} +fn foo() {} //~ ERROR `main` function not found in crate `no_force_extern` + +//~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/fn/fn-bad-block-type.rs b/tests/ui/fn/fn-bad-block-type.rs index c7ad462f1431..47ddc583c877 100644 --- a/tests/ui/fn/fn-bad-block-type.rs +++ b/tests/ui/fn/fn-bad-block-type.rs @@ -1,5 +1,3 @@ -//@ error-pattern:mismatched types - -fn f() -> isize { true } +fn f() -> isize { true } //~ ERROR mismatched types fn main() { } diff --git a/tests/ui/fn/fn-bad-block-type.stderr b/tests/ui/fn/fn-bad-block-type.stderr index 6917bea65915..287caee45821 100644 --- a/tests/ui/fn/fn-bad-block-type.stderr +++ b/tests/ui/fn/fn-bad-block-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/fn-bad-block-type.rs:3:19 + --> $DIR/fn-bad-block-type.rs:1:19 | LL | fn f() -> isize { true } | ----- ^^^^ expected `isize`, found `bool` diff --git a/tests/ui/imports/import-loop-2.rs b/tests/ui/imports/import-loop-2.rs index d9a56cb13784..1bd0f06c671a 100644 --- a/tests/ui/imports/import-loop-2.rs +++ b/tests/ui/imports/import-loop-2.rs @@ -1,11 +1,9 @@ -//@ error-pattern:import - mod a { pub use b::x; } mod b { - pub use a::x; + pub use a::x; //~ ERROR unresolved import `a::x` fn main() { let y = x; } } diff --git a/tests/ui/imports/import-loop-2.stderr b/tests/ui/imports/import-loop-2.stderr index 1a95200a6622..2521b6e7c044 100644 --- a/tests/ui/imports/import-loop-2.stderr +++ b/tests/ui/imports/import-loop-2.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `a::x` - --> $DIR/import-loop-2.rs:8:13 + --> $DIR/import-loop-2.rs:6:13 | LL | pub use a::x; | ^^^^ no `x` in `a` diff --git a/tests/ui/imports/import-loop.rs b/tests/ui/imports/import-loop.rs index 1ba9e0900334..fc5bd32adeee 100644 --- a/tests/ui/imports/import-loop.rs +++ b/tests/ui/imports/import-loop.rs @@ -1,9 +1,7 @@ -//@ error-pattern:import - use y::x; mod y { - pub use y::x; + pub use y::x; //~ ERROR unresolved import `y::x` } fn main() { } diff --git a/tests/ui/imports/import-loop.stderr b/tests/ui/imports/import-loop.stderr index 8ad2d6be4d27..801fc2552b6e 100644 --- a/tests/ui/imports/import-loop.stderr +++ b/tests/ui/imports/import-loop.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `y::x` - --> $DIR/import-loop.rs:6:13 + --> $DIR/import-loop.rs:4:13 | LL | pub use y::x; | ^^^^ no `x` in `y` diff --git a/tests/ui/imports/import3.rs b/tests/ui/imports/import3.rs index 71eea0ebb266..7bd6458cba10 100644 --- a/tests/ui/imports/import3.rs +++ b/tests/ui/imports/import3.rs @@ -1,4 +1,3 @@ -//@ error-pattern: unresolved -use main::bar; +use main::bar; //~ ERROR unresolved import `main` fn main() { println!("foo"); } diff --git a/tests/ui/imports/import3.stderr b/tests/ui/imports/import3.stderr index 7f5811467811..871104ce50da 100644 --- a/tests/ui/imports/import3.stderr +++ b/tests/ui/imports/import3.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `main` - --> $DIR/import3.rs:2:5 + --> $DIR/import3.rs:1:5 | LL | use main::bar; | ^^^^ use of unresolved module or unlinked crate `main` diff --git a/tests/ui/imports/import4.rs b/tests/ui/imports/import4.rs index 8d727ced8907..01535fc6f45d 100644 --- a/tests/ui/imports/import4.rs +++ b/tests/ui/imports/import4.rs @@ -1,7 +1,4 @@ -//@ error-pattern: import - - mod a { pub use b::foo; } -mod b { pub use a::foo; } +mod b { pub use a::foo; } //~ ERROR unresolved import `a::foo` fn main() { println!("loop"); } diff --git a/tests/ui/imports/import4.stderr b/tests/ui/imports/import4.stderr index c99e83851187..c979d6c9ae24 100644 --- a/tests/ui/imports/import4.stderr +++ b/tests/ui/imports/import4.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `a::foo` - --> $DIR/import4.rs:5:17 + --> $DIR/import4.rs:2:17 | LL | mod b { pub use a::foo; } | ^^^^^^ no `foo` in `a` diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs index e28b8f373dab..f50c4a5207a5 100644 --- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs +++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs @@ -1,8 +1,6 @@ +//~ ERROR reached the recursion limit while instantiating ` as Pointee>::Metadata` as a rigid projection after reaching the recursion // limit when finding the struct tail. @@ -73,3 +71,16 @@ fn main() { let test = SomeData([0; 256]); test.virtualize(); } + +//~? ERROR reached the recursion limit finding the struct tail for `[u8; 256]` +//~? ERROR reached the recursion limit finding the struct tail for `[u8; 256]` +//~? ERROR reached the recursion limit finding the struct tail for `[u8; 256]` +//~? ERROR reached the recursion limit finding the struct tail for `[u8; 256]` +//~? ERROR reached the recursion limit finding the struct tail for `SomeData<256>` +//~? ERROR reached the recursion limit finding the struct tail for `SomeData<256>` +//~? ERROR reached the recursion limit finding the struct tail for `SomeData<256>` +//~? ERROR reached the recursion limit finding the struct tail for `SomeData<256>` +//~? ERROR reached the recursion limit finding the struct tail for `VirtualWrapper, 0>` +//~? ERROR reached the recursion limit finding the struct tail for `VirtualWrapper, 0>` +//~? ERROR reached the recursion limit finding the struct tail for `VirtualWrapper, 0>` +//~? ERROR reached the recursion limit finding the struct tail for `VirtualWrapper, 0>` diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr index 475e26fd0f06..59addc5cc4a7 100644 --- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr +++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr @@ -18,7 +18,7 @@ error: reached the recursion limit finding the struct tail for `[u8; 256]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` note: the above error was encountered while instantiating `fn virtualize_my_trait::, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>` - --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18 + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:18 | LL | unsafe { virtualize_my_trait(L, self) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ error: reached the recursion limit finding the struct tail for `SomeData<256>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` note: the above error was encountered while instantiating `fn virtualize_my_trait::, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>` - --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18 + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:18 | LL | unsafe { virtualize_my_trait(L, self) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ error: reached the recursion limit finding the struct tail for `VirtualWrapper, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>` - --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18 + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:18 | LL | unsafe { virtualize_my_trait(L, self) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | unsafe { virtualize_my_trait(L, self) } error: reached the recursion limit while instantiating `, 1>, 1>, 1>, 1> as MyTrait>::virtualize` | note: ` as MyTrait>::virtualize` defined here - --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:25:5 + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:23:5 | LL | fn virtualize(&self) -> &dyn MyTrait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/instrument-xray/flags-always-never-1.rs b/tests/ui/instrument-xray/flags-always-never-1.rs index 91032662e6b2..97f03fca1027 100644 --- a/tests/ui/instrument-xray/flags-always-never-1.rs +++ b/tests/ui/instrument-xray/flags-always-never-1.rs @@ -2,6 +2,7 @@ // //@ needs-xray //@ compile-flags: -Z instrument-xray=always,never -//@ error-pattern: incorrect value `always,never` for unstable option `instrument-xray` fn main() {} + +//~? ERROR incorrect value `always,never` for unstable option `instrument-xray` diff --git a/tests/ui/instrument-xray/flags-dupe-always.rs b/tests/ui/instrument-xray/flags-dupe-always.rs index 41e4f267b471..e3a5b3b1c3e2 100644 --- a/tests/ui/instrument-xray/flags-dupe-always.rs +++ b/tests/ui/instrument-xray/flags-dupe-always.rs @@ -2,6 +2,7 @@ // //@ needs-xray //@ compile-flags: -Z instrument-xray=always,always -//@ error-pattern: incorrect value `always,always` for unstable option `instrument-xray` fn main() {} + +//~? ERROR incorrect value `always,always` for unstable option `instrument-xray` diff --git a/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs b/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs index ba5ea28d40b7..648bd1446326 100644 --- a/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs +++ b/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs @@ -2,6 +2,7 @@ // //@ needs-xray //@ compile-flags: -Z instrument-xray=ignore-loops,ignore-loops -//@ error-pattern: incorrect value `ignore-loops,ignore-loops` for unstable option `instrument-xray` fn main() {} + +//~? ERROR incorrect value `ignore-loops,ignore-loops` for unstable option `instrument-xray` diff --git a/tests/ui/instrument-xray/target-not-supported.rs b/tests/ui/instrument-xray/target-not-supported.rs index cdae26f993d3..2045913b186c 100644 --- a/tests/ui/instrument-xray/target-not-supported.rs +++ b/tests/ui/instrument-xray/target-not-supported.rs @@ -2,8 +2,9 @@ // //@ needs-llvm-components: x86 //@ compile-flags: -Z instrument-xray --target x86_64-apple-darwin -//@ error-pattern: error: XRay instrumentation is not supported for this target #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR XRay instrumentation is not supported for this target diff --git a/tests/ui/internal/internal-unstable-noallow.rs b/tests/ui/internal/internal-unstable-noallow.rs index 57ddb93d8801..507eeebddc0d 100644 --- a/tests/ui/internal/internal-unstable-noallow.rs +++ b/tests/ui/internal/internal-unstable-noallow.rs @@ -4,20 +4,18 @@ // the // ~ form. //@ aux-build:internal_unstable.rs -//@ error-pattern:use of unstable library feature `function` -//@ error-pattern:use of unstable library feature `struct_field` -//@ error-pattern:use of unstable library feature `method` -//@ error-pattern:use of unstable library feature `struct2_field` #[macro_use] extern crate internal_unstable; fn main() { - call_unstable_noallow!(); + call_unstable_noallow!(); //~ ERROR use of unstable library feature `function` - construct_unstable_noallow!(0); + construct_unstable_noallow!(0); //~ ERROR use of unstable library feature `struct_field` |x: internal_unstable::Foo| { call_method_noallow!(x) }; + //~^ ERROR use of unstable library feature `method` |x: internal_unstable::Bar| { access_field_noallow!(x) }; + //~^ ERROR use of unstable library feature `struct2_field` } diff --git a/tests/ui/internal/internal-unstable-noallow.stderr b/tests/ui/internal/internal-unstable-noallow.stderr index 22f42abbd114..2cc55022ef3d 100644 --- a/tests/ui/internal/internal-unstable-noallow.stderr +++ b/tests/ui/internal/internal-unstable-noallow.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable-noallow.rs:16:5 + --> $DIR/internal-unstable-noallow.rs:12:5 | LL | call_unstable_noallow!(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | call_unstable_noallow!(); = note: this error originates in the macro `call_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature `struct_field` - --> $DIR/internal-unstable-noallow.rs:18:5 + --> $DIR/internal-unstable-noallow.rs:14:5 | LL | construct_unstable_noallow!(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | construct_unstable_noallow!(0); = note: this error originates in the macro `construct_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature `method` - --> $DIR/internal-unstable-noallow.rs:20:35 + --> $DIR/internal-unstable-noallow.rs:16:35 | LL | |x: internal_unstable::Foo| { call_method_noallow!(x) }; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | |x: internal_unstable::Foo| { call_method_noallow!(x) }; = note: this error originates in the macro `call_method_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature `struct2_field` - --> $DIR/internal-unstable-noallow.rs:22:35 + --> $DIR/internal-unstable-noallow.rs:19:35 | LL | |x: internal_unstable::Bar| { access_field_noallow!(x) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/invalid-compile-flags/crate-type-flag.rs b/tests/ui/invalid-compile-flags/crate-type-flag.rs index 010143071497..8ccce97f7bfa 100644 --- a/tests/ui/invalid-compile-flags/crate-type-flag.rs +++ b/tests/ui/invalid-compile-flags/crate-type-flag.rs @@ -45,16 +45,17 @@ // `proc-macro` is accepted, but `proc_macro` is not. //@ revisions: proc_underscore_macro //@[proc_underscore_macro] compile-flags: --crate-type=proc_macro -//@[proc_underscore_macro] error-pattern: unknown crate type: `proc_macro` // Empty `--crate-type` not accepted. //@ revisions: empty_crate_type //@[empty_crate_type] compile-flags: --crate-type= -//@[empty_crate_type] error-pattern: unknown crate type: `` // Random unknown crate type. Also check that we can handle non-ASCII. //@ revisions: unknown //@[unknown] compile-flags: --crate-type=🤡 -//@[unknown] error-pattern: unknown crate type: `🤡` fn main() {} + +//[proc_underscore_macro]~? ERROR unknown crate type: `proc_macro` +//[empty_crate_type]~? ERROR unknown crate type: `` +//[unknown]~? ERROR unknown crate type: `🤡` diff --git a/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs b/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs index 6a4ecb9d8397..c7973c686da0 100644 --- a/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs +++ b/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs @@ -13,8 +13,9 @@ //@[aarch64] check-fail //@[aarch64] needs-llvm-components: aarch64 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu -//@[aarch64] error-pattern: `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 #![feature(no_core)] #![no_core] #![no_main] + +//[aarch64]~? ERROR `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 diff --git a/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs b/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs index f4be36e08f09..fa3958c1f987 100644 --- a/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs +++ b/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs @@ -14,8 +14,9 @@ //@[large] check-fail //@[large] compile-flags: -Ccode-model=large -//@[large] error-pattern: `-Zfunction-return=thunk-extern` is only supported on non-large code models #![feature(no_core)] #![no_core] #![no_main] + +//[large]~? ERROR `-Zfunction-return=thunk-extern` is only supported on non-large code models diff --git a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs index b5e34bece320..436442ee7299 100644 --- a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs +++ b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs @@ -9,13 +9,14 @@ //@[x86_64] check-fail //@[x86_64] needs-llvm-components: x86 //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -//@[x86_64] error-pattern: `-Zreg-struct-return` is only supported on x86 //@[aarch64] check-fail //@[aarch64] needs-llvm-components: aarch64 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu -//@[aarch64] error-pattern: `-Zreg-struct-return` is only supported on x86 #![feature(no_core)] #![no_core] #![no_main] + +//[x86_64]~? ERROR `-Zreg-struct-return` is only supported on x86 +//[aarch64]~? ERROR `-Zreg-struct-return` is only supported on x86 diff --git a/tests/ui/invalid-compile-flags/regparm/regparm-valid-values.rs b/tests/ui/invalid-compile-flags/regparm/regparm-valid-values.rs index b548d678520b..a66dfe859771 100644 --- a/tests/ui/invalid-compile-flags/regparm/regparm-valid-values.rs +++ b/tests/ui/invalid-compile-flags/regparm/regparm-valid-values.rs @@ -17,8 +17,9 @@ //@[regparm4] check-fail //@[regparm4] compile-flags: -Zregparm=4 -//@[regparm4] error-pattern: `-Zregparm=4` is unsupported (valid values 0-3) #![feature(no_core)] #![no_core] #![no_main] + +//[regparm4]~? ERROR `-Zregparm=4` is unsupported (valid values 0-3) diff --git a/tests/ui/invalid-compile-flags/regparm/requires-x86.rs b/tests/ui/invalid-compile-flags/regparm/requires-x86.rs index ce6e437fb476..32c4b5af3577 100644 --- a/tests/ui/invalid-compile-flags/regparm/requires-x86.rs +++ b/tests/ui/invalid-compile-flags/regparm/requires-x86.rs @@ -9,13 +9,14 @@ //@[x86_64] check-fail //@[x86_64] needs-llvm-components: x86 //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -//@[x86_64] error-pattern: `-Zregparm=N` is only supported on x86 //@[aarch64] check-fail //@[aarch64] needs-llvm-components: aarch64 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu -//@[aarch64] error-pattern: `-Zregparm=N` is only supported on x86 #![feature(no_core)] #![no_core] #![no_main] + +//[x86_64]~? ERROR `-Zregparm=N` is only supported on x86 +//[aarch64]~? ERROR `-Zregparm=N` is only supported on x86 diff --git a/tests/ui/invalid/issue-114435-layout-type-err.rs b/tests/ui/invalid/issue-114435-layout-type-err.rs index 2a86839e416f..07f310478d3c 100644 --- a/tests/ui/invalid/issue-114435-layout-type-err.rs +++ b/tests/ui/invalid/issue-114435-layout-type-err.rs @@ -1,6 +1,5 @@ //@ check-fail //@ compile-flags: --crate-type lib -Cdebuginfo=2 -//@ error-pattern: recursion limit #![recursion_limit = "10"] macro_rules! link { @@ -41,3 +40,5 @@ link!(J, K); link!(K, Bottom); fn main() {} + +//~? ERROR reached the recursion limit finding the struct tail for `Bottom` diff --git a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs index 7cae77eb67f4..5a5d0086aa96 100644 --- a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs +++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs @@ -16,8 +16,6 @@ // rely on the checking of the normalized stderr output as our actual // "verification" of the diagnostic). -//@ error-pattern: error - // On Mac OS X, we get an error like the below //@ normalize-stderr: "failed to write bytecode to ./does-not-exist/output.non_ice_error_on_worker_io_fail.*" -> "io error modifying ./does-not-exist/" @@ -29,3 +27,5 @@ //@ ignore-arm - the file-system issues do not replicate here, at least on armhf-gnu #![crate_type = "lib"] + +//~? ERROR /does-not-exist/ diff --git a/tests/ui/issues/issue-37131.rs b/tests/ui/issues/issue-37131.rs index 3ea14672e239..16681ac21d11 100644 --- a/tests/ui/issues/issue-37131.rs +++ b/tests/ui/issues/issue-37131.rs @@ -1,3 +1,4 @@ +//~ ERROR can't find crate for `std` // Tests that compiling for a target which is not installed will result in a helpful // error message. diff --git a/tests/ui/lang-items/lang-item-missing.rs b/tests/ui/lang-items/lang-item-missing.rs index 5b832a5bb8f0..75e203d04f29 100644 --- a/tests/ui/lang-items/lang-item-missing.rs +++ b/tests/ui/lang-items/lang-item-missing.rs @@ -1,13 +1,11 @@ // Test that a missing lang item (in this case `sized`) does not cause an ICE, // see #17392. -//@ error-pattern: requires `sized` lang_item - #![feature(lang_items, no_core)] #![no_core] #![no_main] #[no_mangle] -extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { //~ ERROR requires `sized` lang_item loop {} } diff --git a/tests/ui/lang-items/lang-item-missing.stderr b/tests/ui/lang-items/lang-item-missing.stderr index 63bca95adf70..85e9eaafe72c 100644 --- a/tests/ui/lang-items/lang-item-missing.stderr +++ b/tests/ui/lang-items/lang-item-missing.stderr @@ -1,5 +1,5 @@ error: requires `sized` lang_item - --> $DIR/lang-item-missing.rs:11:60 + --> $DIR/lang-item-missing.rs:9:60 | LL | extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { | ^^^ diff --git a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs index 9b634ee8ee3e..f92a00e602cf 100644 --- a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs +++ b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs @@ -1,5 +1,3 @@ -//@ error-pattern: requires `copy` lang_item - #![feature(lang_items, no_core)] #![no_core] #![no_main] @@ -11,5 +9,5 @@ struct S; #[no_mangle] extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { - argc + argc //~ ERROR requires `copy` lang_item } diff --git a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr index 3dc7716ecd2a..9b25b1db292f 100644 --- a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr +++ b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr @@ -1,5 +1,5 @@ error: requires `copy` lang_item - --> $DIR/missing-copy-lang-item-issue-19660.rs:14:5 + --> $DIR/missing-copy-lang-item-issue-19660.rs:12:5 | LL | argc | ^^^^ diff --git a/tests/ui/layout/size-of-val-raw-too-big.rs b/tests/ui/layout/size-of-val-raw-too-big.rs index dfca6d6eb764..566b01255fae 100644 --- a/tests/ui/layout/size-of-val-raw-too-big.rs +++ b/tests/ui/layout/size-of-val-raw-too-big.rs @@ -1,7 +1,8 @@ +//~ ERROR values of the type `Example` are too big for the target architecture //@ build-fail //@ compile-flags: --crate-type lib //@ only-32bit Layout computation rejects this layout for different reasons on 64-bit. -//@ error-pattern: too big for the target architecture + #![feature(core_intrinsics)] #![allow(internal_features)] diff --git a/tests/ui/layout/unknown-when-no-type-parameter.rs b/tests/ui/layout/unknown-when-no-type-parameter.rs index 94c32cf262f2..500b7938eeb0 100644 --- a/tests/ui/layout/unknown-when-no-type-parameter.rs +++ b/tests/ui/layout/unknown-when-no-type-parameter.rs @@ -1,6 +1,5 @@ #![feature(trivial_bounds)] -//@ error-pattern: error[E0080]: evaluation of constant value failed //@ error-pattern: the type `<() as Project>::Assoc` has an unknown layout trait Project { @@ -8,7 +7,7 @@ trait Project { } fn foo() where (): Project { - [(); size_of::<<() as Project>::Assoc>()]; + [(); size_of::<<() as Project>::Assoc>()]; //~ ERROR evaluation of constant value failed } fn main() {} diff --git a/tests/ui/layout/unknown-when-no-type-parameter.stderr b/tests/ui/layout/unknown-when-no-type-parameter.stderr index 9e414d224bbc..a2dbb191ee27 100644 --- a/tests/ui/layout/unknown-when-no-type-parameter.stderr +++ b/tests/ui/layout/unknown-when-no-type-parameter.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/unknown-when-no-type-parameter.rs:11:10 + --> $DIR/unknown-when-no-type-parameter.rs:10:10 | LL | [(); size_of::<<() as Project>::Assoc>()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `<() as Project>::Assoc` has an unknown layout diff --git a/tests/ui/limits/issue-17913.rs b/tests/ui/limits/issue-17913.rs index 5407902daba5..85deab4bc4c7 100644 --- a/tests/ui/limits/issue-17913.rs +++ b/tests/ui/limits/issue-17913.rs @@ -1,6 +1,5 @@ //@ build-fail //@ normalize-stderr: "\[&usize; \d+\]" -> "[&usize; usize::MAX]" -//@ error-pattern: too big for the target architecture #[cfg(target_pointer_width = "64")] fn main() { @@ -15,3 +14,5 @@ fn main() { let a: Box<_> = Box::new([&n; 0xFFFFFFFF_usize]); println!("{}", a[0xFFFFFF_usize]); } + +//~? ERROR are too big for the target architecture diff --git a/tests/ui/limits/issue-55878.rs b/tests/ui/limits/issue-55878.rs index db4a2724452a..614ff328bf5e 100644 --- a/tests/ui/limits/issue-55878.rs +++ b/tests/ui/limits/issue-55878.rs @@ -1,6 +1,6 @@ //@ build-fail -//@ error-pattern: are too big for the target architecture fn main() { println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); + //~^ ERROR evaluation of constant value failed } diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr index d705b3daf79e..9b3922d7933d 100644 --- a/tests/ui/limits/issue-55878.stderr +++ b/tests/ui/limits/issue-55878.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/issue-55878.rs:5:26 + --> $DIR/issue-55878.rs:4:26 | LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; usize::MAX]` are too big for the target architecture diff --git a/tests/ui/link-native-libs/empty-kind-1.rs b/tests/ui/link-native-libs/empty-kind-1.rs index d9b8d8a7f7d6..04e7e3c2c7b3 100644 --- a/tests/ui/link-native-libs/empty-kind-1.rs +++ b/tests/ui/link-native-libs/empty-kind-1.rs @@ -1,6 +1,7 @@ // Unspecified kind should fail with an error //@ compile-flags: -l =mylib -//@ error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg fn main() {} + +//~? ERROR unknown library kind `` diff --git a/tests/ui/link-native-libs/empty-kind-2.rs b/tests/ui/link-native-libs/empty-kind-2.rs index 16cb3b917e4b..1436c086dfdc 100644 --- a/tests/ui/link-native-libs/empty-kind-2.rs +++ b/tests/ui/link-native-libs/empty-kind-2.rs @@ -1,6 +1,7 @@ // Unspecified kind should fail with an error //@ compile-flags: -l :+bundle=mylib -//@ error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg fn main() {} + +//~? ERROR unknown library kind `` diff --git a/tests/ui/link-native-libs/link-arg-error.rs b/tests/ui/link-native-libs/link-arg-error.rs index 4defb108178b..9d9dcc27ccb8 100644 --- a/tests/ui/link-native-libs/link-arg-error.rs +++ b/tests/ui/link-native-libs/link-arg-error.rs @@ -1,4 +1,5 @@ //@ compile-flags: -l link-arg:+bundle=arg -Z unstable-options -//@ error-pattern: linking modifier `bundle` is only compatible with `static` linking kind fn main() {} + +//~? ERROR linking modifier `bundle` is only compatible with `static` linking kind diff --git a/tests/ui/link-native-libs/manual-link-bad-form.rs b/tests/ui/link-native-libs/manual-link-bad-form.rs index 0f5723adec98..71e80c60dece 100644 --- a/tests/ui/link-native-libs/manual-link-bad-form.rs +++ b/tests/ui/link-native-libs/manual-link-bad-form.rs @@ -1,5 +1,6 @@ //@ compile-flags:-l static= -//@ error-pattern: library name must not be empty fn main() { } + +//~? ERROR library name must not be empty diff --git a/tests/ui/link-native-libs/manual-link-bad-kind.rs b/tests/ui/link-native-libs/manual-link-bad-kind.rs index d070faa65745..8b5f478e80a6 100644 --- a/tests/ui/link-native-libs/manual-link-bad-kind.rs +++ b/tests/ui/link-native-libs/manual-link-bad-kind.rs @@ -1,5 +1,6 @@ //@ compile-flags:-l bar=foo -//@ error-pattern: unknown library kind `bar`, expected one of: static, dylib, framework, link-arg fn main() { } + +//~? ERROR unknown library kind `bar` diff --git a/tests/ui/link-native-libs/manual-link-bad-search-path.rs b/tests/ui/link-native-libs/manual-link-bad-search-path.rs index c9ced4734fc0..cc4a5ef22679 100644 --- a/tests/ui/link-native-libs/manual-link-bad-search-path.rs +++ b/tests/ui/link-native-libs/manual-link-bad-search-path.rs @@ -1,5 +1,6 @@ //@ compile-flags:-L native= -//@ error-pattern: empty search path given via `-L` fn main() { } + +//~? ERROR empty search path given via `-L` diff --git a/tests/ui/link-native-libs/manual-link-framework.rs b/tests/ui/link-native-libs/manual-link-framework.rs index 43cdda0a4e6a..b3c3d6a7c3c2 100644 --- a/tests/ui/link-native-libs/manual-link-framework.rs +++ b/tests/ui/link-native-libs/manual-link-framework.rs @@ -1,5 +1,6 @@ //@ ignore-apple //@ compile-flags:-l framework=foo -//@ error-pattern: library kind `framework` is only supported on Apple targets fn main() {} + +//~? ERROR library kind `framework` is only supported on Apple targets diff --git a/tests/ui/link-native-libs/manual-link-unsupported-kind.rs b/tests/ui/link-native-libs/manual-link-unsupported-kind.rs index b5b9e3e65777..3dfe9bdebc55 100644 --- a/tests/ui/link-native-libs/manual-link-unsupported-kind.rs +++ b/tests/ui/link-native-libs/manual-link-unsupported-kind.rs @@ -1,5 +1,6 @@ //@ compile-flags:-l raw-dylib=foo -//@ error-pattern: unknown library kind `raw-dylib`, expected one of: static, dylib, framework, link-arg fn main() { } + +//~? ERROR unknown library kind `raw-dylib` diff --git a/tests/ui/link-native-libs/modifiers-override-3.rs b/tests/ui/link-native-libs/modifiers-override-3.rs index d05735ad6162..3d269dbd8124 100644 --- a/tests/ui/link-native-libs/modifiers-override-3.rs +++ b/tests/ui/link-native-libs/modifiers-override-3.rs @@ -2,6 +2,7 @@ // overrides another command line library with modifiers. //@ compile-flags:-lstatic:+whole-archive=foo -lstatic:+whole-archive=foo -//@ error-pattern: overriding linking modifiers from command line is not supported fn main() {} + +//~? ERROR overriding linking modifiers from command line is not supported diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.rs b/tests/ui/link-native-libs/suggest-libname-only-1.rs index 328181fb5cbf..4ccfa086bde6 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-1.rs +++ b/tests/ui/link-native-libs/suggest-libname-only-1.rs @@ -1,9 +1,10 @@ //@ build-fail //@ compile-flags: --crate-type rlib -//@ error-pattern: could not find native static library `libfoo.a` //@ error-pattern: only provide the library name `foo`, not the full filename #[link(name = "libfoo.a", kind = "static")] -extern { } +extern { } //~ WARN extern declarations without an explicit ABI are deprecated pub fn main() { } + +//~? ERROR could not find native static library `libfoo.a` diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.stderr b/tests/ui/link-native-libs/suggest-libname-only-1.stderr index 47f7d92c9f9e..85a3599e8dbd 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-1.stderr +++ b/tests/ui/link-native-libs/suggest-libname-only-1.stderr @@ -1,5 +1,5 @@ warning: extern declarations without an explicit ABI are deprecated - --> $DIR/suggest-libname-only-1.rs:7:1 + --> $DIR/suggest-libname-only-1.rs:6:1 | LL | extern { } | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.rs b/tests/ui/link-native-libs/suggest-libname-only-2.rs index 7ed106e4ab43..c35b4a674b77 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-2.rs +++ b/tests/ui/link-native-libs/suggest-libname-only-2.rs @@ -1,9 +1,10 @@ //@ build-fail //@ compile-flags: --crate-type rlib -//@ error-pattern: could not find native static library `bar.lib` //@ error-pattern: only provide the library name `bar`, not the full filename #[link(name = "bar.lib", kind = "static")] -extern { } +extern { } //~ WARN extern declarations without an explicit ABI are deprecated pub fn main() { } + +//~? ERROR could not find native static library `bar.lib` diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.stderr b/tests/ui/link-native-libs/suggest-libname-only-2.stderr index a2d8f4c8191b..d5c88931ad54 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-2.stderr +++ b/tests/ui/link-native-libs/suggest-libname-only-2.stderr @@ -1,5 +1,5 @@ warning: extern declarations without an explicit ABI are deprecated - --> $DIR/suggest-libname-only-2.rs:7:1 + --> $DIR/suggest-libname-only-2.rs:6:1 | LL | extern { } | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` diff --git a/tests/ui/linkage-attr/incompatible-flavor.rs b/tests/ui/linkage-attr/incompatible-flavor.rs index acf720bc97a1..7f583f47e2f5 100644 --- a/tests/ui/linkage-attr/incompatible-flavor.rs +++ b/tests/ui/linkage-attr/incompatible-flavor.rs @@ -1,6 +1,7 @@ //@ compile-flags: --target=x86_64-unknown-linux-gnu -C linker-flavor=msvc --crate-type=rlib -//@ error-pattern: linker flavor `msvc` is incompatible with the current target //@ needs-llvm-components: #![feature(no_core)] #![no_core] + +//~? ERROR linker flavor `msvc` is incompatible with the current target diff --git a/tests/ui/linkage-attr/issue-10755.rs b/tests/ui/linkage-attr/issue-10755.rs index 58d5b5ead573..509f484adf82 100644 --- a/tests/ui/linkage-attr/issue-10755.rs +++ b/tests/ui/linkage-attr/issue-10755.rs @@ -1,10 +1,11 @@ //@ build-fail //@ dont-check-compiler-stderr //@ compile-flags: -C linker=llllll -//@ error-pattern: `llllll` // Before, the error-pattern checked for "not found". On WSL with appendWindowsPath=true, running // in invalid command returns a PermissionDenied instead. fn main() { } + +//~? ERROR `llllll` diff --git a/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs index f4715ff2d3d6..030b95198f54 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs @@ -35,3 +35,5 @@ fn main() { meooooooooooooooow(); woooooooooooooooooof(); } + +//[without]~? ERROR linking with ` diff --git a/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs index fe9c7884e54d..20de4afcee0b 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs @@ -26,3 +26,5 @@ unsafe extern "C" { fn main() { meooooooooooooooow(); } + +//[without]~? ERROR linking with ` diff --git a/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs index 72cba18d8411..302ec0edeaa1 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs @@ -27,3 +27,5 @@ unsafe extern "C" { fn main() { meooooooooooooooow(); } + +//[without]~? ERROR linking with ` diff --git a/tests/ui/linkage-attr/unstable-flavor.rs b/tests/ui/linkage-attr/unstable-flavor.rs index 82d9dff38741..6aa9efb58d1f 100644 --- a/tests/ui/linkage-attr/unstable-flavor.rs +++ b/tests/ui/linkage-attr/unstable-flavor.rs @@ -4,11 +4,12 @@ // //@ revisions: bpf ptx //@ [bpf] compile-flags: --target=bpfel-unknown-none -C linker-flavor=bpf --crate-type=rlib -//@ [bpf] error-pattern: linker flavor `bpf` is unstable, the `-Z unstable-options` flag //@ [bpf] needs-llvm-components: //@ [ptx] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=ptx --crate-type=rlib -//@ [ptx] error-pattern: linker flavor `ptx` is unstable, the `-Z unstable-options` flag //@ [ptx] needs-llvm-components: #![feature(no_core)] #![no_core] + +//[bpf]~? ERROR the linker flavor `bpf` is unstable +//[ptx]~? ERROR the linker flavor `ptx` is unstable diff --git a/tests/ui/lint/bad-lint-cap.rs b/tests/ui/lint/bad-lint-cap.rs index aab3f723796d..c219cb1b6655 100644 --- a/tests/ui/lint/bad-lint-cap.rs +++ b/tests/ui/lint/bad-lint-cap.rs @@ -1,4 +1,5 @@ //@ compile-flags: --cap-lints test -//@ error-pattern: unknown lint level: `test` fn main() {} + +//~? ERROR unknown lint level: `test` diff --git a/tests/ui/lint/cli-unknown-force-warn.rs b/tests/ui/lint/cli-unknown-force-warn.rs index 007f8dd8732a..330d5570e21b 100644 --- a/tests/ui/lint/cli-unknown-force-warn.rs +++ b/tests/ui/lint/cli-unknown-force-warn.rs @@ -4,8 +4,11 @@ //@ check-pass //@ compile-flags: --force-warn foo-qux -//@ error-pattern: unknown lint: `foo_qux` //@ error-pattern: requested on the command line with `--force-warn foo_qux` //@ error-pattern: `#[warn(unknown_lints)]` on by default fn main() {} + +//~? WARN unknown lint: `foo_qux` +//~? WARN unknown lint: `foo_qux` +//~? WARN unknown lint: `foo_qux` diff --git a/tests/ui/lint/command-line-register-unknown-lint-tool.rs b/tests/ui/lint/command-line-register-unknown-lint-tool.rs index b4e9a067fe29..a517f4c7ea68 100644 --- a/tests/ui/lint/command-line-register-unknown-lint-tool.rs +++ b/tests/ui/lint/command-line-register-unknown-lint-tool.rs @@ -1,4 +1,7 @@ //@ compile-flags: -A unknown_tool::foo -//@ error-pattern: unknown lint tool: `unknown_tool` fn main() {} + +//~? ERROR unknown lint tool: `unknown_tool` +//~? ERROR unknown lint tool: `unknown_tool` +//~? ERROR unknown lint tool: `unknown_tool` diff --git a/tests/ui/lint/force-warn/warnings-lint-group.rs b/tests/ui/lint/force-warn/warnings-lint-group.rs index 944070527a15..28de42639d3a 100644 --- a/tests/ui/lint/force-warn/warnings-lint-group.rs +++ b/tests/ui/lint/force-warn/warnings-lint-group.rs @@ -1,5 +1,8 @@ // --force-warn warnings is an error //@ compile-flags: --force-warn warnings -//@ error-pattern: `warnings` lint group is not supported fn main() {} + +//~? ERROR `warnings` lint group is not supported with ´--force-warn´ +//~? ERROR `warnings` lint group is not supported with ´--force-warn´ +//~? ERROR `warnings` lint group is not supported with ´--force-warn´ diff --git a/tests/ui/lint/issue-104897.rs b/tests/ui/lint/issue-104897.rs index 3cfe94bbd222..99bc1cf3a429 100644 --- a/tests/ui/lint/issue-104897.rs +++ b/tests/ui/lint/issue-104897.rs @@ -1,5 +1,2 @@ -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter - +//~v ERROR this file contains an unclosed delimiter fn f(){(print!(á diff --git a/tests/ui/lint/issue-104897.stderr b/tests/ui/lint/issue-104897.stderr index 584902ee4c03..ebc794bfb730 100644 --- a/tests/ui/lint/issue-104897.stderr +++ b/tests/ui/lint/issue-104897.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-104897.rs:5:18 + --> $DIR/issue-104897.rs:2:18 | LL | fn f(){(print!(á | -- - ^ diff --git a/tests/ui/lint/lint-pre-expansion-extern-module.rs b/tests/ui/lint/lint-pre-expansion-extern-module.rs index b76879ccbb80..f1ab0cf3b742 100644 --- a/tests/ui/lint/lint-pre-expansion-extern-module.rs +++ b/tests/ui/lint/lint-pre-expansion-extern-module.rs @@ -1,7 +1,9 @@ //@ check-pass //@ compile-flags: -W rust-2018-compatibility -//@ error-pattern: `try` is a keyword in the 2018 edition fn main() {} mod lint_pre_expansion_extern_module_aux; + +//~? WARN `try` is a keyword in the 2018 edition +//~? WARN this is accepted in the current edition diff --git a/tests/ui/lint/lint-removed-cmdline-deny.rs b/tests/ui/lint/lint-removed-cmdline-deny.rs index e56a95d292a4..6616781d5cb7 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.rs +++ b/tests/ui/lint/lint-removed-cmdline-deny.rs @@ -3,11 +3,14 @@ //@ compile-flags:-D renamed-and-removed-lints -D raw_pointer_derive -//@ error-pattern:lint `raw_pointer_derive` has been removed //@ error-pattern:requested on the command line with `-D raw_pointer_derive` //@ error-pattern:requested on the command line with `-D renamed-and-removed-lints` #![warn(unused)] #[deny(warnings)] -fn main() { let unused = (); } +fn main() { let unused = (); } //~ ERROR unused variable: `unused` + +//~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok diff --git a/tests/ui/lint/lint-removed-cmdline-deny.stderr b/tests/ui/lint/lint-removed-cmdline-deny.stderr index 3321afa7fcd7..27a3504a16a7 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-removed-cmdline-deny.stderr @@ -14,13 +14,13 @@ error: lint `raw_pointer_derive` has been removed: using derive with raw pointer = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-removed-cmdline-deny.rs:13:17 + --> $DIR/lint-removed-cmdline-deny.rs:12:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-removed-cmdline-deny.rs:12:8 + --> $DIR/lint-removed-cmdline-deny.rs:11:8 | LL | #[deny(warnings)] | ^^^^^^^^ diff --git a/tests/ui/lint/lint-removed-cmdline.rs b/tests/ui/lint/lint-removed-cmdline.rs index 3c9d3eb8e7ba..4dde3dbc3817 100644 --- a/tests/ui/lint/lint-removed-cmdline.rs +++ b/tests/ui/lint/lint-removed-cmdline.rs @@ -3,11 +3,14 @@ //@ compile-flags:-D raw_pointer_derive -//@ error-pattern:lint `raw_pointer_derive` has been removed //@ error-pattern:`#[warn(renamed_and_removed_lints)]` on by default //@ error-pattern:requested on the command line with `-D raw_pointer_derive` #![warn(unused)] #[deny(warnings)] -fn main() { let unused = (); } +fn main() { let unused = (); } //~ ERROR unused variable: `unused` + +//~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr index fd63433c3086..7994f9bcfd91 100644 --- a/tests/ui/lint/lint-removed-cmdline.stderr +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -14,13 +14,13 @@ warning: lint `raw_pointer_derive` has been removed: using derive with raw point = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-removed-cmdline.rs:13:17 + --> $DIR/lint-removed-cmdline.rs:12:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-removed-cmdline.rs:12:8 + --> $DIR/lint-removed-cmdline.rs:11:8 | LL | #[deny(warnings)] | ^^^^^^^^ diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.rs b/tests/ui/lint/lint-renamed-cmdline-deny.rs index 13500d006f86..0ea4ce408175 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.rs +++ b/tests/ui/lint/lint-renamed-cmdline-deny.rs @@ -1,10 +1,12 @@ //@ compile-flags:-D renamed-and-removed-lints -D bare_trait_object -//@ error-pattern:lint `bare_trait_object` has been renamed to `bare_trait_objects` //@ error-pattern:use the new name `bare_trait_objects` //@ error-pattern:requested on the command line with `-D bare_trait_object` //@ error-pattern:requested on the command line with `-D renamed-and-removed-lints` -//@ error-pattern:unused #[deny(unused)] -fn main() { let unused = (); } +fn main() { let unused = (); } //~ ERROR unused variable: `unused` + +//~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects` diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.stderr b/tests/ui/lint/lint-renamed-cmdline-deny.stderr index 0e182a4e5dea..a49cdc84f9e4 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-renamed-cmdline-deny.stderr @@ -17,13 +17,13 @@ error: lint `bare_trait_object` has been renamed to `bare_trait_objects` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-renamed-cmdline-deny.rs:10:17 + --> $DIR/lint-renamed-cmdline-deny.rs:8:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-renamed-cmdline-deny.rs:9:8 + --> $DIR/lint-renamed-cmdline-deny.rs:7:8 | LL | #[deny(unused)] | ^^^^^^ diff --git a/tests/ui/lint/lint-renamed-cmdline.rs b/tests/ui/lint/lint-renamed-cmdline.rs index 7adea98a609f..45df7b6d640d 100644 --- a/tests/ui/lint/lint-renamed-cmdline.rs +++ b/tests/ui/lint/lint-renamed-cmdline.rs @@ -1,9 +1,11 @@ //@ compile-flags:-D bare_trait_object -//@ error-pattern:lint `bare_trait_object` has been renamed to `bare_trait_objects` //@ error-pattern:requested on the command line with `-D bare_trait_object` //@ error-pattern:`#[warn(renamed_and_removed_lints)]` on by default -//@ error-pattern:unused #[deny(unused)] -fn main() { let unused = (); } +fn main() { let unused = (); } //~ ERROR unused variable: `unused` + +//~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr index d6bb72f34dce..901e7a642d1f 100644 --- a/tests/ui/lint/lint-renamed-cmdline.stderr +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -17,13 +17,13 @@ warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-renamed-cmdline.rs:9:17 + --> $DIR/lint-renamed-cmdline.rs:7:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-renamed-cmdline.rs:8:8 + --> $DIR/lint-renamed-cmdline.rs:6:8 | LL | #[deny(unused)] | ^^^^^^ diff --git a/tests/ui/lint/lint-stability2.rs b/tests/ui/lint/lint-stability2.rs index 254ec8f9bee1..056ff5a3e0ad 100644 --- a/tests/ui/lint/lint-stability2.rs +++ b/tests/ui/lint/lint-stability2.rs @@ -1,5 +1,4 @@ //@ aux-build:lint_stability.rs -//@ error-pattern: use of deprecated function #![deny(deprecated)] @@ -9,5 +8,5 @@ extern crate lint_stability; use lint_stability::*; fn main() { - macro_test!(); + macro_test!(); //~ ERROR use of deprecated function `lint_stability::deprecated`: text } diff --git a/tests/ui/lint/lint-stability2.stderr b/tests/ui/lint/lint-stability2.stderr index 3df0c4281679..fa1bce716fc0 100644 --- a/tests/ui/lint/lint-stability2.stderr +++ b/tests/ui/lint/lint-stability2.stderr @@ -1,11 +1,11 @@ error: use of deprecated function `lint_stability::deprecated`: text - --> $DIR/lint-stability2.rs:12:5 + --> $DIR/lint-stability2.rs:11:5 | LL | macro_test!(); | ^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-stability2.rs:4:9 + --> $DIR/lint-stability2.rs:3:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ diff --git a/tests/ui/lint/lint-stability3.rs b/tests/ui/lint/lint-stability3.rs index 3c5652ae0304..1ca346f746ad 100644 --- a/tests/ui/lint/lint-stability3.rs +++ b/tests/ui/lint/lint-stability3.rs @@ -1,5 +1,4 @@ //@ aux-build:lint_stability.rs -//@ error-pattern: use of deprecated function #![deny(deprecated)] #![allow(warnings)] @@ -11,4 +10,5 @@ use lint_stability::*; fn main() { macro_test_arg_nested!(deprecated_text); + //~^ ERROR use of deprecated function `lint_stability::deprecated_text`: text } diff --git a/tests/ui/lint/lint-stability3.stderr b/tests/ui/lint/lint-stability3.stderr index 3a2af452ce20..85f14c6fc17b 100644 --- a/tests/ui/lint/lint-stability3.stderr +++ b/tests/ui/lint/lint-stability3.stderr @@ -1,11 +1,11 @@ error: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability3.rs:13:28 + --> $DIR/lint-stability3.rs:12:28 | LL | macro_test_arg_nested!(deprecated_text); | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-stability3.rs:4:9 + --> $DIR/lint-stability3.rs:3:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs b/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs index c92c3999ce90..e2f7c73eacf0 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs +++ b/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs @@ -1,9 +1,15 @@ //@ compile-flags:-D unknown-lints -D bogus -D dead_cod -//@ error-pattern:unknown lint: `bogus` //@ error-pattern:requested on the command line with `-D bogus` //@ error-pattern:requested on the command line with `-D dead_cod` //@ error-pattern:requested on the command line with `-D unknown-lints` //@ error-pattern:did you mean: `dead_code` fn main() { } + +//~? ERROR unknown lint: `bogus` +//~? ERROR unknown lint: `dead_cod` +//~? ERROR unknown lint: `bogus` +//~? ERROR unknown lint: `dead_cod` +//~? ERROR unknown lint: `bogus` +//~? ERROR unknown lint: `dead_cod` diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.rs b/tests/ui/lint/lint-unknown-lint-cmdline.rs index 202c617235fa..931e945a1a32 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline.rs +++ b/tests/ui/lint/lint-unknown-lint-cmdline.rs @@ -1,11 +1,16 @@ //@ check-pass //@ compile-flags:-D bogus -D dead_cod -//@ error-pattern:unknown lint: `bogus` //@ error-pattern:requested on the command line with `-D bogus` //@ error-pattern:`#[warn(unknown_lints)]` on by default -//@ error-pattern:unknown lint: `dead_cod` //@ error-pattern:requested on the command line with `-D dead_cod` //@ error-pattern:did you mean: `dead_code` fn main() { } + +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `dead_cod` +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `dead_cod` +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `dead_cod` diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.rs b/tests/ui/lint/unused_parens_multibyte_recovery.rs index 630b25d192a4..8f53c7ad2626 100644 --- a/tests/ui/lint/unused_parens_multibyte_recovery.rs +++ b/tests/ui/lint/unused_parens_multibyte_recovery.rs @@ -1,10 +1,7 @@ // ignore-tidy-trailing-newlines -// -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter -// + // Verify that unused parens lint does not try to create a span // which points in the middle of a multibyte character. +//~v ERROR this file contains an unclosed delimiter fn f(){(print!(á \ No newline at end of file diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.stderr b/tests/ui/lint/unused_parens_multibyte_recovery.stderr index ef4089f31f43..770fd6f084e3 100644 --- a/tests/ui/lint/unused_parens_multibyte_recovery.stderr +++ b/tests/ui/lint/unused_parens_multibyte_recovery.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/unused_parens_multibyte_recovery.rs:10:17 + --> $DIR/unused_parens_multibyte_recovery.rs:7:17 | LL | fn f(){(print!(á | -- - ^ diff --git a/tests/ui/lto/issue-11154.rs b/tests/ui/lto/issue-11154.rs index 914b0b73e474..7770aeccd6a8 100644 --- a/tests/ui/lto/issue-11154.rs +++ b/tests/ui/lto/issue-11154.rs @@ -1,6 +1,6 @@ //@ build-fail //@ compile-flags: -C lto -C prefer-dynamic -//@ error-pattern: cannot prefer dynamic linking - fn main() {} + +//~? ERROR cannot prefer dynamic linking when performing LTO diff --git a/tests/ui/lto/lto-duplicate-symbols.rs b/tests/ui/lto/lto-duplicate-symbols.rs index 27bdde418f85..a62ab2e22172 100644 --- a/tests/ui/lto/lto-duplicate-symbols.rs +++ b/tests/ui/lto/lto-duplicate-symbols.rs @@ -1,7 +1,6 @@ //@ build-fail //@ aux-build:lto-duplicate-symbols1.rs //@ aux-build:lto-duplicate-symbols2.rs -//@ error-pattern:Linking globals named 'foo': symbol multiply defined! //@ compile-flags: -C lto //@ no-prefer-dynamic //@ normalize-stderr: "lto-duplicate-symbols2\.lto_duplicate_symbols2\.[0-9a-zA-Z]+-cgu" -> "lto-duplicate-symbols2.lto_duplicate_symbols2.HASH-cgu" @@ -9,3 +8,6 @@ extern crate lto_duplicate_symbols1; extern crate lto_duplicate_symbols2; fn main() {} + +//~? WARN Linking globals named 'foo': symbol multiply defined +//~? ERROR failed to load bitcode of module "lto-duplicate-symbols2.lto_duplicate_symbols2 diff --git a/tests/ui/macros/not-utf8.rs b/tests/ui/macros/not-utf8.rs index ad8ac39d230e..0993c0688605 100644 --- a/tests/ui/macros/not-utf8.rs +++ b/tests/ui/macros/not-utf8.rs @@ -1,7 +1,7 @@ -//@ error-pattern: did not contain valid UTF-8 //@ reference: input.encoding.utf8 //@ reference: input.encoding.invalid fn foo() { include!("not-utf8.bin"); + //~^ ERROR couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 } diff --git a/tests/ui/macros/not-utf8.stderr b/tests/ui/macros/not-utf8.stderr index d466d5087d4b..c310e70935e3 100644 --- a/tests/ui/macros/not-utf8.stderr +++ b/tests/ui/macros/not-utf8.stderr @@ -1,5 +1,5 @@ error: couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 - --> $DIR/not-utf8.rs:6:5 + --> $DIR/not-utf8.rs:5:5 | LL | include!("not-utf8.bin"); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/unreachable-arg.edition_2021.stderr b/tests/ui/macros/unreachable-arg.edition_2021.stderr index ddaa2b9c1efe..fa776070789c 100644 --- a/tests/ui/macros/unreachable-arg.edition_2021.stderr +++ b/tests/ui/macros/unreachable-arg.edition_2021.stderr @@ -1,5 +1,5 @@ error: format argument must be a string literal - --> $DIR/unreachable-arg.rs:15:18 + --> $DIR/unreachable-arg.rs:14:18 | LL | unreachable!(a); | ^ diff --git a/tests/ui/macros/unreachable-arg.rs b/tests/ui/macros/unreachable-arg.rs index 702bd053ab02..d18272c8072e 100644 --- a/tests/ui/macros/unreachable-arg.rs +++ b/tests/ui/macros/unreachable-arg.rs @@ -6,11 +6,10 @@ //@ [edition_2015]run-fail //@ [edition_2021]check-fail //@ [edition_2015]error-pattern:internal error: entered unreachable code: hello -//@ [edition_2021]error-pattern:format argument must be a string literal #![allow(non_fmt_panics)] fn main() { let a = "hello"; - unreachable!(a); + unreachable!(a); //[edition_2021]~ ERROR format argument must be a string literal } diff --git a/tests/ui/macros/unreachable-format-args.edition_2015.stderr b/tests/ui/macros/unreachable-format-args.edition_2015.stderr index 9104848a58bd..e2286b72e64c 100644 --- a/tests/ui/macros/unreachable-format-args.edition_2015.stderr +++ b/tests/ui/macros/unreachable-format-args.edition_2015.stderr @@ -1,5 +1,5 @@ error: there is no argument named `x` - --> $DIR/unreachable-format-args.rs:13:5 + --> $DIR/unreachable-format-args.rs:12:5 | LL | unreachable!("x is {x} and y is {y}", y = 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/unreachable-format-args.rs b/tests/ui/macros/unreachable-format-args.rs index 856fc992685a..79a851348ffe 100644 --- a/tests/ui/macros/unreachable-format-args.rs +++ b/tests/ui/macros/unreachable-format-args.rs @@ -5,10 +5,10 @@ //@ [edition_2021]edition:2021 //@ [edition_2015]check-fail //@ [edition_2021]run-fail -//@ [edition_2015]error-pattern:there is no argument named `x` //@ [edition_2021]error-pattern:internal error: entered unreachable code: x is 5 and y is 0 fn main() { let x = 5; unreachable!("x is {x} and y is {y}", y = 0); + //[edition_2015]~^ ERROR there is no argument named `x` } diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs index da56fe03184a..94e6900bf40e 100644 --- a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs +++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs @@ -1,7 +1,4 @@ // check that we don't generate a span that points beyond EOF -//@ error-pattern: unclosed delimiter -//@ error-pattern: unclosed delimiter -//@ error-pattern: unclosed delimiter - +//~v ERROR this file contains an unclosed delimiter fn a(){{{ diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr index d9748843fd7a..9a86c267340c 100644 --- a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr +++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11 + --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:4:11 | LL | fn a(){{{ | ---^ diff --git a/tests/ui/minus-string.rs b/tests/ui/minus-string.rs index 8d9b8d8bbf49..b83347b937ed 100644 --- a/tests/ui/minus-string.rs +++ b/tests/ui/minus-string.rs @@ -1,3 +1 @@ -//@ error-pattern:cannot apply unary operator `-` to type `String` - -fn main() { -"foo".to_string(); } +fn main() { -"foo".to_string(); } //~ ERROR cannot apply unary operator `-` to type `String` diff --git a/tests/ui/minus-string.stderr b/tests/ui/minus-string.stderr index cf63ec244167..153965c810ea 100644 --- a/tests/ui/minus-string.stderr +++ b/tests/ui/minus-string.stderr @@ -1,5 +1,5 @@ error[E0600]: cannot apply unary operator `-` to type `String` - --> $DIR/minus-string.rs:3:13 + --> $DIR/minus-string.rs:1:13 | LL | fn main() { -"foo".to_string(); } | ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-` diff --git a/tests/ui/mir/enable_passes_validation.rs b/tests/ui/mir/enable_passes_validation.rs index 405ada77183b..b97ddfba37f5 100644 --- a/tests/ui/mir/enable_passes_validation.rs +++ b/tests/ui/mir/enable_passes_validation.rs @@ -1,24 +1,25 @@ //@ revisions: empty unprefixed all_unknown all_known mixed //@[empty] compile-flags: -Zmir-enable-passes= -//@[empty] error-pattern error: incorrect value `` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected //@[unprefixed] compile-flags: -Zmir-enable-passes=CheckAlignment -//@[unprefixed] error-pattern error: incorrect value `CheckAlignment` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected //@[all_unknown] check-pass //@[all_unknown] compile-flags: -Zmir-enable-passes=+ThisPass,-DoesNotExist -//@[all_unknown] error-pattern: warning: MIR pass `ThisPass` is unknown and will be ignored -//@[all_unknown] error-pattern: warning: MIR pass `DoesNotExist` is unknown and will be ignored //@[all_known] check-pass //@[all_known] compile-flags: -Zmir-enable-passes=+CheckAlignment,+LowerIntrinsics //@[mixed] check-pass //@[mixed] compile-flags: -Zmir-enable-passes=+ThisPassDoesNotExist,+CheckAlignment -//@[mixed] error-pattern: warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored fn main() {} //[empty]~? ERROR incorrect value `` for unstable option `mir-enable-passes` //[unprefixed]~? ERROR incorrect value `CheckAlignment` for unstable option `mir-enable-passes` +//[mixed]~? WARN MIR pass `ThisPassDoesNotExist` is unknown and will be ignored +//[mixed]~? WARN MIR pass `ThisPassDoesNotExist` is unknown and will be ignored +//[all_unknown]~? MIR pass `ThisPass` is unknown and will be ignored +//[all_unknown]~? MIR pass `DoesNotExist` is unknown and will be ignored +//[all_unknown]~? MIR pass `ThisPass` is unknown and will be ignored +//[all_unknown]~? MIR pass `DoesNotExist` is unknown and will be ignored diff --git a/tests/ui/mir/lint/assignment-overlap.rs b/tests/ui/mir/lint/assignment-overlap.rs index 6396cccd4e88..950279b1555f 100644 --- a/tests/ui/mir/lint/assignment-overlap.rs +++ b/tests/ui/mir/lint/assignment-overlap.rs @@ -12,7 +12,7 @@ pub fn main() { mir! { let a: [u8; 1024]; { - a = a; + a = a; //~ ERROR broken MIR Return() } } diff --git a/tests/ui/mir/lint/call-overlap.rs b/tests/ui/mir/lint/call-overlap.rs index def78ea1e3b1..3c42e04e3ec8 100644 --- a/tests/ui/mir/lint/call-overlap.rs +++ b/tests/ui/mir/lint/call-overlap.rs @@ -12,7 +12,7 @@ pub fn main() { mir! { let a: [u8; 1024]; { - Call(a = f(Move(a)), ReturnTo(bb1), UnwindUnreachable()) + Call(a = f(Move(a)), ReturnTo(bb1), UnwindUnreachable()) //~ ERROR broken MIR } bb1 = { Return() diff --git a/tests/ui/mir/lint/no-storage.rs b/tests/ui/mir/lint/no-storage.rs index a6af8646f6ec..68c1a2d2aabd 100644 --- a/tests/ui/mir/lint/no-storage.rs +++ b/tests/ui/mir/lint/no-storage.rs @@ -21,7 +21,7 @@ pub fn f(a: bool) { Goto(bb3) } bb3 = { - b = (); + b = (); //~ ERROR broken MIR RET = b; StorageDead(b); Return() diff --git a/tests/ui/mir/lint/storage-live.rs b/tests/ui/mir/lint/storage-live.rs index 3e0cc4ee0614..19d046b619c4 100644 --- a/tests/ui/mir/lint/storage-live.rs +++ b/tests/ui/mir/lint/storage-live.rs @@ -20,7 +20,7 @@ fn multiple_storage() { let a: usize; { StorageLive(a); - StorageLive(a); + StorageLive(a); //~ ERROR broken MIR Return() } } diff --git a/tests/ui/mir/lint/storage-return.rs b/tests/ui/mir/lint/storage-return.rs index d51aee9518fb..3bbd0045d9db 100644 --- a/tests/ui/mir/lint/storage-return.rs +++ b/tests/ui/mir/lint/storage-return.rs @@ -13,7 +13,7 @@ fn main() { { StorageLive(a); RET = a; - Return() + Return() //~ ERROR broken MIR } } } diff --git a/tests/ui/mir/validate/noncleanup-cleanup.rs b/tests/ui/mir/validate/noncleanup-cleanup.rs index b46bb46952b8..3010a3804ce7 100644 --- a/tests/ui/mir/validate/noncleanup-cleanup.rs +++ b/tests/ui/mir/validate/noncleanup-cleanup.rs @@ -2,16 +2,16 @@ // //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: cleanuppad mismatch + #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; #[custom_mir(dialect = "built")] -pub fn main() { +pub fn main() { //~ WARN function cannot return without recursing mir! { { - Call(RET = main(), ReturnTo(block), UnwindCleanup(block)) + Call(RET = main(), ReturnTo(block), UnwindCleanup(block)) //~ ERROR cleanuppad mismatch } block = { Return() diff --git a/tests/ui/mir/validate/noncleanup-resume.rs b/tests/ui/mir/validate/noncleanup-resume.rs index b2a0e92e0686..a80e99e29677 100644 --- a/tests/ui/mir/validate/noncleanup-resume.rs +++ b/tests/ui/mir/validate/noncleanup-resume.rs @@ -2,7 +2,7 @@ // //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: resume on non-cleanup block + #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; @@ -11,7 +11,7 @@ use core::intrinsics::mir::*; pub fn main() { mir! { { - UnwindResume() + UnwindResume() //~ ERROR resume on non-cleanup block } } } diff --git a/tests/ui/mir/validate/noncleanup-terminate.rs b/tests/ui/mir/validate/noncleanup-terminate.rs index 24cf75e7d8e1..859c5e71c0ef 100644 --- a/tests/ui/mir/validate/noncleanup-terminate.rs +++ b/tests/ui/mir/validate/noncleanup-terminate.rs @@ -2,7 +2,7 @@ // //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: terminate on non-cleanup block + #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; @@ -11,7 +11,7 @@ use core::intrinsics::mir::*; pub fn main() { mir! { { - UnwindTerminate(ReasonAbi) + UnwindTerminate(ReasonAbi) //~ ERROR terminate on non-cleanup block } } } diff --git a/tests/ui/missing/missing-main.rs b/tests/ui/missing/missing-main.rs index 3cafca09afb3..2b8995fb8ff3 100644 --- a/tests/ui/missing/missing-main.rs +++ b/tests/ui/missing/missing-main.rs @@ -1,2 +1 @@ -//@ error-pattern: `main` function not found -fn mian() { } +fn mian() { } //~ ERROR `main` function not found in crate `missing_main` diff --git a/tests/ui/missing/missing-main.stderr b/tests/ui/missing/missing-main.stderr index 2139981eac0d..51a299d6a850 100644 --- a/tests/ui/missing/missing-main.stderr +++ b/tests/ui/missing/missing-main.stderr @@ -1,5 +1,5 @@ error[E0601]: `main` function not found in crate `missing_main` - --> $DIR/missing-main.rs:2:14 + --> $DIR/missing-main.rs:1:14 | LL | fn mian() { } | ^ consider adding a `main` function to `$DIR/missing-main.rs` diff --git a/tests/ui/missing/missing-return.rs b/tests/ui/missing/missing-return.rs index defd8a3bb78a..5d9839a969c1 100644 --- a/tests/ui/missing/missing-return.rs +++ b/tests/ui/missing/missing-return.rs @@ -1,5 +1,5 @@ //@ error-pattern: return -fn f() -> isize { } +fn f() -> isize { } //~ ERROR mismatched types fn main() { f(); } diff --git a/tests/ui/nested-ty-params.rs b/tests/ui/nested-ty-params.rs index b7cedf97c910..866e6230f9ea 100644 --- a/tests/ui/nested-ty-params.rs +++ b/tests/ui/nested-ty-params.rs @@ -1,6 +1,8 @@ //@ error-pattern:can't use generic parameters from outer item fn hd(v: Vec ) -> U { fn hd1(w: [U]) -> U { return w[0]; } + //~^ ERROR can't use generic parameters from outer item + //~| ERROR can't use generic parameters from outer item return hd1(v); } diff --git a/tests/ui/no-capture-arc.rs b/tests/ui/no-capture-arc.rs index aafb170c7e1a..9c957a4e01b4 100644 --- a/tests/ui/no-capture-arc.rs +++ b/tests/ui/no-capture-arc.rs @@ -1,5 +1,3 @@ -//@ error-pattern: borrow of moved value - use std::sync::Arc; use std::thread; @@ -11,7 +9,7 @@ fn main() { assert_eq!((*arc_v)[3], 4); }); - assert_eq!((*arc_v)[2], 3); + assert_eq!((*arc_v)[2], 3); //~ ERROR borrow of moved value: `arc_v` println!("{:?}", *arc_v); } diff --git a/tests/ui/no-capture-arc.stderr b/tests/ui/no-capture-arc.stderr index 4a51ddb67a39..9c1f5c65066f 100644 --- a/tests/ui/no-capture-arc.stderr +++ b/tests/ui/no-capture-arc.stderr @@ -1,5 +1,5 @@ error[E0382]: borrow of moved value: `arc_v` - --> $DIR/no-capture-arc.rs:14:18 + --> $DIR/no-capture-arc.rs:12:18 | LL | let arc_v = Arc::new(v); | ----- move occurs because `arc_v` has type `Arc>`, which does not implement the `Copy` trait diff --git a/tests/ui/no_std/no-std-no-start-binary.rs b/tests/ui/no_std/no-std-no-start-binary.rs index 5c8a0e6c0b8d..df68b99346af 100644 --- a/tests/ui/no_std/no-std-no-start-binary.rs +++ b/tests/ui/no_std/no-std-no-start-binary.rs @@ -11,3 +11,5 @@ fn handler(_info: &core::panic::PanicInfo<'_>) -> ! { } fn main() {} + +//~? ERROR using `fn main` requires the standard library diff --git a/tests/ui/no_std/no-std-unwind-binary.rs b/tests/ui/no_std/no-std-unwind-binary.rs index 74c80d75c3e1..cb1dc4427ae1 100644 --- a/tests/ui/no_std/no-std-unwind-binary.rs +++ b/tests/ui/no_std/no-std-unwind-binary.rs @@ -1,4 +1,3 @@ -//@ error-pattern:unwinding panics are not supported without std //@ needs-unwind //@ compile-flags: -Cpanic=unwind @@ -13,3 +12,5 @@ fn handler(_info: &core::panic::PanicInfo<'_>) -> ! { } fn main() {} + +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/packed/packed-struct-generic-transmute.rs b/tests/ui/packed/packed-struct-generic-transmute.rs index ed655a1d483d..17e72bebc7dc 100644 --- a/tests/ui/packed/packed-struct-generic-transmute.rs +++ b/tests/ui/packed/packed-struct-generic-transmute.rs @@ -22,6 +22,7 @@ fn main() { let foo = Foo { bar: [1u8, 2, 3, 4, 5], baz: 10i32 }; unsafe { let oof: Oof<[u8; 5], i32> = mem::transmute(foo); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types println!("{:?} {:?}", &oof.rab[..], oof.zab); } } diff --git a/tests/ui/packed/packed-struct-transmute.rs b/tests/ui/packed/packed-struct-transmute.rs index 98feeea88714..5ad6524ff817 100644 --- a/tests/ui/packed/packed-struct-transmute.rs +++ b/tests/ui/packed/packed-struct-transmute.rs @@ -24,6 +24,7 @@ fn main() { let foo = Foo { bar: 1, baz: 10 }; unsafe { let oof: Oof = mem::transmute(foo); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types println!("{:?}", oof); } } diff --git a/tests/ui/panic-handler/panic-handler-missing.rs b/tests/ui/panic-handler/panic-handler-missing.rs index 09fbd9a69cfd..ab617f93a991 100644 --- a/tests/ui/panic-handler/panic-handler-missing.rs +++ b/tests/ui/panic-handler/panic-handler-missing.rs @@ -1,5 +1,4 @@ //@ dont-check-compiler-stderr -//@ error-pattern: `#[panic_handler]` function required, but not found #![feature(lang_items)] #![no_main] @@ -7,3 +6,5 @@ #[lang = "eh_personality"] fn eh() {} + +//~? ERROR `#[panic_handler]` function required, but not found diff --git a/tests/ui/panic-handler/panic-handler-std.rs b/tests/ui/panic-handler/panic-handler-std.rs index 4eb05b5365fe..f6a4b60461ce 100644 --- a/tests/ui/panic-handler/panic-handler-std.rs +++ b/tests/ui/panic-handler/panic-handler-std.rs @@ -1,12 +1,11 @@ //@ normalize-stderr: "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" -//@ error-pattern: found duplicate lang item `panic_impl` extern crate core; use core::panic::PanicInfo; #[panic_handler] -fn panic(info: PanicInfo) -> ! { +fn panic(info: PanicInfo) -> ! { //~ ERROR found duplicate lang item `panic_impl` loop {} } diff --git a/tests/ui/panic-handler/panic-handler-std.stderr b/tests/ui/panic-handler/panic-handler-std.stderr index caae16118ef7..48c216ce27ec 100644 --- a/tests/ui/panic-handler/panic-handler-std.stderr +++ b/tests/ui/panic-handler/panic-handler-std.stderr @@ -1,5 +1,5 @@ error[E0152]: found duplicate lang item `panic_impl` - --> $DIR/panic-handler-std.rs:9:1 + --> $DIR/panic-handler-std.rs:8:1 | LL | / fn panic(info: PanicInfo) -> ! { LL | | loop {} diff --git a/tests/ui/panic-handler/weak-lang-item.rs b/tests/ui/panic-handler/weak-lang-item.rs index 605e1bdd94b7..cc5ccb75104b 100644 --- a/tests/ui/panic-handler/weak-lang-item.rs +++ b/tests/ui/panic-handler/weak-lang-item.rs @@ -1,12 +1,13 @@ //@ aux-build:weak-lang-items.rs -//@ error-pattern: `#[panic_handler]` function required, but not found -//@ error-pattern: unwinding panics are not supported without std //@ needs-unwind since it affects the error output //@ ignore-emscripten missing eh_catch_typeinfo lang item #![no_std] -extern crate core; +extern crate core; //~ ERROR the name `core` is defined multiple times extern crate weak_lang_items; fn main() {} + +//~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/panic-handler/weak-lang-item.stderr b/tests/ui/panic-handler/weak-lang-item.stderr index 5dcb37df6892..5acd3e318705 100644 --- a/tests/ui/panic-handler/weak-lang-item.stderr +++ b/tests/ui/panic-handler/weak-lang-item.stderr @@ -1,5 +1,5 @@ error[E0259]: the name `core` is defined multiple times - --> $DIR/weak-lang-item.rs:9:1 + --> $DIR/weak-lang-item.rs:7:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ `core` reimported here diff --git a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs index 2939835b0f41..8b782413f6a4 100644 --- a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs +++ b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs @@ -4,7 +4,6 @@ //@ ignore-musl - no dylibs here //@ ignore-emscripten //@ ignore-sgx no dynamic lib support -//@ error-pattern:`panic_unwind` is not compiled with this crate's panic strategy // This is a test where the local crate, compiled with `panic=abort`, links to // the standard library **dynamically** which is already linked against @@ -16,3 +15,5 @@ fn main() { } + +//~? ERROR the linked panic runtime `panic_unwind` is not compiled with this crate's panic strategy `abort` diff --git a/tests/ui/panic-runtime/bad-panic-flag1.rs b/tests/ui/panic-runtime/bad-panic-flag1.rs index 82b7c2f723b4..117935847cbd 100644 --- a/tests/ui/panic-runtime/bad-panic-flag1.rs +++ b/tests/ui/panic-runtime/bad-panic-flag1.rs @@ -1,4 +1,5 @@ //@ compile-flags:-C panic=foo -//@ error-pattern:either `unwind` or `abort` was expected fn main() {} + +//~? ERROR incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected diff --git a/tests/ui/panic-runtime/bad-panic-flag2.rs b/tests/ui/panic-runtime/bad-panic-flag2.rs index 3875325deae2..b5d0442a0332 100644 --- a/tests/ui/panic-runtime/bad-panic-flag2.rs +++ b/tests/ui/panic-runtime/bad-panic-flag2.rs @@ -1,4 +1,5 @@ //@ compile-flags:-C panic -//@ error-pattern:requires either `unwind` or `abort` fn main() {} + +//~? ERROR codegen option `panic` requires either `unwind` or `abort` diff --git a/tests/ui/panic-runtime/need-abort-got-unwind.rs b/tests/ui/panic-runtime/need-abort-got-unwind.rs index 74b7edd968fa..afd084263954 100644 --- a/tests/ui/panic-runtime/need-abort-got-unwind.rs +++ b/tests/ui/panic-runtime/need-abort-got-unwind.rs @@ -1,8 +1,9 @@ //@ build-fail //@ needs-unwind -//@ error-pattern:is incompatible with this crate's strategy of `unwind` //@ aux-build:needs-abort.rs extern crate needs_abort; fn main() {} + +//~? ERROR the crate `needs_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` diff --git a/tests/ui/panic-runtime/need-unwind-got-abort.rs b/tests/ui/panic-runtime/need-unwind-got-abort.rs index 6bc41509b6b2..bc65e9ab3d9e 100644 --- a/tests/ui/panic-runtime/need-unwind-got-abort.rs +++ b/tests/ui/panic-runtime/need-unwind-got-abort.rs @@ -1,5 +1,4 @@ //@ build-fail -//@ error-pattern:is incompatible with this crate's strategy of `abort` //@ aux-build:needs-unwind.rs //@ compile-flags:-C panic=abort //@ no-prefer-dynamic @@ -7,3 +6,5 @@ extern crate needs_unwind; fn main() {} + +//~? ERROR the crate `needs_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs b/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs index d0a82bd8507d..eb00c071702c 100644 --- a/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs +++ b/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs @@ -1,8 +1,9 @@ //@ dont-check-compiler-stderr //@ aux-build:needs-panic-runtime.rs //@ aux-build:depends.rs -//@ error-pattern:cannot depend on a crate that needs a panic runtime extern crate depends; fn main() {} + +//~? ERROR the crate `depends` cannot depend on a crate that needs a panic runtime, but it depends on `needs_panic_runtime` diff --git a/tests/ui/panic-runtime/transitive-link-a-bunch.rs b/tests/ui/panic-runtime/transitive-link-a-bunch.rs index 15557d35bc5c..2a0b9e3fa632 100644 --- a/tests/ui/panic-runtime/transitive-link-a-bunch.rs +++ b/tests/ui/panic-runtime/transitive-link-a-bunch.rs @@ -5,7 +5,6 @@ //@ aux-build:wants-panic-runtime-unwind.rs //@ aux-build:wants-panic-runtime-abort.rs //@ aux-build:panic-runtime-lang-items.rs -//@ error-pattern: is not compiled with this crate's panic strategy `unwind` #![no_std] #![no_main] @@ -13,3 +12,7 @@ extern crate wants_panic_runtime_unwind; extern crate wants_panic_runtime_abort; extern crate panic_runtime_lang_items; + +//~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_abort +//~? ERROR the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` +//~? ERROR the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` diff --git a/tests/ui/panic-runtime/two-panic-runtimes.rs b/tests/ui/panic-runtime/two-panic-runtimes.rs index 3608dca2124c..37d041a8c7b9 100644 --- a/tests/ui/panic-runtime/two-panic-runtimes.rs +++ b/tests/ui/panic-runtime/two-panic-runtimes.rs @@ -1,6 +1,5 @@ //@ build-fail //@ dont-check-compiler-stderr -//@ error-pattern:cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 //@ aux-build:panic-runtime-unwind.rs //@ aux-build:panic-runtime-unwind2.rs //@ aux-build:panic-runtime-lang-items.rs @@ -13,3 +12,5 @@ extern crate panic_runtime_unwind2; extern crate panic_runtime_lang_items; fn main() {} + +//~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 diff --git a/tests/ui/panic-runtime/want-abort-got-unwind.rs b/tests/ui/panic-runtime/want-abort-got-unwind.rs index ad9fa52f3d44..76e15a1e16ea 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind.rs @@ -1,9 +1,12 @@ //@ build-fail //@ dont-check-compiler-stderr -//@ error-pattern:is not compiled with this crate's panic strategy `abort` //@ aux-build:panic-runtime-unwind.rs //@ compile-flags:-C panic=abort extern crate panic_runtime_unwind; fn main() {} + +//~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind +//~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +//~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/want-abort-got-unwind2.rs b/tests/ui/panic-runtime/want-abort-got-unwind2.rs index d63161db55cb..53cba457424f 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind2.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind2.rs @@ -1,6 +1,5 @@ //@ build-fail //@ dont-check-compiler-stderr -//@ error-pattern:is not compiled with this crate's panic strategy `abort` //@ aux-build:panic-runtime-unwind.rs //@ aux-build:wants-panic-runtime-unwind.rs //@ compile-flags:-C panic=abort @@ -8,3 +7,7 @@ extern crate wants_panic_runtime_unwind; fn main() {} + +//~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind +//~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +//~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/want-unwind-got-abort.rs b/tests/ui/panic-runtime/want-unwind-got-abort.rs index 93342a09182b..497d1eafda5b 100644 --- a/tests/ui/panic-runtime/want-unwind-got-abort.rs +++ b/tests/ui/panic-runtime/want-unwind-got-abort.rs @@ -1,6 +1,5 @@ //@ build-fail //@ needs-unwind -//@ error-pattern:is not compiled with this crate's panic strategy `unwind` //@ aux-build:panic-runtime-abort.rs //@ aux-build:panic-runtime-lang-items.rs @@ -9,3 +8,5 @@ extern crate panic_runtime_abort; extern crate panic_runtime_lang_items; + +//~? ERROR the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` diff --git a/tests/ui/panic-runtime/want-unwind-got-abort2.rs b/tests/ui/panic-runtime/want-unwind-got-abort2.rs index ee3f221d09c6..2609545336c3 100644 --- a/tests/ui/panic-runtime/want-unwind-got-abort2.rs +++ b/tests/ui/panic-runtime/want-unwind-got-abort2.rs @@ -1,6 +1,5 @@ //@ build-fail //@ needs-unwind -//@ error-pattern:is incompatible with this crate's strategy of `unwind` //@ aux-build:panic-runtime-abort.rs //@ aux-build:wants-panic-runtime-abort.rs //@ aux-build:panic-runtime-lang-items.rs @@ -10,3 +9,6 @@ extern crate wants_panic_runtime_abort; extern crate panic_runtime_lang_items; + +//~? ERROR the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` +//~? ERROR the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` diff --git a/tests/ui/panics/default-backtrace-ice.rs b/tests/ui/panics/default-backtrace-ice.rs index 9933f5487583..cf8b0cea8496 100644 --- a/tests/ui/panics/default-backtrace-ice.rs +++ b/tests/ui/panics/default-backtrace-ice.rs @@ -20,4 +20,4 @@ // Ignored on msvc because the `__rust_{begin,end}_short_backtrace` symbols // aren't reliable. -fn main() { missing_ident; } +fn main() { missing_ident; } //~ ERROR cannot find value `missing_ident` in this scope diff --git a/tests/ui/parser/attribute/attr-dangling-in-fn.rs b/tests/ui/parser/attribute/attr-dangling-in-fn.rs index d59f90aed5d1..b1436b8d89db 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-fn.rs +++ b/tests/ui/parser/attribute/attr-dangling-in-fn.rs @@ -1,7 +1,5 @@ -//@ error-pattern:expected statement - fn f() { - #[foo = "bar"] + #[foo = "bar"] //~ ERROR expected statement after outer attribute } fn main() { diff --git a/tests/ui/parser/attribute/attr-dangling-in-fn.stderr b/tests/ui/parser/attribute/attr-dangling-in-fn.stderr index c7b948ea8f76..3e9413f53574 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-fn.stderr +++ b/tests/ui/parser/attribute/attr-dangling-in-fn.stderr @@ -1,5 +1,5 @@ error: expected statement after outer attribute - --> $DIR/attr-dangling-in-fn.rs:4:3 + --> $DIR/attr-dangling-in-fn.rs:2:3 | LL | #[foo = "bar"] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/parser/attribute/attr-dangling-in-mod.rs b/tests/ui/parser/attribute/attr-dangling-in-mod.rs index 001ac1135f6e..17bc7e547d95 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-mod.rs +++ b/tests/ui/parser/attribute/attr-dangling-in-mod.rs @@ -1,6 +1,4 @@ -//@ error-pattern:expected item - fn main() { } -#[foo = "bar"] +#[foo = "bar"] //~ ERROR expected item after attributes diff --git a/tests/ui/parser/attribute/attr-dangling-in-mod.stderr b/tests/ui/parser/attribute/attr-dangling-in-mod.stderr index 882400c1d6fb..22cc092109d1 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-mod.stderr +++ b/tests/ui/parser/attribute/attr-dangling-in-mod.stderr @@ -1,5 +1,5 @@ error: expected item after attributes - --> $DIR/attr-dangling-in-mod.rs:6:1 + --> $DIR/attr-dangling-in-mod.rs:4:1 | LL | #[foo = "bar"] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/parser/circular_modules_main.rs b/tests/ui/parser/circular_modules_main.rs index d5cdff34a264..c130c6792b86 100644 --- a/tests/ui/parser/circular_modules_main.rs +++ b/tests/ui/parser/circular_modules_main.rs @@ -1,5 +1,3 @@ -//@ error-pattern: circular modules - #[path = "circular_modules_hello.rs"] mod circular_modules_hello; @@ -10,3 +8,5 @@ pub fn hi_str() -> String { fn main() { circular_modules_hello::say_hello(); } + +//~? ERROR circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs diff --git a/tests/ui/parser/class-implements-bad-trait.rs b/tests/ui/parser/class-implements-bad-trait.rs index 152fe09b51c0..e30c1bc3a7f7 100644 --- a/tests/ui/parser/class-implements-bad-trait.rs +++ b/tests/ui/parser/class-implements-bad-trait.rs @@ -1,5 +1,4 @@ -//@ error-pattern:nonexistent -class cat : nonexistent { +class cat : nonexistent { //~ ERROR expected one of `!` or `::`, found `cat` let meows: usize; new(in_x : usize) { self.meows = in_x; } } diff --git a/tests/ui/parser/class-implements-bad-trait.stderr b/tests/ui/parser/class-implements-bad-trait.stderr index 5290e3594d55..5cdb85a8cffb 100644 --- a/tests/ui/parser/class-implements-bad-trait.stderr +++ b/tests/ui/parser/class-implements-bad-trait.stderr @@ -1,5 +1,5 @@ error: expected one of `!` or `::`, found `cat` - --> $DIR/class-implements-bad-trait.rs:2:7 + --> $DIR/class-implements-bad-trait.rs:1:7 | LL | class cat : nonexistent { | ^^^ expected one of `!` or `::` diff --git a/tests/ui/parser/import-from-path.rs b/tests/ui/parser/import-from-path.rs index 54349d4971ef..0d38c7224c51 100644 --- a/tests/ui/parser/import-from-path.rs +++ b/tests/ui/parser/import-from-path.rs @@ -1,2 +1 @@ -//@ error-pattern:expected -use foo::{bar}::baz +use foo::{bar}::baz //~ ERROR expected `;`, found `::` diff --git a/tests/ui/parser/import-from-path.stderr b/tests/ui/parser/import-from-path.stderr index b63e48d6679a..f70c3b2e8707 100644 --- a/tests/ui/parser/import-from-path.stderr +++ b/tests/ui/parser/import-from-path.stderr @@ -1,5 +1,5 @@ error: expected `;`, found `::` - --> $DIR/import-from-path.rs:2:15 + --> $DIR/import-from-path.rs:1:15 | LL | use foo::{bar}::baz | ^^ expected `;` diff --git a/tests/ui/parser/import-from-rename.rs b/tests/ui/parser/import-from-rename.rs index f6a4bb55553c..4929b270e45f 100644 --- a/tests/ui/parser/import-from-rename.rs +++ b/tests/ui/parser/import-from-rename.rs @@ -1,6 +1,4 @@ -//@ error-pattern:expected - -use foo::{bar} as baz; +use foo::{bar} as baz; //~ ERROR expected `;`, found keyword `as` mod foo { pub fn bar() {} diff --git a/tests/ui/parser/import-from-rename.stderr b/tests/ui/parser/import-from-rename.stderr index 2f267a8d0269..3289f1bdbe72 100644 --- a/tests/ui/parser/import-from-rename.stderr +++ b/tests/ui/parser/import-from-rename.stderr @@ -1,5 +1,5 @@ error: expected `;`, found keyword `as` - --> $DIR/import-from-rename.rs:3:16 + --> $DIR/import-from-rename.rs:1:16 | LL | use foo::{bar} as baz; | ^^ expected `;` diff --git a/tests/ui/parser/import-glob-path.rs b/tests/ui/parser/import-glob-path.rs index cb854de0cff6..3f1c98fcade9 100644 --- a/tests/ui/parser/import-glob-path.rs +++ b/tests/ui/parser/import-glob-path.rs @@ -1,2 +1 @@ -//@ error-pattern:expected -use foo::*::bar +use foo::*::bar //~ ERROR expected `;`, found `::` diff --git a/tests/ui/parser/import-glob-path.stderr b/tests/ui/parser/import-glob-path.stderr index 3bde32d1ea4d..04f8a6e96fad 100644 --- a/tests/ui/parser/import-glob-path.stderr +++ b/tests/ui/parser/import-glob-path.stderr @@ -1,5 +1,5 @@ error: expected `;`, found `::` - --> $DIR/import-glob-path.rs:2:11 + --> $DIR/import-glob-path.rs:1:11 | LL | use foo::*::bar | ^^ expected `;` diff --git a/tests/ui/parser/import-glob-rename.rs b/tests/ui/parser/import-glob-rename.rs index 899818b15b6f..5027a75f881e 100644 --- a/tests/ui/parser/import-glob-rename.rs +++ b/tests/ui/parser/import-glob-rename.rs @@ -1,6 +1,4 @@ -//@ error-pattern:expected - -use foo::* as baz; +use foo::* as baz; //~ ERROR expected `;`, found keyword `as` mod foo { pub fn bar() {} diff --git a/tests/ui/parser/import-glob-rename.stderr b/tests/ui/parser/import-glob-rename.stderr index 24e6c3f00063..2a5f2b66404d 100644 --- a/tests/ui/parser/import-glob-rename.stderr +++ b/tests/ui/parser/import-glob-rename.stderr @@ -1,5 +1,5 @@ error: expected `;`, found keyword `as` - --> $DIR/import-glob-rename.rs:3:12 + --> $DIR/import-glob-rename.rs:1:12 | LL | use foo::* as baz; | ^^ expected `;` diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs index ff28548b795f..9c164813de2a 100644 --- a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs +++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs @@ -1,6 +1,7 @@ -//@ error-pattern: circular modules // Regression test for #97589: a doc-comment on a circular module bypassed cycle detection #![crate_type = "lib"] pub mod recursive; + +//~? ERROR circular modules: $DIR/recursive.rs -> $DIR/recursive.rs diff --git a/tests/ui/parser/issues/issue-21146.rs b/tests/ui/parser/issues/issue-21146.rs index 81112808b21e..95cae47939f7 100644 --- a/tests/ui/parser/issues/issue-21146.rs +++ b/tests/ui/parser/issues/issue-21146.rs @@ -1,3 +1,4 @@ -//@ error-pattern: expected one of `!` or `::`, found `` include!("auxiliary/issue-21146-inc.rs"); fn main() {} + +//~? ERROR expected one of `!` or `::`, found `` diff --git a/tests/ui/parser/issues/issue-66473.rs b/tests/ui/parser/issues/issue-66473.rs index baa00f95e12fa34d1d94108d48ee36224b4a8715..d0786add1af501e9569b399244f217b2b47c1516 100644 GIT binary patch literal 287 zcmY#B+rfYVxb*ew;uKtig8YLNO7pVw^2_rSic1oUN)+|0RSSJSo8n@ delta 61 zcmbQw)W|5LukWCcT2z!@q+5_!Qj%JfXEjklT$l@s@DFuHt_fo7+_Gk}3=CWVM`978 diff --git a/tests/ui/parser/issues/issue-66473.stderr b/tests/ui/parser/issues/issue-66473.stderr index ba38c4fa1b7a..65b2d5a34ee4 100644 --- a/tests/ui/parser/issues/issue-66473.stderr +++ b/tests/ui/parser/issues/issue-66473.stderr @@ -1,11 +1,11 @@ error: unknown start of token: \u{348} - --> $DIR/issue-66473.rs:4:2 + --> $DIR/issue-66473.rs:1:2 | LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ | ^ error: unknown start of token: \u{0} - --> $DIR/issue-66473.rs:4:3 + --> $DIR/issue-66473.rs:1:3 | LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ | ^^^^^^^^^^^^^^^^^^ @@ -14,19 +14,19 @@ LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ = note: character appears 17 more times error: unknown start of token: \u{1d} - --> $DIR/issue-66473.rs:5:2 + --> $DIR/issue-66473.rs:4:2 | LL | ␋␝6␝␀␀ | ^ error: unknown start of token: \u{1d} - --> $DIR/issue-66473.rs:5:4 + --> $DIR/issue-66473.rs:4:4 | LL | ␋␝6␝␀␀ | ^ error: unknown start of token: \u{0} - --> $DIR/issue-66473.rs:5:5 + --> $DIR/issue-66473.rs:4:5 | LL | ␋␝6␝␀␀ | ^^ @@ -35,10 +35,11 @@ LL | ␋␝6␝␀␀ = note: character appears once more error: expected one of `!` or `[`, found `6` - --> $DIR/issue-66473.rs:5:3 + --> $DIR/issue-66473.rs:4:3 | LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ | - expected one of `!` or `[` +... LL | ␋␝6␝␀␀ | ^ unexpected token diff --git a/tests/ui/parser/issues/issue-68629.rs b/tests/ui/parser/issues/issue-68629.rs index d353d1f56ce18b877685da664042ba364ab5f172..d1ea4ca8b03719e38fae4daa22e504e9acf9b795 100644 GIT binary patch literal 258 zcmdPbuPXxq1=pY;{~(3ZyzIRE@;rs&lEk7Ch5R&ylKkw{JS&Bm(rUxxS}v$+A{3{= z6cbi!K)O<>p(Poa#R_SeIjIWC`FSOYnR&$uiFpd8dC58X#i=O@DXBS`xtS%YMO-rS fCB+Pi(bbt;3=9eiX?Y4ocX#I}+7;d1oy!FP$4gpC delta 79 zcmZo-YGxGD*LP4zEh@?{(k)0VDM>BLvzo{!F3g2Rc#oDWmyCQ#F@s`sbtV@BgMva@ So $DIR/issue-68629.rs:4:1 + --> $DIR/issue-68629.rs:6:1 | LL | ␜␟ts␀![{i | ^ error: unknown start of token: \u{1f} - --> $DIR/issue-68629.rs:4:2 + --> $DIR/issue-68629.rs:6:2 | LL | ␜␟ts␀![{i | ^ error: unknown start of token: \u{0} - --> $DIR/issue-68629.rs:4:5 + --> $DIR/issue-68629.rs:6:5 | LL | ␜␟ts␀![{i | ^ @@ -19,7 +19,7 @@ LL | ␜␟ts␀![{i = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/issue-68629.rs:5:1 + --> $DIR/issue-68629.rs:7:1 | LL | ␀␀ fn rݻoa>rݻm | ^^ @@ -28,7 +28,7 @@ LL | ␀␀ fn rݻoa>rݻm = note: character appears once more error: this file contains an unclosed delimiter - --> $DIR/issue-68629.rs:5:17 + --> $DIR/issue-68629.rs:7:17 | LL | ␜␟ts␀![{i | -- unclosed delimiter diff --git a/tests/ui/parser/issues/issue-68730.rs b/tests/ui/parser/issues/issue-68730.rs index f7f11cbc98ba8d28f6000544c35766d0b02c3d23..9cf51b720eb386c4461b1b96315f65d0bd54ab82 100644 GIT binary patch literal 305 zcmdPbSIA7y%P&gREy+x&)GaAW%*@HmOV`ayEzil!OD*Q&($}vm0|5ospdkMsh0?t2 zy!`S!h2oOLq7sGtG=-A~(!3Of U1e*k|)V$JMhSXe!(@m$F0Hz9R6aWAK delta 65 zcmdnUw2^UwqL9A6gF $DIR/issue-68730.rs:5:5 + --> $DIR/issue-68730.rs:8:5 | LL | enum␀em␀˂˂ | ^ @@ -7,7 +7,7 @@ LL | enum␀em␀˂˂ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/issue-68730.rs:5:8 + --> $DIR/issue-68730.rs:8:8 | LL | enum␀em␀˂˂ | ^ @@ -15,7 +15,7 @@ LL | enum␀em␀˂˂ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{2c2} - --> $DIR/issue-68730.rs:5:9 + --> $DIR/issue-68730.rs:8:9 | LL | enum␀em␀˂˂ | ^^ @@ -28,7 +28,7 @@ LL + enum␀em␀<< | error: unknown start of token: \u{2c2} - --> $DIR/issue-68730.rs:5:10 + --> $DIR/issue-68730.rs:8:10 | LL | enum␀em␀˂˂ | ^ @@ -40,7 +40,7 @@ LL + enum␀em␀˂< | error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `<` - --> $DIR/issue-68730.rs:5:10 + --> $DIR/issue-68730.rs:8:10 | LL | enum␀em␀˂˂ | ^ expected one of `#`, `>`, `const`, identifier, or lifetime diff --git a/tests/ui/parser/shebang/shebang-split.rs b/tests/ui/parser/shebang/shebang-split.rs index 470bb6691430..eb8f0f769c85 100644 --- a/tests/ui/parser/shebang/shebang-split.rs +++ b/tests/ui/parser/shebang/shebang-split.rs @@ -1,5 +1,4 @@ // empty line # !/bin/env - +//~^ ERROR expected `[`, found `/` // checks that diagnostics for shebang lookalikes is not present -//@ error-pattern: expected `[`\n\n diff --git a/tests/ui/parser/utf16-be-without-bom.rs b/tests/ui/parser/utf16-be-without-bom.rs index f5fe8dc5a8c79bf7c01402d57dd7380553efd29e..538728735f06c249c0bff31d9ffc067cc19a2a01 100644 GIT binary patch delta 47 zcmZ3)c#2U&U*AC?IX|}`GbdFyEhjO(*h)cHH?^oJzeqPNzbH4c#5SWeH!+WE!Xf~8 C2oRnC delta 7 OcmX@bxQKD0#v%X $DIR/utf16-be-without-bom.rs:5:1 + --> $DIR/utf16-be-without-bom.rs:6:1 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -7,7 +7,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:3 + --> $DIR/utf16-be-without-bom.rs:6:3 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -15,7 +15,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:5 + --> $DIR/utf16-be-without-bom.rs:6:5 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -23,7 +23,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:7 + --> $DIR/utf16-be-without-bom.rs:6:7 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -31,7 +31,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:9 + --> $DIR/utf16-be-without-bom.rs:6:9 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -39,7 +39,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:11 + --> $DIR/utf16-be-without-bom.rs:6:11 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -47,7 +47,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:13 + --> $DIR/utf16-be-without-bom.rs:6:13 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -55,7 +55,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:15 + --> $DIR/utf16-be-without-bom.rs:6:15 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -63,7 +63,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:17 + --> $DIR/utf16-be-without-bom.rs:6:17 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -71,7 +71,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:19 + --> $DIR/utf16-be-without-bom.rs:6:19 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -79,7 +79,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:21 + --> $DIR/utf16-be-without-bom.rs:6:21 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -87,7 +87,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:23 + --> $DIR/utf16-be-without-bom.rs:6:23 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -95,7 +95,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:25 + --> $DIR/utf16-be-without-bom.rs:6:25 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -103,7 +103,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: expected one of `!` or `::`, found `n` - --> $DIR/utf16-be-without-bom.rs:5:4 + --> $DIR/utf16-be-without-bom.rs:6:4 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ expected one of `!` or `::` diff --git a/tests/ui/parser/utf16-le-without-bom.rs b/tests/ui/parser/utf16-le-without-bom.rs index 8c781b27dc02efc15938bf6798e745bfcb656509..fc413663c9c09ac7b521f8a39e7e856c3067fb0f 100644 GIT binary patch delta 47 zcmZ3?c$!f|U*AC?IX|}`GbdFyEhjO(*h)cHH?^oJzeqPNzbH4c#5SWeH!+WE!eRh; CWe}kN delta 7 OcmX@jxR`OG#$o^qa{|o( diff --git a/tests/ui/parser/utf16-le-without-bom.stderr b/tests/ui/parser/utf16-le-without-bom.stderr index 4b195ed0da1a..701379d4067e 100644 --- a/tests/ui/parser/utf16-le-without-bom.stderr +++ b/tests/ui/parser/utf16-le-without-bom.stderr @@ -1,5 +1,5 @@ error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:2 + --> $DIR/utf16-le-without-bom.rs:6:2 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -7,7 +7,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:4 + --> $DIR/utf16-le-without-bom.rs:6:4 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -15,7 +15,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:6 + --> $DIR/utf16-le-without-bom.rs:6:6 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -23,7 +23,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:8 + --> $DIR/utf16-le-without-bom.rs:6:8 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -31,7 +31,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:10 + --> $DIR/utf16-le-without-bom.rs:6:10 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -39,7 +39,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:12 + --> $DIR/utf16-le-without-bom.rs:6:12 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -47,7 +47,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:14 + --> $DIR/utf16-le-without-bom.rs:6:14 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -55,7 +55,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:16 + --> $DIR/utf16-le-without-bom.rs:6:16 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -63,7 +63,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:18 + --> $DIR/utf16-le-without-bom.rs:6:18 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -71,7 +71,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:20 + --> $DIR/utf16-le-without-bom.rs:6:20 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -79,7 +79,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:22 + --> $DIR/utf16-le-without-bom.rs:6:22 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -87,7 +87,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:24 + --> $DIR/utf16-le-without-bom.rs:6:24 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -95,7 +95,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:6:1 + --> $DIR/utf16-le-without-bom.rs:7:1 | LL | ␀ | ^ @@ -103,7 +103,7 @@ LL | ␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: expected one of `!` or `::`, found `n` - --> $DIR/utf16-le-without-bom.rs:5:3 + --> $DIR/utf16-le-without-bom.rs:6:3 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ expected one of `!` or `::` diff --git a/tests/ui/print-request/print-lints-help.rs b/tests/ui/print-request/print-lints-help.rs index 420eae27ed43..6dd88a701c31 100644 --- a/tests/ui/print-request/print-lints-help.rs +++ b/tests/ui/print-request/print-lints-help.rs @@ -2,6 +2,7 @@ //! `--print=lints` (which is not a valid print request). //@ compile-flags: --print lints -//@ error-pattern: error: unknown print request: `lints` //@ error-pattern: help: use `-Whelp` to print a list of lints //@ error-pattern: help: for more information, see the rustc book + +//~? ERROR unknown print request: `lints` diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs index 0ec0886e941e..22f279802cd7 100644 --- a/tests/ui/print-request/stability.rs +++ b/tests/ui/print-request/stability.rs @@ -16,7 +16,6 @@ //@ revisions: all_target_specs_json //@[all_target_specs_json] compile-flags: --print=all-target-specs-json -//@[all_target_specs_json] error-pattern: the `-Z unstable-options` flag must also be passed //@ revisions: crate_root_lint_levels //@[crate_root_lint_levels] compile-flags: --print=crate-root-lint-levels @@ -24,15 +23,12 @@ //@ revisions: check_cfg //@[check_cfg] compile-flags: --print=check-cfg -//@[check_cfg] error-pattern: the `-Z unstable-options` flag must also be passed //@ revisions: supported_crate_types //@[supported_crate_types] compile-flags: --print=supported-crate-types -//@[supported_crate_types] error-pattern: the `-Z unstable-options` flag must also be passed //@ revisions: target_spec_json //@[target_spec_json] compile-flags: --print=target-spec-json -//@[target_spec_json] error-pattern: the `-Z unstable-options` flag must also be passed // ======================= // Stable print requests @@ -109,3 +105,8 @@ //@[tls_models] check-pass fn main() {} + +//[all_target_specs_json]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `all-target-specs-json` print option +//[check_cfg]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `check-cfg` print option +//[supported_crate_types]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `supported-crate-types` print option +//[target_spec_json]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `target-spec-json` print option diff --git a/tests/ui/privacy/private-inferred-type-3.rs b/tests/ui/privacy/private-inferred-type-3.rs index 7bf6bea4b0f6..820b0cbb30fa 100644 --- a/tests/ui/privacy/private-inferred-type-3.rs +++ b/tests/ui/privacy/private-inferred-type-3.rs @@ -1,17 +1,16 @@ //@ aux-build:private-inferred-type.rs -//@ error-pattern:type `fn() {ext::priv_fn}` is private -//@ error-pattern:static `ext::PRIV_STATIC` is private -//@ error-pattern:type `ext::PrivEnum` is private -//@ error-pattern:type `fn() {::method}` is private -//@ error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private -//@ error-pattern:type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private -//@ error-pattern:type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private - #![feature(decl_macro)] extern crate private_inferred_type as ext; fn main() { ext::m!(); + //~^ ERROR type `fn() {ext::priv_fn}` is private + //~| ERROR static `ext::PRIV_STATIC` is private + //~| ERROR type `ext::PrivEnum` is private + //~| ERROR type `fn() {::method}` is private + //~| ERROR type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private + //~| ERROR type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private + //~| ERROR type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private } diff --git a/tests/ui/privacy/private-inferred-type-3.stderr b/tests/ui/privacy/private-inferred-type-3.stderr index 42faeb4bf341..0b4899c8d3d1 100644 --- a/tests/ui/privacy/private-inferred-type-3.stderr +++ b/tests/ui/privacy/private-inferred-type-3.stderr @@ -1,5 +1,5 @@ error: type `fn() {ext::priv_fn}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -7,7 +7,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: static `ext::PRIV_STATIC` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private static @@ -15,7 +15,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `ext::PrivEnum` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -23,7 +23,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `fn() {::method}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -31,7 +31,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -39,7 +39,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -47,7 +47,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type diff --git a/tests/ui/proc-macro/export-macro.rs b/tests/ui/proc-macro/export-macro.rs index e6001d06f0f3..33bf8cfb2552 100644 --- a/tests/ui/proc-macro/export-macro.rs +++ b/tests/ui/proc-macro/export-macro.rs @@ -1,11 +1,9 @@ -//@ error-pattern: cannot export macro_rules! macros from a `proc-macro` crate - //@ force-host //@ no-prefer-dynamic #![crate_type = "proc-macro"] #[macro_export] -macro_rules! foo { +macro_rules! foo { //~ ERROR cannot export macro_rules! macros from a `proc-macro` crate type ($e:expr) => ($e) } diff --git a/tests/ui/proc-macro/export-macro.stderr b/tests/ui/proc-macro/export-macro.stderr index 410770eca08a..be586d504598 100644 --- a/tests/ui/proc-macro/export-macro.stderr +++ b/tests/ui/proc-macro/export-macro.stderr @@ -1,5 +1,5 @@ error: cannot export macro_rules! macros from a `proc-macro` crate type currently - --> $DIR/export-macro.rs:9:1 + --> $DIR/export-macro.rs:7:1 | LL | macro_rules! foo { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs index 6afafb7114a6..df236cce6d2a 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs @@ -4,8 +4,10 @@ //@ edition:2018 //@ proc-macro: issue-59191.rs //@ needs-unwind (affects error output) -//@ error-pattern: error: `#[panic_handler]` function required #![feature(custom_inner_attributes)] #![issue_59191::no_main] #![issue_59191::no_main] + +//~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/proc-macro/panic-abort.rs b/tests/ui/proc-macro/panic-abort.rs index 40d8aec5ef69..58e1d0064330 100644 --- a/tests/ui/proc-macro/panic-abort.rs +++ b/tests/ui/proc-macro/panic-abort.rs @@ -1,4 +1,5 @@ -//@ error-pattern: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic //@ compile-flags: --crate-type proc-macro -Cpanic=abort //@ force-host //@ check-pass + +//~? WARN building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic diff --git a/tests/ui/proc-macro/two-crate-types-1.rs b/tests/ui/proc-macro/two-crate-types-1.rs index 432b0a601b22..9d21a4305371 100644 --- a/tests/ui/proc-macro/two-crate-types-1.rs +++ b/tests/ui/proc-macro/two-crate-types-1.rs @@ -1,7 +1,7 @@ -//@ error-pattern: cannot mix `proc-macro` crate type with others - //@ force-host //@ no-prefer-dynamic #![crate_type = "proc-macro"] #![crate_type = "rlib"] + +//~? ERROR cannot mix `proc-macro` crate type with others diff --git a/tests/ui/proc-macro/two-crate-types-2.rs b/tests/ui/proc-macro/two-crate-types-2.rs index 491c5c71d76c..c4cc0b4d80df 100644 --- a/tests/ui/proc-macro/two-crate-types-2.rs +++ b/tests/ui/proc-macro/two-crate-types-2.rs @@ -1,3 +1,4 @@ -//@ error-pattern: cannot mix `proc-macro` crate type with others //@ compile-flags: --crate-type rlib --crate-type proc-macro //@ force-host + +//~? ERROR cannot mix `proc-macro` crate type with others diff --git a/tests/ui/reachable/unreachable-code-ret.rs b/tests/ui/reachable/unreachable-code-ret.rs index ed9fbd5c5a2d..746c4d53e7bf 100644 --- a/tests/ui/reachable/unreachable-code-ret.rs +++ b/tests/ui/reachable/unreachable-code-ret.rs @@ -1,8 +1,6 @@ -//@ error-pattern: unreachable statement - #![deny(unreachable_code)] fn main() { return; - println!("Paul is dead"); + println!("Paul is dead"); //~ ERROR unreachable statement } diff --git a/tests/ui/reachable/unreachable-code-ret.stderr b/tests/ui/reachable/unreachable-code-ret.stderr index 824515a2271f..d86def536df8 100644 --- a/tests/ui/reachable/unreachable-code-ret.stderr +++ b/tests/ui/reachable/unreachable-code-ret.stderr @@ -1,5 +1,5 @@ error: unreachable statement - --> $DIR/unreachable-code-ret.rs:7:5 + --> $DIR/unreachable-code-ret.rs:5:5 | LL | return; | ------ any code following this expression is unreachable @@ -7,7 +7,7 @@ LL | println!("Paul is dead"); | ^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here - --> $DIR/unreachable-code-ret.rs:3:9 + --> $DIR/unreachable-code-ret.rs:1:9 | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/resolve/bad-env-capture.rs b/tests/ui/resolve/bad-env-capture.rs index ccd98b6ef062..a0efe88e2a9e 100644 --- a/tests/ui/resolve/bad-env-capture.rs +++ b/tests/ui/resolve/bad-env-capture.rs @@ -1,6 +1,8 @@ -//@ error-pattern: can't capture dynamic environment in a fn item fn foo() { let x: isize; fn bar() { log(debug, x); } + //~^ ERROR can't capture dynamic environment in a fn item + //~| ERROR cannot find value `debug` in this scope + //~| ERROR cannot find function `log` in this scope } fn main() { foo(); } diff --git a/tests/ui/resolve/bad-env-capture.stderr b/tests/ui/resolve/bad-env-capture.stderr index 59b1fabfd7c4..a3a15ca245b2 100644 --- a/tests/ui/resolve/bad-env-capture.stderr +++ b/tests/ui/resolve/bad-env-capture.stderr @@ -1,5 +1,5 @@ error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/bad-env-capture.rs:4:27 + --> $DIR/bad-env-capture.rs:3:27 | LL | fn bar() { log(debug, x); } | ^ @@ -7,13 +7,13 @@ LL | fn bar() { log(debug, x); } = help: use the `|| { ... }` closure form instead error[E0425]: cannot find value `debug` in this scope - --> $DIR/bad-env-capture.rs:4:20 + --> $DIR/bad-env-capture.rs:3:20 | LL | fn bar() { log(debug, x); } | ^^^^^ not found in this scope error[E0425]: cannot find function `log` in this scope - --> $DIR/bad-env-capture.rs:4:16 + --> $DIR/bad-env-capture.rs:3:16 | LL | fn bar() { log(debug, x); } | ^^^ not found in this scope diff --git a/tests/ui/resolve/bad-env-capture2.rs b/tests/ui/resolve/bad-env-capture2.rs index 84d1832be607..8298e6fcd243 100644 --- a/tests/ui/resolve/bad-env-capture2.rs +++ b/tests/ui/resolve/bad-env-capture2.rs @@ -1,5 +1,7 @@ -//@ error-pattern: can't capture dynamic environment in a fn item fn foo(x: isize) { fn bar() { log(debug, x); } + //~^ ERROR can't capture dynamic environment in a fn item + //~| ERROR cannot find value `debug` in this scope + //~| ERROR cannot find function `log` in this scope } fn main() { foo(2); } diff --git a/tests/ui/resolve/bad-env-capture2.stderr b/tests/ui/resolve/bad-env-capture2.stderr index 811c259de6bd..403fe2d32b98 100644 --- a/tests/ui/resolve/bad-env-capture2.stderr +++ b/tests/ui/resolve/bad-env-capture2.stderr @@ -1,5 +1,5 @@ error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/bad-env-capture2.rs:3:27 + --> $DIR/bad-env-capture2.rs:2:27 | LL | fn bar() { log(debug, x); } | ^ @@ -7,13 +7,13 @@ LL | fn bar() { log(debug, x); } = help: use the `|| { ... }` closure form instead error[E0425]: cannot find value `debug` in this scope - --> $DIR/bad-env-capture2.rs:3:20 + --> $DIR/bad-env-capture2.rs:2:20 | LL | fn bar() { log(debug, x); } | ^^^^^ not found in this scope error[E0425]: cannot find function `log` in this scope - --> $DIR/bad-env-capture2.rs:3:16 + --> $DIR/bad-env-capture2.rs:2:16 | LL | fn bar() { log(debug, x); } | ^^^ not found in this scope diff --git a/tests/ui/resolve/bad-env-capture3.rs b/tests/ui/resolve/bad-env-capture3.rs index 849b84cb1ab7..8f5440d33397 100644 --- a/tests/ui/resolve/bad-env-capture3.rs +++ b/tests/ui/resolve/bad-env-capture3.rs @@ -1,7 +1,9 @@ -//@ error-pattern: can't capture dynamic environment in a fn item fn foo(x: isize) { fn mth() { fn bar() { log(debug, x); } + //~^ ERROR can't capture dynamic environment in a fn item + //~| ERROR cannot find value `debug` in this scope + //~| ERROR cannot find function `log` in this scope } } diff --git a/tests/ui/resolve/bad-env-capture3.stderr b/tests/ui/resolve/bad-env-capture3.stderr index eab37fde96e4..962eb72ee68b 100644 --- a/tests/ui/resolve/bad-env-capture3.stderr +++ b/tests/ui/resolve/bad-env-capture3.stderr @@ -1,5 +1,5 @@ error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/bad-env-capture3.rs:4:31 + --> $DIR/bad-env-capture3.rs:3:31 | LL | fn bar() { log(debug, x); } | ^ @@ -7,13 +7,13 @@ LL | fn bar() { log(debug, x); } = help: use the `|| { ... }` closure form instead error[E0425]: cannot find value `debug` in this scope - --> $DIR/bad-env-capture3.rs:4:24 + --> $DIR/bad-env-capture3.rs:3:24 | LL | fn bar() { log(debug, x); } | ^^^^^ not found in this scope error[E0425]: cannot find function `log` in this scope - --> $DIR/bad-env-capture3.rs:4:20 + --> $DIR/bad-env-capture3.rs:3:20 | LL | fn bar() { log(debug, x); } | ^^^ not found in this scope diff --git a/tests/ui/return/ret-non-nil.rs b/tests/ui/return/ret-non-nil.rs index 1d039ffe18c2..b9a53086b3c3 100644 --- a/tests/ui/return/ret-non-nil.rs +++ b/tests/ui/return/ret-non-nil.rs @@ -1,7 +1,5 @@ -//@ error-pattern: `return;` in a function whose return type is not `()` - fn f() { return; } -fn g() -> isize { return; } +fn g() -> isize { return; } //~ ERROR `return;` in a function whose return type is not `()` fn main() { f(); g(); } diff --git a/tests/ui/return/ret-non-nil.stderr b/tests/ui/return/ret-non-nil.stderr index 802900e61a30..44edecf501fc 100644 --- a/tests/ui/return/ret-non-nil.stderr +++ b/tests/ui/return/ret-non-nil.stderr @@ -1,5 +1,5 @@ error[E0069]: `return;` in a function whose return type is not `()` - --> $DIR/ret-non-nil.rs:5:19 + --> $DIR/ret-non-nil.rs:3:19 | LL | fn g() -> isize { return; } | ----- ^^^^^^ return type is not `()` diff --git a/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs index d54b428bf22f..9dc856959c00 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs +++ b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs @@ -1,4 +1,5 @@ //@ compile-flags: -l foo:bar -//@ error-pattern: renaming of the library `foo` was specified #![crate_type = "lib"] + +//~? ERROR renaming of the library `foo` was specified diff --git a/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs index ec1a246245e3..69132895510b 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs +++ b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs @@ -1,7 +1,8 @@ //@ compile-flags: -l foo:bar -l foo:baz -//@ error-pattern: multiple renamings were specified for library #![crate_type = "lib"] #[link(name = "foo")] extern "C" {} + +//~? ERROR multiple renamings were specified for library `foo` diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs index 2a13d22e22ae..e1fec3059328 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs +++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs @@ -1,5 +1,4 @@ //@ compile-flags: -l dylib=foo:bar -//@ error-pattern: overriding linking modifiers from command line is not supported #![feature(native_link_modifiers_as_needed)] @@ -7,3 +6,4 @@ #[link(name = "foo", kind = "dylib", modifiers = "-as-needed")] extern "C" {} +//~^ ERROR overriding linking modifiers from command line is not supported diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr index ce145689f901..84b197a9b986 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr +++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr @@ -1,5 +1,5 @@ error: overriding linking modifiers from command line is not supported - --> $DIR/rename-modifiers.rs:9:1 + --> $DIR/rename-modifiers.rs:8:1 | LL | extern "C" {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs index 39205a11dd73..6fee80f02948 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs +++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs @@ -1,7 +1,8 @@ //@ compile-flags: -l foo: -//@ error-pattern: an empty renaming target was specified for library #![crate_type = "lib"] #[link(name = "foo")] extern "C" {} + +//~? ERROR an empty renaming target was specified for library `foo` diff --git a/tests/ui/rmeta/rmeta_bin.rs b/tests/ui/rmeta/rmeta_bin.rs index c7d2050cd59f..9eb65241fafd 100644 --- a/tests/ui/rmeta/rmeta_bin.rs +++ b/tests/ui/rmeta/rmeta_bin.rs @@ -2,7 +2,6 @@ //@ compile-flags: --crate-type=bin //@ aux-build:rmeta-meta.rs //@ no-prefer-dynamic -//@ error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found // Check that building a bin crate fails if a dependent crate is metadata-only. @@ -12,3 +11,5 @@ use rmeta_meta::Foo; fn main() { let _ = Foo { field: 42 }; } + +//~? ERROR crate `rmeta_meta` required to be available in rlib format, but was not found in this form diff --git a/tests/ui/rmeta/rmeta_lib.rs b/tests/ui/rmeta/rmeta_lib.rs index 1be4ee8de793..d1a2b653ed80 100644 --- a/tests/ui/rmeta/rmeta_lib.rs +++ b/tests/ui/rmeta/rmeta_lib.rs @@ -1,7 +1,6 @@ //@ build-fail //@ aux-build:rmeta-meta.rs //@ no-prefer-dynamic -//@ error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found // Check that building a non-metadata crate fails if a dependent crate is // metadata-only. @@ -12,3 +11,5 @@ use rmeta_meta::Foo; fn main() { let _ = Foo { field: 42 }; } + +//~? ERROR crate `rmeta_meta` required to be available in rlib format, but was not found in this form diff --git a/tests/ui/sanitizer/incompatible.rs b/tests/ui/sanitizer/incompatible.rs index d000abb26ac7..c706a5a2e4e7 100644 --- a/tests/ui/sanitizer/incompatible.rs +++ b/tests/ui/sanitizer/incompatible.rs @@ -1,7 +1,8 @@ //@ compile-flags: -Z sanitizer=address -Z sanitizer=memory --target x86_64-unknown-linux-gnu //@ needs-llvm-components: x86 -//@ error-pattern: error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` diff --git a/tests/ui/sanitizer/unsupported-target.rs b/tests/ui/sanitizer/unsupported-target.rs index 7c7dc24b5d9a..14925548e927 100644 --- a/tests/ui/sanitizer/unsupported-target.rs +++ b/tests/ui/sanitizer/unsupported-target.rs @@ -1,6 +1,8 @@ //@ compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu //@ needs-llvm-components: x86 -//@ error-pattern: error: leak sanitizer is not supported for this target + #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR leak sanitizer is not supported for this target diff --git a/tests/ui/simd/monomorphize-too-long.rs b/tests/ui/simd/monomorphize-too-long.rs index 4bcde782292d..4fac987b0b5a 100644 --- a/tests/ui/simd/monomorphize-too-long.rs +++ b/tests/ui/simd/monomorphize-too-long.rs @@ -1,5 +1,4 @@ //@ build-fail -//@ error-pattern: monomorphising SIMD type `Simd` of length greater than 32768 #![feature(repr_simd)] @@ -9,3 +8,5 @@ struct Simd([T; N]); fn main() { let _too_big = Simd([1_u16; 54321]); } + +//~? ERROR monomorphising SIMD type `Simd` of length greater than 32768 diff --git a/tests/ui/simd/monomorphize-zero-length.rs b/tests/ui/simd/monomorphize-zero-length.rs index 44b4cfc0bcfa..d38870c572d9 100644 --- a/tests/ui/simd/monomorphize-zero-length.rs +++ b/tests/ui/simd/monomorphize-zero-length.rs @@ -1,5 +1,4 @@ //@ build-fail -//@ error-pattern: monomorphising SIMD type `Simd` of zero length #![feature(repr_simd)] @@ -9,3 +8,5 @@ struct Simd([T; N]); fn main() { let _empty = Simd([1.0; 0]); } + +//~? ERROR monomorphising SIMD type `Simd` of zero length diff --git a/tests/ui/simd/type-generic-monomorphisation-empty.rs b/tests/ui/simd/type-generic-monomorphisation-empty.rs index 4700f642065b..c08dc9fe3df2 100644 --- a/tests/ui/simd/type-generic-monomorphisation-empty.rs +++ b/tests/ui/simd/type-generic-monomorphisation-empty.rs @@ -2,11 +2,11 @@ #![feature(repr_simd, intrinsics)] -//@ error-pattern:monomorphising SIMD type `Simd<0>` of zero length - #[repr(simd)] struct Simd([f32; N]); fn main() { let _ = Simd::<0>([]); } + +//~? ERROR monomorphising SIMD type `Simd<0>` of zero length diff --git a/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs b/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs index a2f6998c6d93..7924aeb86849 100644 --- a/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs +++ b/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs @@ -4,11 +4,11 @@ struct E; -//@ error-pattern:monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `E` - #[repr(simd)] struct S([T; 4]); fn main() { let _v: Option> = None; } + +//~? ERROR monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `E` diff --git a/tests/ui/simd/type-generic-monomorphisation-oversized.rs b/tests/ui/simd/type-generic-monomorphisation-oversized.rs index 9949f913c445..efe3480317c9 100644 --- a/tests/ui/simd/type-generic-monomorphisation-oversized.rs +++ b/tests/ui/simd/type-generic-monomorphisation-oversized.rs @@ -2,11 +2,11 @@ #![feature(repr_simd, intrinsics)] -//@ error-pattern:monomorphising SIMD type `Simd<65536>` of length greater than 32768 - #[repr(simd)] struct Simd([f32; N]); fn main() { let _ = Simd::<65536>([0.; 65536]); } + +//~? ERROR monomorphising SIMD type `Simd<65536>` of length greater than 32768 diff --git a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs index 18fc07534306..97640514dee9 100644 --- a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs +++ b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs @@ -2,11 +2,11 @@ #![feature(repr_simd)] -//@ error-pattern:monomorphising SIMD type `S<*mut [u8]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` - #[repr(simd)] struct S([T; 4]); fn main() { let _v: Option> = None; } + +//~? ERROR monomorphising SIMD type `S<*mut [u8]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` diff --git a/tests/ui/simd/type-generic-monomorphisation.rs b/tests/ui/simd/type-generic-monomorphisation.rs index 8b8d645a2649..2563b917e344 100644 --- a/tests/ui/simd/type-generic-monomorphisation.rs +++ b/tests/ui/simd/type-generic-monomorphisation.rs @@ -2,9 +2,6 @@ #![feature(repr_simd, intrinsics)] - -//@ error-pattern:monomorphising SIMD type `Simd2` with a non-primitive-scalar (integer/float/pointer) element type `X` - struct X(Vec); #[repr(simd)] struct Simd2([T; 2]); @@ -12,3 +9,5 @@ struct Simd2([T; 2]); fn main() { let _ = Simd2([X(vec![]), X(vec![])]); } + +//~? ERROR monomorphising SIMD type `Simd2` with a non-primitive-scalar (integer/float/pointer) element type `X` diff --git a/tests/ui/simd/type-wide-ptr.rs b/tests/ui/simd/type-wide-ptr.rs index 41d9fac26ad4..5740a4e8318a 100644 --- a/tests/ui/simd/type-wide-ptr.rs +++ b/tests/ui/simd/type-wide-ptr.rs @@ -2,11 +2,11 @@ #![feature(repr_simd)] -//@ error-pattern:monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` - #[repr(simd)] struct S([*mut [u8]; 4]); fn main() { let _v: Option = None; } + +//~? ERROR monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` diff --git a/tests/ui/tail-typeck.rs b/tests/ui/tail-typeck.rs index feef58a33886..1deb43c94965 100644 --- a/tests/ui/tail-typeck.rs +++ b/tests/ui/tail-typeck.rs @@ -1,6 +1,4 @@ -//@ error-pattern: mismatched types - -fn f() -> isize { return g(); } +fn f() -> isize { return g(); } //~ ERROR mismatched types fn g() -> usize { return 0; } diff --git a/tests/ui/tail-typeck.stderr b/tests/ui/tail-typeck.stderr index 0e470a7b4057..3cfbfa0fb562 100644 --- a/tests/ui/tail-typeck.stderr +++ b/tests/ui/tail-typeck.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/tail-typeck.rs:3:26 + --> $DIR/tail-typeck.rs:1:26 | LL | fn f() -> isize { return g(); } | ----- ^^^ expected `isize`, found `usize` diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs index 81f138b175f2..12e7e3bc45b3 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs @@ -5,9 +5,11 @@ //@ compile-flags: -Ctarget-feature=-sse // For now this is just a warning. //@ build-pass -//@error-pattern: must be enabled to ensure that the ABI + #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs index 7242bcc85bfd..33e4f12694f3 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs @@ -3,9 +3,11 @@ //@ compile-flags: -Ctarget-feature=-neon // For now this is just a warning. //@ build-pass -//@error-pattern: must be enabled to ensure that the ABI + #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `neon` must be enabled to ensure that the ABI of the current target can be implemented correctly diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs index 7eebcf05dc0f..e1bd25ffad1e 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs @@ -4,9 +4,12 @@ //@ compile-flags: -Ctarget-feature=-x87 // For now this is just a warning. //@ build-pass -//@error-pattern: must be enabled to ensure that the ABI + #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `x87` must be enabled to ensure that the ABI of the current target can be implemented correctly +//~? WARN unstable feature specified for `-Ctarget-feature`: `x87` diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs index f277a309cd69..4ccc6e0e941f 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs @@ -4,9 +4,12 @@ //@ compile-flags: -Ctarget-feature=+soft-float // For now this is just a warning. //@ build-pass -//@error-pattern: must be disabled to ensure that the ABI + #![feature(no_core, lang_items, riscv_target_feature)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `soft-float` must be disabled to ensure that the ABI of the current target can be implemented correctl +//~? WARN unstable feature specified for `-Ctarget-feature`: `soft-float` diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs index cf85c5212289..fda0b1c08cb2 100644 --- a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs @@ -10,3 +10,5 @@ #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `forced-atomics` cannot be disabled with `-Ctarget-feature`: unsound because it changes the ABI of atomic operations diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.rs b/tests/ui/target-feature/forbidden-target-feature-flag.rs index 245841eb0395..a04d7e347530 100644 --- a/tests/ui/target-feature/forbidden-target-feature-flag.rs +++ b/tests/ui/target-feature/forbidden-target-feature-flag.rs @@ -4,9 +4,11 @@ //@ compile-flags: -Ctarget-feature=+forced-atomics // For now this is just a warning. //@ build-pass -//@error-pattern: unsound because it changes the ABI + #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `forced-atomics` cannot be enabled with `-Ctarget-feature`: unsound because it changes the ABI of atomic operations diff --git a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs index 28d026c1a9a2..be6cd2b6faf8 100644 --- a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs +++ b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs @@ -3,10 +3,11 @@ //@ compile-flags: -Ctarget-cpu=pentium // For now this is just a warning. //@ build-pass -//@error-pattern: must be enabled #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly diff --git a/tests/ui/target-feature/tied-features-no-implication.pacg.stderr b/tests/ui/target-feature/tied-features-no-implication.pacg.stderr index 0e31dea24ea4..4ff42d31e946 100644 --- a/tests/ui/target-feature/tied-features-no-implication.pacg.stderr +++ b/tests/ui/target-feature/tied-features-no-implication.pacg.stderr @@ -1,10 +1,10 @@ error[E0428]: the name `foo` is defined multiple times - --> $DIR/tied-features-no-implication.rs:28:1 + --> $DIR/tied-features-no-implication.rs:27:1 | LL | fn foo() {} | -------- previous definition of the value `foo` here ... -LL | pub unsafe fn foo() { +LL | pub unsafe fn foo() {} | ^^^^^^^^^^^^^^^^^^^ `foo` redefined here | = note: `foo` must be defined only once in the value namespace of this module diff --git a/tests/ui/target-feature/tied-features-no-implication.rs b/tests/ui/target-feature/tied-features-no-implication.rs index 157b50bb0d32..1625f71431a6 100644 --- a/tests/ui/target-feature/tied-features-no-implication.rs +++ b/tests/ui/target-feature/tied-features-no-implication.rs @@ -2,9 +2,8 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 //@[paca] compile-flags: -Ctarget-feature=+paca -//@[paca] error-pattern: the target features paca, pacg must all be either enabled or disabled together //@[pacg] compile-flags: -Ctarget-feature=+pacg -//@[pacg] error-pattern: the name `foo` is defined multiple times + #![feature(no_core, lang_items)] #![no_core] @@ -25,5 +24,6 @@ fn foo() {} // be). #[cfg(target_feature = "pacg")] -pub unsafe fn foo() { -} +pub unsafe fn foo() {} //[pacg]~ ERROR the name `foo` is defined multiple times + +//[paca]~? ERROR the target features paca, pacg must all be either enabled or disabled together diff --git a/tests/ui/test-attrs/test-panic-abort-disabled.rs b/tests/ui/test-attrs/test-panic-abort-disabled.rs index e83be65f9250..cb1b2af9e26d 100644 --- a/tests/ui/test-attrs/test-panic-abort-disabled.rs +++ b/tests/ui/test-attrs/test-panic-abort-disabled.rs @@ -1,4 +1,3 @@ -//@ error-pattern:building tests with panic=abort is not supported //@ no-prefer-dynamic //@ compile-flags: --test -Cpanic=abort -Zpanic-abort-tests=no //@ run-flags: --test-threads=1 @@ -18,3 +17,5 @@ fn it_works() { fn it_panics() { assert_eq!(1 + 1, 4); } + +//~? ERROR building tests with panic=abort is not supported without `-Zpanic_abort_tests` diff --git a/tests/ui/track-diagnostics/track.rs b/tests/ui/track-diagnostics/track.rs index 9e81cb53fc11..78ff85489bed 100644 --- a/tests/ui/track-diagnostics/track.rs +++ b/tests/ui/track-diagnostics/track.rs @@ -15,4 +15,7 @@ fn main() { break rust + //~^ ERROR cannot find value `rust` in this scope + //~| ERROR `break` outside of a loop or labeled block + //~| ERROR It looks like you're trying to break rust; would you like some ICE? } diff --git a/tests/ui/track-diagnostics/track2.rs b/tests/ui/track-diagnostics/track2.rs index 5805fd21220d..f51a42cf86f9 100644 --- a/tests/ui/track-diagnostics/track2.rs +++ b/tests/ui/track-diagnostics/track2.rs @@ -6,5 +6,5 @@ //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" fn main() { - let _moved @ _from = String::from("foo"); + let _moved @ _from = String::from("foo"); //~ ERROR use of moved value } diff --git a/tests/ui/track-diagnostics/track3.rs b/tests/ui/track-diagnostics/track3.rs index bac1fc7e184b..428067572af7 100644 --- a/tests/ui/track-diagnostics/track3.rs +++ b/tests/ui/track-diagnostics/track3.rs @@ -7,4 +7,6 @@ fn main() { let _unimported = Blah { field: u8 }; + //~^ ERROR cannot find struct, variant or union type `Blah` in this scope + //~| ERROR expected value, found builtin type `u8` } diff --git a/tests/ui/track-diagnostics/track4.rs b/tests/ui/track-diagnostics/track4.rs index ec9e3efa481c..b6edfdba2596 100644 --- a/tests/ui/track-diagnostics/track4.rs +++ b/tests/ui/track-diagnostics/track4.rs @@ -5,7 +5,7 @@ // updating everytime someone adds or removes a line. //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" -pub onion { +pub onion { //~ ERROR missing `enum` for enum definition Owo(u8), Uwu(i8), } diff --git a/tests/ui/track-diagnostics/track5.rs b/tests/ui/track-diagnostics/track5.rs index e72e3482ad38..800bb21b2b16 100644 --- a/tests/ui/track-diagnostics/track5.rs +++ b/tests/ui/track-diagnostics/track5.rs @@ -5,4 +5,4 @@ // updating everytime someone adds or removes a line. //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" -} +} //~ ERROR unexpected closing delimiter: `}` diff --git a/tests/ui/track-diagnostics/track6.rs b/tests/ui/track-diagnostics/track6.rs index e4d124a22e49..55db2ecf939d 100644 --- a/tests/ui/track-diagnostics/track6.rs +++ b/tests/ui/track-diagnostics/track6.rs @@ -11,7 +11,7 @@ pub trait Foo { } impl Foo for T { - default fn bar() {} + default fn bar() {} //~ ERROR specialization is unstable } fn main() {} diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs index 1f5d0a772a2b..723179302e30 100644 --- a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs @@ -4,7 +4,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[unique_next] compile-flags: -Znext-solver //@[multiple_next] compile-flags: -Znext-solver -//@ error-pattern: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` trait Bound {} trait Normalize { @@ -25,3 +24,5 @@ struct Hello { } fn main() {} + +//~? ERROR reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` diff --git a/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs b/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs index 0b75bb23faff..cfb2d7c52180 100644 --- a/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs +++ b/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs @@ -6,5 +6,5 @@ fn main() { #[deny(while_true)] - while true {} + while true {} //~ ERROR denote infinite loops with `loop { ... }` } diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.rs b/tests/ui/treat-err-as-bug/span_delayed_bug.rs index 88a9d07c94cf..a242d11129f7 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.rs +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.rs @@ -9,4 +9,4 @@ #![feature(rustc_attrs)] #[rustc_delayed_bug_from_inside_query] -fn main() {} +fn main() {} //~ ERROR delayed bug triggered by #[rustc_delayed_bug_from_inside_query] diff --git a/tests/ui/type/issue-91268.rs b/tests/ui/type/issue-91268.rs index 16d5b2411456..6297880702e8 100644 --- a/tests/ui/type/issue-91268.rs +++ b/tests/ui/type/issue-91268.rs @@ -1,5 +1,6 @@ -//@ error-pattern: this file contains an unclosed delimiter // ignore-tidy-trailing-newlines // `ţ` must be the last character in this file, it cannot be followed by a newline + +//~vv ERROR this file contains an unclosed delimiter fn main() { 0: u8(ţ \ No newline at end of file diff --git a/tests/ui/type/issue-91268.stderr b/tests/ui/type/issue-91268.stderr index 395559442d1c..db7b5a188cf8 100644 --- a/tests/ui/type/issue-91268.stderr +++ b/tests/ui/type/issue-91268.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-91268.rs:5:12 + --> $DIR/issue-91268.rs:6:12 | LL | fn main() { | - unclosed delimiter diff --git a/tests/ui/type/type-arg-out-of-scope.rs b/tests/ui/type/type-arg-out-of-scope.rs index 3f8a6ff10165..05ed54ec832f 100644 --- a/tests/ui/type/type-arg-out-of-scope.rs +++ b/tests/ui/type/type-arg-out-of-scope.rs @@ -1,5 +1,6 @@ -//@ error-pattern:can't use generic parameters from outer item fn foo(x: T) { fn bar(f: Box T>) { } + //~^ ERROR can't use generic parameters from outer item + //~| ERROR can't use generic parameters from outer item } fn main() { foo(1); } diff --git a/tests/ui/type/type-arg-out-of-scope.stderr b/tests/ui/type/type-arg-out-of-scope.stderr index 8665001e2431..fcaaca1770f6 100644 --- a/tests/ui/type/type-arg-out-of-scope.stderr +++ b/tests/ui/type/type-arg-out-of-scope.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/type-arg-out-of-scope.rs:3:29 + --> $DIR/type-arg-out-of-scope.rs:2:29 | LL | fn foo(x: T) { | - type parameter from outer item @@ -9,7 +9,7 @@ LL | fn bar(f: Box T>) { } | help: try introducing a local generic parameter here: `` error[E0401]: can't use generic parameters from outer item - --> $DIR/type-arg-out-of-scope.rs:3:35 + --> $DIR/type-arg-out-of-scope.rs:2:35 | LL | fn foo(x: T) { | - type parameter from outer item diff --git a/tests/ui/typeck/issue-91334.rs b/tests/ui/typeck/issue-91334.rs index ec0d4ad70f15..c820014ff937 100644 --- a/tests/ui/typeck/issue-91334.rs +++ b/tests/ui/typeck/issue-91334.rs @@ -1,7 +1,7 @@ // Regression test for the ICE described in issue #91334. -//@ error-pattern: this file contains an unclosed delimiter - #![feature(coroutines)] +//~vv ERROR mismatched closing delimiter: `)` +//~v ERROR this file contains an unclosed delimiter fn f(){||yield(((){), diff --git a/tests/ui/typeck/output-type-mismatch.rs b/tests/ui/typeck/output-type-mismatch.rs index d5691c9c3535..0d7c7d1dfe17 100644 --- a/tests/ui/typeck/output-type-mismatch.rs +++ b/tests/ui/typeck/output-type-mismatch.rs @@ -1,5 +1,3 @@ -//@ error-pattern: mismatched types - fn f() { } -fn main() { let i: isize; i = f(); } +fn main() { let i: isize; i = f(); } //~ ERROR mismatched types diff --git a/tests/ui/typeck/output-type-mismatch.stderr b/tests/ui/typeck/output-type-mismatch.stderr index c6df6650654a..ba50cd4e6d75 100644 --- a/tests/ui/typeck/output-type-mismatch.stderr +++ b/tests/ui/typeck/output-type-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/output-type-mismatch.rs:5:31 + --> $DIR/output-type-mismatch.rs:3:31 | LL | fn main() { let i: isize; i = f(); } | ----- ^^^ expected `isize`, found `()` diff --git a/tests/ui/typeck/while-type-error.rs b/tests/ui/typeck/while-type-error.rs index ca3b8921f540..abc607516e60 100644 --- a/tests/ui/typeck/while-type-error.rs +++ b/tests/ui/typeck/while-type-error.rs @@ -1,3 +1 @@ -//@ error-pattern: mismatched types - -fn main() { while main { } } +fn main() { while main { } } //~ ERROR mismatched types diff --git a/tests/ui/typeck/while-type-error.stderr b/tests/ui/typeck/while-type-error.stderr index b67ec561531f..4bd86aafc177 100644 --- a/tests/ui/typeck/while-type-error.stderr +++ b/tests/ui/typeck/while-type-error.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/while-type-error.rs:3:19 + --> $DIR/while-type-error.rs:1:19 | LL | fn main() { while main { } } | ^^^^ expected `bool`, found fn item diff --git a/tests/ui/typeck/wrong-ret-type.rs b/tests/ui/typeck/wrong-ret-type.rs index b83aefad1e9f..2d6751a823cf 100644 --- a/tests/ui/typeck/wrong-ret-type.rs +++ b/tests/ui/typeck/wrong-ret-type.rs @@ -1,3 +1,2 @@ -//@ error-pattern: mismatched types -fn mk_int() -> usize { let i: isize = 3; return i; } +fn mk_int() -> usize { let i: isize = 3; return i; } //~ ERROR mismatched types fn main() { } diff --git a/tests/ui/typeck/wrong-ret-type.stderr b/tests/ui/typeck/wrong-ret-type.stderr index 33a094ce95d3..918eb2d5c889 100644 --- a/tests/ui/typeck/wrong-ret-type.stderr +++ b/tests/ui/typeck/wrong-ret-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/wrong-ret-type.rs:2:49 + --> $DIR/wrong-ret-type.rs:1:49 | LL | fn mk_int() -> usize { let i: isize = 3; return i; } | ----- ^ expected `usize`, found `isize` diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs index 7bd4df472207..9304e20b4290 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs @@ -1,6 +1,6 @@ +//~ ERROR unknown lint: `test_unstable_lint` //@ check-fail //@ compile-flags: -Dunknown_lints -Atest_unstable_lint -//@ error-pattern: unknown lint: `test_unstable_lint` //@ error-pattern: the `test_unstable_lint` lint is unstable fn main() {} diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs index 995f65ef83da..76983419c685 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs @@ -1,6 +1,6 @@ +//~ WARN unknown lint: `test_unstable_lint` //@ check-pass //@ compile-flags: -Wunknown_lints -Atest_unstable_lint -//@ error-pattern: unknown lint: `test_unstable_lint` //@ error-pattern: the `test_unstable_lint` lint is unstable fn main() {} diff --git a/tests/ui/use/use-meta-mismatch.rs b/tests/ui/use/use-meta-mismatch.rs index 2c5ae9cd9a1c..8d15e46375c3 100644 --- a/tests/ui/use/use-meta-mismatch.rs +++ b/tests/ui/use/use-meta-mismatch.rs @@ -1,5 +1,3 @@ -//@ error-pattern:can't find crate for `fake_crate` - -extern crate fake_crate as extra; +extern crate fake_crate as extra; //~ ERROR can't find crate for `fake_crate` fn main() { } diff --git a/tests/ui/use/use-meta-mismatch.stderr b/tests/ui/use/use-meta-mismatch.stderr index b793229e5fdd..ffc471fa7224 100644 --- a/tests/ui/use/use-meta-mismatch.stderr +++ b/tests/ui/use/use-meta-mismatch.stderr @@ -1,5 +1,5 @@ error[E0463]: can't find crate for `fake_crate` - --> $DIR/use-meta-mismatch.rs:3:1 + --> $DIR/use-meta-mismatch.rs:1:1 | LL | extern crate fake_crate as extra; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate diff --git a/tests/ui/windows-subsystem/windows-subsystem-invalid.rs b/tests/ui/windows-subsystem/windows-subsystem-invalid.rs index c6a6dd00a921..4dadfc6fd5d7 100644 --- a/tests/ui/windows-subsystem/windows-subsystem-invalid.rs +++ b/tests/ui/windows-subsystem/windows-subsystem-invalid.rs @@ -1,5 +1,5 @@ -//@ error-pattern: invalid windows subsystem `wrong`, only `windows` and `console` are allowed - #![windows_subsystem = "wrong"] fn main() {} + +//~? ERROR invalid windows subsystem `wrong` From 4916d44b59a2b5347506b4551b389fe902bdf54b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 2 Apr 2025 18:13:53 +0300 Subject: [PATCH 100/176] Fix up tests on wasm and msvc, and rebase conflicts Can be fixed properly later by adding a new flag for non-exhaustive line annotation checking --- tests/ui/cfg/cfg_false_no_std-2.rs | 7 +++++-- .../debuginfo-type-name-layout-ice-94961-2.rs | 8 ++++++-- tests/ui/panic-runtime/two-panic-runtimes.rs | 8 +++++++- .../ui/panic-runtime/unwind-tables-target-required.rs | 3 ++- tests/ui/panic-runtime/want-abort-got-unwind.rs | 10 +++++++--- tests/ui/panic-runtime/want-abort-got-unwind2.rs | 10 +++++++--- tests/ui/print-request/stability.rs | 2 +- 7 files changed, 35 insertions(+), 13 deletions(-) diff --git a/tests/ui/cfg/cfg_false_no_std-2.rs b/tests/ui/cfg/cfg_false_no_std-2.rs index fa6042f5892c..35e545aae34b 100644 --- a/tests/ui/cfg/cfg_false_no_std-2.rs +++ b/tests/ui/cfg/cfg_false_no_std-2.rs @@ -1,5 +1,7 @@ // Error, the linked empty library is `no_std` and doesn't provide a panic handler. +//@ compile-flags: --error-format=human +//@ error-pattern: `#[panic_handler]` function required, but not found //@ dont-check-compiler-stderr //@ aux-build: cfg_false_lib_no_std_before.rs @@ -9,5 +11,6 @@ extern crate cfg_false_lib_no_std_before as _; fn main() {} -//~? ERROR `#[panic_handler]` function required, but not found -//~? ERROR unwinding panics are not supported without std +// FIXME: The second error is target-dependent. +//FIXME~? ERROR `#[panic_handler]` function required, but not found +//FIXME~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs index e9b021e4f484..b79b5ff6fdb1 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs @@ -1,11 +1,12 @@ -//~ ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture +//FIXME~ ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture // Make sure the compiler does not ICE when trying to generate the debuginfo name of a type that // causes a layout error. // This version of the test already ICE'd before the commit that introduce the ICE described in // https://github.com/rust-lang/rust/issues/94961. -//@ compile-flags:-C debuginfo=2 +//@ compile-flags:-C debuginfo=2 --error-format=human //@ build-fail +//@ error-pattern: values of the type `[u8; usize::MAX]` are too big for the target architecture #![crate_type = "rlib"] @@ -16,3 +17,6 @@ pub enum Foo { pub fn foo() -> usize { std::mem::size_of::>() } + +// FIXME: the error is reported on different lines on different targets +//FIXME~? ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture diff --git a/tests/ui/panic-runtime/two-panic-runtimes.rs b/tests/ui/panic-runtime/two-panic-runtimes.rs index 37d041a8c7b9..15c08cbe30d3 100644 --- a/tests/ui/panic-runtime/two-panic-runtimes.rs +++ b/tests/ui/panic-runtime/two-panic-runtimes.rs @@ -1,4 +1,7 @@ +// ignore-tidy-linelength //@ build-fail +//@ compile-flags: --error-format=human +//@ error-pattern: cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ aux-build:panic-runtime-unwind2.rs @@ -13,4 +16,7 @@ extern crate panic_runtime_lang_items; fn main() {} -//~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 +// FIXME: The second and third errors are target-dependent. +//FIXME~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 +//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind2` is not compiled with this crate's panic strategy `abort` +//FIXME~? ERROR the crate `panic_runtime_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/unwind-tables-target-required.rs b/tests/ui/panic-runtime/unwind-tables-target-required.rs index 5c6ec19c16d0..ff8df284f6b1 100644 --- a/tests/ui/panic-runtime/unwind-tables-target-required.rs +++ b/tests/ui/panic-runtime/unwind-tables-target-required.rs @@ -5,7 +5,8 @@ //@ compile-flags: -C force-unwind-tables=no // //@ dont-check-compiler-stderr -//@ error-pattern: target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` pub fn main() { } + +//~? ERROR target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` diff --git a/tests/ui/panic-runtime/want-abort-got-unwind.rs b/tests/ui/panic-runtime/want-abort-got-unwind.rs index 76e15a1e16ea..ed61c2613df8 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind.rs @@ -1,4 +1,7 @@ +// ignore-tidy-linelength //@ build-fail +//@ compile-flags: --error-format=human +//@ error-pattern: the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ compile-flags:-C panic=abort @@ -7,6 +10,7 @@ extern crate panic_runtime_unwind; fn main() {} -//~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind -//~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` -//~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` +// FIXME: The first and third errors are target-dependent. +//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind +//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/want-abort-got-unwind2.rs b/tests/ui/panic-runtime/want-abort-got-unwind2.rs index 53cba457424f..504fd779e09a 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind2.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind2.rs @@ -1,4 +1,7 @@ +// ignore-tidy-linelength //@ build-fail +//@ compile-flags: --error-format=human +//@ error-pattern: the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ aux-build:wants-panic-runtime-unwind.rs @@ -8,6 +11,7 @@ extern crate wants_panic_runtime_unwind; fn main() {} -//~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind -//~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` -//~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` +// FIXME: The first and third errors are target-dependent. +//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind +//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs index 22f279802cd7..54142ce78cef 100644 --- a/tests/ui/print-request/stability.rs +++ b/tests/ui/print-request/stability.rs @@ -19,7 +19,6 @@ //@ revisions: crate_root_lint_levels //@[crate_root_lint_levels] compile-flags: --print=crate-root-lint-levels -//@[crate_root_lint_levels] error-pattern: the `-Z unstable-options` flag must also be passed //@ revisions: check_cfg //@[check_cfg] compile-flags: --print=check-cfg @@ -107,6 +106,7 @@ fn main() {} //[all_target_specs_json]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `all-target-specs-json` print option +//[crate_root_lint_levels]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `crate-root-lint-levels` print option //[check_cfg]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `check-cfg` print option //[supported_crate_types]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `supported-crate-types` print option //[target_spec_json]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `target-spec-json` print option From fadea8e0ba18f1e6a33720451943f079caad0856 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 31 Mar 2025 15:09:43 +0000 Subject: [PATCH 101/176] Unset RUSTC_WRAPPER in cg_clif's build system --- compiler/rustc_codegen_cranelift/build_system/utils.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs index c2114caf8692..f23997684596 100644 --- a/compiler/rustc_codegen_cranelift/build_system/utils.rs +++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs @@ -105,7 +105,11 @@ impl CargoProject { .arg(self.manifest_path(dirs)) .arg("--target-dir") .arg(self.target_dir(dirs)) - .arg("--locked"); + .arg("--locked") + // bootstrap sets both RUSTC and RUSTC_WRAPPER to the same wrapper. RUSTC is already + // respected by the rustc-clif wrapper, but RUSTC_WRAPPER will misinterpret rustc-clif + // as filename, so we need to unset it. + .env_remove("RUSTC_WRAPPER"); if dirs.frozen { cmd.arg("--frozen"); From abc838be131d0ac1be3ce8a694a6056473f89619 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 2 Apr 2025 14:17:13 +0200 Subject: [PATCH 102/176] rm RpitConstraintChecker we already collect opaque types from nested items during `mir_borrowck` of the root, checking that they are consistent this way. --- .../src/collect/type_of/opaque.rs | 72 ------------------- 1 file changed, 72 deletions(-) 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 3dec1e286b4e..8a3a6a8be110 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -318,20 +318,6 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied(); if let Some(mir_opaque_ty) = mir_opaque_ty { - if mir_opaque_ty.references_error() { - return mir_opaque_ty.ty; - } - - debug!(?owner_def_id); - let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty }; - - match tcx.hir_node_by_def_id(owner_def_id) { - Node::Item(it) => intravisit::walk_item(&mut locator, it), - Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it), - Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it), - other => bug!("{:?} is not a valid scope for an opaque type item", other), - } - mir_opaque_ty.ty } else if let Some(guar) = tables.tainted_by_errors { // Some error in the owner fn prevented us from populating @@ -352,61 +338,3 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( } } } - -struct RpitConstraintChecker<'tcx> { - tcx: TyCtxt<'tcx>, - - /// def_id of the opaque type whose defining uses are being checked - def_id: LocalDefId, - - found: ty::OpaqueHiddenType<'tcx>, -} - -impl RpitConstraintChecker<'_> { - #[instrument(skip(self), level = "debug")] - fn check(&self, def_id: LocalDefId) { - // Use borrowck to get the type with unerased regions. - let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; - debug!(?concrete_opaque_types); - if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) { - debug!(?concrete_type, "found constraint"); - if concrete_type.ty != self.found.ty { - if let Ok(d) = self.found.build_mismatch_error(&concrete_type, self.tcx) { - d.emit(); - } - } - } - } -} - -impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { - self.tcx - } - fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { - intravisit::walk_expr(self, ex); - } - fn visit_item(&mut self, it: &'tcx Item<'tcx>) { - trace!(?it.owner_id); - // The opaque type itself or its children are not within its reveal scope. - if it.owner_id.def_id != self.def_id { - self.check(it.owner_id.def_id); - intravisit::walk_item(self, it); - } - } - fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { - trace!(?it.owner_id); - // The opaque type itself or its children are not within its reveal scope. - if it.owner_id.def_id != self.def_id { - self.check(it.owner_id.def_id); - intravisit::walk_impl_item(self, it); - } - } - fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { - trace!(?it.owner_id); - self.check(it.owner_id.def_id); - intravisit::walk_trait_item(self, it); - } -} From 990201cb78a77ec0c148a880e6ab46bafa3468df Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 1 Apr 2025 23:34:00 +0200 Subject: [PATCH 103/176] move `check_opaque_type_parameter_valid` --- compiler/rustc_borrowck/messages.ftl | 7 - .../src/region_infer/opaque_types.rs | 167 +----------------- .../rustc_borrowck/src/session_diagnostics.rs | 11 -- compiler/rustc_trait_selection/messages.ftl | 7 + compiler/rustc_trait_selection/src/errors.rs | 13 +- compiler/rustc_trait_selection/src/lib.rs | 1 + .../rustc_trait_selection/src/opaque_types.rs | 165 +++++++++++++++++ 7 files changed, 189 insertions(+), 182 deletions(-) create mode 100644 compiler/rustc_trait_selection/src/opaque_types.rs diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index ada20e5c614f..33b80c4b03d6 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -162,13 +162,6 @@ borrowck_opaque_type_lifetime_mismatch = .prev_lifetime_label = lifetime `{$prev}` previously used here .note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types -borrowck_opaque_type_non_generic_param = - expected generic {$kind} parameter, found `{$ty}` - .label = {STREQ($ty, "'static") -> - [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type - *[other] this generic parameter must be used with a generic {$kind} parameter - } - borrowck_partial_var_move_by_use_in_closure = variable {$is_partial -> [true] partially moved diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index ca8b9fb4e9d8..2f15c2bc4644 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,22 +1,16 @@ use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::ErrorGuaranteed; -use rustc_hir::OpaqueTyOrigin; -use rustc_hir::def_id::LocalDefId; -use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; +use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_macros::extension; use rustc_middle::ty::{ - self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, - TypeVisitableExt, TypingMode, fold_regions, + self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, }; use rustc_span::Span; -use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt; -use rustc_trait_selection::traits::ObligationCtxt; +use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid; use tracing::{debug, instrument}; use super::RegionInferenceContext; use crate::opaque_types::ConcreteOpaqueTypes; -use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam}; +use crate::session_diagnostics::LifetimeMismatchOpaqueParam; use crate::universal_regions::RegionClassification; impl<'tcx> RegionInferenceContext<'tcx> { @@ -289,156 +283,3 @@ impl<'tcx> InferCtxt<'tcx> { definition_ty } } - -/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter]. -/// -/// [rustc-dev-guide chapter]: -/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html -fn check_opaque_type_parameter_valid<'tcx>( - infcx: &InferCtxt<'tcx>, - opaque_type_key: OpaqueTypeKey<'tcx>, - span: Span, -) -> Result<(), ErrorGuaranteed> { - let tcx = infcx.tcx; - let opaque_generics = tcx.generics_of(opaque_type_key.def_id); - let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id); - let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); - - for (i, arg) in opaque_type_key.iter_captured_args(tcx) { - let arg_is_param = match arg.unpack() { - GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), - GenericArgKind::Lifetime(lt) => { - matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_)) - || (lt.is_static() && opaque_env.param_equal_static(i)) - } - GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), - }; - - if arg_is_param { - // Register if the same lifetime appears multiple times in the generic args. - // There is an exception when the opaque type *requires* the lifetimes to be equal. - // See [rustc-dev-guide chapter] § "An exception to uniqueness rule". - let seen_where = seen_params.entry(arg).or_default(); - if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) { - seen_where.push(i); - } - } else { - // Prevent `fn foo() -> Foo` from being defining. - let opaque_param = opaque_generics.param_at(i, tcx); - let kind = opaque_param.kind.descr(); - - opaque_env.param_is_error(i)?; - - return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam { - ty: arg, - kind, - span, - param_span: tcx.def_span(opaque_param.def_id), - })); - } - } - - for (_, indices) in seen_params { - if indices.len() > 1 { - let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); - let spans: Vec<_> = indices - .into_iter() - .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) - .collect(); - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] - return Err(infcx - .dcx() - .struct_span_err(span, "non-defining opaque type use in defining scope") - .with_span_note(spans, format!("{descr} used multiple times")) - .emit()); - } - } - - Ok(()) -} - -/// Computes if an opaque type requires a lifetime parameter to be equal to -/// another one or to the `'static` lifetime. -/// These requirements are derived from the explicit and implied bounds. -struct LazyOpaqueTyEnv<'tcx> { - tcx: TyCtxt<'tcx>, - def_id: LocalDefId, - - /// Equal parameters will have the same name. Computed Lazily. - /// Example: - /// `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;` - /// Identity args: `['a, 'b, 'c]` - /// Canonical args: `['static, 'b, 'b]` - canonical_args: std::cell::OnceCell>, -} - -impl<'tcx> LazyOpaqueTyEnv<'tcx> { - fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { - Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() } - } - - fn param_equal_static(&self, param_index: usize) -> bool { - self.get_canonical_args()[param_index].expect_region().is_static() - } - - fn params_equal(&self, param1: usize, param2: usize) -> bool { - let canonical_args = self.get_canonical_args(); - canonical_args[param1] == canonical_args[param2] - } - - fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> { - self.get_canonical_args()[param_index].error_reported() - } - - fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> { - if let Some(&canonical_args) = self.canonical_args.get() { - return canonical_args; - } - - let &Self { tcx, def_id, .. } = self; - let origin = tcx.local_opaque_ty_origin(def_id); - let parent = match origin { - OpaqueTyOrigin::FnReturn { parent, .. } - | OpaqueTyOrigin::AsyncFn { parent, .. } - | OpaqueTyOrigin::TyAlias { parent, .. } => parent, - }; - let param_env = tcx.param_env(parent); - let args = GenericArgs::identity_for_item(tcx, parent).extend_to( - tcx, - def_id.to_def_id(), - |param, _| { - tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into() - }, - ); - - // FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're - // in a body here. - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); - let ocx = ObligationCtxt::new(&infcx); - - let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| { - tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds"); - Default::default() - }); - let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys); - - let mut seen = vec![tcx.lifetimes.re_static]; - let canonical_args = fold_regions(tcx, args, |r1, _| { - if r1.is_error() { - r1 - } else if let Some(&r2) = seen.iter().find(|&&r2| { - let free_regions = outlives_env.free_region_map(); - free_regions.sub_free_regions(tcx, r1, r2) - && free_regions.sub_free_regions(tcx, r2, r1) - }) { - r2 - } else { - seen.push(r1); - r1 - } - }); - self.canonical_args.set(canonical_args).unwrap(); - canonical_args - } -} diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 4be5d0dbf428..5143b2fa2059 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -294,17 +294,6 @@ pub(crate) struct MoveBorrow<'a> { pub borrow_span: Span, } -#[derive(Diagnostic)] -#[diag(borrowck_opaque_type_non_generic_param, code = E0792)] -pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { - pub ty: GenericArg<'tcx>, - pub kind: &'a str, - #[primary_span] - pub span: Span, - #[label] - pub param_span: Span, -} - #[derive(Diagnostic)] #[diag(borrowck_opaque_type_lifetime_mismatch)] pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> { diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 4db9d9915b13..05bbb42fb7c6 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -264,8 +264,15 @@ trait_selection_oc_no_diverge = `else` clause of `let...else` does not diverge trait_selection_oc_no_else = `if` may be missing an `else` clause trait_selection_oc_try_compat = `?` operator has incompatible types trait_selection_oc_type_compat = type not compatible with trait + trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds .label = opaque type defined here +trait_selection_opaque_type_non_generic_param = + expected generic {$kind} parameter, found `{$ty}` + .label = {STREQ($ty, "'static") -> + [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type + *[other] this generic parameter must be used with a generic {$kind} parameter + } trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content... diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index b30390a9330e..9f7bfe5101ab 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -12,7 +12,7 @@ use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty}; use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, IsAnonInPath, Node}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath}; -use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt}; +use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, GenericArg, Region, Ty, TyCtxt}; use rustc_span::{BytePos, Ident, Span, Symbol, kw}; use crate::error_reporting::infer::ObligationCauseAsDiagArg; @@ -1922,3 +1922,14 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture { } } } + +#[derive(Diagnostic)] +#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)] +pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { + pub ty: GenericArg<'tcx>, + pub kind: &'a str, + #[primary_span] + pub span: Span, + #[label] + pub param_span: Span, +} diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index b18fb0fb8fd3..93c118053045 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -36,6 +36,7 @@ pub mod error_reporting; pub mod errors; pub mod infer; +pub mod opaque_types; pub mod regions; pub mod solve; pub mod traits; diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs new file mode 100644 index 000000000000..5af912fee549 --- /dev/null +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -0,0 +1,165 @@ +use rustc_data_structures::fx::FxIndexMap; +use rustc_hir::OpaqueTyOrigin; +use rustc_hir::def_id::LocalDefId; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_middle::ty::{ + self, GenericArgKind, GenericArgs, OpaqueTypeKey, TyCtxt, TypeVisitableExt, + TypingMode, fold_regions, +}; +use rustc_span::{ErrorGuaranteed, Span}; + +use crate::errors::NonGenericOpaqueTypeParam; +use crate::regions::OutlivesEnvironmentBuildExt; +use crate::traits::ObligationCtxt; + +/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter]. +/// +/// [rustc-dev-guide chapter]: +/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html +pub fn check_opaque_type_parameter_valid<'tcx>( + infcx: &InferCtxt<'tcx>, + opaque_type_key: OpaqueTypeKey<'tcx>, + span: Span, +) -> Result<(), ErrorGuaranteed> { + let tcx = infcx.tcx; + let opaque_generics = tcx.generics_of(opaque_type_key.def_id); + let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id); + let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); + + for (i, arg) in opaque_type_key.iter_captured_args(tcx) { + let arg_is_param = match arg.unpack() { + GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), + GenericArgKind::Lifetime(lt) => { + matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_)) + || (lt.is_static() && opaque_env.param_equal_static(i)) + } + GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), + }; + + if arg_is_param { + // Register if the same lifetime appears multiple times in the generic args. + // There is an exception when the opaque type *requires* the lifetimes to be equal. + // See [rustc-dev-guide chapter] § "An exception to uniqueness rule". + let seen_where = seen_params.entry(arg).or_default(); + if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) { + seen_where.push(i); + } + } else { + // Prevent `fn foo() -> Foo` from being defining. + let opaque_param = opaque_generics.param_at(i, tcx); + let kind = opaque_param.kind.descr(); + + opaque_env.param_is_error(i)?; + + return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam { + ty: arg, + kind, + span, + param_span: tcx.def_span(opaque_param.def_id), + })); + } + } + + for (_, indices) in seen_params { + if indices.len() > 1 { + let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); + let spans: Vec<_> = indices + .into_iter() + .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) + .collect(); + return Err(infcx + .dcx() + .struct_span_err(span, "non-defining opaque type use in defining scope") + .with_span_note(spans, format!("{descr} used multiple times")) + .emit()); + } + } + + Ok(()) +} + +/// Computes if an opaque type requires a lifetime parameter to be equal to +/// another one or to the `'static` lifetime. +/// These requirements are derived from the explicit and implied bounds. +struct LazyOpaqueTyEnv<'tcx> { + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + + /// Equal parameters will have the same name. Computed Lazily. + /// Example: + /// `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;` + /// Identity args: `['a, 'b, 'c]` + /// Canonical args: `['static, 'b, 'b]` + canonical_args: std::cell::OnceCell>, +} + +impl<'tcx> LazyOpaqueTyEnv<'tcx> { + fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() } + } + + fn param_equal_static(&self, param_index: usize) -> bool { + self.get_canonical_args()[param_index].expect_region().is_static() + } + + fn params_equal(&self, param1: usize, param2: usize) -> bool { + let canonical_args = self.get_canonical_args(); + canonical_args[param1] == canonical_args[param2] + } + + fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> { + self.get_canonical_args()[param_index].error_reported() + } + + fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> { + if let Some(&canonical_args) = self.canonical_args.get() { + return canonical_args; + } + + let &Self { tcx, def_id, .. } = self; + let origin = tcx.local_opaque_ty_origin(def_id); + let parent = match origin { + OpaqueTyOrigin::FnReturn { parent, .. } + | OpaqueTyOrigin::AsyncFn { parent, .. } + | OpaqueTyOrigin::TyAlias { parent, .. } => parent, + }; + let param_env = tcx.param_env(parent); + let args = GenericArgs::identity_for_item(tcx, parent).extend_to( + tcx, + def_id.to_def_id(), + |param, _| { + tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into() + }, + ); + + // FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're + // in a body here. + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let ocx = ObligationCtxt::new(&infcx); + + let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| { + tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds"); + Default::default() + }); + let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys); + + let mut seen = vec![tcx.lifetimes.re_static]; + let canonical_args = fold_regions(tcx, args, |r1, _| { + if r1.is_error() { + r1 + } else if let Some(&r2) = seen.iter().find(|&&r2| { + let free_regions = outlives_env.free_region_map(); + free_regions.sub_free_regions(tcx, r1, r2) + && free_regions.sub_free_regions(tcx, r2, r1) + }) { + r2 + } else { + seen.push(r1); + r1 + } + }); + self.canonical_args.set(canonical_args).unwrap(); + canonical_args + } +} From 509a144eed84e6ccd1227cd0d90f877a774aae70 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 1 Apr 2025 23:48:41 +0200 Subject: [PATCH 104/176] add `TypingMode::Borrowck` --- compiler/rustc_borrowck/src/lib.rs | 38 +-- .../src/region_infer/opaque_types.rs | 18 +- compiler/rustc_hir_analysis/src/collect.rs | 1 + .../rustc_hir_analysis/src/collect/type_of.rs | 59 +++- .../src/collect/type_of/opaque.rs | 265 +++++++----------- compiler/rustc_hir_typeck/src/writeback.rs | 51 +++- compiler/rustc_infer/src/infer/mod.rs | 6 +- .../rustc_infer/src/infer/opaque_types/mod.rs | 35 ++- compiler/rustc_middle/src/query/mod.rs | 8 + compiler/rustc_middle/src/ty/context.rs | 8 + compiler/rustc_middle/src/ty/mod.rs | 37 ++- compiler/rustc_middle/src/ty/opaque_types.rs | 36 +-- .../rustc_middle/src/ty/typeck_results.rs | 2 +- .../rustc_next_trait_solver/src/solve/mod.rs | 1 + .../src/solve/normalizes_to/opaque_types.rs | 36 +++ .../src/solve/search_graph.rs | 1 + .../src/solve/trait_goals.rs | 1 + compiler/rustc_pattern_analysis/src/rustc.rs | 5 +- compiler/rustc_session/src/options.rs | 3 + .../rustc_trait_selection/src/opaque_types.rs | 27 +- .../src/solve/delegate.rs | 1 + .../src/traits/normalize.rs | 2 + .../src/traits/project.rs | 1 + .../src/traits/query/normalize.rs | 1 + .../src/traits/select/mod.rs | 4 +- compiler/rustc_ty_utils/src/instance.rs | 1 + compiler/rustc_type_ir/src/infer_ctxt.rs | 12 + compiler/rustc_type_ir/src/interner.rs | 2 + compiler/rustc_type_ir/src/relate/combine.rs | 1 + tests/crashes/112201.rs | 19 -- tests/crashes/137751.rs | 6 - tests/ui/coroutine/clone-rpit.next.stderr | 6 +- .../generic-associated-types/issue-87258_a.rs | 2 +- .../issue-87258_a.stderr | 11 +- .../generic-associated-types/issue-87258_b.rs | 2 +- .../issue-87258_b.stderr | 11 +- ...e-method-resolution-opaque-type.old.stderr | 17 +- ...rm-before-method-resolution-opaque-type.rs | 1 - tests/ui/impl-trait/issue-55872-1.rs | 1 + tests/ui/impl-trait/issue-55872-1.stderr | 8 +- tests/ui/impl-trait/issue-55872-2.rs | 2 +- tests/ui/impl-trait/issue-55872-2.stderr | 12 +- tests/ui/impl-trait/issue-55872-3.rs | 1 + tests/ui/impl-trait/issue-55872-3.stderr | 16 +- tests/ui/impl-trait/issue-55872.rs | 2 +- tests/ui/impl-trait/issue-55872.stderr | 6 +- tests/ui/impl-trait/issue-99073-2.rs | 3 +- tests/ui/impl-trait/issue-99073-2.stderr | 14 +- tests/ui/impl-trait/issue-99073.rs | 3 +- tests/ui/impl-trait/issue-99073.stderr | 18 +- .../issues/fuzzer-ice-issue-112201.rs | 17 ++ .../issues/fuzzer-ice-issue-112201.stderr | 18 ++ tests/ui/impl-trait/issues/issue-86800.rs | 2 - tests/ui/impl-trait/issues/issue-86800.stderr | 29 +- .../as-projection-term.next.stderr | 12 + .../non-defining-uses/as-projection-term.rs | 17 ++ .../ui/impl-trait/recursive-ice-101862.stderr | 18 +- tests/ui/impl-trait/rpit/early_bound.rs | 3 +- tests/ui/impl-trait/rpit/early_bound.stderr | 26 +- tests/ui/impl-trait/rpit/non-defining-use.rs | 3 +- .../impl-trait/rpit/non-defining-use.stderr | 22 +- .../transmute/in-defining-scope.stderr | 25 ++ ...o_tait_defining_each_other2.current.stderr | 17 +- .../two_tait_defining_each_other2.rs | 3 +- .../opaques/ambig-in-mir-typeck.rs} | 5 +- .../no-define-in-wf-check.current.stderr | 44 ++- .../opaques/no-define-in-wf-check.rs | 8 +- .../opaques/revealing-use-in-nested-body.rs | 11 + .../bad-tait-no-substs.rs | 1 - .../bad-tait-no-substs.stderr | 17 +- .../type-alias-impl-trait/bound_reduction2.rs | 2 +- .../bound_reduction2.stderr | 6 +- .../different_args_considered_equal.rs | 2 +- .../different_defining_uses.rs | 2 +- .../different_defining_uses.stderr | 12 +- .../different_defining_uses_never_type-2.rs | 1 - ...ifferent_defining_uses_never_type-2.stderr | 20 +- ...ifferent_defining_uses_never_type-3.stderr | 6 +- .../different_defining_uses_never_type.stderr | 8 +- ...different_defining_uses_never_type3.stderr | 4 +- .../failed-to-normalize-ice-99945.rs | 1 - .../failed-to-normalize-ice-99945.stderr | 16 +- .../generic_different_defining_uses.rs | 2 +- .../generic_different_defining_uses.stderr | 12 +- .../generic_duplicate_param_use.rs | 4 +- .../generic_duplicate_param_use.stderr | 12 +- .../generic_duplicate_param_use3.rs | 2 +- .../generic_duplicate_param_use3.stderr | 12 +- .../generic_duplicate_param_use5.rs | 2 +- .../generic_duplicate_param_use5.stderr | 12 +- .../generic_duplicate_param_use6.rs | 2 +- .../generic_duplicate_param_use6.stderr | 12 +- .../generic_duplicate_param_use8.rs | 2 +- .../generic_duplicate_param_use8.stderr | 12 +- .../generic_duplicate_param_use9.rs | 2 +- .../generic_duplicate_param_use9.stderr | 12 +- .../generic_nondefining_use.rs | 4 +- .../generic_nondefining_use.stderr | 12 +- .../type-alias-impl-trait/generic_not_used.rs | 2 +- .../generic_not_used.stderr | 6 +- .../type-alias-impl-trait/hkl_forbidden4.rs | 9 +- .../hkl_forbidden4.stderr | 39 +-- .../in-where-clause.stderr | 35 +++ .../ui/type-alias-impl-trait/issue-109054.rs | 2 +- .../type-alias-impl-trait/issue-109054.stderr | 12 +- .../issue-53092-2.stderr | 25 ++ tests/ui/type-alias-impl-trait/issue-53598.rs | 2 +- .../type-alias-impl-trait/issue-53598.stderr | 6 +- tests/ui/type-alias-impl-trait/issue-60564.rs | 2 +- .../type-alias-impl-trait/issue-60564.stderr | 6 +- .../issue-68368-non-defining-use-2.stderr | 4 +- .../issue-68368-non-defining-use.stderr | 4 +- tests/ui/type-alias-impl-trait/issue-77179.rs | 6 +- .../type-alias-impl-trait/issue-77179.stderr | 18 +- tests/ui/type-alias-impl-trait/multi-error.rs | 2 +- .../type-alias-impl-trait/multi-error.stderr | 8 +- .../multiple-def-uses-in-one-fn-infer.rs | 3 +- .../multiple-def-uses-in-one-fn-infer.stderr | 12 +- .../multiple-def-uses-in-one-fn2.rs | 2 +- .../multiple-def-uses-in-one-fn2.stderr | 12 +- .../nested_type_alias_impl_trait.rs | 2 +- .../non-defining-method.stderr | 4 +- .../normalize-hidden-types.current.stderr | 34 +-- .../not_a_defining_use.rs | 2 +- .../not_a_defining_use.stderr | 12 +- .../recursive-fn-tait.rs | 3 +- .../recursive-fn-tait.stderr | 12 +- .../recursive-tait-conflicting-defn-2.rs | 2 +- .../recursive-tait-conflicting-defn-2.stderr | 12 +- .../recursive-tait-conflicting-defn.rs | 5 +- .../recursive-tait-conflicting-defn.stderr | 12 +- 131 files changed, 888 insertions(+), 747 deletions(-) delete mode 100644 tests/crashes/112201.rs delete mode 100644 tests/crashes/137751.rs create mode 100644 tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.rs create mode 100644 tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.stderr create mode 100644 tests/ui/impl-trait/non-defining-uses/as-projection-term.next.stderr create mode 100644 tests/ui/impl-trait/non-defining-uses/as-projection-term.rs rename tests/{crashes/132335.rs => ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs} (74%) create mode 100644 tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 7f0ee28531cf..240bd20053b1 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -35,7 +35,7 @@ use rustc_infer::infer::{ }; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode, fold_regions}; +use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, @@ -171,12 +171,6 @@ fn do_mir_borrowck<'tcx>( let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted); let body = &body_owned; // no further changes - // FIXME(-Znext-solver): A bit dubious that we're only registering - // predefined opaques in the typeck root. - if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) { - infcx.register_predefined_opaques_for_next_solver(def); - } - let location_table = PoloniusLocationTable::new(body); let move_data = MoveData::gather_moves(body, tcx, |_| true); @@ -431,7 +425,12 @@ pub(crate) struct BorrowckInferCtxt<'tcx> { impl<'tcx> BorrowckInferCtxt<'tcx> { pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { - let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id)); + let typing_mode = if tcx.use_typing_mode_borrowck() { + TypingMode::borrowck(tcx, def_id) + } else { + TypingMode::analysis_in_body(tcx, def_id) + }; + let infcx = tcx.infer_ctxt().build(typing_mode); let param_env = tcx.param_env(def_id); BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env } } @@ -478,29 +477,6 @@ impl<'tcx> BorrowckInferCtxt<'tcx> { next_region } - - /// With the new solver we prepopulate the opaque type storage during - /// MIR borrowck with the hidden types from HIR typeck. This is necessary - /// to avoid ambiguities as earlier goals can rely on the hidden type - /// of an opaque which is only constrained by a later goal. - fn register_predefined_opaques_for_next_solver(&self, def_id: LocalDefId) { - let tcx = self.tcx; - // OK to use the identity arguments for each opaque type key, since - // we remap opaques from HIR typeck back to their definition params. - for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) { - // HIR typeck did not infer the regions of the opaque, so we instantiate - // them with fresh inference variables. - let (key, hidden_ty) = fold_regions(tcx, data, |_, _| { - self.next_nll_region_var_in_universe( - NllRegionVariableOrigin::Existential { from_forall: false }, - ty::UniverseIndex::ROOT, - ) - }); - - let prev = self.register_hidden_type_in_storage(key, hidden_ty); - assert_eq!(prev, None); - } - } } impl<'tcx> Deref for BorrowckInferCtxt<'tcx> { diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 2f15c2bc4644..a098450352ff 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -2,7 +2,8 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_macros::extension; use rustc_middle::ty::{ - self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, + self, DefiningScopeKind, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, + TypeVisitableExt, fold_regions, }; use rustc_span::Span; use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid; @@ -266,14 +267,21 @@ impl<'tcx> InferCtxt<'tcx> { return Ty::new_error(self.tcx, e); } - if let Err(guar) = - check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span) - { + if let Err(guar) = check_opaque_type_parameter_valid( + self, + opaque_type_key, + instantiated_ty.span, + DefiningScopeKind::MirBorrowck, + ) { return Ty::new_error(self.tcx, guar); } let definition_ty = instantiated_ty - .remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false) + .remap_generic_params_to_declaration_params( + opaque_type_key, + self.tcx, + DefiningScopeKind::MirBorrowck, + ) .ty; if let Err(e) = definition_ty.error_reported() { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 075abc325944..625f51dd29ea 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -61,6 +61,7 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { type_of: type_of::type_of, type_of_opaque: type_of::type_of_opaque, + type_of_opaque_hir_typeck: type_of::type_of_opaque_hir_typeck, type_alias_is_lazy: type_of::type_alias_is_lazy, item_bounds: item_bounds::item_bounds, explicit_item_bounds: item_bounds::explicit_item_bounds, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index afda2c142e22..694c12288596 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -7,7 +7,9 @@ use rustc_hir::{self as hir, AmbigArg, HirId}; use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, fold_regions}; +use rustc_middle::ty::{ + self, DefiningScopeKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, fold_regions, +}; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span}; @@ -324,10 +326,18 @@ pub(super) fn type_of_opaque( if let Some(def_id) = def_id.as_local() { Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin { hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => { - opaque::find_opaque_ty_constraints_for_tait(tcx, def_id) + opaque::find_opaque_ty_constraints_for_tait( + tcx, + def_id, + DefiningScopeKind::MirBorrowck, + ) } hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. } => { - opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id) + opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type( + tcx, + def_id, + DefiningScopeKind::MirBorrowck, + ) } // Opaque types desugared from `impl Trait`. hir::OpaqueTyOrigin::FnReturn { parent: owner, in_trait_or_impl } @@ -340,7 +350,12 @@ pub(super) fn type_of_opaque( "tried to get type of this RPITIT with no definition" ); } - opaque::find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) + opaque::find_opaque_ty_constraints_for_rpit( + tcx, + def_id, + owner, + DefiningScopeKind::MirBorrowck, + ) } })) } else { @@ -350,6 +365,42 @@ pub(super) fn type_of_opaque( } } +pub(super) fn type_of_opaque_hir_typeck( + tcx: TyCtxt<'_>, + def_id: LocalDefId, +) -> ty::EarlyBinder<'_, Ty<'_>> { + ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin { + hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => { + opaque::find_opaque_ty_constraints_for_tait(tcx, def_id, DefiningScopeKind::HirTypeck) + } + hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. } => { + opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type( + tcx, + def_id, + DefiningScopeKind::HirTypeck, + ) + } + // Opaque types desugared from `impl Trait`. + hir::OpaqueTyOrigin::FnReturn { parent: owner, in_trait_or_impl } + | hir::OpaqueTyOrigin::AsyncFn { parent: owner, in_trait_or_impl } => { + if in_trait_or_impl == Some(hir::RpitContext::Trait) + && !tcx.defaultness(owner).has_value() + { + span_bug!( + tcx.def_span(def_id), + "tried to get type of this RPITIT with no definition" + ); + } + opaque::find_opaque_ty_constraints_for_rpit( + tcx, + def_id, + owner, + DefiningScopeKind::HirTypeck, + ) + } + }) +} + fn infer_placeholder_type<'tcx>( cx: &dyn HirTyLowerer<'tcx>, def_id: LocalDefId, 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 8a3a6a8be110..3fe3d71b32da 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -3,8 +3,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def, intravisit}; use rustc_middle::bug; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::DUMMY_SP; +use rustc_middle::ty::{self, DefiningScopeKind, Ty, TyCtxt, TypeVisitableExt}; use tracing::{debug, instrument, trace}; use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType}; @@ -15,6 +14,7 @@ use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType}; pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( tcx: TyCtxt<'_>, def_id: LocalDefId, + opaque_types_from: DefiningScopeKind, ) -> Ty<'_> { let mut parent_def_id = def_id; while tcx.def_kind(parent_def_id) == def::DefKind::OpaqueTy { @@ -27,7 +27,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( other => bug!("invalid impl trait in assoc type parent: {other:?}"), } - let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] }; + let mut locator = TaitConstraintLocator { def_id, tcx, found: None, opaque_types_from }; for &assoc_id in tcx.associated_item_def_ids(impl_def_id) { let assoc = tcx.associated_item(assoc_id); @@ -39,25 +39,14 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( } if let Some(hidden) = locator.found { - // Only check against typeck if we didn't already error - if !hidden.ty.references_error() { - for concrete_type in locator.typeck_types { - if concrete_type.ty != tcx.erase_regions(hidden.ty) { - if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) { - d.emit(); - } - } - } - } - hidden.ty } else { - let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType { + let guar = tcx.dcx().emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), name: tcx.item_ident(parent_def_id.to_def_id()), what: "impl", }); - Ty::new_error(tcx, reported) + Ty::new_error(tcx, guar) } } @@ -80,23 +69,16 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( /// fn b() -> Foo { .. } /// ``` #[instrument(skip(tcx), level = "debug")] -pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { - let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] }; +pub(super) fn find_opaque_ty_constraints_for_tait( + tcx: TyCtxt<'_>, + def_id: LocalDefId, + opaque_types_from: DefiningScopeKind, +) -> Ty<'_> { + let mut locator = TaitConstraintLocator { def_id, tcx, found: None, opaque_types_from }; tcx.hir_walk_toplevel_module(&mut locator); if let Some(hidden) = locator.found { - // Only check against typeck if we didn't already error - if !hidden.ty.references_error() { - for concrete_type in locator.typeck_types { - if concrete_type.ty != tcx.erase_regions(hidden.ty) { - if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) { - d.emit(); - } - } - } - } - hidden.ty } else { let mut parent_def_id = def_id; @@ -104,12 +86,12 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local // Account for `type Alias = impl Trait;` (#116031) parent_def_id = tcx.local_parent(parent_def_id); } - let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType { + let guar = tcx.dcx().emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), name: tcx.item_ident(parent_def_id.to_def_id()), what: "crate", }); - Ty::new_error(tcx, reported) + Ty::new_error(tcx, guar) } } @@ -126,22 +108,44 @@ struct TaitConstraintLocator<'tcx> { /// type). found: Option>, - /// In the presence of dead code, typeck may figure out a hidden type - /// while borrowck will not. We collect these cases here and check at - /// the end that we actually found a type that matches (modulo regions). - typeck_types: Vec>, + opaque_types_from: DefiningScopeKind, } -impl TaitConstraintLocator<'_> { +impl<'tcx> TaitConstraintLocator<'tcx> { + fn insert_found(&mut self, hidden_ty: ty::OpaqueHiddenType<'tcx>) { + if let Some(prev) = &mut self.found { + if hidden_ty.ty != prev.ty { + let (Ok(guar) | Err(guar)) = + prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit()); + prev.ty = Ty::new_error(self.tcx, guar); + } + } else { + self.found = Some(hidden_ty); + } + } + + fn non_defining_use_in_defining_scope(&mut self, item_def_id: LocalDefId) { + let guar = self.tcx.dcx().emit_err(TaitForwardCompat2 { + span: self + .tcx + .def_ident_span(item_def_id) + .unwrap_or_else(|| self.tcx.def_span(item_def_id)), + opaque_type_span: self.tcx.def_span(self.def_id), + opaque_type: self.tcx.def_path_str(self.def_id), + }); + self.insert_found(ty::OpaqueHiddenType::new_error(self.tcx, guar)); + } + #[instrument(skip(self), level = "debug")] fn check(&mut self, item_def_id: LocalDefId) { // Don't try to check items that cannot possibly constrain the type. - if !self.tcx.has_typeck_results(item_def_id) { + let tcx = self.tcx; + if !tcx.has_typeck_results(item_def_id) { debug!("no constraint: no typeck results"); return; } - let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id); + let opaque_types_defined_by = tcx.opaque_types_defined_by(item_def_id); // Don't try to check items that cannot possibly constrain the type. if !opaque_types_defined_by.contains(&self.def_id) { debug!("no constraint: no opaque types defined"); @@ -152,7 +156,7 @@ impl TaitConstraintLocator<'_> { // "non-defining use" errors for them. // Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former // excludes closures, which are allowed to have `_` in their return type. - let hir_node = self.tcx.hir_node_by_def_id(item_def_id); + let hir_node = tcx.hir_node_by_def_id(item_def_id); debug_assert!( !matches!(hir_node, Node::ForeignItem(..)), "foreign items cannot constrain opaque types", @@ -164,88 +168,39 @@ impl TaitConstraintLocator<'_> { hir_sig.decl.output.span(), "inferring return types and opaque types do not mix well", ); - self.found = - Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) }); + self.found = Some(ty::OpaqueHiddenType::new_error(tcx, guar)); return; } - // Calling `mir_borrowck` can lead to cycle errors through - // const-checking, avoid calling it if we don't have to. - // ```rust - // type Foo = impl Fn() -> usize; // when computing type for this - // const fn bar() -> Foo { - // || 0usize - // } - // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles - // // because we again need to reveal `Foo` so we can check whether the - // // constant does not contain interior mutability. - // ``` - let tables = self.tcx.typeck(item_def_id); - if let Some(guar) = tables.tainted_by_errors { - self.found = - Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) }); - return; - } - - let mut constrained = false; - for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types { - if opaque_type_key.def_id != self.def_id { - continue; - } - constrained = true; - - let concrete_type = - self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params( - opaque_type_key, - self.tcx, - true, - )); - if self.typeck_types.iter().all(|prev| prev.ty != concrete_type.ty) { - self.typeck_types.push(concrete_type); - } - } - - if !constrained { - debug!("no constraints in typeck results"); - if opaque_types_defined_by.contains(&self.def_id) { - let guar = self.tcx.dcx().emit_err(TaitForwardCompat2 { - span: self - .tcx - .def_ident_span(item_def_id) - .unwrap_or_else(|| self.tcx.def_span(item_def_id)), - opaque_type_span: self.tcx.def_span(self.def_id), - opaque_type: self.tcx.def_path_str(self.def_id), - }); - // Avoid "opaque type not constrained" errors on the opaque itself. - self.found = Some(ty::OpaqueHiddenType { - span: DUMMY_SP, - ty: Ty::new_error(self.tcx, guar), - }); - } - return; - }; - - // Use borrowck to get the type with unerased regions. - let borrowck_results = &self.tcx.mir_borrowck(item_def_id); - - // If the body was tainted, then assume the opaque may have been constrained and just set it to error. - if let Some(guar) = borrowck_results.tainted_by_errors { - self.found = - Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) }); - return; - } - - debug!(?borrowck_results.concrete_opaque_types); - if let Some(&concrete_type) = borrowck_results.concrete_opaque_types.get(&self.def_id) { - debug!(?concrete_type, "found constraint"); - if let Some(prev) = &mut self.found { - if concrete_type.ty != prev.ty { - let (Ok(guar) | Err(guar)) = - prev.build_mismatch_error(&concrete_type, self.tcx).map(|d| d.emit()); - prev.ty = Ty::new_error(self.tcx, guar); + match self.opaque_types_from { + DefiningScopeKind::HirTypeck => { + let tables = tcx.typeck(item_def_id); + if let Some(guar) = tables.tainted_by_errors { + self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)); + } else if let Some(&hidden_type) = tables.concrete_opaque_types.get(&self.def_id) { + self.insert_found(hidden_type); + } else { + self.non_defining_use_in_defining_scope(item_def_id); + } + } + DefiningScopeKind::MirBorrowck => { + let borrowck_result = tcx.mir_borrowck(item_def_id); + if let Some(guar) = borrowck_result.tainted_by_errors { + self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)); + } else if let Some(&hidden_type) = + borrowck_result.concrete_opaque_types.get(&self.def_id) + { + debug!(?hidden_type, "found constraint"); + self.insert_found(hidden_type); + } else if let Err(guar) = tcx + .type_of_opaque_hir_typeck(self.def_id) + .instantiate_identity() + .error_reported() + { + self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)); + } else { + self.non_defining_use_in_defining_scope(item_def_id); } - } else { - self.found = Some(concrete_type); } } } @@ -287,54 +242,42 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, owner_def_id: LocalDefId, + opaque_types_from: DefiningScopeKind, ) -> Ty<'tcx> { - let tables = tcx.typeck(owner_def_id); - - // Check that all of the opaques we inferred during HIR are compatible. - // FIXME: We explicitly don't check that the types inferred during HIR - // typeck are compatible with the one that we infer during borrowck, - // because that one actually sometimes has consts evaluated eagerly so - // using strict type equality will fail. - let mut hir_opaque_ty: Option> = None; - if tables.tainted_by_errors.is_none() { - for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types { - if opaque_type_key.def_id != def_id { - continue; - } - let concrete_type = tcx.erase_regions( - hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true), - ); - if let Some(prev) = &mut hir_opaque_ty { - if concrete_type.ty != prev.ty { - if let Ok(d) = prev.build_mismatch_error(&concrete_type, tcx) { - d.emit(); - } - } + match opaque_types_from { + DefiningScopeKind::HirTypeck => { + let tables = tcx.typeck(owner_def_id); + if let Some(guar) = tables.tainted_by_errors { + Ty::new_error(tcx, guar) + } else if let Some(hidden_ty) = tables.concrete_opaque_types.get(&def_id) { + hidden_ty.ty } else { - hir_opaque_ty = Some(concrete_type); + // FIXME(-Znext-solver): This should not be necessary and we should + // instead rely on inference variable fallback inside of typeck itself. + + // We failed to resolve the opaque type or it + // resolves to itself. We interpret this as the + // no values of the hidden type ever being constructed, + // so we can just make the hidden type be `!`. + // For backwards compatibility reasons, we fall back to + // `()` until we the diverging default is changed. + Ty::new_diverging_default(tcx) } } - } - - let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied(); - if let Some(mir_opaque_ty) = mir_opaque_ty { - mir_opaque_ty.ty - } else if let Some(guar) = tables.tainted_by_errors { - // Some error in the owner fn prevented us from populating - // the `concrete_opaque_types` table. - Ty::new_error(tcx, guar) - } else { - // Fall back to the RPIT we inferred during HIR typeck - if let Some(hir_opaque_ty) = hir_opaque_ty { - hir_opaque_ty.ty - } else { - // We failed to resolve the opaque type or it - // resolves to itself. We interpret this as the - // no values of the hidden type ever being constructed, - // so we can just make the hidden type be `!`. - // For backwards compatibility reasons, we fall back to - // `()` until we the diverging default is changed. - Ty::new_diverging_default(tcx) + DefiningScopeKind::MirBorrowck => { + let borrowck_result = tcx.mir_borrowck(owner_def_id); + if let Some(guar) = borrowck_result.tainted_by_errors { + Ty::new_error(tcx, guar) + } else if let Some(hidden_ty) = borrowck_result.concrete_opaque_types.get(&def_id) { + hidden_ty.ty + } else { + let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity(); + if let Err(guar) = hir_ty.error_reported() { + Ty::new_error(tcx, guar) + } else { + hir_ty + } + } } } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 588383534f6b..4d7e2c7629f0 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -12,10 +12,12 @@ use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, fold_regions, + self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, fold_regions, }; use rustc_span::{Span, sym}; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; +use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid; use rustc_trait_selection::solve; use tracing::{debug, instrument}; @@ -553,6 +555,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { #[instrument(skip(self), level = "debug")] fn visit_opaque_types(&mut self) { + let tcx = self.tcx(); // We clone the opaques instead of stealing them here as they are still used for // normalization in the next generation trait solver. // @@ -575,16 +578,46 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - // Here we only detect impl trait definition conflicts when they - // are equal modulo regions. - if let Some(last_opaque_ty) = - self.typeck_results.concrete_opaque_types.insert(opaque_type_key, hidden_type) - && last_opaque_ty.ty != hidden_type.ty + if let Err(guar) = check_opaque_type_parameter_valid( + &self.fcx, + opaque_type_key, + hidden_type.span, + DefiningScopeKind::HirTypeck, + ) { + self.typeck_results + .concrete_opaque_types + .insert(opaque_type_key.def_id, ty::OpaqueHiddenType::new_error(tcx, guar)); + } + + let hidden_type = hidden_type.remap_generic_params_to_declaration_params( + opaque_type_key, + tcx, + DefiningScopeKind::HirTypeck, + ); + + if let Some(prev) = self + .typeck_results + .concrete_opaque_types + .insert(opaque_type_key.def_id, hidden_type) { - assert!(!self.fcx.next_trait_solver()); - if let Ok(d) = hidden_type.build_mismatch_error(&last_opaque_ty, self.tcx()) { - d.emit(); + let entry = &mut self + .typeck_results + .concrete_opaque_types + .get_mut(&opaque_type_key.def_id) + .unwrap(); + if prev.ty != hidden_type.ty { + if let Some(guar) = self.typeck_results.tainted_by_errors { + entry.ty = Ty::new_error(tcx, guar); + } else { + let (Ok(guar) | Err(guar)) = + prev.build_mismatch_error(&hidden_type, tcx).map(|d| d.emit()); + entry.ty = Ty::new_error(tcx, guar); + } } + + // Pick a better span if there is one. + // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. + entry.span = prev.span.substitute_dummy(hidden_type.span); } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fa8dea064daa..20aa8e44f439 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -966,7 +966,8 @@ impl<'tcx> InferCtxt<'tcx> { pub fn can_define_opaque_ty(&self, id: impl Into) -> bool { debug_assert!(!self.next_trait_solver()); match self.typing_mode() { - TypingMode::Analysis { defining_opaque_types } => { + TypingMode::Analysis { defining_opaque_types } + | TypingMode::Borrowck { defining_opaque_types } => { id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id)) } // FIXME(#132279): This function is quite weird in post-analysis @@ -1260,7 +1261,8 @@ impl<'tcx> InferCtxt<'tcx> { // to handle them without proper canonicalization. This means we may cause cycle // errors and fail to reveal opaques while inside of bodies. We should rename this // function and require explicit comments on all use-sites in the future. - ty::TypingMode::Analysis { defining_opaque_types: _ } => { + ty::TypingMode::Analysis { defining_opaque_types: _ } + | ty::TypingMode::Borrowck { defining_opaque_types: _ } => { TypingMode::non_body_analysis() } mode @ (ty::TypingMode::Coherence diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index d9297fb41944..ce5d2e6e17a9 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{ use rustc_span::Span; use tracing::{debug, instrument}; -use super::DefineOpaqueTypes; +use super::{DefineOpaqueTypes, RegionVariableOrigin}; use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{InferCtxt, InferOk}; use crate::traits::{self, Obligation, PredicateObligations}; @@ -221,6 +221,7 @@ impl<'tcx> InferCtxt<'tcx> { hidden_ty: Ty<'tcx>, goals: &mut Vec>>, ) -> Result<(), TypeError<'tcx>> { + let tcx = self.tcx; // Ideally, we'd get the span where *this specific `ty` came // from*, but right now we just use the span from the overall // value being folded. In simple cases like `-> impl Foo`, @@ -231,7 +232,7 @@ impl<'tcx> InferCtxt<'tcx> { // During intercrate we do not define opaque types but instead always // force ambiguity unless the hidden type is known to not implement // our trait. - goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous)); + goals.push(Goal::new(tcx, param_env, ty::PredicateKind::Ambiguous)); } ty::TypingMode::Analysis { .. } => { let prev = self @@ -249,6 +250,36 @@ impl<'tcx> InferCtxt<'tcx> { ); } } + ty::TypingMode::Borrowck { .. } => { + let prev = self + .inner + .borrow_mut() + .opaque_types() + .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span }); + + // We either equate the new hidden type with the previous entry or with the type + // inferred by HIR typeck. + let actual = prev.unwrap_or_else(|| { + let actual = tcx + .type_of_opaque_hir_typeck(opaque_type_key.def_id) + .instantiate(self.tcx, opaque_type_key.args); + let actual = ty::fold_regions(tcx, actual, |re, _dbi| match re.kind() { + ty::ReErased => { + self.next_region_var(RegionVariableOrigin::MiscVariable(span)) + } + _ => re, + }); + actual + }); + + goals.extend( + self.at(&ObligationCause::dummy_with_span(span), param_env) + .eq(DefineOpaqueTypes::Yes, hidden_ty, actual)? + .obligations + .into_iter() + .map(|obligation| obligation.as_goal()), + ); + } mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => { bug!("insert hidden type in {mode:?}") } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 698859c663b1..0d5fba3cc69b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -267,6 +267,8 @@ rustc_queries! { /// /// This is a specialized instance of [`Self::type_of`] that detects query cycles. /// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead. + /// This is used to improve the error message in cases where revealing the hidden type + /// for auto-trait leakage cycles. /// /// # Panics /// @@ -278,6 +280,12 @@ rustc_queries! { } cycle_stash } + query type_of_opaque_hir_typeck(key: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + desc { |tcx| + "computing type of opaque `{path}` via HIR typeck", + path = tcx.def_path_str(key), + } + } /// Returns whether the type alias given by `DefId` is lazy. /// diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 618a65a01864..b1ace6744046 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -206,6 +206,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { self.type_of(def_id) } + fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + self.type_of_opaque_hir_typeck(def_id) + } type AdtDef = ty::AdtDef<'tcx>; fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { @@ -3248,6 +3251,11 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.opts.unstable_opts.next_solver.coherence } + #[allow(rustc::bad_opt_access)] + pub fn use_typing_mode_borrowck(self) -> bool { + self.next_trait_solver_globally() || self.sess.opts.unstable_opts.typing_mode_borrowck + } + pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { self.opt_rpitit_info(def_id).is_some() } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 255d464d2654..8db0c7c9b3aa 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -48,7 +48,7 @@ use rustc_serialize::{Decodable, Encodable}; use rustc_session::lint::LintBuffer; pub use rustc_session::lint::RegisteredTools; use rustc_span::hygiene::MacroKind; -use rustc_span::{ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym}; +use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym}; pub use rustc_type_ir::relate::VarianceDiagInfo; pub use rustc_type_ir::*; use tracing::{debug, instrument}; @@ -782,7 +782,22 @@ pub struct OpaqueHiddenType<'tcx> { pub ty: Ty<'tcx>, } +/// Whether we're currently in HIR typeck or MIR borrowck. +#[derive(Debug, Clone, Copy)] +pub enum DefiningScopeKind { + /// During writeback in typeck, we don't care about regions and simply + /// erase them. This means we also don't check whether regions are + /// universal in the opaque type key. This will only be checked in + /// MIR borrowck. + HirTypeck, + MirBorrowck, +} + impl<'tcx> OpaqueHiddenType<'tcx> { + pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> OpaqueHiddenType<'tcx> { + OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(tcx, guar) } + } + pub fn build_mismatch_error( &self, other: &Self, @@ -808,8 +823,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> { self, opaque_type_key: OpaqueTypeKey<'tcx>, tcx: TyCtxt<'tcx>, - // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck. - ignore_errors: bool, + defining_scope_kind: DefiningScopeKind, ) -> Self { let OpaqueTypeKey { def_id, args } = opaque_type_key; @@ -828,10 +842,19 @@ impl<'tcx> OpaqueHiddenType<'tcx> { let map = args.iter().zip(id_args).collect(); debug!("map = {:#?}", map); - // Convert the type from the function into a type valid outside - // the function, by replacing invalid regions with 'static, - // after producing an error for each of them. - self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors)) + // Convert the type from the function into a type valid outside by mapping generic + // parameters to into the context of the opaque. + // + // We erase regions when doing this during HIR typeck. + let this = match defining_scope_kind { + DefiningScopeKind::HirTypeck => tcx.erase_regions(self), + DefiningScopeKind::MirBorrowck => self, + }; + let result = this.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span)); + if cfg!(debug_assertions) && matches!(defining_scope_kind, DefiningScopeKind::HirTypeck) { + assert_eq!(result.ty, tcx.erase_regions(result.ty)); + } + result } } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 56c44c8a84c0..c72efde09949 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -20,12 +20,6 @@ pub(super) struct ReverseMapper<'tcx> { /// for an explanation of this field. do_not_error: bool, - /// We do not want to emit any errors in typeck because - /// the spans in typeck are subpar at the moment. - /// Borrowck will do the same work again (this time with - /// lifetime information) and thus report better errors. - ignore_errors: bool, - /// Span of function being checked. span: Span, } @@ -35,9 +29,8 @@ impl<'tcx> ReverseMapper<'tcx> { tcx: TyCtxt<'tcx>, map: FxHashMap, GenericArg<'tcx>>, span: Span, - ignore_errors: bool, ) -> Self { - Self { tcx, map, do_not_error: false, ignore_errors, span } + Self { tcx, map, do_not_error: false, span } } fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> { @@ -176,20 +169,18 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { Some(u) => panic!("type mapped to unexpected kind: {u:?}"), None => { debug!(?param, ?self.map); - if !self.ignore_errors { - self.tcx - .dcx() - .struct_span_err( - self.span, - format!( - "type parameter `{ty}` is part of concrete type but not \ + let guar = self + .tcx + .dcx() + .struct_span_err( + self.span, + format!( + "type parameter `{ty}` is part of concrete type but not \ used in parameter list for the `impl Trait` type alias" - ), - ) - .emit(); - } - - Ty::new_misc_error(self.tcx) + ), + ) + .emit(); + Ty::new_error(self.tcx, guar) } } } @@ -217,8 +208,7 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { ct: ct.to_string(), span: self.span, }) - .emit_unless(self.ignore_errors); - + .emit(); ty::Const::new_error(self.tcx, guar) } } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 3d3f4e2773a2..7c437abfe24c 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -158,7 +158,7 @@ pub struct TypeckResults<'tcx> { /// We also store the type here, so that the compiler can use it as a hint /// for figuring out hidden types, even if they are only set in dead code /// (which doesn't show up in MIR). - pub concrete_opaque_types: FxIndexMap, ty::OpaqueHiddenType<'tcx>>, + pub concrete_opaque_types: FxIndexMap>, /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 199f0c7512e1..7641e9a16ee6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -330,6 +330,7 @@ where // During analysis, opaques are rigid unless they may be defined by // the current body. TypingMode::Analysis { defining_opaque_types: non_rigid_opaques } + | TypingMode::Borrowck { defining_opaque_types: non_rigid_opaques } | TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => { !def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id)) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 82dae51b3d03..aa89e77bb6fb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -96,6 +96,42 @@ where ); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } + // Very similar to `TypingMode::Analysis` with some notably differences: + // - we accept opaque types even if they have non-universal arguments + // - we do a structural lookup instead of semantically unifying regions + // - the hidden type starts out as the type from HIR typeck with fresh region + // variables instead of a fully unconstrained inference variable + TypingMode::Borrowck { defining_opaque_types } => { + let Some(def_id) = opaque_ty + .def_id + .as_local() + .filter(|&def_id| defining_opaque_types.contains(&def_id)) + else { + self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + }; + + let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args }; + let actual = self + .register_hidden_type_in_storage(opaque_type_key, expected) + .unwrap_or_else(|| { + let actual = + cx.type_of_opaque_hir_typeck(def_id).instantiate(cx, opaque_ty.args); + let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() { + ty::ReErased => self.next_region_var(), + _ => re, + }); + actual + }); + self.eq(goal.param_env, expected, actual)?; + self.add_item_bounds_for_hidden_type( + def_id.into(), + opaque_ty.args, + goal.param_env, + expected, + ); + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } TypingMode::PostBorrowckAnalysis { defined_opaque_types } => { let Some(def_id) = opaque_ty .def_id diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index eba496fa2265..ecffbbff7a2d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -62,6 +62,7 @@ where response_no_constraints(cx, input, Certainty::overflow(false)) } TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => Err(NoSolution), }, diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index b72f776e5cb4..2a1196735cd3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -72,6 +72,7 @@ where (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() { TypingMode::Coherence => Certainty::AMBIGUOUS, TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution), }, diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index a25a80cd45f7..31c4ee0fa0bb 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -135,7 +135,10 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Returns the hidden type corresponding to this key if the body under analysis is allowed to /// know it. fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option> { - self.typeck_results.concrete_opaque_types.get(&key).map(|x| x.ty) + self.typeck_results + .concrete_opaque_types + .get(&key.def_id) + .map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args)) } // This can take a non-revealed `Ty` because it reveals opaques itself. pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index cd5e2c4173e7..36f7486f1d4c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2553,6 +2553,9 @@ written to standard error output)"), "in diagnostics, use heuristics to shorten paths referring to items"), tune_cpu: Option = (None, parse_opt_string, [TRACKED], "select processor to schedule for (`rustc --print target-cpus` for details)"), + #[rustc_lint_opt_deny_field_access("use `TyCtxt::use_typing_mode_borrowck` instead of this field")] + typing_mode_borrowck: bool = (false, parse_bool, [TRACKED], + "enable `TypingMode::Borrowck`, changing the way opaque types are handled during MIR borrowck"), #[rustc_lint_opt_deny_field_access("use `Session::ub_checks` instead of this field")] ub_checks: Option = (None, parse_opt_bool, [TRACKED], "emit runtime checks for Undefined Behavior (default: -Cdebug-assertions)"), diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 5af912fee549..c7b8f0631962 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -4,7 +4,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_middle::ty::{ - self, GenericArgKind, GenericArgs, OpaqueTypeKey, TyCtxt, TypeVisitableExt, + self, DefiningScopeKind, GenericArgKind, GenericArgs, OpaqueTypeKey, TyCtxt, TypeVisitableExt, TypingMode, fold_regions, }; use rustc_span::{ErrorGuaranteed, Span}; @@ -21,19 +21,36 @@ pub fn check_opaque_type_parameter_valid<'tcx>( infcx: &InferCtxt<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, span: Span, + defining_scope_kind: DefiningScopeKind, ) -> Result<(), ErrorGuaranteed> { let tcx = infcx.tcx; let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); + // Avoid duplicate errors in case the opaque has already been malformed in + // HIR typeck. + if let DefiningScopeKind::MirBorrowck = defining_scope_kind { + if let Err(guar) = infcx + .tcx + .type_of_opaque_hir_typeck(opaque_type_key.def_id) + .instantiate_identity() + .error_reported() + { + return Err(guar); + } + } + for (i, arg) in opaque_type_key.iter_captured_args(tcx) { let arg_is_param = match arg.unpack() { + GenericArgKind::Lifetime(lt) => match defining_scope_kind { + DefiningScopeKind::HirTypeck => continue, + DefiningScopeKind::MirBorrowck => { + matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_)) + || (lt.is_static() && opaque_env.param_equal_static(i)) + } + }, GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), - GenericArgKind::Lifetime(lt) => { - matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_)) - || (lt.is_static() && opaque_env.param_equal_static(i)) - } GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), }; diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index f2725411e13c..e0b425fa7391 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -195,6 +195,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< match self.typing_mode() { TypingMode::Coherence | TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } => false, TypingMode::PostAnalysis => { let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index ad62b456ad46..4ac45172a0e1 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -130,6 +130,7 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis TypingMode::Coherence | TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), TypingMode::PostAnalysis => {} } @@ -226,6 +227,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis TypingMode::Coherence | TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self), TypingMode::PostAnalysis => { let recursion_limit = self.cx().recursion_limit(); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6057b66c483f..349569d750e0 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -952,6 +952,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( match selcx.infcx.typing_mode() { TypingMode::Coherence | TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } => { debug!( assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id), diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 165c63f3745a..5dbb4382fd1b 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -216,6 +216,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { match self.infcx.typing_mode() { TypingMode::Coherence | TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?, TypingMode::PostAnalysis => { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0679dbf1296a..d78938225f1d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1446,6 +1446,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.infcx.typing_mode() { TypingMode::Coherence => {} TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => return Ok(()), } @@ -1491,7 +1492,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // However, if we disqualify *all* goals from being cached, perf suffers. // This is likely fixed by better caching in general in the new solver. // See: . - TypingMode::Analysis { defining_opaque_types } => { + TypingMode::Analysis { defining_opaque_types } + | TypingMode::Borrowck { defining_opaque_types } => { defining_opaque_types.is_empty() || !pred.has_opaque_types() } // The hidden types of `defined_opaque_types` is not local to the current diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 962e1353ebcd..66c18bed5e71 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -149,6 +149,7 @@ fn resolve_associated_item<'tcx>( match typing_env.typing_mode { ty::TypingMode::Coherence | ty::TypingMode::Analysis { .. } + | ty::TypingMode::Borrowck { .. } | ty::TypingMode::PostBorrowckAnalysis { .. } => false, ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(), } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index e512e8fc838f..fec6e24e2cb4 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -66,6 +66,14 @@ pub enum TypingMode { /// } /// ``` Analysis { defining_opaque_types: I::DefiningOpaqueTypes }, + /// The behavior during MIR borrowck is identical to `TypingMode::Analysis` + /// except that the initial value for opaque types is the type computed during + /// HIR typeck with unique unconstrained region inference variables. + /// + /// This is currently only used with by the new solver as it results in new + /// non-universal defining uses of opaque types, which is a breaking change. + /// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs. + Borrowck { defining_opaque_types: I::DefiningOpaqueTypes }, /// Any analysis after borrowck for a given body should be able to use all the /// hidden types defined by borrowck, without being able to define any new ones. /// @@ -95,6 +103,10 @@ impl TypingMode { TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) } } + pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode { + TypingMode::Borrowck { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) } + } + pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode { TypingMode::PostBorrowckAnalysis { defined_opaque_types: cx.opaque_types_defined_by(body_def_id), diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 8f86270d7dce..44b260ddd3a2 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -149,6 +149,8 @@ pub trait Interner: ) -> Option; fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder; + fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId) + -> ty::EarlyBinder; type AdtDef: AdtDef; fn adt_def(self, adt_def_id: Self::DefId) -> Self::AdtDef; diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index d49f8d3093db..8dd7c4df2442 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -137,6 +137,7 @@ where Ok(a) } TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b), } diff --git a/tests/crashes/112201.rs b/tests/crashes/112201.rs deleted file mode 100644 index 5d363403b8ac..000000000000 --- a/tests/crashes/112201.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ known-bug: #112201 - -pub fn compose( - f1: impl FnOnce(f64) -> f64 + Clone, - f2: impl FnOnce(f64) -> f64 + Clone, -) -> impl FnOnce(f64) -> f64 + Clone { - move |x| f1(f2(x)) -} - -fn repeat_helper( - f: impl FnOnce(f64) -> f64 + Clone, - res: impl FnOnce(f64) -> f64 + Clone, - times: usize, -) -> impl FnOnce(f64) -> f64 + Clone { - return res; - repeat_helper(f.clone(), compose(f, res), times - 1) -} - -fn main() {} diff --git a/tests/crashes/137751.rs b/tests/crashes/137751.rs deleted file mode 100644 index 85ae3acd53d3..000000000000 --- a/tests/crashes/137751.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #137751 -//@ compile-flags: --edition=2021 -Znext-solver=globally -async fn test() { - Box::pin(test()).await; -} -fn main() {} diff --git a/tests/ui/coroutine/clone-rpit.next.stderr b/tests/ui/coroutine/clone-rpit.next.stderr index c223f1f211ac..213e9e908f56 100644 --- a/tests/ui/coroutine/clone-rpit.next.stderr +++ b/tests/ui/coroutine/clone-rpit.next.stderr @@ -35,11 +35,11 @@ note: ...which requires type-checking `foo::{closure#0}`... LL | move |_: ()| { | ^^^^^^^^^^^^ = note: ...which again requires type-checking `foo`, completing the cycle -note: cycle used when computing type of opaque `foo::{opaque#0}` - --> $DIR/clone-rpit.rs:13:25 +note: cycle used when match-checking `foo` + --> $DIR/clone-rpit.rs:13:1 | LL | pub fn foo<'a, 'b>() -> impl Clone { - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-87258_a.rs b/tests/ui/generic-associated-types/issue-87258_a.rs index 6f737b21f53c..2ea77bbca768 100644 --- a/tests/ui/generic-associated-types/issue-87258_a.rs +++ b/tests/ui/generic-associated-types/issue-87258_a.rs @@ -15,8 +15,8 @@ pub trait Trait2 { impl<'c, S: Trait2> Trait2 for &'c mut S { type FooFuture<'a> = impl Trait1; - //~^ ERROR unconstrained opaque type fn foo<'a>() -> Self::FooFuture<'a> { + //~^ ERROR item does not constrain `<&'c mut S as Trait2>::FooFuture::{opaque#0}` Struct(unimplemented!()) } } diff --git a/tests/ui/generic-associated-types/issue-87258_a.stderr b/tests/ui/generic-associated-types/issue-87258_a.stderr index 01f2a92f94a6..f175c15bd02b 100644 --- a/tests/ui/generic-associated-types/issue-87258_a.stderr +++ b/tests/ui/generic-associated-types/issue-87258_a.stderr @@ -1,10 +1,15 @@ -error: unconstrained opaque type +error: item does not constrain `<&'c mut S as Trait2>::FooFuture::{opaque#0}` + --> $DIR/issue-87258_a.rs:18:8 + | +LL | fn foo<'a>() -> Self::FooFuture<'a> { + | ^^^ + | + = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` +note: this opaque type is supposed to be constrained --> $DIR/issue-87258_a.rs:17:26 | LL | type FooFuture<'a> = impl Trait1; | ^^^^^^^^^^^ - | - = note: `FooFuture` must be used in combination with a concrete type within the same impl error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-87258_b.rs b/tests/ui/generic-associated-types/issue-87258_b.rs index 84c7182cdcbc..8b820e75f604 100644 --- a/tests/ui/generic-associated-types/issue-87258_b.rs +++ b/tests/ui/generic-associated-types/issue-87258_b.rs @@ -14,12 +14,12 @@ pub trait Trait2 { } type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; -//~^ ERROR unconstrained opaque type impl<'c, S: Trait2> Trait2 for &'c mut S { type FooFuture<'a> = Helper<'c, 'a, S>; #[define_opaque(Helper)] fn foo<'a>() -> Self::FooFuture<'a> { + //~^ ERROR item does not constrain `Helper::{opaque#0}` Struct(unimplemented!()) } } diff --git a/tests/ui/generic-associated-types/issue-87258_b.stderr b/tests/ui/generic-associated-types/issue-87258_b.stderr index 906ce1f50da7..56abcef0d377 100644 --- a/tests/ui/generic-associated-types/issue-87258_b.stderr +++ b/tests/ui/generic-associated-types/issue-87258_b.stderr @@ -1,10 +1,15 @@ -error: unconstrained opaque type +error: item does not constrain `Helper::{opaque#0}` + --> $DIR/issue-87258_b.rs:21:8 + | +LL | fn foo<'a>() -> Self::FooFuture<'a> { + | ^^^ + | + = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` +note: this opaque type is supposed to be constrained --> $DIR/issue-87258_b.rs:16:49 | LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; | ^^^^^^^^^^^ - | - = note: `Helper` must be used in combination with a concrete type within the same crate error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr index 34617448a692..79ded34d9cd9 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr @@ -1,18 +1,5 @@ -error: item does not constrain `Foo::{opaque#0}` - --> $DIR/norm-before-method-resolution-opaque-type.rs:17:4 - | -LL | fn weird_bound(x: &>::Out) -> X - | ^^^^^^^^^^^ - | - = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` -note: this opaque type is supposed to be constrained - --> $DIR/norm-before-method-resolution-opaque-type.rs:14:12 - | -LL | type Foo = impl Sized; - | ^^^^^^^^^^ - error[E0507]: cannot move out of `*x` which is behind a shared reference - --> $DIR/norm-before-method-resolution-opaque-type.rs:23:13 + --> $DIR/norm-before-method-resolution-opaque-type.rs:22:13 | LL | let x = *x; | ^^ move occurs because `*x` has type `>::Out`, which does not implement the `Copy` trait @@ -23,6 +10,6 @@ LL - let x = *x; LL + let x = x; | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs index bb663c82abb0..f881fcb779fa 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs @@ -15,7 +15,6 @@ type Foo = impl Sized; #[define_opaque(Foo)] fn weird_bound(x: &>::Out) -> X -//[old]~^ ERROR: item does not constrain where for<'a> X: Trait<'a>, for<'a> >::Out<()>: Copy, diff --git a/tests/ui/impl-trait/issue-55872-1.rs b/tests/ui/impl-trait/issue-55872-1.rs index f36a310ddf31..663cdbc2f5cb 100644 --- a/tests/ui/impl-trait/issue-55872-1.rs +++ b/tests/ui/impl-trait/issue-55872-1.rs @@ -13,6 +13,7 @@ impl Bar for S { //~^ ERROR impl has stricter requirements than trait //~| ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277] //~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277] + //~| ERROR type parameter `T` is part of concrete type (S::default(), T::default()) } } diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr index 81759760bf13..e048bec1b6d2 100644 --- a/tests/ui/impl-trait/issue-55872-1.stderr +++ b/tests/ui/impl-trait/issue-55872-1.stderr @@ -37,7 +37,13 @@ help: consider further restricting type parameter `T` with trait `Copy` LL | fn foo() -> Self::E { | +++++++++++++++++++ -error: aborting due to 3 previous errors +error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/issue-55872-1.rs:12:29 + | +LL | fn foo() -> Self::E { + | ^^^^^^^ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0276, E0277. For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/impl-trait/issue-55872-2.rs b/tests/ui/impl-trait/issue-55872-2.rs index caca5c69a4ae..a3b2225126a2 100644 --- a/tests/ui/impl-trait/issue-55872-2.rs +++ b/tests/ui/impl-trait/issue-55872-2.rs @@ -11,9 +11,9 @@ pub trait Bar { impl Bar for S { type E = impl std::marker::Send; fn foo() -> Self::E { - async {} //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias //~| ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + async {} } } diff --git a/tests/ui/impl-trait/issue-55872-2.stderr b/tests/ui/impl-trait/issue-55872-2.stderr index b5b7f293a40b..51a7dd00ade6 100644 --- a/tests/ui/impl-trait/issue-55872-2.stderr +++ b/tests/ui/impl-trait/issue-55872-2.stderr @@ -1,14 +1,14 @@ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:14:9 + --> $DIR/issue-55872-2.rs:13:20 | -LL | async {} - | ^^^^^^^^ +LL | fn foo() -> Self::E { + | ^^^^^^^ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:14:9 + --> $DIR/issue-55872-2.rs:13:20 | -LL | async {} - | ^^^^^^^^ +LL | fn foo() -> Self::E { + | ^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/impl-trait/issue-55872-3.rs b/tests/ui/impl-trait/issue-55872-3.rs index 50b9eb3ce0ec..698e7f362341 100644 --- a/tests/ui/impl-trait/issue-55872-3.rs +++ b/tests/ui/impl-trait/issue-55872-3.rs @@ -13,6 +13,7 @@ impl Bar for S { type E = impl std::marker::Copy; fn foo() -> Self::E { //~^ ERROR : Copy` is not satisfied [E0277] + //~| ERROR type parameter `T` is part of concrete type async {} } } diff --git a/tests/ui/impl-trait/issue-55872-3.stderr b/tests/ui/impl-trait/issue-55872-3.stderr index 827155d48b82..3281dcc3501d 100644 --- a/tests/ui/impl-trait/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issue-55872-3.stderr @@ -1,12 +1,18 @@ -error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}: Copy` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}: Copy` is not satisfied --> $DIR/issue-55872-3.rs:14:20 | LL | fn foo() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}` -LL | + | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}` +... LL | async {} - | -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}` here + | -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}` here -error: aborting due to 1 previous error +error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/issue-55872-3.rs:14:20 + | +LL | fn foo() -> Self::E { + | ^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issue-55872.rs b/tests/ui/impl-trait/issue-55872.rs index 10850f0a9335..b76f8182b204 100644 --- a/tests/ui/impl-trait/issue-55872.rs +++ b/tests/ui/impl-trait/issue-55872.rs @@ -10,8 +10,8 @@ impl Bar for S { type E = impl Copy; fn foo() -> Self::E { - || () //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + || () } } diff --git a/tests/ui/impl-trait/issue-55872.stderr b/tests/ui/impl-trait/issue-55872.stderr index 4ff8527bbe9d..54e852f8edf8 100644 --- a/tests/ui/impl-trait/issue-55872.stderr +++ b/tests/ui/impl-trait/issue-55872.stderr @@ -1,8 +1,8 @@ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872.rs:13:9 + --> $DIR/issue-55872.rs:12:20 | -LL | || () - | ^^^^^ +LL | fn foo() -> Self::E { + | ^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issue-99073-2.rs b/tests/ui/impl-trait/issue-99073-2.rs index 37ea211bec36..bfb8850857de 100644 --- a/tests/ui/impl-trait/issue-99073-2.rs +++ b/tests/ui/impl-trait/issue-99073-2.rs @@ -7,8 +7,7 @@ fn main() { fn test(t: T, recurse: bool) -> impl Display { let f = || { let i: u32 = test::(-1, false); - //~^ ERROR concrete type differs from previous defining opaque type use - //~| ERROR expected generic type parameter, found `i32` + //~^ ERROR expected generic type parameter, found `i32` println!("{i}"); }; if recurse { diff --git a/tests/ui/impl-trait/issue-99073-2.stderr b/tests/ui/impl-trait/issue-99073-2.stderr index 0bcac7c7c534..519530b53962 100644 --- a/tests/ui/impl-trait/issue-99073-2.stderr +++ b/tests/ui/impl-trait/issue-99073-2.stderr @@ -1,15 +1,3 @@ -error: concrete type differs from previous defining opaque type use - --> $DIR/issue-99073-2.rs:9:22 - | -LL | let i: u32 = test::(-1, false); - | ^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `u32` - | -note: previous use here - --> $DIR/issue-99073-2.rs:7:45 - | -LL | fn test(t: T, recurse: bool) -> impl Display { - | ^^^^^^^^^^^^ - error[E0792]: expected generic type parameter, found `i32` --> $DIR/issue-99073-2.rs:9:22 | @@ -19,6 +7,6 @@ LL | let f = || { LL | let i: u32 = test::(-1, false); | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/issue-99073.rs b/tests/ui/impl-trait/issue-99073.rs index b4ef3e66f964..d2a2a61a4084 100644 --- a/tests/ui/impl-trait/issue-99073.rs +++ b/tests/ui/impl-trait/issue-99073.rs @@ -4,6 +4,5 @@ fn main() { fn fix(f: F) -> impl Fn() { move || f(fix(&f)) - //~^ ERROR concrete type differs from previous defining opaque type use - //~| ERROR expected generic type parameter, found `&F` + //~^ ERROR expected generic type parameter, found `&F` } diff --git a/tests/ui/impl-trait/issue-99073.stderr b/tests/ui/impl-trait/issue-99073.stderr index 19854ef89405..1917c1bfd6b4 100644 --- a/tests/ui/impl-trait/issue-99073.stderr +++ b/tests/ui/impl-trait/issue-99073.stderr @@ -1,23 +1,11 @@ -error: concrete type differs from previous defining opaque type use - --> $DIR/issue-99073.rs:6:13 - | -LL | move || f(fix(&f)) - | ^^^^^^^ expected `{closure@$DIR/issue-99073.rs:6:3: 6:10}`, got `G` - | -note: previous use here - --> $DIR/issue-99073.rs:5:36 - | -LL | fn fix(f: F) -> impl Fn() { - | ^^^^^^^^^ - error[E0792]: expected generic type parameter, found `&F` - --> $DIR/issue-99073.rs:6:11 + --> $DIR/issue-99073.rs:6:13 | LL | fn fix(f: F) -> impl Fn() { | - this generic parameter must be used with a generic type parameter LL | move || f(fix(&f)) - | ^^^^^^^^^^ + | ^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.rs b/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.rs new file mode 100644 index 000000000000..a76ed7b09474 --- /dev/null +++ b/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.rs @@ -0,0 +1,17 @@ +// Regression test for #112201. This recursive call previously meant that +// we delay an error when checking opaques at the end of writeback but don't +// encounter that incorrect defining use during borrowck as it's in dead code. + +pub fn wrap(x: T) -> impl Sized { + x +} + +fn repeat_helper(x: T) -> impl Sized { + return x; + repeat_helper(wrap(x)) + //~^ ERROR expected generic type parameter, found `impl Sized` + //~| ERROR type parameter `T` is part of concrete type +} + + +fn main() {} diff --git a/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.stderr b/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.stderr new file mode 100644 index 000000000000..f507ad385a17 --- /dev/null +++ b/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.stderr @@ -0,0 +1,18 @@ +error[E0792]: expected generic type parameter, found `impl Sized` + --> $DIR/fuzzer-ice-issue-112201.rs:11:5 + | +LL | fn repeat_helper(x: T) -> impl Sized { + | - this generic parameter must be used with a generic type parameter +LL | return x; +LL | repeat_helper(wrap(x)) + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/fuzzer-ice-issue-112201.rs:11:5 + | +LL | repeat_helper(wrap(x)) + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs index 9e8ea439dde9..cf82467b72ee 100644 --- a/tests/ui/impl-trait/issues/issue-86800.rs +++ b/tests/ui/impl-trait/issues/issue-86800.rs @@ -29,7 +29,6 @@ where F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f, { f - //~^ ERROR expected generic lifetime parameter, found `'_` } impl Context { @@ -39,7 +38,6 @@ impl Context { &self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>, ) -> TransactionResult { - //~^ ERROR expected generic lifetime parameter, found `'_` let mut conn = Connection {}; let mut transaction = TestTransaction { conn: &mut conn }; f(&mut transaction).await diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr index 80aa5d75c3c6..e122fc229ccd 100644 --- a/tests/ui/impl-trait/issues/issue-86800.stderr +++ b/tests/ui/impl-trait/issues/issue-86800.stderr @@ -12,7 +12,7 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future $DIR/issue-86800.rs:37:14 + --> $DIR/issue-86800.rs:36:14 | LL | async fn do_transaction( | ^^^^^^^^^^^^^^ @@ -24,30 +24,5 @@ note: this opaque type is supposed to be constrained LL | type TransactionFuture<'__, O> = impl '__ + Future>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/issue-86800.rs:31:5 - | -LL | type TransactionFuture<'__, O> = impl '__ + Future>; - | --- this generic parameter must be used with a generic lifetime parameter -... -LL | f - | ^ +error: aborting due to 2 previous errors -error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/issue-86800.rs:41:31 - | -LL | type TransactionFuture<'__, O> = impl '__ + Future>; - | --- this generic parameter must be used with a generic lifetime parameter -... -LL | ) -> TransactionResult { - | _______________________________^ -LL | | -LL | | let mut conn = Connection {}; -LL | | let mut transaction = TestTransaction { conn: &mut conn }; -LL | | f(&mut transaction).await -LL | | } - | |_____^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/non-defining-uses/as-projection-term.next.stderr b/tests/ui/impl-trait/non-defining-uses/as-projection-term.next.stderr new file mode 100644 index 000000000000..08c8365b1805 --- /dev/null +++ b/tests/ui/impl-trait/non-defining-uses/as-projection-term.next.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/as-projection-term.rs:14:19 + | +LL | fn recur<'a>() -> impl Sized + 'a { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | prove_proj(|| recur()); + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/non-defining-uses/as-projection-term.rs b/tests/ui/impl-trait/non-defining-uses/as-projection-term.rs new file mode 100644 index 000000000000..4c5adc7a00ab --- /dev/null +++ b/tests/ui/impl-trait/non-defining-uses/as-projection-term.rs @@ -0,0 +1,17 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[current] check-pass + +fn prove_proj(_: impl FnOnce() -> R) {} +fn recur<'a>() -> impl Sized + 'a { + // The closure has the signature `fn() -> opaque<'1>`. `prove_proj` + // requires us to prove `>::Output = opaque<'2>`. + // The old solver uses `replace_opaque_types_with_infer` during normalization + // to replace `opaque<'2>` with its hidden type. If that hidden type is still an + // inference variable at this point, we unify it with `opaque<'1>` and + // end up ignoring that defining use as the hidden type is equal to its key. + prove_proj(|| recur()); + //[next]~^ ERROR expected generic lifetime parameter, found `'_` +} +fn main() {} diff --git a/tests/ui/impl-trait/recursive-ice-101862.stderr b/tests/ui/impl-trait/recursive-ice-101862.stderr index 970373422e8a..85745c25e2bf 100644 --- a/tests/ui/impl-trait/recursive-ice-101862.stderr +++ b/tests/ui/impl-trait/recursive-ice-101862.stderr @@ -1,3 +1,12 @@ +error[E0792]: expected generic type parameter, found `&str` + --> $DIR/recursive-ice-101862.rs:6:19 + | +LL | pub fn ice(x: impl AsRef) -> impl IntoIterator { + | --------------- this generic parameter must be used with a generic type parameter +LL | +LL | vec![].append(&mut ice(x.as_ref())); + | ^^^^^^^^^^^^^^^^^^^^ + warning: function cannot return without recursing --> $DIR/recursive-ice-101862.rs:4:1 | @@ -10,15 +19,6 @@ LL | vec![].append(&mut ice(x.as_ref())); = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -error[E0792]: expected generic type parameter, found `&str` - --> $DIR/recursive-ice-101862.rs:6:19 - | -LL | pub fn ice(x: impl AsRef) -> impl IntoIterator { - | --------------- this generic parameter must be used with a generic type parameter -LL | -LL | vec![].append(&mut ice(x.as_ref())); - | ^^^^^^^^^^^^^^^^^^^^ - error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/rpit/early_bound.rs b/tests/ui/impl-trait/rpit/early_bound.rs index 005bcea59f24..0337f605e487 100644 --- a/tests/ui/impl-trait/rpit/early_bound.rs +++ b/tests/ui/impl-trait/rpit/early_bound.rs @@ -1,11 +1,10 @@ use std::convert::identity; fn test<'a: 'a>(n: bool) -> impl Sized + 'a { - //~^ ERROR concrete type differs from previous defining opaque type use let true = n else { loop {} }; let _ = || { let _ = identity::<&'a ()>(test(false)); - //~^ ERROR expected generic lifetime parameter, found `'_` + //~^ ERROR concrete type differs from previous defining opaque type use }; loop {} } diff --git a/tests/ui/impl-trait/rpit/early_bound.stderr b/tests/ui/impl-trait/rpit/early_bound.stderr index 230dde95764b..d00005f20d4a 100644 --- a/tests/ui/impl-trait/rpit/early_bound.stderr +++ b/tests/ui/impl-trait/rpit/early_bound.stderr @@ -1,24 +1,14 @@ error: concrete type differs from previous defining opaque type use + --> $DIR/early_bound.rs:6:36 + | +LL | let _ = identity::<&'a ()>(test(false)); + | ^^^^^^^^^^^ expected `()`, got `&()` + | +note: previous use here --> $DIR/early_bound.rs:3:29 | LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a { - | ^^^^^^^^^^^^^^^ expected `&()`, got `()` - | -note: previous use here - --> $DIR/early_bound.rs:7:36 - | -LL | let _ = identity::<&'a ()>(test(false)); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/early_bound.rs:7:17 - | -LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a { - | -- this generic parameter must be used with a generic lifetime parameter -... -LL | let _ = identity::<&'a ()>(test(false)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/rpit/non-defining-use.rs b/tests/ui/impl-trait/rpit/non-defining-use.rs index 255a8929a878..3ab0e0ee4e29 100644 --- a/tests/ui/impl-trait/rpit/non-defining-use.rs +++ b/tests/ui/impl-trait/rpit/non-defining-use.rs @@ -6,8 +6,7 @@ fn foo() -> impl Sized { fn bar(val: T) -> impl Sized { let _: u8 = bar(0u8); - //~^ ERROR concrete type differs from previous defining opaque type use - //~| ERROR expected generic type parameter, found `u8` + //~^ ERROR expected generic type parameter, found `u8` val } diff --git a/tests/ui/impl-trait/rpit/non-defining-use.stderr b/tests/ui/impl-trait/rpit/non-defining-use.stderr index 10a8232e646d..c2b1b0f82497 100644 --- a/tests/ui/impl-trait/rpit/non-defining-use.stderr +++ b/tests/ui/impl-trait/rpit/non-defining-use.stderr @@ -1,31 +1,19 @@ error[E0792]: expected generic type parameter, found `u8` - --> $DIR/non-defining-use.rs:4:12 + --> $DIR/non-defining-use.rs:4:17 | LL | fn foo() -> impl Sized { | - this generic parameter must be used with a generic type parameter LL | let _: () = foo::(); - | ^^ - -error: concrete type differs from previous defining opaque type use - --> $DIR/non-defining-use.rs:8:17 - | -LL | let _: u8 = bar(0u8); - | ^^^^^^^^ expected `T`, got `u8` - | -note: previous use here - --> $DIR/non-defining-use.rs:7:22 - | -LL | fn bar(val: T) -> impl Sized { - | ^^^^^^^^^^ + | ^^^^^^^^^^^ error[E0792]: expected generic type parameter, found `u8` - --> $DIR/non-defining-use.rs:8:12 + --> $DIR/non-defining-use.rs:8:17 | LL | fn bar(val: T) -> impl Sized { | - this generic parameter must be used with a generic type parameter LL | let _: u8 = bar(0u8); - | ^^ + | ^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/transmute/in-defining-scope.stderr b/tests/ui/impl-trait/transmute/in-defining-scope.stderr index 7172bfdf0d7e..315356951783 100644 --- a/tests/ui/impl-trait/transmute/in-defining-scope.stderr +++ b/tests/ui/impl-trait/transmute/in-defining-scope.stderr @@ -9,6 +9,31 @@ note: ...which requires computing type of opaque `foo::{opaque#0}`... | LL | fn foo() -> impl Sized { | ^^^^^^^^^^ +note: ...which requires borrow-checking `foo`... + --> $DIR/in-defining-scope.rs:6:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `foo`... + --> $DIR/in-defining-scope.rs:6:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires checking if `foo` contains FFI-unwind calls... + --> $DIR/in-defining-scope.rs:6:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `foo`... + --> $DIR/in-defining-scope.rs:6:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires match-checking `foo`... + --> $DIR/in-defining-scope.rs:6:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires type-checking `foo`... --> $DIR/in-defining-scope.rs:6:1 | diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr index 0711af1cad40..11b57ad98c45 100644 --- a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr +++ b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr @@ -1,18 +1,5 @@ -error: item does not constrain `A::{opaque#0}` - --> $DIR/two_tait_defining_each_other2.rs:12:4 - | -LL | fn muh(x: A) -> B { - | ^^^ - | - = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` -note: this opaque type is supposed to be constrained - --> $DIR/two_tait_defining_each_other2.rs:6:10 - | -LL | type A = impl Foo; - | ^^^^^^^^ - error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/two_tait_defining_each_other2.rs:15:5 + --> $DIR/two_tait_defining_each_other2.rs:14:5 | LL | x // B's hidden type is A (opaquely) | ^ one of the two opaque types used here has to be outside its defining scope @@ -28,5 +15,5 @@ note: opaque type being used as hidden type LL | type A = impl Foo; | ^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs index a3223b07a7ed..6c454bba5023 100644 --- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs +++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs @@ -10,8 +10,7 @@ trait Foo {} #[define_opaque(A, B)] fn muh(x: A) -> B { - //[current]~^ ERROR: item does not constrain `A::{opaque#0}` - //[next]~^^ ERROR: cannot satisfy `_ == A` + //[next]~^ ERROR: cannot satisfy `_ == A` x // B's hidden type is A (opaquely) //[current]~^ ERROR opaque type's hidden type cannot be another opaque type } diff --git a/tests/crashes/132335.rs b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs similarity index 74% rename from tests/crashes/132335.rs rename to tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs index 2294539cfcfa..e5208e3e47d0 100644 --- a/tests/crashes/132335.rs +++ b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs @@ -1,5 +1,8 @@ -//@ known-bug: #132335 +// Regression test for #132335. This previously ICE'd due to ambiguity +// in MIR typeck. + //@ compile-flags: -Znext-solver=globally --crate-type lib --edition=2018 +//@ check-pass use core::future::Future; use core::pin::Pin; diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr index 5625cb24d426..ff0afd319d90 100644 --- a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr +++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr @@ -1,34 +1,54 @@ -error: unconstrained opaque type +error: item does not constrain `ex1::Tait1::{opaque#0}` + --> $DIR/no-define-in-wf-check.rs:21:8 + | +LL | fn foo(x: Tait1) -> impl Sized { + | ^^^ + | + = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` +note: this opaque type is supposed to be constrained --> $DIR/no-define-in-wf-check.rs:19:18 | LL | type Tait1 = impl Sized; | ^^^^^^^^^^ - | - = note: `Tait1` must be used in combination with a concrete type within the same crate -error: unconstrained opaque type +error: item does not constrain `ex2::Tait1::{opaque#0}` + --> $DIR/no-define-in-wf-check.rs:31:8 + | +LL | fn foo(x: Tait1) -> Tait2 { + | ^^^ + | + = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` +note: this opaque type is supposed to be constrained --> $DIR/no-define-in-wf-check.rs:28:18 | LL | type Tait1 = impl Sized; | ^^^^^^^^^^ - | - = note: `Tait1` must be used in combination with a concrete type within the same crate -error: unconstrained opaque type +error: item does not constrain `ex3::Tait1::{opaque#0}` + --> $DIR/no-define-in-wf-check.rs:43:8 + | +LL | fn foo(x: Tait1) -> Tait2 { + | ^^^ + | + = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` +note: this opaque type is supposed to be constrained --> $DIR/no-define-in-wf-check.rs:38:18 | LL | type Tait1 = impl Sized; | ^^^^^^^^^^ - | - = note: `Tait1` must be used in combination with a concrete type within the same crate -error: unconstrained opaque type +error: item does not constrain `ex4::Tait1::{opaque#0}` + --> $DIR/no-define-in-wf-check.rs:64:8 + | +LL | fn foo(x: Tait1) -> Tait2 { + | ^^^ + | + = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` +note: this opaque type is supposed to be constrained --> $DIR/no-define-in-wf-check.rs:50:18 | LL | type Tait1 = impl Sized; | ^^^^^^^^^^ - | - = note: `Tait1` must be used in combination with a concrete type within the same crate error: aborting due to 4 previous errors diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs index 31d07d89d8dc..26c17edeb93b 100644 --- a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs +++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs @@ -17,38 +17,37 @@ mod ex0 { } mod ex1 { type Tait1 = impl Sized; - //[current]~^ ERROR unconstrained opaque type #[define_opaque(Tait1)] fn foo(x: Tait1) -> impl Sized { + //[current]~^ ERROR item does not constrain `ex1::Tait1::{opaque#0}` let () = x; } } mod ex2 { type Tait1 = impl Sized; - //[current]~^ ERROR unconstrained opaque type type Tait2 = impl Sized; #[define_opaque(Tait1, Tait2)] fn foo(x: Tait1) -> Tait2 { + //[current]~^ ERROR item does not constrain `ex2::Tait1::{opaque#0}` let () = x; } } mod ex3 { type Tait1 = impl Sized; - //[current]~^ ERROR unconstrained opaque type trait Something {} impl Something for T {} type Tait2 = impl Something; #[define_opaque(Tait1, Tait2)] fn foo(x: Tait1) -> Tait2 { + //[current]~^ ERROR item does not constrain `ex3::Tait1::{opaque#0}` let () = x; } } mod ex4 { type Tait1 = impl Sized; - //[current]~^ ERROR unconstrained opaque type trait Trait { type Assoc; } @@ -63,6 +62,7 @@ mod ex4 { type Tait2 = impl Trait<(), Assoc = impl Trait>; #[define_opaque(Tait1, Tait2)] fn foo(x: Tait1) -> Tait2 { + //[current]~^ ERROR item does not constrain `ex4::Tait1::{opaque#0}` let () = x; } } diff --git a/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs new file mode 100644 index 000000000000..8388751fea64 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs @@ -0,0 +1,11 @@ +// Regression test for #137751. This previously ICE'd as +// we did not provide the hidden type of the opaque inside +// of the async block. This caused borrowck of the recursive +// call to ICE. + +//@ compile-flags: --edition=2021 +//@ check-pass +async fn test() { + Box::pin(test()).await; +} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs index b6870b164509..5c93bd14d325 100644 --- a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs +++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs @@ -12,7 +12,6 @@ pub enum UninhabitedVariants { #[define_opaque(Alias)] fn uwu(x: UninhabitedVariants) { - //~^ ERROR item does not constrain match x {} //~^ ERROR non-exhaustive patterns } diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr index 59909197e7bc..72fae0173cbb 100644 --- a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr +++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr @@ -26,21 +26,8 @@ help: add missing generic argument LL | Tuple(Alias), | +++ -error: item does not constrain `Alias::{opaque#0}` - --> $DIR/bad-tait-no-substs.rs:14:4 - | -LL | fn uwu(x: UninhabitedVariants) { - | ^^^ - | - = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` -note: this opaque type is supposed to be constrained - --> $DIR/bad-tait-no-substs.rs:5:21 - | -LL | type Alias<'a, U> = impl Trait; - | ^^^^^^^^^^^^^ - error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` not covered - --> $DIR/bad-tait-no-substs.rs:16:11 + --> $DIR/bad-tait-no-substs.rs:15:11 | LL | match x {} | ^ pattern `UninhabitedVariants::Tuple(_)` not covered @@ -60,7 +47,7 @@ LL + UninhabitedVariants::Tuple(_) => todo!(), LL ~ } | -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0004, E0106, E0107. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.rs b/tests/ui/type-alias-impl-trait/bound_reduction2.rs index 78288caffefe..fadc2beba719 100644 --- a/tests/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.rs @@ -14,6 +14,6 @@ impl Trait for () {} #[define_opaque(Foo)] fn foo_desugared(_: T) -> Foo { - () //~^ ERROR expected generic type parameter, found `::Assoc` + () } diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr index 289826cc1d02..53b20d61025f 100644 --- a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -1,11 +1,11 @@ error[E0792]: expected generic type parameter, found `::Assoc` - --> $DIR/bound_reduction2.rs:17:5 + --> $DIR/bound_reduction2.rs:16:46 | LL | type Foo = impl Trait; | - this generic parameter must be used with a generic type parameter ... -LL | () - | ^^ +LL | fn foo_desugared(_: T) -> Foo { + | ^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs b/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs index e56f60a6693e..b5a9bf4a59f3 100644 --- a/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs +++ b/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs @@ -9,7 +9,7 @@ fn get_one<'a>(a: *mut &'a str) -> Opaque<'a> { #[define_opaque(Opaque)] fn get_iter<'a>() -> impl IntoIterator> { - //~^ ERROR: item does not constrain + //~^ ERROR item does not constrain `Opaque::{opaque#0}` None::> } diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.rs b/tests/ui/type-alias-impl-trait/different_defining_uses.rs index 246f255e8fcf..547696b83da5 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses.rs +++ b/tests/ui/type-alias-impl-trait/different_defining_uses.rs @@ -12,6 +12,6 @@ fn foo() -> Foo { #[define_opaque(Foo)] fn bar() -> Foo { + //~^ ERROR concrete type differs 42i32 - //~^ ERROR concrete type differs from previous } diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr index 9a7f4b416f4b..36d7e33dca0a 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/different_defining_uses.rs:15:5 + --> $DIR/different_defining_uses.rs:14:13 | -LL | 42i32 - | ^^^^^ expected `&'static str`, got `i32` +LL | fn bar() -> Foo { + | ^^^ expected `&str`, got `i32` | note: previous use here - --> $DIR/different_defining_uses.rs:10:5 + --> $DIR/different_defining_uses.rs:9:13 | -LL | "" - | ^^ +LL | fn foo() -> Foo { + | ^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs index e8c40e8bf926..bbbc2086bdf5 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs @@ -12,7 +12,6 @@ fn foo<'a, 'b>() -> Tait<'a> { } let x: Tait<'a> = (); x - //~^ ERROR concrete type differs from previous defining opaque type use } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr index d4bd39759247..4d7dd6b2ad5f 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr @@ -1,15 +1,3 @@ -error: concrete type differs from previous defining opaque type use - --> $DIR/different_defining_uses_never_type-2.rs:14:5 - | -LL | x - | ^ expected `i32`, got `()` - | -note: previous use here - --> $DIR/different_defining_uses_never_type-2.rs:9:31 - | -LL | let y: Tait<'b> = 1i32; - | ^^^^ - error: concrete type differs from previous defining opaque type use --> $DIR/different_defining_uses_never_type-2.rs:9:31 | @@ -17,10 +5,10 @@ LL | let y: Tait<'b> = 1i32; | ^^^^ expected `()`, got `i32` | note: previous use here - --> $DIR/different_defining_uses_never_type-2.rs:8:14 + --> $DIR/different_defining_uses_never_type-2.rs:14:5 | -LL | if { return } { - | ^^^^^^ +LL | x + | ^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr index cb12fddd9a03..eb9001cc6244 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr @@ -5,10 +5,10 @@ LL | let y: Tait = 1i32; | ^^^^ expected `()`, got `i32` | note: previous use here - --> $DIR/different_defining_uses_never_type-3.rs:13:22 + --> $DIR/different_defining_uses_never_type-3.rs:14:5 | -LL | let x: Tait = (); - | ^^ +LL | x + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr index 38afa3cbcd0e..0914dd1c546e 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr @@ -2,13 +2,13 @@ error: concrete type differs from previous defining opaque type use --> $DIR/different_defining_uses_never_type.rs:14:13 | LL | fn bar() -> Foo { - | ^^^ expected `&'static str`, got `()` + | ^^^ expected `&str`, got `()` | note: previous use here - --> $DIR/different_defining_uses_never_type.rs:10:5 + --> $DIR/different_defining_uses_never_type.rs:9:13 | -LL | "" - | ^^ +LL | fn foo() -> Foo { + | ^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr index 21fab8180633..78a9f6b63654 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr @@ -5,10 +5,10 @@ LL | fn two() -> Tait { Two::<()>(todo!()) } | ^^^^ expected `One`, got `Two<()>` | note: previous use here - --> $DIR/different_defining_uses_never_type3.rs:7:20 + --> $DIR/different_defining_uses_never_type3.rs:7:13 | LL | fn one() -> Tait { One } - | ^^^ + | ^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs index 726820bbd5a1..c2578297006b 100644 --- a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs +++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs @@ -31,7 +31,6 @@ impl Fn(&'a ()) -> StateWidget<'a>> Widget<()> for StatefulWidget fn new_stateful_widget Fn(&'a ()) -> StateWidget<'a>>(build: F) -> impl Widget<()> { //~^ ERROR item does not constrain StatefulWidget(build) - //~^ ERROR expected generic lifetime parameter, found `'a` } fn main() { diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr index 4f5c65adab9c..dee729e1f9f4 100644 --- a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr +++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr @@ -24,17 +24,8 @@ note: this opaque type is supposed to be constrained LL | type StateWidget<'a> = impl Widget<&'a ()>; | ^^^^^^^^^^^^^^^^^^^ -error[E0792]: expected generic lifetime parameter, found `'a` - --> $DIR/failed-to-normalize-ice-99945.rs:33:5 - | -LL | type StateWidget<'a> = impl Widget<&'a ()>; - | -- this generic parameter must be used with a generic lifetime parameter -... -LL | StatefulWidget(build) - | ^^^^^^^^^^^^^^^^^^^^^ - error[E0308]: mismatched types - --> $DIR/failed-to-normalize-ice-99945.rs:38:29 + --> $DIR/failed-to-normalize-ice-99945.rs:37:29 | LL | type StateWidget<'a> = impl Widget<&'a ()>; | ------------------- the expected opaque type @@ -45,7 +36,6 @@ LL | new_stateful_widget(|_| ()).make_state(); = note: expected opaque type `StateWidget<'_>` found unit type `()` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0792. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs index d55a9a376b9f..41fb6fe8587f 100644 --- a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs +++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs @@ -11,6 +11,6 @@ fn my_iter(t: T) -> MyIter { #[define_opaque(MyIter)] fn my_iter2(t: T) -> MyIter { - Some(t).into_iter() //~^ ERROR concrete type differs from previous + Some(t).into_iter() } diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr index 6d3279144d8f..b4be8542163f 100644 --- a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr +++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_different_defining_uses.rs:14:5 + --> $DIR/generic_different_defining_uses.rs:13:25 | -LL | Some(t).into_iter() - | ^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once`, got `std::option::IntoIter` +LL | fn my_iter2(t: T) -> MyIter { + | ^^^^^^^^^ expected `std::iter::Once`, got `std::option::IntoIter` | note: previous use here - --> $DIR/generic_different_defining_uses.rs:9:5 + --> $DIR/generic_different_defining_uses.rs:8:24 | -LL | std::iter::once(t) - | ^^^^^^^^^^^^^^^^^^ +LL | fn my_iter(t: T) -> MyIter { + | ^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs index e8ed38a24ceb..6e791a3bdb9d 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -20,8 +20,8 @@ type TwoConsts = impl Debug; #[define_opaque(TwoTys)] fn one_ty(t: T) -> TwoTys { - t //~^ ERROR non-defining opaque type use in defining scope + t } #[define_opaque(TwoLifetimes)] @@ -32,6 +32,6 @@ fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { #[define_opaque(TwoConsts)] fn one_const(t: *mut [u8; N]) -> TwoConsts { - t //~^ ERROR non-defining opaque type use in defining scope + t } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr index 3e048c8138d0..022e534df1a2 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:23:5 + --> $DIR/generic_duplicate_param_use.rs:22:30 | -LL | t - | ^ +LL | fn one_ty(t: T) -> TwoTys { + | ^^^^^^^^^^^^ | note: type used multiple times --> $DIR/generic_duplicate_param_use.rs:15:13 @@ -23,10 +23,10 @@ LL | type TwoLifetimes<'a, 'b> = impl Debug; | ^^ ^^ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:35:5 + --> $DIR/generic_duplicate_param_use.rs:34:50 | -LL | t - | ^ +LL | fn one_const(t: *mut [u8; N]) -> TwoConsts { + | ^^^^^^^^^^^^^^^ | note: constant used multiple times --> $DIR/generic_duplicate_param_use.rs:19:16 diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs index f732b2333961..873c7b614b69 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -14,6 +14,6 @@ fn two(t: T, _: U) -> Two { #[define_opaque(Two)] fn three(_: T, u: U) -> Two { - u //~^ ERROR concrete type differs + u } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr index b0a1bd77f857..3f5f2c93c59d 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use3.rs:17:5 + --> $DIR/generic_duplicate_param_use3.rs:16:38 | -LL | u - | ^ expected `T`, got `U` +LL | fn three(_: T, u: U) -> Two { + | ^^^^^^^^^ expected `T`, got `U` | note: previous use here - --> $DIR/generic_duplicate_param_use3.rs:12:5 + --> $DIR/generic_duplicate_param_use3.rs:11:36 | -LL | t - | ^ +LL | fn two(t: T, _: U) -> Two { + | ^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs index d450bef57581..1d4d3ab737f3 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs @@ -14,6 +14,6 @@ fn two(t: T, u: U) -> Two { #[define_opaque(Two)] fn three(t: T, u: U) -> Two { - (u, t) //~^ ERROR concrete type differs + (u, t) } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr index b8a2a9374161..59b37a8b792c 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use5.rs:17:5 + --> $DIR/generic_duplicate_param_use5.rs:16:45 | -LL | (u, t) - | ^^^^^^ expected `(T, U)`, got `(U, T)` +LL | fn three(t: T, u: U) -> Two { + | ^^^^^^^^^ expected `(T, U)`, got `(U, T)` | note: previous use here - --> $DIR/generic_duplicate_param_use5.rs:12:5 + --> $DIR/generic_duplicate_param_use5.rs:11:43 | -LL | (t, u) - | ^^^^^^ +LL | fn two(t: T, u: U) -> Two { + | ^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs index 24d03b9e60d2..961e2910dbee 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs @@ -14,6 +14,6 @@ fn two(t: T, u: U) -> Two { #[define_opaque(Two)] fn three(t: T, u: U) -> Two { - (u, t) //~^ ERROR concrete type differs + (u, t) } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr index 983e58d3c702..0940d6f541fc 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use6.rs:17:5 + --> $DIR/generic_duplicate_param_use6.rs:16:52 | -LL | (u, t) - | ^^^^^^ expected `(T, T)`, got `(U, T)` +LL | fn three(t: T, u: U) -> Two { + | ^^^^^^^^^ expected `(T, T)`, got `(U, T)` | note: previous use here - --> $DIR/generic_duplicate_param_use6.rs:12:5 + --> $DIR/generic_duplicate_param_use6.rs:11:50 | -LL | (t, t) - | ^^^^^^ +LL | fn two(t: T, u: U) -> Two { + | ^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs index 03057c847825..d01cc7ff04eb 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs @@ -13,6 +13,6 @@ fn two(t: T, _: U) -> Two { #[define_opaque(Two)] fn three(_: T, u: U) -> Two { - (u, 4u32) //~^ concrete type differs + (u, 4u32) } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr index 48c98c1e2b15..f9615d455d13 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use8.rs:16:5 + --> $DIR/generic_duplicate_param_use8.rs:15:45 | -LL | (u, 4u32) - | ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)` +LL | fn three(_: T, u: U) -> Two { + | ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)` | note: previous use here - --> $DIR/generic_duplicate_param_use8.rs:11:5 + --> $DIR/generic_duplicate_param_use8.rs:10:43 | -LL | (t, 4u32) - | ^^^^^^^^^ +LL | fn two(t: T, _: U) -> Two { + | ^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs index 74176550ab24..ec03ff1675ed 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs @@ -18,6 +18,6 @@ fn two(t: T, u: U) -> Two { #[define_opaque(Two)] fn three(t: T, u: U) -> Two { - (t, u, 42) //~^ ERROR concrete type differs + (t, u, 42) } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr index 542324c949f1..df9984cd0739 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use9.rs:21:5 + --> $DIR/generic_duplicate_param_use9.rs:20:45 | -LL | (t, u, 42) - | ^^^^^^^^^^ expected `(A, B, ::Bar)`, got `(A, B, i32)` +LL | fn three(t: T, u: U) -> Two { + | ^^^^^^^^^ expected `(A, B, ::Bar)`, got `(A, B, i32)` | note: previous use here - --> $DIR/generic_duplicate_param_use9.rs:16:5 + --> $DIR/generic_duplicate_param_use9.rs:15:49 | -LL | (t, u, T::BAR) - | ^^^^^^^^^^^^^^ +LL | fn two(t: T, u: U) -> Two { + | ^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs index 7791410294c0..cf38c93bd921 100644 --- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -14,8 +14,8 @@ type OneConst = impl Debug; #[define_opaque(OneTy)] fn concrete_ty() -> OneTy { - 5u32 //~^ ERROR: expected generic type parameter, found `u32` + 5u32 } #[define_opaque(OneLifetime)] @@ -26,6 +26,6 @@ fn concrete_lifetime() -> OneLifetime<'static> { #[define_opaque(OneConst)] fn concrete_const() -> OneConst<{ 123 }> { - 7u32 //~^ ERROR: expected generic constant parameter, found `123` + 7u32 } diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 1b0ce7cc619f..71e415271ee8 100644 --- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -1,11 +1,11 @@ error[E0792]: expected generic type parameter, found `u32` - --> $DIR/generic_nondefining_use.rs:17:5 + --> $DIR/generic_nondefining_use.rs:16:21 | LL | type OneTy = impl Debug; | - this generic parameter must be used with a generic type parameter ... -LL | 5u32 - | ^^^^ +LL | fn concrete_ty() -> OneTy { + | ^^^^^^^^^^ error[E0792]: expected generic lifetime parameter, found `'static` --> $DIR/generic_nondefining_use.rs:23:5 @@ -17,13 +17,13 @@ LL | 6u32 | ^^^^ error[E0792]: expected generic constant parameter, found `123` - --> $DIR/generic_nondefining_use.rs:29:5 + --> $DIR/generic_nondefining_use.rs:28:24 | LL | type OneConst = impl Debug; | -------------- this generic parameter must be used with a generic constant parameter ... -LL | 7u32 - | ^^^^ +LL | fn concrete_const() -> OneConst<{ 123 }> { + | ^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.rs b/tests/ui/type-alias-impl-trait/generic_not_used.rs index 6042cdd30a94..f270f65f43ed 100644 --- a/tests/ui/type-alias-impl-trait/generic_not_used.rs +++ b/tests/ui/type-alias-impl-trait/generic_not_used.rs @@ -7,6 +7,6 @@ type WrongGeneric = impl 'static; #[define_opaque(WrongGeneric)] fn wrong_generic(_: U, v: V) -> WrongGeneric { - v //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list + v } diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.stderr b/tests/ui/type-alias-impl-trait/generic_not_used.stderr index 5fe2fefcecfd..a480040006ea 100644 --- a/tests/ui/type-alias-impl-trait/generic_not_used.stderr +++ b/tests/ui/type-alias-impl-trait/generic_not_used.stderr @@ -5,10 +5,10 @@ LL | type WrongGeneric = impl 'static; | ^^^^^^^^^^^^ error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/generic_not_used.rs:10:5 + --> $DIR/generic_not_used.rs:9:57 | -LL | v - | ^ +LL | fn wrong_generic(_: U, v: V) -> WrongGeneric { + | ^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs index cbd8150d1177..4b4db8ec2ed3 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs @@ -10,18 +10,15 @@ use std::future::Future; type FutNothing<'a> = impl 'a + Future; async fn operation(_: &mut ()) -> () { - //~^ ERROR: concrete type differs from previous call(operation).await - //~^ ERROR: expected generic lifetime parameter, found `'any` + //~^ ERROR: concrete type differs from previous } #[define_opaque(FutNothing)] async fn call(_f: F) -//~^ ERROR item does not constrain +//~^ ERROR item does not constrain `FutNothing::{opaque#0}` where for<'any> F: FnMut(&'any mut ()) -> FutNothing<'any>, -{ - //~^ ERROR: expected generic lifetime parameter, found `'any` -} +{} fn main() {} diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr index 2c0be0cbcdca..2aacf9698379 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr @@ -1,5 +1,5 @@ error: item does not constrain `FutNothing::{opaque#0}` - --> $DIR/hkl_forbidden4.rs:19:10 + --> $DIR/hkl_forbidden4.rs:18:10 | LL | async fn call(_f: F) | ^^^^ @@ -12,37 +12,16 @@ LL | type FutNothing<'a> = impl 'a + Future; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: concrete type differs from previous defining opaque type use + --> $DIR/hkl_forbidden4.rs:13:5 + | +LL | call(operation).await + | ^^^^^^^^^^^^^^^ expected `{async fn body of operation()}`, got `FutNothing<'_>` + | +note: previous use here --> $DIR/hkl_forbidden4.rs:12:1 | LL | async fn operation(_: &mut ()) -> () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}` - | -note: previous use here - --> $DIR/hkl_forbidden4.rs:14:5 - | -LL | call(operation).await - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0792]: expected generic lifetime parameter, found `'any` - --> $DIR/hkl_forbidden4.rs:14:5 - | -LL | async fn operation(_: &mut ()) -> () { - | - this generic parameter must be used with a generic lifetime parameter -LL | -LL | call(operation).await - | ^^^^^^^^^^^^^^^ +error: aborting due to 2 previous errors -error[E0792]: expected generic lifetime parameter, found `'any` - --> $DIR/hkl_forbidden4.rs:23:1 - | -LL | type FutNothing<'a> = impl 'a + Future; - | -- this generic parameter must be used with a generic lifetime parameter -... -LL | / { -LL | | -LL | | } - | |_^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr index 114cac64573c..9fcb26c20a68 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr +++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr @@ -20,6 +20,41 @@ error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}` LL | type Bar = impl Sized; | ^^^^^^^^^^ | +note: ...which requires borrow-checking `foo`... + --> $DIR/in-where-clause.rs:9:1 + | +LL | / fn foo() -> Bar +LL | | where +LL | | Bar: Send, + | |______________^ +note: ...which requires promoting constants in MIR for `foo`... + --> $DIR/in-where-clause.rs:9:1 + | +LL | / fn foo() -> Bar +LL | | where +LL | | Bar: Send, + | |______________^ +note: ...which requires checking if `foo` contains FFI-unwind calls... + --> $DIR/in-where-clause.rs:9:1 + | +LL | / fn foo() -> Bar +LL | | where +LL | | Bar: Send, + | |______________^ +note: ...which requires building MIR for `foo`... + --> $DIR/in-where-clause.rs:9:1 + | +LL | / fn foo() -> Bar +LL | | where +LL | | Bar: Send, + | |______________^ +note: ...which requires match-checking `foo`... + --> $DIR/in-where-clause.rs:9:1 + | +LL | / fn foo() -> Bar +LL | | where +LL | | Bar: Send, + | |______________^ note: ...which requires type-checking `foo`... --> $DIR/in-where-clause.rs:9:1 | diff --git a/tests/ui/type-alias-impl-trait/issue-109054.rs b/tests/ui/type-alias-impl-trait/issue-109054.rs index 0c9304a42f35..a8bb5ee3301f 100644 --- a/tests/ui/type-alias-impl-trait/issue-109054.rs +++ b/tests/ui/type-alias-impl-trait/issue-109054.rs @@ -18,7 +18,7 @@ impl std::ops::Deref for CallMe { async move { *val * 2 } } - &inner //~ ERROR: expected generic lifetime parameter, found `'_` + &inner } } diff --git a/tests/ui/type-alias-impl-trait/issue-109054.stderr b/tests/ui/type-alias-impl-trait/issue-109054.stderr index 919b0a287c4f..5ce6f54e5f9a 100644 --- a/tests/ui/type-alias-impl-trait/issue-109054.stderr +++ b/tests/ui/type-alias-impl-trait/issue-109054.stderr @@ -11,15 +11,5 @@ note: this opaque type is supposed to be constrained LL | type ReturnType<'a> = impl std::future::Future + 'a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/issue-109054.rs:21:9 - | -LL | type ReturnType<'a> = impl std::future::Future + 'a; - | -- this generic parameter must be used with a generic lifetime parameter -... -LL | &inner - | ^^^^^^ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr index 3062e55dc490..c8db9fdfc579 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -9,6 +9,31 @@ note: ...which requires computing type of opaque `Bug::{opaque#0}`... | LL | type Bug = impl Fn(T) -> U + Copy; | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires borrow-checking `CONST_BUG`... + --> $DIR/issue-53092-2.rs:8:1 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `CONST_BUG`... + --> $DIR/issue-53092-2.rs:8:1 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `CONST_BUG`... + --> $DIR/issue-53092-2.rs:8:1 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `CONST_BUG`... + --> $DIR/issue-53092-2.rs:8:1 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires match-checking `CONST_BUG`... + --> $DIR/issue-53092-2.rs:8:1 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires type-checking `CONST_BUG`... --> $DIR/issue-53092-2.rs:8:1 | diff --git a/tests/ui/type-alias-impl-trait/issue-53598.rs b/tests/ui/type-alias-impl-trait/issue-53598.rs index e3e2787b66bb..3262c69cf5a4 100644 --- a/tests/ui/type-alias-impl-trait/issue-53598.rs +++ b/tests/ui/type-alias-impl-trait/issue-53598.rs @@ -17,8 +17,8 @@ impl Foo for S2 { type Item = impl Debug; fn foo(_: T) -> Self::Item { - S::(Default::default()) //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + S::(Default::default()) } } diff --git a/tests/ui/type-alias-impl-trait/issue-53598.stderr b/tests/ui/type-alias-impl-trait/issue-53598.stderr index a31aabedba54..f1dd3c69443c 100644 --- a/tests/ui/type-alias-impl-trait/issue-53598.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53598.stderr @@ -1,8 +1,8 @@ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-53598.rs:20:9 + --> $DIR/issue-53598.rs:19:31 | -LL | S::(Default::default()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo(_: T) -> Self::Item { + | ^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-60564.rs b/tests/ui/type-alias-impl-trait/issue-60564.rs index f28258b3b227..ae9a4d026703 100644 --- a/tests/ui/type-alias-impl-trait/issue-60564.rs +++ b/tests/ui/type-alias-impl-trait/issue-60564.rs @@ -18,8 +18,8 @@ where type BitsIter = IterBitsIter; #[define_opaque(IterBitsIter)] fn iter_bits(self, n: u8) -> Self::BitsIter { - (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) //~^ ERROR expected generic type parameter, found `u8` + (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) } } diff --git a/tests/ui/type-alias-impl-trait/issue-60564.stderr b/tests/ui/type-alias-impl-trait/issue-60564.stderr index 6aaed7d4296a..bfe8d92fedd3 100644 --- a/tests/ui/type-alias-impl-trait/issue-60564.stderr +++ b/tests/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,11 +1,11 @@ error[E0792]: expected generic type parameter, found `u8` - --> $DIR/issue-60564.rs:21:9 + --> $DIR/issue-60564.rs:20:34 | LL | type IterBitsIter = impl std::iter::Iterator; | - this generic parameter must be used with a generic type parameter ... -LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn iter_bits(self, n: u8) -> Self::BitsIter { + | ^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr index 178aa5cf3453..e58b2d4aa609 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -1,11 +1,11 @@ error[E0792]: expected generic type parameter, found `()` - --> $DIR/issue-68368-non-defining-use-2.rs:10:29 + --> $DIR/issue-68368-non-defining-use-2.rs:10:15 | LL | type Alias<'a, U> = impl Trait; | - this generic parameter must be used with a generic type parameter ... LL | fn f<'a>() -> Alias<'a, ()> {} - | ^^ + | ^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr index bfbd506a7a5c..3ec19e206008 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -1,11 +1,11 @@ error[E0792]: expected generic type parameter, found `()` - --> $DIR/issue-68368-non-defining-use.rs:10:29 + --> $DIR/issue-68368-non-defining-use.rs:10:15 | LL | type Alias<'a, U> = impl Trait; | - this generic parameter must be used with a generic type parameter ... LL | fn f<'a>() -> Alias<'a, ()> {} - | ^^ + | ^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs index 18afc54dbdc6..9e0c8fbbd269 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.rs +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -6,9 +6,9 @@ type Pointer = impl std::ops::Deref; #[define_opaque(Pointer)] fn test() -> Pointer<_> { - //~^ ERROR: the placeholder `_` is not allowed within types + //~^ ERROR the placeholder `_` is not allowed within types + //~| ERROR expected generic type parameter, found `i32` Box::new(1) - //~^ ERROR: expected generic type parameter, found `i32` } fn main() { @@ -17,5 +17,5 @@ fn main() { extern "Rust" { fn bar() -> Pointer<_>; - //~^ ERROR: the placeholder `_` is not allowed within types + //~^ ERROR the placeholder `_` is not allowed within types } diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index bc11283f3282..c0f197ec48c3 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -1,3 +1,12 @@ +error[E0792]: expected generic type parameter, found `i32` + --> $DIR/issue-77179.rs:8:14 + | +LL | type Pointer = impl std::ops::Deref; + | - this generic parameter must be used with a generic type parameter +... +LL | fn test() -> Pointer<_> { + | ^^^^^^^^^^ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-77179.rs:8:22 | @@ -13,15 +22,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | fn bar() -> Pointer<_>; | ^ not allowed in type signatures -error[E0792]: expected generic type parameter, found `i32` - --> $DIR/issue-77179.rs:10:5 - | -LL | type Pointer = impl std::ops::Deref; - | - this generic parameter must be used with a generic type parameter -... -LL | Box::new(1) - | ^^^^^^^^^^^ - error: aborting due to 3 previous errors Some errors have detailed explanations: E0121, E0792. diff --git a/tests/ui/type-alias-impl-trait/multi-error.rs b/tests/ui/type-alias-impl-trait/multi-error.rs index cb4ad4dc6337..2f42f14d4cb4 100644 --- a/tests/ui/type-alias-impl-trait/multi-error.rs +++ b/tests/ui/type-alias-impl-trait/multi-error.rs @@ -16,8 +16,8 @@ impl Foo for () { type Baz = impl Sized; fn foo() -> (Self::Bar, Self::Baz) { //~^ ERROR non-defining opaque type use + //~| ERROR expected generic type parameter, found `u32` ((), ()) - //~^ ERROR expected generic type parameter } } diff --git a/tests/ui/type-alias-impl-trait/multi-error.stderr b/tests/ui/type-alias-impl-trait/multi-error.stderr index 761f01b32acf..3cb267c7c261 100644 --- a/tests/ui/type-alias-impl-trait/multi-error.stderr +++ b/tests/ui/type-alias-impl-trait/multi-error.stderr @@ -11,13 +11,13 @@ LL | type Bar = impl Sized; | ^^^^^^^^^^ error[E0792]: expected generic type parameter, found `u32` - --> $DIR/multi-error.rs:19:9 + --> $DIR/multi-error.rs:17:17 | LL | type Bar = impl Sized; | - this generic parameter must be used with a generic type parameter -... -LL | ((), ()) - | ^^^^^^^^ +LL | type Baz = impl Sized; +LL | fn foo() -> (Self::Bar, Self::Baz) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs index 3dd2d53fe3d8..839ac4716238 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs @@ -8,7 +8,8 @@ type Y = impl std::fmt::Debug; #[define_opaque(Y)] fn g() -> (Y, Y) { - (42_i64, 60) //~ ERROR concrete type differs from previous defining opaque type use + //~^ ERROR concrete type differs from previous defining opaque type use + (42_i64, 60) } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr index d6558576577f..e044cbe819e8 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr @@ -1,11 +1,11 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/multiple-def-uses-in-one-fn-infer.rs:11:5 + --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:17 | -LL | (42_i64, 60) - | ^^^^^^^^^^^^ - | | - | expected `i64`, got `i32` - | this expression supplies two conflicting concrete types for the same opaque type +LL | fn g() -> (Y, Y) { + | ^^^^^^^^^^^^^^^^^^ + | | + | expected `i64`, got `i32` + | this expression supplies two conflicting concrete types for the same opaque type error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs index 1357d772be17..aa31901fc5ef 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs @@ -8,8 +8,8 @@ type X = impl ToString; #[define_opaque(X)] fn f(a: A, b: B) -> (X, X) { - (a.clone(), a) //~^ ERROR concrete type differs from previous defining opaque type + (a.clone(), a) } fn main() { diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr index 15e9b6fbf761..8d79b37f0f5f 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr @@ -1,11 +1,11 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/multiple-def-uses-in-one-fn2.rs:11:5 + --> $DIR/multiple-def-uses-in-one-fn2.rs:10:63 | -LL | (a.clone(), a) - | ^^^^^^^^^^^^^^ - | | - | expected `A`, got `B` - | this expression supplies two conflicting concrete types for the same opaque type +LL | fn f(a: A, b: B) -> (X, X) { + | ^^^^^^^^^^^^^^^^^^ + | | + | expected `A`, got `B` + | this expression supplies two conflicting concrete types for the same opaque type error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs index 5adae476bfe2..57fa86f5eb75 100644 --- a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs +++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs @@ -12,7 +12,7 @@ pub fn get_foo() -> Foo { #[define_opaque(Foot, Foo)] pub fn get_foot(_: Foo) -> Foot { - //~^ ERROR: item does not constrain `Foo::{opaque#0}` + //~^ ERROR item does not constrain `Foo::{opaque#0}` get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type } diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.stderr b/tests/ui/type-alias-impl-trait/non-defining-method.stderr index 49a393ca745b..22f173b5be9f 100644 --- a/tests/ui/type-alias-impl-trait/non-defining-method.stderr +++ b/tests/ui/type-alias-impl-trait/non-defining-method.stderr @@ -11,12 +11,12 @@ LL | type Bar = impl Sized; | ^^^^^^^^^^ error[E0792]: expected generic type parameter, found `u32` - --> $DIR/non-defining-method.rs:16:32 + --> $DIR/non-defining-method.rs:16:17 | LL | type Bar = impl Sized; | - this generic parameter must be used with a generic type parameter LL | fn foo() -> Self::Bar {} - | ^^ + | ^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr index 75cc5948e93c..53e312e3e64f 100644 --- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr +++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr @@ -1,26 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/normalize-hidden-types.rs:27:20 + --> $DIR/normalize-hidden-types.rs:38:22 | -LL | fn define() -> Opaque { - | ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(::Gat<'a>)` +LL | fn define_2() -> Opaque { dyn_hoops::(0) } + | ^^^^^^ expected `*const dyn for<'a> FnOnce(::Gat<'a>)`, got `*const dyn FnOnce(())` | note: previous use here - --> $DIR/normalize-hidden-types.rs:28:9 - | -LL | dyn_hoops::<_>(0) - | ^^^^^^^^^^^^^^^^^ - -error: concrete type differs from previous defining opaque type use --> $DIR/normalize-hidden-types.rs:36:22 | LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) } - | ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(::Gat<'a>)` - | -note: previous use here - --> $DIR/normalize-hidden-types.rs:36:31 - | -LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) } - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^ error[E0308]: mismatched types --> $DIR/normalize-hidden-types.rs:47:25 @@ -38,18 +26,6 @@ LL | let _: Opaque = dyn_hoops::(0); = help: consider constraining the associated type `::Gat<'_>` to `()` or calling a method that returns `::Gat<'_>` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -error: concrete type differs from previous defining opaque type use - --> $DIR/normalize-hidden-types.rs:57:25 - | -LL | let _: Opaque = dyn_hoops::<_>(0); - | ^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(::Gat<'a>)` - | -note: previous use here - --> $DIR/normalize-hidden-types.rs:58:9 - | -LL | None - | ^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs index d20622dc2e05..cfbbf9ce487c 100644 --- a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -23,8 +23,8 @@ impl Bar for u32 { #[define_opaque(Two)] fn four(t: T) -> Two { - (t, ::FOO) //~^ ERROR concrete type differs + (t, ::FOO) } fn is_sync() {} diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr index d90e4531879b..37d28b3883c2 100644 --- a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/not_a_defining_use.rs:26:5 + --> $DIR/not_a_defining_use.rs:25:36 | -LL | (t, ::FOO) - | ^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, ::Blub)` +LL | fn four(t: T) -> Two { + | ^^^^^^^^^ expected `(T, i8)`, got `(T, ::Blub)` | note: previous use here - --> $DIR/not_a_defining_use.rs:11:5 + --> $DIR/not_a_defining_use.rs:10:32 | -LL | (t, 5i8) - | ^^^^^^^^ +LL | fn three(t: T) -> Two { + | ^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs index cfd7e1bf3823..94597adfed04 100644 --- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs +++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs @@ -13,7 +13,8 @@ pub fn add( n: Diff, m: Diff, ) -> Diff { - move |x: usize| m(n(x)) //~ ERROR: concrete type differs + //~^ ERROR concrete type differs + move |x: usize| m(n(x)) } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr index 1a8ab2194049..59ff99176124 100644 --- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/recursive-fn-tait.rs:16:5 + --> $DIR/recursive-fn-tait.rs:15:6 | -LL | move |x: usize| m(n(x)) - | ^^^^^^^^^^^^^^^^^^^^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:8:5: 8:16}`, got `{closure@$DIR/recursive-fn-tait.rs:16:5: 16:20}` +LL | ) -> Diff { + | ^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:8:5: 8:16}`, got `{closure@$DIR/recursive-fn-tait.rs:17:5: 17:20}` | note: previous use here - --> $DIR/recursive-fn-tait.rs:8:5 + --> $DIR/recursive-fn-tait.rs:7:18 | -LL | |_: usize |loop {} - | ^^^^^^^^^^^^^^^^^^ +LL | pub fn lift() -> Diff { + | ^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs index 26ffd5c16a29..858f2a2feb67 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs @@ -13,8 +13,8 @@ fn transform() -> impl std::fmt::Display { } #[define_opaque(Op)] fn bad() -> Op { - transform::() //~^ ERROR concrete type differs from previous defining opaque type use + transform::() } fn main() { diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr index 259f3b2b9f3d..e527b5bc7f8f 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/recursive-tait-conflicting-defn-2.rs:16:5 + --> $DIR/recursive-tait-conflicting-defn-2.rs:15:13 | -LL | transform::() - | ^^^^^^^^^^^^^^^^^ expected `&'static &'static str`, got `impl std::fmt::Display` +LL | fn bad() -> Op { + | ^^ expected `&&str`, got `impl std::fmt::Display` | note: previous use here - --> $DIR/recursive-tait-conflicting-defn-2.rs:8:5 + --> $DIR/recursive-tait-conflicting-defn-2.rs:7:13 | -LL | &"hello world" - | ^^^^^^^^^^^^^^ +LL | fn foo() -> Op { + | ^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs index c9e2773905d7..90581a98a346 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs @@ -23,10 +23,9 @@ pub fn test() -> TestImpl { #[define_opaque(TestImpl)] fn make_option2() -> Option { - let inner = make_option().unwrap(); - - Some(B { inner }) //~^ ERROR concrete type differs from previous defining opaque type use + let inner = make_option().unwrap(); + Some(B { inner }) } fn make_option() -> Option { diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr index 47471c9728c4..256f13b62217 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/recursive-tait-conflicting-defn.rs:28:5 + --> $DIR/recursive-tait-conflicting-defn.rs:25:22 | -LL | Some(B { inner }) - | ^^^^^^^^^^^^^^^^^ expected `A`, got `B` +LL | fn make_option2() -> Option { + | ^^^^^^^^^^^^^^^^ expected `A`, got `B` | note: previous use here - --> $DIR/recursive-tait-conflicting-defn.rs:21:5 + --> $DIR/recursive-tait-conflicting-defn.rs:20:18 | -LL | A - | ^ +LL | pub fn test() -> TestImpl { + | ^^^^^^^^ error: aborting due to 1 previous error From f3eaf1624c7bc900900248c5112ba8a6be849c85 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 18 Mar 2025 17:18:54 +0000 Subject: [PATCH 105/176] Split ExpectationLintId off Level --- .../src/annotate_snippet_emitter_writer.rs | 4 +- compiler/rustc_errors/src/diagnostic.rs | 21 ++++++++-- compiler/rustc_errors/src/json.rs | 2 +- compiler/rustc_errors/src/lib.rs | 39 +++++++++---------- compiler/rustc_middle/src/lint.rs | 16 ++++---- 5 files changed, 48 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f0636b600b70..f3aeb8d224b9 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -91,13 +91,13 @@ fn annotation_level_for_level(level: Level) -> annotate_snippets::Level { Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => { annotate_snippets::Level::Error } - Level::ForceWarning(_) | Level::Warning => annotate_snippets::Level::Warning, + Level::ForceWarning | Level::Warning => annotate_snippets::Level::Warning, Level::Note | Level::OnceNote => annotate_snippets::Level::Note, Level::Help | Level::OnceHelp => annotate_snippets::Level::Help, // FIXME(#59346): Not sure how to map this level Level::FailureNote => annotate_snippets::Level::Error, Level::Allow => panic!("Should not call with Allow"), - Level::Expect(_) => panic!("Should not call with Expect"), + Level::Expect => panic!("Should not call with Expect"), } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 9f4d2ea5c1ad..794502d7aaee 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -9,7 +9,7 @@ use std::thread::panicking; use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::{FluentValue, fluent_value_from_str_list_sep_by_and}; -use rustc_lint_defs::Applicability; +use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span, Symbol}; @@ -296,6 +296,7 @@ pub struct DiagInner { pub messages: Vec<(DiagMessage, Style)>, pub code: Option, + pub lint_id: Option, pub span: MultiSpan, pub children: Vec, pub suggestions: Suggestions, @@ -324,6 +325,7 @@ impl DiagInner { pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self { DiagInner { level, + lint_id: None, messages, code: None, span: MultiSpan::new(), @@ -346,7 +348,7 @@ impl DiagInner { match self.level { Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true, - Level::ForceWarning(_) + Level::ForceWarning | Level::Warning | Level::Note | Level::OnceNote @@ -354,7 +356,7 @@ impl DiagInner { | Level::OnceHelp | Level::FailureNote | Level::Allow - | Level::Expect(_) => false, + | Level::Expect => false, } } @@ -365,7 +367,7 @@ impl DiagInner { pub(crate) fn is_force_warn(&self) -> bool { match self.level { - Level::ForceWarning(_) => { + Level::ForceWarning => { assert!(self.is_lint.is_some()); true } @@ -1259,6 +1261,17 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } + with_fn! { with_lint_id, + /// Add an argument. + #[rustc_lint_diagnostics] + pub fn lint_id( + &mut self, + id: LintExpectationId, + ) -> &mut Self { + self.lint_id = Some(id); + self + } } + with_fn! { with_primary_message, /// Add a primary message. #[rustc_lint_diagnostics] diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 7d7f364fec23..a6583407b7e7 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -144,7 +144,7 @@ impl Emitter for JsonEmitter { // // So to avoid ICEs and confused users we "upgrade" the lint level for // those `FutureBreakageItem` to warn. - if matches!(diag.level, crate::Level::Allow | crate::Level::Expect(..)) { + if matches!(diag.level, crate::Level::Allow | crate::Level::Expect) { diag.level = crate::Level::Warning; } FutureBreakageItem { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 80e43ede4453..f5f7618285e1 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -905,8 +905,8 @@ impl<'a> DiagCtxtHandle<'a> { DelayedBug => { return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); } - ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow - | Expect(_) => None, + ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow + | Expect => None, }; // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic @@ -1045,7 +1045,7 @@ impl<'a> DiagCtxtHandle<'a> { // Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a // configuration like `--cap-lints allow --force-warn bare_trait_objects`. inner.emit_diagnostic( - DiagInner::new(ForceWarning(None), DiagMessage::Str(warnings)), + DiagInner::new(ForceWarning, DiagMessage::Str(warnings)), None, ); } @@ -1450,7 +1450,7 @@ impl<'a> DiagCtxtHandle<'a> { #[rustc_lint_diagnostics] #[track_caller] pub fn struct_expect(self, msg: impl Into, id: LintExpectationId) -> Diag<'a, ()> { - Diag::new(self, Expect(id), msg) + Diag::new(self, Expect, msg).with_lint_id(id) } } @@ -1510,7 +1510,7 @@ impl DiagCtxtInner { // Future breakages aren't emitted if they're `Level::Allow` or // `Level::Expect`, but they still need to be constructed and // stashed below, so they'll trigger the must_produce_diag check. - assert_matches!(diagnostic.level, Error | Warning | Allow | Expect(_)); + assert_matches!(diagnostic.level, Error | Warning | Allow | Expect); self.future_breakage_diagnostics.push(diagnostic.clone()); } @@ -1558,7 +1558,7 @@ impl DiagCtxtInner { }; } } - ForceWarning(None) => {} // `ForceWarning(Some(...))` is below, with `Expect` + ForceWarning if diagnostic.lint_id.is_none() => {} // `ForceWarning(Some(...))` is below, with `Expect` Warning => { if !self.flags.can_emit_warnings { // We are not emitting warnings. @@ -1580,9 +1580,9 @@ impl DiagCtxtInner { } return None; } - Expect(expect_id) | ForceWarning(Some(expect_id)) => { - self.fulfilled_expectations.insert(expect_id); - if let Expect(_) = diagnostic.level { + Expect | ForceWarning => { + self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap()); + if let Expect = diagnostic.level { // Nothing emitted here for expected lints. TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); self.suppressed_expected_diag = true; @@ -1631,7 +1631,7 @@ impl DiagCtxtInner { if is_error { self.deduplicated_err_count += 1; - } else if matches!(diagnostic.level, ForceWarning(_) | Warning) { + } else if matches!(diagnostic.level, ForceWarning | Warning) { self.deduplicated_warn_count += 1; } self.has_printed = true; @@ -1899,9 +1899,9 @@ pub enum Level { /// A `force-warn` lint warning about the code being compiled. Does not prevent compilation /// from finishing. /// - /// The [`LintExpectationId`] is used for expected lint diagnostics. In all other cases this + /// Requires a [`LintExpectationId`] for expected lint diagnostics. In all other cases this /// should be `None`. - ForceWarning(Option), + ForceWarning, /// A warning about the code being compiled. Does not prevent compilation from finishing. /// Will be skipped if `can_emit_warnings` is false. @@ -1926,8 +1926,8 @@ pub enum Level { /// Only used for lints. Allow, - /// Only used for lints. - Expect(LintExpectationId), + /// Only used for lints. Requires a [`LintExpectationId`] for silencing the lints. + Expect, } impl fmt::Display for Level { @@ -1943,7 +1943,7 @@ impl Level { Bug | Fatal | Error | DelayedBug => { spec.set_fg(Some(Color::Red)).set_intense(true); } - ForceWarning(_) | Warning => { + ForceWarning | Warning => { spec.set_fg(Some(Color::Yellow)).set_intense(cfg!(windows)); } Note | OnceNote => { @@ -1953,7 +1953,7 @@ impl Level { spec.set_fg(Some(Color::Cyan)).set_intense(true); } FailureNote => {} - Allow | Expect(_) => unreachable!(), + Allow | Expect => unreachable!(), } spec } @@ -1962,11 +1962,11 @@ impl Level { match self { Bug | DelayedBug => "error: internal compiler error", Fatal | Error => "error", - ForceWarning(_) | Warning => "warning", + ForceWarning | Warning => "warning", Note | OnceNote => "note", Help | OnceHelp => "help", FailureNote => "failure-note", - Allow | Expect(_) => unreachable!(), + Allow | Expect => unreachable!(), } } @@ -1977,8 +1977,7 @@ impl Level { // Can this level be used in a subdiagnostic message? fn can_be_subdiag(&self) -> bool { match self { - Bug | DelayedBug | Fatal | Error | ForceWarning(_) | FailureNote | Allow - | Expect(_) => false, + Bug | DelayedBug | Fatal | Error | ForceWarning | FailureNote | Allow | Expect => false, Warning | Note | Help | OnceNote | OnceHelp => true, } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 88bf17070b9c..a4df3d183ea4 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -293,10 +293,10 @@ pub fn lint_level( ); // Convert lint level to error level. - let err_level = match level { + let (err_level, lint_id) = match level { Level::Allow => { if has_future_breakage { - rustc_errors::Level::Allow + (rustc_errors::Level::Allow, None) } else { return; } @@ -309,17 +309,19 @@ pub fn lint_level( // We can also not mark the lint expectation as fulfilled here right away, as it // can still be cancelled in the decorate function. All of this means that we simply // create a `Diag` and continue as we would for warnings. - rustc_errors::Level::Expect(expect_id) + (rustc_errors::Level::Expect, Some(expect_id)) } - Level::ForceWarn(Some(expect_id)) => rustc_errors::Level::ForceWarning(Some(expect_id)), - Level::ForceWarn(None) => rustc_errors::Level::ForceWarning(None), - Level::Warn => rustc_errors::Level::Warning, - Level::Deny | Level::Forbid => rustc_errors::Level::Error, + Level::ForceWarn(expect_id) => (rustc_errors::Level::ForceWarning, expect_id), + Level::Warn => (rustc_errors::Level::Warning, None), + Level::Deny | Level::Forbid => (rustc_errors::Level::Error, None), }; let mut err = Diag::new(sess.dcx(), err_level, ""); if let Some(span) = span { err.span(span); } + if let Some(lint_id) = lint_id { + err.lint_id(lint_id); + } // If this code originates in a foreign macro, aka something that this crate // did not itself author, then it's likely that there's nothing this crate From c51816ee59576477f79d58e633e145bec381d807 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 19 Mar 2025 09:41:38 +0000 Subject: [PATCH 106/176] Make LevelAndSource a struct --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 +- compiler/rustc_codegen_ssa/src/lib.rs | 5 +- .../src/const_eval/machine.rs | 2 +- compiler/rustc_hir_typeck/src/upvar.rs | 5 +- compiler/rustc_lint/src/builtin.rs | 4 +- compiler/rustc_lint/src/context.rs | 4 +- compiler/rustc_lint/src/levels.rs | 59 +++++++++++-------- compiler/rustc_lint/src/non_ascii_idents.rs | 9 +-- compiler/rustc_metadata/src/creader.rs | 2 +- compiler/rustc_middle/src/lint.rs | 28 +++++---- compiler/rustc_middle/src/middle/stability.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 12 ++-- .../rustc_mir_build/src/check_unsafety.rs | 8 ++- .../src/thir/pattern/check_match.rs | 2 +- compiler/rustc_passes/src/dead.rs | 4 +- compiler/rustc_passes/src/stability.rs | 2 +- compiler/rustc_pattern_analysis/src/lints.rs | 11 ++-- .../passes/calculate_doc_coverage.rs | 7 ++- .../passes/check_doc_test_visibility.rs | 6 +- src/tools/clippy/clippy_lints/src/booleans.rs | 4 +- .../src/disallowed_script_idents.rs | 2 +- .../clippy/clippy_lints/src/module_style.rs | 4 +- src/tools/clippy/clippy_utils/src/lib.rs | 5 +- 23 files changed, 105 insertions(+), 86 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7d4110872417..2e91a1d921dd 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -959,9 +959,9 @@ fn link_natively( } } - let (level, src) = codegen_results.crate_info.lint_levels.linker_messages; + let level = codegen_results.crate_info.lint_levels.linker_messages; let lint = |msg| { - lint_level(sess, LINKER_MESSAGES, level, src, None, |diag| { + lint_level(sess, LINKER_MESSAGES, level, None, |diag| { LinkerOutput { inner: msg }.decorate_lint(diag) }) }; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index d26d6edf3149..f36e42cc6b95 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -34,7 +34,7 @@ use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::CrateNum; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_middle::dep_graph::WorkProduct; -use rustc_middle::lint::LintLevelSource; +use rustc_middle::lint::LevelAndSource; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; @@ -45,7 +45,6 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; -use rustc_session::lint::Level; use rustc_session::lint::builtin::LINKER_MESSAGES; use rustc_session::utils::NativeLibKind; use rustc_span::Symbol; @@ -341,7 +340,7 @@ impl CodegenResults { /// Instead, encode exactly the information we need. #[derive(Copy, Clone, Debug, Encodable, Decodable)] pub struct CodegenLintLevels { - linker_messages: (Level, LintLevelSource), + linker_messages: LevelAndSource, } impl CodegenLintLevels { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 496f6c86f719..61a7ec13511c 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -546,7 +546,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { rustc_session::lint::builtin::LONG_RUNNING_CONST_EVAL, hir_id, ) - .0 + .level .is_error(); let span = ecx.cur_span(); ecx.tcx.emit_node_span_lint( diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index b4ac143f5135..56ba2a23bfb3 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -2323,8 +2323,9 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis( return false; } - let (level, _) = - tcx.lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id); + let level = tcx + .lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id) + .level; !matches!(level, lint::Level::Allow) } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c56dbc2e1c40..dae0efcbbc46 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -29,6 +29,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::FnKind as HirFnKind; use rustc_hir::{Body, FnDecl, GenericParamKind, PatKind, PredicateOrigin}; use rustc_middle::bug; +use rustc_middle::lint::LevelAndSource; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; @@ -694,7 +695,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { } // Avoid listing trait impls if the trait is allowed. - let (level, _) = cx.tcx.lint_level_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()); + let LevelAndSource { level, .. } = + cx.tcx.lint_level_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()); if level == Level::Allow { return; } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 017ae943e916..49ddeb590459 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -643,7 +643,7 @@ impl<'tcx> LintContext for LateContext<'tcx> { } fn get_lint_level(&self, lint: &'static Lint) -> Level { - self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs).0 + self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs).level } } @@ -664,7 +664,7 @@ impl LintContext for EarlyContext<'_> { } fn get_lint_level(&self, lint: &'static Lint) -> Level { - self.builder.lint_level(lint).0 + self.builder.lint_level(lint).level } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 313d8f6ba8ff..12816c0829b0 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -87,7 +87,7 @@ impl LintLevelSets { let level = reveal_actual_level(level, &mut src, sess, lint, |id| { self.raw_lint_id_level(id, idx, aux) }); - (level, src) + LevelAndSource { level, src } } fn raw_lint_id_level( @@ -97,14 +97,14 @@ impl LintLevelSets { aux: Option<&FxIndexMap>, ) -> (Option, LintLevelSource) { if let Some(specs) = aux - && let Some(&(level, src)) = specs.get(&id) + && let Some(&LevelAndSource { level, src }) = specs.get(&id) { return (Some(level), src); } loop { let LintSet { ref specs, parent } = self.list[idx]; - if let Some(&(level, src)) = specs.get(&id) { + if let Some(&LevelAndSource { level, src }) = specs.get(&id) { return (Some(level), src); } if idx == COMMAND_LINE { @@ -131,8 +131,8 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { }) .filter_map(|lint| { let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID); - if matches!(lint_level, (Level::Allow, ..)) - || (matches!(lint_level, (.., LintLevelSource::Default))) + if matches!(lint_level.level, Level::Allow) + || (matches!(lint_level.src, LintLevelSource::Default)) && lint.default_level(tcx.sess.edition()) == Level::Allow { Some(LintId::of(lint)) @@ -595,7 +595,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; for id in ids { // ForceWarn and Forbid cannot be overridden - if let Some((Level::ForceWarn(_) | Level::Forbid, _)) = + if let Some(LevelAndSource { level: Level::ForceWarn(_) | Level::Forbid, .. }) = self.current_specs().get(&id) { continue; @@ -603,7 +603,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if self.check_gated_lint(id, DUMMY_SP, true) { let src = LintLevelSource::CommandLine(lint_flag_val, orig_level); - self.insert(id, (level, src)); + self.insert(id, LevelAndSource { level, src }); } } } @@ -612,8 +612,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. - fn insert_spec(&mut self, id: LintId, (level, src): LevelAndSource) { - let (old_level, old_src) = self.provider.get_lint_level(id.lint, self.sess); + fn insert_spec(&mut self, id: LintId, LevelAndSource { level, src }: LevelAndSource) { + let LevelAndSource { level: old_level, src: old_src } = + self.provider.get_lint_level(id.lint, self.sess); // Setting to a non-forbid level is an error if the lint previously had // a forbid level. Note that this is not necessarily true even with a @@ -693,13 +694,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { match (old_level, level) { // If the new level is an expectation store it in `ForceWarn` - (Level::ForceWarn(_), Level::Expect(expectation_id)) => { - self.insert(id, (Level::ForceWarn(Some(expectation_id)), old_src)) - } + (Level::ForceWarn(_), Level::Expect(expectation_id)) => self.insert( + id, + LevelAndSource { level: Level::ForceWarn(Some(expectation_id)), src: old_src }, + ), // Keep `ForceWarn` level but drop the expectation - (Level::ForceWarn(_), _) => self.insert(id, (Level::ForceWarn(None), old_src)), + (Level::ForceWarn(_), _) => { + self.insert(id, LevelAndSource { level: Level::ForceWarn(None), src: old_src }) + } // Set the lint level as normal - _ => self.insert(id, (level, src)), + _ => self.insert(id, LevelAndSource { level, src }), }; } @@ -714,7 +718,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if attr.has_name(sym::automatically_derived) { self.insert( LintId::of(SINGLE_USE_LIFETIMES), - (Level::Allow, LintLevelSource::Default), + LevelAndSource { level: Level::Allow, src: LintLevelSource::Default }, ); continue; } @@ -725,7 +729,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { .meta_item_list() .is_some_and(|l| ast::attr::list_contains_name(&l, sym::hidden)) { - self.insert(LintId::of(MISSING_DOCS), (Level::Allow, LintLevelSource::Default)); + self.insert( + LintId::of(MISSING_DOCS), + LevelAndSource { level: Level::Allow, src: LintLevelSource::Default }, + ); continue; } @@ -933,7 +940,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let src = LintLevelSource::Node { name, span: sp, reason }; for &id in ids { if self.check_gated_lint(id, sp, false) { - self.insert_spec(id, (level, src)); + self.insert_spec(id, LevelAndSource { level, src }); } } @@ -964,7 +971,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } if self.lint_added_lints && !is_crate_node { - for (id, &(level, ref src)) in self.current_specs().iter() { + for (id, &LevelAndSource { level, ref src }) in self.current_specs().iter() { if !id.lint.crate_level_only { continue; } @@ -1002,10 +1009,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if self.lint_added_lints { let lint = builtin::UNKNOWN_LINTS; - let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS); + let level = self.lint_level(builtin::UNKNOWN_LINTS); // FIXME: make this translatable #[allow(rustc::diagnostic_outside_of_impl)] - lint_level(self.sess, lint, level, src, Some(span.into()), |lint| { + lint_level(self.sess, lint, level, Some(span.into()), |lint| { lint.primary_message(fluent::lint_unknown_gated_lint); lint.arg("name", lint_id.lint.name_lower()); lint.note(fluent::lint_note); @@ -1040,8 +1047,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { span: Option, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - let (level, src) = self.lint_level(lint); - lint_level(self.sess, lint, level, src, span, decorate) + let level = self.lint_level(lint); + lint_level(self.sess, lint, level, span, decorate) } #[track_caller] @@ -1051,16 +1058,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { span: MultiSpan, decorate: impl for<'a> LintDiagnostic<'a, ()>, ) { - let (level, src) = self.lint_level(lint); - lint_level(self.sess, lint, level, src, Some(span), |lint| { + let level = self.lint_level(lint); + lint_level(self.sess, lint, level, Some(span), |lint| { decorate.decorate_lint(lint); }); } #[track_caller] pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> LintDiagnostic<'a, ()>) { - let (level, src) = self.lint_level(lint); - lint_level(self.sess, lint, level, src, None, |lint| { + let level = self.lint_level(lint); + lint_level(self.sess, lint, level, None, |lint| { decorate.decorate_lint(lint); }); } diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 66e207a451ef..9c11fb41aa6d 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -159,12 +159,13 @@ impl EarlyLintPass for NonAsciiIdents { use rustc_span::Span; use unicode_security::GeneralSecurityProfile; - let check_non_ascii_idents = cx.builder.lint_level(NON_ASCII_IDENTS).0 != Level::Allow; + let check_non_ascii_idents = cx.builder.lint_level(NON_ASCII_IDENTS).level != Level::Allow; let check_uncommon_codepoints = - cx.builder.lint_level(UNCOMMON_CODEPOINTS).0 != Level::Allow; - let check_confusable_idents = cx.builder.lint_level(CONFUSABLE_IDENTS).0 != Level::Allow; + cx.builder.lint_level(UNCOMMON_CODEPOINTS).level != Level::Allow; + let check_confusable_idents = + cx.builder.lint_level(CONFUSABLE_IDENTS).level != Level::Allow; let check_mixed_script_confusables = - cx.builder.lint_level(MIXED_SCRIPT_CONFUSABLES).0 != Level::Allow; + cx.builder.lint_level(MIXED_SCRIPT_CONFUSABLES).level != Level::Allow; if !check_non_ascii_idents && !check_uncommon_codepoints diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 16f87ab79bee..1c3222bbfeb6 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -340,7 +340,7 @@ impl CStore { } let level = tcx .lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID) - .0; + .level; if level != lint::Level::Allow { let unused_externs = self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::>(); diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index a4df3d183ea4..363acb4f33e3 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -51,8 +51,12 @@ impl LintLevelSource { } } -/// A tuple of a lint level and its source. -pub type LevelAndSource = (Level, LintLevelSource); +/// Convenience helper for moving things around together that frequently are paired +#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] +pub struct LevelAndSource { + pub level: Level, + pub src: LintLevelSource, +} /// Return type for the `shallow_lint_levels_on` query. /// @@ -123,7 +127,7 @@ impl ShallowLintLevelMap { start: HirId, ) -> (Option, LintLevelSource) { if let Some(map) = self.specs.get(&start.local_id) - && let Some(&(level, src)) = map.get(&id) + && let Some(&LevelAndSource { level, src }) = map.get(&id) { return (Some(level), src); } @@ -137,7 +141,7 @@ impl ShallowLintLevelMap { specs = &tcx.shallow_lint_levels_on(owner).specs; } if let Some(map) = specs.get(&parent.local_id) - && let Some(&(level, src)) = map.get(&id) + && let Some(&LevelAndSource { level, src }) = map.get(&id) { return (Some(level), src); } @@ -153,18 +157,18 @@ impl ShallowLintLevelMap { tcx: TyCtxt<'_>, lint: LintId, cur: HirId, - ) -> (Level, LintLevelSource) { + ) -> LevelAndSource { let (level, mut src) = self.probe_for_lint_level(tcx, lint, cur); let level = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| { self.probe_for_lint_level(tcx, lint, cur) }); - (level, src) + LevelAndSource { level, src } } } impl TyCtxt<'_> { /// Fetch and return the user-visible lint level for the given lint at the given HirId. - pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) { + pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> LevelAndSource { self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(self, LintId::of(lint), id) } } @@ -267,8 +271,7 @@ fn explain_lint_level_source( pub fn lint_level( sess: &Session, lint: &'static Lint, - level: Level, - src: LintLevelSource, + level: LevelAndSource, span: Option, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { @@ -278,11 +281,12 @@ pub fn lint_level( fn lint_level_impl( sess: &Session, lint: &'static Lint, - level: Level, - src: LintLevelSource, + level: LevelAndSource, span: Option, decorate: Box FnOnce(&'b mut Diag<'a, ()>)>, ) { + let LevelAndSource { level, src } = level; + // Check for future incompatibility lints and issue a stronger warning. let future_incompatible = lint.future_incompatible; @@ -421,5 +425,5 @@ pub fn lint_level( explain_lint_level_source(lint, level, src, &mut err); err.emit() } - lint_level_impl(sess, lint, level, src, span, Box::new(decorate)) + lint_level_impl(sess, lint, level, span, Box::new(decorate)) } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index ec128c8c4786..9912e659b05f 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -255,7 +255,7 @@ fn late_report_deprecation( // Calculating message for lint involves calling `self.def_path_str`, // which will by default invoke the expensive `visible_parent_map` query. // Skip all that work if the lint is allowed anyway. - if tcx.lint_level_at_node(lint, hir_id).0 == Level::Allow { + if tcx.lint_level_at_node(lint, hir_id).level == Level::Allow { return; } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 618a65a01864..f064bdb25766 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3022,8 +3022,8 @@ impl<'tcx> TyCtxt<'tcx> { span: impl Into, decorator: impl for<'a> LintDiagnostic<'a, ()>, ) { - let (level, src) = self.lint_level_at_node(lint, hir_id); - lint_level(self.sess, lint, level, src, Some(span.into()), |lint| { + let level = self.lint_level_at_node(lint, hir_id); + lint_level(self.sess, lint, level, Some(span.into()), |lint| { decorator.decorate_lint(lint); }) } @@ -3040,8 +3040,8 @@ impl<'tcx> TyCtxt<'tcx> { span: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - let (level, src) = self.lint_level_at_node(lint, hir_id); - lint_level(self.sess, lint, level, src, Some(span.into()), decorate); + let level = self.lint_level_at_node(lint, hir_id); + lint_level(self.sess, lint, level, Some(span.into()), decorate); } /// Find the crate root and the appropriate span where `use` and outer attributes can be @@ -3108,8 +3108,8 @@ impl<'tcx> TyCtxt<'tcx> { id: HirId, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - let (level, src) = self.lint_level_at_node(lint, id); - lint_level(self.sess, lint, level, src, None, decorate); + let level = self.lint_level_at_node(lint, id); + lint_level(self.sess, lint, level, None, decorate); } pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 2a9bfb25b842..6fb9974fc8e2 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -195,7 +195,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { /// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node. fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool { - self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).0 == Level::Allow + self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).level == Level::Allow } /// Handle closures/coroutines/inline-consts, which is unsafecked with their parent body. @@ -292,8 +292,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }); } BlockSafety::ExplicitUnsafe(hir_id) => { - let used = - matches!(self.tcx.lint_level_at_node(UNUSED_UNSAFE, hir_id), (Level::Allow, _)); + let used = matches!( + self.tcx.lint_level_at_node(UNUSED_UNSAFE, hir_id).level, + Level::Allow + ); self.in_safety_context( SafetyContext::UnsafeBlock { span: block.span, 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 ea8c7303c0af..9f5e2c06b229 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1025,7 +1025,7 @@ fn find_fallback_pattern_typo<'tcx>( pat: &Pat<'tcx>, lint: &mut UnreachablePattern<'_>, ) { - if let (Level::Allow, _) = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id) { + if let Level::Allow = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id).level { // This is because we use `with_no_trimmed_paths` later, so if we never emit the lint we'd // ICE. At the same time, we don't really need to do all of this if we won't emit anything. return; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index b62d94d65f1f..b588aacf6756 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -696,7 +696,7 @@ fn has_allow_dead_code_or_lang_attr( fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { let hir_id = tcx.local_def_id_to_hir_id(def_id); - let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; + let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).level; matches!(lint_level, lint::Allow | lint::Expect(_)) } @@ -961,7 +961,7 @@ impl<'tcx> DeadVisitor<'tcx> { fn def_lint_level(&self, id: LocalDefId) -> lint::Level { let hir_id = self.tcx.local_def_id_to_hir_id(id); - self.tcx.lint_level_at_node(DEAD_CODE, hir_id).0 + self.tcx.lint_level_at_node(DEAD_CODE, hir_id).level } // # Panics diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 6dec96f9f502..d7baad69c786 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -980,7 +980,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // Calculating message for lint involves calling `self.def_path_str`, // which will by default invoke the expensive `visible_parent_map` query. // Skip all that work if the lint is allowed anyway. - if self.tcx.lint_level_at_node(DEPRECATED, id).0 + if self.tcx.lint_level_at_node(DEPRECATED, id).level == lint::Level::Allow { return; diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 585cda1d24b7..950a13536bff 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,3 +1,4 @@ +use rustc_middle::lint::LevelAndSource; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::ErrorGuaranteed; use tracing::instrument; @@ -64,7 +65,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( scrut_ty: RevealedTy<'tcx>, ) -> Result<(), ErrorGuaranteed> { if !matches!( - rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0, + rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).level, rustc_session::lint::Level::Allow ) { let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?; @@ -88,13 +89,13 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( // arm. This no longer makes sense so we warn users, to avoid silently breaking their // usage of the lint. for arm in arms { - let (lint_level, lint_level_source) = + let LevelAndSource { level, src } = rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data); - if !matches!(lint_level, rustc_session::lint::Level::Allow) { + if !matches!(level, rustc_session::lint::Level::Allow) { let decorator = NonExhaustiveOmittedPatternLintOnArm { - lint_span: lint_level_source.span(), + lint_span: src.span(), suggest_lint_on_match: rcx.whole_match_span.map(|span| span.shrink_to_lo()), - lint_level: lint_level.as_str(), + lint_level: level.as_str(), lint_name: "non_exhaustive_omitted_patterns", }; diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index f8f670f575bf..7e22cf4c4103 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -5,7 +5,7 @@ use std::ops; use rustc_hir as hir; use rustc_lint::builtin::MISSING_DOCS; -use rustc_middle::lint::LintLevelSource; +use rustc_middle::lint::{LevelAndSource, LintLevelSource}; use rustc_session::lint; use rustc_span::FileName; use serde::Serialize; @@ -216,7 +216,8 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { let has_doc_example = tests.found_tests != 0; let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap(); - let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); + let LevelAndSource { level, src } = + self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); // In case we have: // @@ -251,7 +252,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { // unless the user had an explicit `allow`. // let should_have_docs = !should_be_ignored - && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default)); + && (level != lint::Level::Allow || matches!(src, LintLevelSource::Default)); if let Some(span) = i.span(self.ctx.tcx) { let filename = span.filename(self.ctx.sess()); diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 0fefd13f7633..0dd1eb1d40fd 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -6,7 +6,7 @@ //! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests. use rustc_hir as hir; -use rustc_middle::lint::LintLevelSource; +use rustc_middle::lint::{LevelAndSource, LintLevelSource}; use rustc_session::lint; use tracing::debug; @@ -107,11 +107,11 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - { return false; } - let (level, source) = cx.tcx.lint_level_at_node( + let LevelAndSource { level, src } = cx.tcx.lint_level_at_node( crate::lint::MISSING_DOC_CODE_EXAMPLES, cx.tcx.local_def_id_to_hir_id(def_id), ); - level != lint::Level::Allow || matches!(source, LintLevelSource::Default) + level != lint::Level::Allow || matches!(src, LintLevelSource::Default) } pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) { diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 48b5d4da8886..7bb5dbee126e 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -199,7 +199,7 @@ fn check_simplify_not(cx: &LateContext<'_>, msrv: Msrv, expr: &Expr<'_>) { && !expr.span.from_expansion() && !inner.span.from_expansion() && let Some(suggestion) = simplify_not(cx, msrv, inner) - && cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow + && cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).level != Level::Allow { use clippy_utils::sugg::{Sugg, has_enclosing_paren}; let maybe_par = if let Some(sug) = Sugg::hir_opt(cx, inner) { @@ -605,7 +605,7 @@ impl<'tcx> NonminimalBoolVisitor<'_, 'tcx> { } } let nonminimal_bool_lint = |mut suggestions: Vec<_>| { - if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).0 != Level::Allow { + if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).level != Level::Allow { suggestions.sort(); span_lint_hir_and_then( self.cx, diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs index 53c24a3faf1d..d1a8590c59b4 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs @@ -69,7 +69,7 @@ impl EarlyLintPass for DisallowedScriptIdents { // Implementation is heavily inspired by the implementation of [`non_ascii_idents`] lint: // https://github.com/rust-lang/rust/blob/master/compiler/rustc_lint/src/non_ascii_idents.rs - let check_disallowed_script_idents = cx.builder.lint_level(DISALLOWED_SCRIPT_IDENTS).0 != Level::Allow; + let check_disallowed_script_idents = cx.builder.lint_level(DISALLOWED_SCRIPT_IDENTS).level != Level::Allow; if !check_disallowed_script_idents { return; } diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs index 676d608eb318..7287193326f7 100644 --- a/src/tools/clippy/clippy_lints/src/module_style.rs +++ b/src/tools/clippy/clippy_lints/src/module_style.rs @@ -73,8 +73,8 @@ impl_lint_pass!(ModStyle => [MOD_MODULE_FILES, SELF_NAMED_MODULE_FILES]); impl EarlyLintPass for ModStyle { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { - if cx.builder.lint_level(MOD_MODULE_FILES).0 == Level::Allow - && cx.builder.lint_level(SELF_NAMED_MODULE_FILES).0 == Level::Allow + if cx.builder.lint_level(MOD_MODULE_FILES).level == Level::Allow + && cx.builder.lint_level(SELF_NAMED_MODULE_FILES).level == Level::Allow { return; } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 8dc28fa3077e..b4c5b85dcabc 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -114,6 +114,7 @@ use rustc_hir::{ use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; +use rustc_middle::lint::LevelAndSource; use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -1976,7 +1977,7 @@ pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl I let mut suppress_lint = false; for id in ids { - let (level, _) = cx.tcx.lint_level_at_node(lint, id); + let LevelAndSource { level, .. } = cx.tcx.lint_level_at_node(lint, id); if let Some(expectation) = level.get_expectation_id() { cx.fulfill_expectation(expectation); } @@ -1998,7 +1999,7 @@ pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl I /// make sure to use `span_lint_hir` functions to emit the lint. This ensures that /// expectations at the checked nodes will be fulfilled. pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool { - cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow + cx.tcx.lint_level_at_node(lint, id).level == Level::Allow } pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> { From 805f389da5d8870dc19f879300684bd421194d88 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 19 Mar 2025 08:59:19 +0000 Subject: [PATCH 107/176] Remove `LintExpectationId` from `Level` variants --- compiler/rustc_driver_impl/src/lib.rs | 2 +- compiler/rustc_lint/src/context.rs | 15 ++- compiler/rustc_lint/src/levels.rs | 92 +++++++++---------- compiler/rustc_lint_defs/src/lib.rs | 45 +++++---- compiler/rustc_middle/src/lint.rs | 52 ++++++----- compiler/rustc_passes/src/dead.rs | 11 ++- compiler/rustc_pattern_analysis/src/lints.rs | 2 +- compiler/rustc_session/src/config.rs | 2 +- .../passes/calculate_doc_coverage.rs | 2 +- .../passes/check_doc_test_visibility.rs | 2 +- .../clippy/clippy_lints/src/duplicate_mod.rs | 8 +- src/tools/clippy/clippy_lints/src/lib.rs | 2 +- .../clippy/clippy_lints/src/raw_strings.rs | 2 +- src/tools/clippy/clippy_lints/src/returns.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 8 +- 15 files changed, 124 insertions(+), 123 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index f1dc4bb795e5..a64ffe5da8ee 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -715,7 +715,7 @@ fn print_crate_info( // lint is unstable and feature gate isn't active, don't print continue; } - let level = lint_levels.lint_level(lint).0; + let level = lint_levels.lint_level(lint).level; println_info!("{}={}", lint.name_lower(), level.as_str()); } } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 49ddeb590459..885a7308bdc6 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -17,13 +17,12 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_hir::{Pat, PatKind}; use rustc_middle::bug; +use rustc_middle::lint::LevelAndSource; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths}; use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode}; -use rustc_session::lint::{ - FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, -}; +use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintBuffer, LintExpectationId, LintId}; use rustc_session::{LintStoreMarker, Session}; use rustc_span::edit_distance::find_best_match_for_names; use rustc_span::{Ident, Span, Symbol, sym}; @@ -573,7 +572,7 @@ pub trait LintContext { } /// This returns the lint level for the given lint at the current location. - fn get_lint_level(&self, lint: &'static Lint) -> Level; + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource; /// This function can be used to manually fulfill an expectation. This can /// be used for lints which contain several spans, and should be suppressed, @@ -642,8 +641,8 @@ impl<'tcx> LintContext for LateContext<'tcx> { } } - fn get_lint_level(&self, lint: &'static Lint) -> Level { - self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs).level + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource { + self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs) } } @@ -663,8 +662,8 @@ impl LintContext for EarlyContext<'_> { self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorate) } - fn get_lint_level(&self, lint: &'static Lint) -> Level { - self.builder.lint_level(lint).level + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource { + self.builder.lint_level(lint) } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 12816c0829b0..f1fe07cfcfaa 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -84,10 +84,10 @@ impl LintLevelSets { ) -> LevelAndSource { let lint = LintId::of(lint); let (level, mut src) = self.raw_lint_id_level(lint, idx, aux); - let level = reveal_actual_level(level, &mut src, sess, lint, |id| { + let (level, lint_id) = reveal_actual_level(level, &mut src, sess, lint, |id| { self.raw_lint_id_level(id, idx, aux) }); - LevelAndSource { level, src } + LevelAndSource { level, lint_id, src } } fn raw_lint_id_level( @@ -95,17 +95,17 @@ impl LintLevelSets { id: LintId, mut idx: LintStackIndex, aux: Option<&FxIndexMap>, - ) -> (Option, LintLevelSource) { + ) -> (Option<(Level, Option)>, LintLevelSource) { if let Some(specs) = aux - && let Some(&LevelAndSource { level, src }) = specs.get(&id) + && let Some(&LevelAndSource { level, lint_id, src }) = specs.get(&id) { - return (Some(level), src); + return (Some((level, lint_id)), src); } loop { let LintSet { ref specs, parent } = self.list[idx]; - if let Some(&LevelAndSource { level, src }) = specs.get(&id) { - return (Some(level), src); + if let Some(&LevelAndSource { level, lint_id, src }) = specs.get(&id) { + return (Some((level, lint_id)), src); } if idx == COMMAND_LINE { return (None, LintLevelSource::Default); @@ -379,13 +379,7 @@ impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> { fn visit_attribute(&mut self, attribute: &'tcx hir::Attribute) { if matches!( Level::from_attr(attribute), - Some( - Level::Warn - | Level::Deny - | Level::Forbid - | Level::Expect(..) - | Level::ForceWarn(..), - ) + Some((Level::Warn | Level::Deny | Level::Forbid | Level::Expect | Level::ForceWarn, _)) ) { let store = unerased_lint_store(self.tcx.sess); // Lint attributes are always a metalist inside a @@ -541,9 +535,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { for &(ref lint_name, level) in &self.sess.opts.lint_opts { // Checks the validity of lint names derived from the command line. let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name); - if lint_name_only == crate::WARNINGS.name_lower() - && matches!(level, Level::ForceWarn(_)) - { + if lint_name_only == crate::WARNINGS.name_lower() && matches!(level, Level::ForceWarn) { self.sess .dcx() .emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() }); @@ -586,7 +578,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { _ => {} }; - let orig_level = level; let lint_flag_val = Symbol::intern(lint_name); let Ok(ids) = self.store.find_lints(lint_name) else { @@ -595,15 +586,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; for id in ids { // ForceWarn and Forbid cannot be overridden - if let Some(LevelAndSource { level: Level::ForceWarn(_) | Level::Forbid, .. }) = + if let Some(LevelAndSource { level: Level::ForceWarn | Level::Forbid, .. }) = self.current_specs().get(&id) { continue; } if self.check_gated_lint(id, DUMMY_SP, true) { - let src = LintLevelSource::CommandLine(lint_flag_val, orig_level); - self.insert(id, LevelAndSource { level, src }); + let src = LintLevelSource::CommandLine(lint_flag_val, level); + self.insert(id, LevelAndSource { level, lint_id: None, src }); } } } @@ -612,8 +603,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. - fn insert_spec(&mut self, id: LintId, LevelAndSource { level, src }: LevelAndSource) { - let LevelAndSource { level: old_level, src: old_src } = + fn insert_spec(&mut self, id: LintId, LevelAndSource { level, lint_id, src }: LevelAndSource) { + let LevelAndSource { level: old_level, src: old_src, .. } = self.provider.get_lint_level(id.lint, self.sess); // Setting to a non-forbid level is an error if the lint previously had @@ -686,7 +677,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // The lint `unfulfilled_lint_expectations` can't be expected, as it would suppress itself. // Handling expectations of this lint would add additional complexity with little to no // benefit. The expect level for this lint will therefore be ignored. - if let Level::Expect(_) = level + if let Level::Expect = level && id == LintId::of(UNFULFILLED_LINT_EXPECTATIONS) { return; @@ -694,16 +685,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { match (old_level, level) { // If the new level is an expectation store it in `ForceWarn` - (Level::ForceWarn(_), Level::Expect(expectation_id)) => self.insert( - id, - LevelAndSource { level: Level::ForceWarn(Some(expectation_id)), src: old_src }, - ), - // Keep `ForceWarn` level but drop the expectation - (Level::ForceWarn(_), _) => { - self.insert(id, LevelAndSource { level: Level::ForceWarn(None), src: old_src }) + (Level::ForceWarn, Level::Expect) => { + self.insert(id, LevelAndSource { level: Level::ForceWarn, lint_id, src: old_src }) } + // Keep `ForceWarn` level but drop the expectation + (Level::ForceWarn, _) => self.insert( + id, + LevelAndSource { level: Level::ForceWarn, lint_id: None, src: old_src }, + ), // Set the lint level as normal - _ => self.insert(id, LevelAndSource { level, src }), + _ => self.insert(id, LevelAndSource { level, lint_id, src }), }; } @@ -718,7 +709,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if attr.has_name(sym::automatically_derived) { self.insert( LintId::of(SINGLE_USE_LIFETIMES), - LevelAndSource { level: Level::Allow, src: LintLevelSource::Default }, + LevelAndSource { + level: Level::Allow, + lint_id: None, + src: LintLevelSource::Default, + }, ); continue; } @@ -731,16 +726,20 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { { self.insert( LintId::of(MISSING_DOCS), - LevelAndSource { level: Level::Allow, src: LintLevelSource::Default }, + LevelAndSource { + level: Level::Allow, + lint_id: None, + src: LintLevelSource::Default, + }, ); continue; } - let level = match Level::from_attr(attr) { + let (level, lint_id) = match Level::from_attr(attr) { None => continue, // This is the only lint level with a `LintExpectationId` that can be created from // an attribute. - Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => { + Some((Level::Expect, Some(unstable_id))) if let Some(hir_id) = source_hir_id => { let LintExpectationId::Unstable { lint_index: None, attr_id: _ } = unstable_id else { bug!("stable id Level::from_attr") @@ -752,9 +751,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { lint_index: None, }; - Level::Expect(stable_id) + (Level::Expect, Some(stable_id)) } - Some(lvl) => lvl, + Some((lvl, id)) => (lvl, id), }; let Some(mut metas) = attr.meta_item_list() else { continue }; @@ -802,13 +801,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } for (lint_index, li) in metas.iter_mut().enumerate() { - let level = match level { - Level::Expect(mut id) => { - id.set_lint_index(Some(lint_index as u16)); - Level::Expect(id) - } - level => level, - }; + let mut lint_id = lint_id; + if let Some(id) = &mut lint_id { + id.set_lint_index(Some(lint_index as u16)); + } let sp = li.span(); let meta_item = match li { @@ -940,7 +936,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let src = LintLevelSource::Node { name, span: sp, reason }; for &id in ids { if self.check_gated_lint(id, sp, false) { - self.insert_spec(id, LevelAndSource { level, src }); + self.insert_spec(id, LevelAndSource { level, lint_id, src }); } } @@ -949,7 +945,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // overriding the lint level but instead add an expectation that can't be // fulfilled. The lint message will include an explanation, that the // `unfulfilled_lint_expectations` lint can't be expected. - if let Level::Expect(expect_id) = level { + if let (Level::Expect, Some(expect_id)) = (level, lint_id) { // The `unfulfilled_lint_expectations` lint is not part of any lint // groups. Therefore. we only need to check the slice if it contains a // single lint. @@ -971,7 +967,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } if self.lint_added_lints && !is_crate_node { - for (id, &LevelAndSource { level, ref src }) in self.current_specs().iter() { + for (id, &LevelAndSource { level, ref src, .. }) in self.current_specs().iter() { if !id.lint.crate_level_only { continue; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 46b4b1d43838..9ea9f9cdb922 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -199,9 +199,9 @@ pub enum Level { /// /// See RFC 2383. /// - /// The [`LintExpectationId`] is used to later link a lint emission to the actual + /// Requires a [`LintExpectationId`] to later link a lint emission to the actual /// expectation. It can be ignored in most cases. - Expect(LintExpectationId), + Expect, /// The `warn` level will produce a warning if the lint was violated, however the /// compiler will continue with its execution. Warn, @@ -209,9 +209,9 @@ pub enum Level { /// to ensure that a lint can't be suppressed. This lint level can currently only be set /// via the console and is therefore session specific. /// - /// The [`LintExpectationId`] is intended to fulfill expectations marked via the + /// Requires a [`LintExpectationId`] to fulfill expectations marked via the /// `#[expect]` attribute, that will still be suppressed due to the level. - ForceWarn(Option), + ForceWarn, /// The `deny` level will produce an error and stop further execution after the lint /// pass is complete. Deny, @@ -225,9 +225,9 @@ impl Level { pub fn as_str(self) -> &'static str { match self { Level::Allow => "allow", - Level::Expect(_) => "expect", + Level::Expect => "expect", Level::Warn => "warn", - Level::ForceWarn(_) => "force-warn", + Level::ForceWarn => "force-warn", Level::Deny => "deny", Level::Forbid => "forbid", } @@ -246,24 +246,30 @@ impl Level { } /// Converts an `Attribute` to a level. - pub fn from_attr(attr: &impl AttributeExt) -> Option { + pub fn from_attr(attr: &impl AttributeExt) -> Option<(Self, Option)> { Self::from_symbol(attr.name_or_empty(), || Some(attr.id())) } /// Converts a `Symbol` to a level. - pub fn from_symbol(s: Symbol, id: impl FnOnce() -> Option) -> Option { + pub fn from_symbol( + s: Symbol, + id: impl FnOnce() -> Option, + ) -> Option<(Self, Option)> { match s { - sym::allow => Some(Level::Allow), + sym::allow => Some((Level::Allow, None)), sym::expect => { if let Some(attr_id) = id() { - Some(Level::Expect(LintExpectationId::Unstable { attr_id, lint_index: None })) + Some(( + Level::Expect, + Some(LintExpectationId::Unstable { attr_id, lint_index: None }), + )) } else { None } } - sym::warn => Some(Level::Warn), - sym::deny => Some(Level::Deny), - sym::forbid => Some(Level::Forbid), + sym::warn => Some((Level::Warn, None)), + sym::deny => Some((Level::Deny, None)), + sym::forbid => Some((Level::Forbid, None)), _ => None, } } @@ -274,8 +280,8 @@ impl Level { Level::Deny => "-D", Level::Forbid => "-F", Level::Allow => "-A", - Level::ForceWarn(_) => "--force-warn", - Level::Expect(_) => { + Level::ForceWarn => "--force-warn", + Level::Expect => { unreachable!("the expect level does not have a commandline flag") } } @@ -283,17 +289,10 @@ impl Level { pub fn is_error(self) -> bool { match self { - Level::Allow | Level::Expect(_) | Level::Warn | Level::ForceWarn(_) => false, + Level::Allow | Level::Expect | Level::Warn | Level::ForceWarn => false, Level::Deny | Level::Forbid => true, } } - - pub fn get_expectation_id(&self) -> Option { - match self { - Level::Expect(id) | Level::ForceWarn(Some(id)) => Some(*id), - _ => None, - } - } } /// Specification of a single lint. diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 363acb4f33e3..d5a408fdfa6a 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -55,6 +55,7 @@ impl LintLevelSource { #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] pub struct LevelAndSource { pub level: Level, + pub lint_id: Option, pub src: LintLevelSource, } @@ -73,14 +74,18 @@ pub struct ShallowLintLevelMap { /// /// The return of this function is suitable for diagnostics. pub fn reveal_actual_level( - level: Option, + level: Option<(Level, Option)>, src: &mut LintLevelSource, sess: &Session, lint: LintId, - probe_for_lint_level: impl FnOnce(LintId) -> (Option, LintLevelSource), -) -> Level { + probe_for_lint_level: impl FnOnce( + LintId, + ) + -> (Option<(Level, Option)>, LintLevelSource), +) -> (Level, Option) { // If `level` is none then we actually assume the default level for this lint. - let mut level = level.unwrap_or_else(|| lint.lint.default_level(sess.edition())); + let (mut level, mut lint_id) = + level.unwrap_or_else(|| (lint.lint.default_level(sess.edition()), None)); // If we're about to issue a warning, check at the last minute for any // directives against the warnings "lint". If, for example, there's an @@ -92,16 +97,17 @@ pub fn reveal_actual_level( // future compatibility warning. if level == Level::Warn && lint != LintId::of(FORBIDDEN_LINT_GROUPS) { let (warnings_level, warnings_src) = probe_for_lint_level(LintId::of(builtin::WARNINGS)); - if let Some(configured_warning_level) = warnings_level { + if let Some((configured_warning_level, configured_lint_id)) = warnings_level { if configured_warning_level != Level::Warn { level = configured_warning_level; + lint_id = configured_lint_id; *src = warnings_src; } } } // Ensure that we never exceed the `--cap-lints` argument unless the source is a --force-warn - level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src { + level = if let LintLevelSource::CommandLine(_, Level::ForceWarn) = src { level } else { cmp::min(level, sess.opts.lint_cap.unwrap_or(Level::Forbid)) @@ -112,7 +118,7 @@ pub fn reveal_actual_level( level = cmp::min(*driver_level, level); } - level + (level, lint_id) } impl ShallowLintLevelMap { @@ -125,11 +131,11 @@ impl ShallowLintLevelMap { tcx: TyCtxt<'_>, id: LintId, start: HirId, - ) -> (Option, LintLevelSource) { + ) -> (Option<(Level, Option)>, LintLevelSource) { if let Some(map) = self.specs.get(&start.local_id) - && let Some(&LevelAndSource { level, src }) = map.get(&id) + && let Some(&LevelAndSource { level, lint_id, src }) = map.get(&id) { - return (Some(level), src); + return (Some((level, lint_id)), src); } let mut owner = start.owner; @@ -141,9 +147,9 @@ impl ShallowLintLevelMap { specs = &tcx.shallow_lint_levels_on(owner).specs; } if let Some(map) = specs.get(&parent.local_id) - && let Some(&LevelAndSource { level, src }) = map.get(&id) + && let Some(&LevelAndSource { level, lint_id, src }) = map.get(&id) { - return (Some(level), src); + return (Some((level, lint_id)), src); } } @@ -159,10 +165,10 @@ impl ShallowLintLevelMap { cur: HirId, ) -> LevelAndSource { let (level, mut src) = self.probe_for_lint_level(tcx, lint, cur); - let level = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| { + let (level, lint_id) = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| { self.probe_for_lint_level(tcx, lint, cur) }); - LevelAndSource { level, src } + LevelAndSource { level, lint_id, src } } } @@ -285,7 +291,7 @@ pub fn lint_level( span: Option, decorate: Box FnOnce(&'b mut Diag<'a, ()>)>, ) { - let LevelAndSource { level, src } = level; + let LevelAndSource { level, lint_id, src } = level; // Check for future incompatibility lints and issue a stronger warning. let future_incompatible = lint.future_incompatible; @@ -297,15 +303,15 @@ pub fn lint_level( ); // Convert lint level to error level. - let (err_level, lint_id) = match level { + let err_level = match level { Level::Allow => { if has_future_breakage { - (rustc_errors::Level::Allow, None) + rustc_errors::Level::Allow } else { return; } } - Level::Expect(expect_id) => { + Level::Expect => { // This case is special as we actually allow the lint itself in this context, but // we can't return early like in the case for `Level::Allow` because we still // need the lint diagnostic to be emitted to `rustc_error::DiagCtxtInner`. @@ -313,11 +319,11 @@ pub fn lint_level( // We can also not mark the lint expectation as fulfilled here right away, as it // can still be cancelled in the decorate function. All of this means that we simply // create a `Diag` and continue as we would for warnings. - (rustc_errors::Level::Expect, Some(expect_id)) + rustc_errors::Level::Expect } - Level::ForceWarn(expect_id) => (rustc_errors::Level::ForceWarning, expect_id), - Level::Warn => (rustc_errors::Level::Warning, None), - Level::Deny | Level::Forbid => (rustc_errors::Level::Error, None), + Level::ForceWarn => rustc_errors::Level::ForceWarning, + Level::Warn => rustc_errors::Level::Warning, + Level::Deny | Level::Forbid => rustc_errors::Level::Error, }; let mut err = Diag::new(sess.dcx(), err_level, ""); if let Some(span) = span { @@ -356,7 +362,7 @@ pub fn lint_level( // the compiler. It is therefore not necessary to add any information for the user. // This will therefore directly call the decorate function which will in turn emit // the diagnostic. - if let Level::Expect(_) = level { + if let Level::Expect = level { decorate(&mut err); err.emit(); return; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index b588aacf6756..54168758d0b9 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -19,8 +19,8 @@ use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_session::lint; use rustc_session::lint::builtin::DEAD_CODE; +use rustc_session::lint::{self, LintExpectationId}; use rustc_span::{Symbol, sym}; use crate::errors::{ @@ -697,7 +697,7 @@ fn has_allow_dead_code_or_lang_attr( fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { let hir_id = tcx.local_def_id_to_hir_id(def_id); let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).level; - matches!(lint_level, lint::Allow | lint::Expect(_)) + matches!(lint_level, lint::Allow | lint::Expect) } fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { @@ -915,7 +915,7 @@ fn live_symbols_and_ignored_derived_traits( struct DeadItem { def_id: LocalDefId, name: Symbol, - level: lint::Level, + level: (lint::Level, Option), } struct DeadVisitor<'tcx> { @@ -959,9 +959,10 @@ impl<'tcx> DeadVisitor<'tcx> { ShouldWarnAboutField::Yes } - fn def_lint_level(&self, id: LocalDefId) -> lint::Level { + fn def_lint_level(&self, id: LocalDefId) -> (lint::Level, Option) { let hir_id = self.tcx.local_def_id_to_hir_id(id); - self.tcx.lint_level_at_node(DEAD_CODE, hir_id).level + let level = self.tcx.lint_level_at_node(DEAD_CODE, hir_id); + (level.level, level.lint_id) } // # Panics diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 950a13536bff..3da744dc8c02 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -89,7 +89,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( // arm. This no longer makes sense so we warn users, to avoid silently breaking their // usage of the lint. for arm in arms { - let LevelAndSource { level, src } = + let LevelAndSource { level, src, .. } = rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data); if !matches!(level, rustc_session::lint::Level::Allow) { let decorator = NonExhaustiveOmittedPatternLintOnArm { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 1b01efda2a9e..1f18950feac3 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1700,7 +1700,7 @@ pub fn get_cmd_lint_options( let mut lint_opts_with_position = vec![]; let mut describe_lints = false; - for level in [lint::Allow, lint::Warn, lint::ForceWarn(None), lint::Deny, lint::Forbid] { + for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] { for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { if lint_name == "help" { describe_lints = true; diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 7e22cf4c4103..761282bde7c3 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -216,7 +216,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { let has_doc_example = tests.found_tests != 0; let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap(); - let LevelAndSource { level, src } = + let LevelAndSource { level, src, .. } = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); // In case we have: diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 0dd1eb1d40fd..70dbb944d4c0 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -107,7 +107,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - { return false; } - let LevelAndSource { level, src } = cx.tcx.lint_level_at_node( + let LevelAndSource { level, src, .. } = cx.tcx.lint_level_at_node( crate::lint::MISSING_DOC_CODE_EXAMPLES, cx.tcx.local_def_id_to_hir_id(def_id), ); diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index 243c99a19ce1..ce551a64d998 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Crate, Inline, Item, ItemKind, ModKind}; use rustc_errors::MultiSpan; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; +use rustc_middle::lint::LevelAndSource; use rustc_session::impl_lint_pass; use rustc_span::{FileName, Span}; use std::collections::BTreeMap; @@ -45,11 +46,10 @@ declare_clippy_lint! { "file loaded as module multiple times" } -#[derive(PartialOrd, Ord, PartialEq, Eq)] struct Modules { local_path: PathBuf, spans: Vec, - lint_levels: Vec, + lint_levels: Vec, } #[derive(Default)] @@ -95,11 +95,11 @@ impl EarlyLintPass for DuplicateMod { .iter() .zip(lint_levels) .filter_map(|(span, lvl)| { - if let Some(id) = lvl.get_expectation_id() { + if let Some(id) = lvl.lint_id { cx.fulfill_expectation(id); } - (!matches!(lvl, Level::Allow | Level::Expect(_))).then_some(*span) + (!matches!(lvl.level, Level::Allow | Level::Expect)).then_some(*span) }) .collect(); diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index cc3d972f017b..3fe3cd67e167 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -408,9 +408,9 @@ mod zombie_processes; use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation}; use clippy_utils::macros::FormatArgsStorage; -use utils::attr_collector::{AttrCollector, AttrStorage}; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; +use utils::attr_collector::{AttrCollector, AttrStorage}; /// Register all pre expansion lints /// diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs index c6e6e782f9d4..6a79cae32a59 100644 --- a/src/tools/clippy/clippy_lints/src/raw_strings.rs +++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs @@ -138,7 +138,7 @@ impl RawStrings { ); }, ); - if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS), rustc_lint::Allow) { + if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS).level, rustc_lint::Allow) { return; } } diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 4cb73df8b488..d8e8ead29128 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -404,7 +404,7 @@ fn check_final_expr<'tcx>( match cx.tcx.hir_attrs(expr.hir_id) { [] => {}, [attr] => { - if matches!(Level::from_attr(attr), Some(Level::Expect(_))) + if matches!(Level::from_attr(attr), Some((Level::Expect, _))) && let metas = attr.meta_item_list() && let Some(lst) = metas && let [MetaItemInner::MetaItem(meta_item), ..] = lst.as_slice() diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index b4c5b85dcabc..6d2c2a2d692e 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1977,14 +1977,14 @@ pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl I let mut suppress_lint = false; for id in ids { - let LevelAndSource { level, .. } = cx.tcx.lint_level_at_node(lint, id); - if let Some(expectation) = level.get_expectation_id() { + let LevelAndSource { level, lint_id, .. } = cx.tcx.lint_level_at_node(lint, id); + if let Some(expectation) = lint_id { cx.fulfill_expectation(expectation); } match level { - Level::Allow | Level::Expect(_) => suppress_lint = true, - Level::Warn | Level::ForceWarn(_) | Level::Deny | Level::Forbid => {}, + Level::Allow | Level::Expect => suppress_lint = true, + Level::Warn | Level::ForceWarn | Level::Deny | Level::Forbid => {}, } } From 0795b3de9b36bf209af8206cf4c5b88c4ff63cf4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 17 Mar 2025 12:23:53 +0000 Subject: [PATCH 108/176] Upvars HirIds always have the same owner, thus just use an ItemLocalId --- compiler/rustc_mir_build/src/builder/expr/as_place.rs | 2 +- compiler/rustc_mir_build/src/builder/mod.rs | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index 90e27c85f749..fbe530811567 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -159,7 +159,7 @@ fn find_capture_matching_projections<'a, 'tcx>( ) -> Option<(usize, &'a Capture<'tcx>)> { let hir_projections = convert_to_hir_projections_and_truncate_for_capture(projections); - upvars.get_by_key_enumerated(var_hir_id.0).find(|(_, capture)| { + upvars.get_by_key_enumerated(var_hir_id.0.local_id).find(|(_, capture)| { let possible_ancestor_proj_kinds: Vec<_> = capture.captured_place.place.projections.iter().map(|proj| proj.kind).collect(); is_ancestor_or_same_capture(&possible_ancestor_proj_kinds, &hir_projections) diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index bcc2a4674ead..8ca9ab58e457 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -13,7 +13,7 @@ use rustc_data_structures::sorted_map::SortedIndexMultiMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Node}; +use rustc_hir::{self as hir, BindingMode, ByRef, HirId, ItemLocalId, Node}; use rustc_index::bit_set::GrowableBitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; @@ -221,7 +221,7 @@ struct Builder<'a, 'tcx> { coverage_info: Option, } -type CaptureMap<'tcx> = SortedIndexMultiMap>; +type CaptureMap<'tcx> = SortedIndexMultiMap>; #[derive(Debug)] struct Capture<'tcx> { @@ -853,6 +853,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let capture_tys = upvar_args.upvar_tys(); let tcx = self.tcx; + let mut upvar_owner = None; self.upvars = tcx .closure_captures(self.def_id) .iter() @@ -866,6 +867,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, _ => bug!("Expected an upvar"), }; + let upvar_base = upvar_owner.get_or_insert(var_id.owner); + assert_eq!(*upvar_base, var_id.owner); + let var_id = var_id.local_id; let mutability = captured_place.mutability; From 5a4e7eb04012d7e1faee52b074c1a2e865760851 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 17 Mar 2025 14:38:13 +0000 Subject: [PATCH 109/176] impl !PartialOrd for UpvarMigrationInfo --- compiler/rustc_hir_typeck/src/upvar.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 56ba2a23bfb3..8ab71e5220bb 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Intermediate format to store the hir_id pointing to the use that resulted in the /// corresponding place being captured and a String which contains the captured value's /// name (i.e: a.b.c) -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] enum UpvarMigrationInfo { /// We previously captured all of `x`, but now we capture some sub-path. CapturingPrecise { source_expr: Option, var_name: String }, @@ -1396,14 +1396,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { FxIndexSet::default() }; - // Combine all the captures responsible for needing migrations into one HashSet + // Combine all the captures responsible for needing migrations into one IndexSet let mut capture_diagnostic = drop_reorder_diagnostic.clone(); for key in auto_trait_diagnostic.keys() { capture_diagnostic.insert(key.clone()); } let mut capture_diagnostic = capture_diagnostic.into_iter().collect::>(); - capture_diagnostic.sort(); + capture_diagnostic.sort_by_cached_key(|info| match info { + UpvarMigrationInfo::CapturingPrecise { source_expr: _, var_name } => { + (0, Some(var_name.clone())) + } + UpvarMigrationInfo::CapturingNothing { use_span: _ } => (1, None), + }); for captures_info in capture_diagnostic { // Get the auto trait reasons of why migration is needed because of that capture, if there are any let capture_trait_reasons = From 57c4ab7ff50a0b3c6003a0563bc13925733c0f88 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 17 Mar 2025 12:23:53 +0000 Subject: [PATCH 110/176] impl !PartialOrd for HirId --- compiler/rustc_hir/src/hir_id.rs | 22 +++-------- compiler/rustc_hir/src/lib.rs | 1 + compiler/rustc_lint_defs/src/lib.rs | 12 +++--- compiler/rustc_passes/src/dead.rs | 3 +- .../clippy/clippy_lints/src/macro_use.rs | 38 ++++++++++++++----- 5 files changed, 44 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 3fa06620ea8d..b48a081d3714 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -83,6 +83,12 @@ pub struct HirId { pub local_id: ItemLocalId, } +// To ensure correctness of incremental compilation, +// `HirId` must not implement `Ord` or `PartialOrd`. +// See https://github.com/rust-lang/rust/issues/90317. +impl !Ord for HirId {} +impl !PartialOrd for HirId {} + impl Debug for HirId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10) @@ -116,10 +122,6 @@ impl HirId { pub fn make_owner(owner: LocalDefId) -> Self { Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::ZERO } } - - pub fn index(self) -> (usize, usize) { - (rustc_index::Idx::index(self.owner.def_id), rustc_index::Idx::index(self.local_id)) - } } impl fmt::Display for HirId { @@ -128,18 +130,6 @@ impl fmt::Display for HirId { } } -impl Ord for HirId { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - (self.index()).cmp(&(other.index())) - } -} - -impl PartialOrd for HirId { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - rustc_data_structures::define_stable_id_collections!(HirIdMap, HirIdSet, HirIdMapEntry, HirId); rustc_data_structures::define_id_collections!( ItemLocalMap, diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 4a839d405718..6bc0f797cca5 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -11,6 +11,7 @@ #![feature(debug_closure_helpers)] #![feature(exhaustive_patterns)] #![feature(let_chains)] +#![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 9ea9f9cdb922..7fdbae3a59d7 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -8,7 +8,8 @@ use rustc_data_structures::stable_hasher::{ }; use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_hir::def::Namespace; -use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind}; +use rustc_hir::def_id::DefPathHash; +use rustc_hir::{HashStableContext, HirId, ItemLocalId, MissingLifetimeKind}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; pub use rustc_span::edition::Edition; use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, sym}; @@ -102,7 +103,7 @@ pub enum Applicability { /// The index values have a type of `u16` to reduce the size of the `LintExpectationId`. /// It's reasonable to assume that no user will define 2^16 attributes on one node or /// have that amount of lints listed. `u16` values should therefore suffice. -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, Encodable, Decodable)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Encodable, Decodable)] pub enum LintExpectationId { /// Used for lints emitted during the `EarlyLintPass`. This id is not /// hash stable and should not be cached. @@ -156,13 +157,14 @@ impl HashStable for LintExpectationId { } impl ToStableHashKey for LintExpectationId { - type KeyType = (HirId, u16, u16); + type KeyType = (DefPathHash, ItemLocalId, u16, u16); #[inline] - fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { + fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType { match self { LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { - (*hir_id, *attr_index, *lint_index) + let (def_path_hash, lint_idx) = hir_id.to_stable_hash_key(hcx); + (def_path_hash, lint_idx, *attr_index, *lint_index) } _ => { unreachable!("HashStable should only be called for a filled `LintExpectationId`") diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 54168758d0b9..0060e726a8e0 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -1130,7 +1130,8 @@ impl<'tcx> DeadVisitor<'tcx> { if dead_codes.is_empty() { return; } - dead_codes.sort_by_key(|v| v.level); + // FIXME: `dead_codes` should probably be morally equivalent to `IndexMap<(Level, LintExpectationId), (DefId, Symbol)>` + dead_codes.sort_by_key(|v| v.level.0); for group in dead_codes.chunk_by(|a, b| a.level == b.level) { self.lint_at_single_level(&group, participle, Some(def_id), report_on); } diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index b712b351d063..98ad1f6a160d 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -153,9 +153,15 @@ impl LateLintPass<'_> for MacroUseImports { [] | [_] => return, [root, item] => { if !check_dup.contains(&(*item).to_string()) { - used.entry(((*root).to_string(), span, hir_id)) - .or_insert_with(Vec::new) - .push((*item).to_string()); + used.entry(( + (*root).to_string(), + span, + hir_id.local_id, + cx.tcx.def_path_hash(hir_id.owner.def_id.into()), + )) + .or_insert_with(|| (vec![], hir_id)) + .0 + .push((*item).to_string()); check_dup.push((*item).to_string()); } }, @@ -171,15 +177,27 @@ impl LateLintPass<'_> for MacroUseImports { } }) .collect::>(); - used.entry(((*root).to_string(), span, hir_id)) - .or_insert_with(Vec::new) - .push(filtered.join("::")); + used.entry(( + (*root).to_string(), + span, + hir_id.local_id, + cx.tcx.def_path_hash(hir_id.owner.def_id.into()), + )) + .or_insert_with(|| (vec![], hir_id)) + .0 + .push(filtered.join("::")); check_dup.extend(filtered); } else { let rest = rest.to_vec(); - used.entry(((*root).to_string(), span, hir_id)) - .or_insert_with(Vec::new) - .push(rest.join("::")); + used.entry(( + (*root).to_string(), + span, + hir_id.local_id, + cx.tcx.def_path_hash(hir_id.owner.def_id.into()), + )) + .or_insert_with(|| (vec![], hir_id)) + .0 + .push(rest.join("::")); check_dup.extend(rest.iter().map(ToString::to_string)); } }, @@ -190,7 +208,7 @@ impl LateLintPass<'_> for MacroUseImports { // If mac_refs is not empty we have encountered an import we could not handle // such as `std::prelude::v1::foo` or some other macro that expands to an import. if self.mac_refs.is_empty() { - for ((root, span, hir_id), path) in used { + for ((root, span, ..), (path, hir_id)) in used { let import = if let [single] = &path[..] { format!("{root}::{single}") } else { From 3df2acd31ba14544ddb7fb1b0e73e6235824d4a3 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 21 Mar 2025 05:09:57 +0000 Subject: [PATCH 111/176] Allow boolean literals in `check-cfg` --- compiler/rustc_ast/src/attr/mod.rs | 8 +++++++ compiler/rustc_interface/src/interface.rs | 8 +++++++ tests/ui/cfg/raw-true-false.rs | 24 +++++++------------ .../invalid-arguments.boolean.stderr | 6 ----- ...alid-arguments.boolean_after_values.stderr | 5 ++++ tests/ui/check-cfg/invalid-arguments.rs | 4 ++-- 6 files changed, 31 insertions(+), 24 deletions(-) delete mode 100644 tests/ui/check-cfg/invalid-arguments.boolean.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.boolean_after_values.stderr diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 4d613085d793..0b65246693dd 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -570,6 +570,14 @@ impl MetaItemInner { } } + /// Returns the bool if `self` is a boolean `MetaItemInner::Literal`. + pub fn boolean_literal(&self) -> Option { + match self { + MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => Some(*b), + _ => None, + } + } + /// Returns the `MetaItem` if `self` is a `MetaItemInner::MetaItem` or if it's /// `MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(_), .. })`. pub fn meta_item_or_bool(&self) -> Option<&MetaItemInner> { diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 3f87b1a547be..33b4a48b28de 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -204,6 +204,14 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch error!("`cfg()` names cannot be after values"); } names.push(ident); + } else if let Some(boolean) = arg.boolean_literal() { + if values_specified { + error!("`cfg()` names cannot be after values"); + } + names.push(rustc_span::Ident::new( + if boolean { rustc_span::kw::True } else { rustc_span::kw::False }, + arg.span(), + )); } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() { diff --git a/tests/ui/cfg/raw-true-false.rs b/tests/ui/cfg/raw-true-false.rs index 4cb8bb71c924..c92672fc144e 100644 --- a/tests/ui/cfg/raw-true-false.rs +++ b/tests/ui/cfg/raw-true-false.rs @@ -1,19 +1,11 @@ //@ check-pass -//@ compile-flags: --cfg false --check-cfg=cfg(r#false) - -#![deny(warnings)] - -#[expect(unexpected_cfgs)] -mod a { - #[cfg(r#true)] - pub fn foo() {} -} - -mod b { - #[cfg(r#false)] - pub fn bar() {} -} - +//@ revisions: r0x0 r0x1 r1x0 r1x1 +//@[r0x0] compile-flags: --cfg false --check-cfg=cfg(false) +//@[r0x1] compile-flags: --cfg false --check-cfg=cfg(r#false) +//@[r1x0] compile-flags: --cfg r#false --check-cfg=cfg(false) +//@[r1x1] compile-flags: --cfg r#false --check-cfg=cfg(r#false) +#![deny(unexpected_cfgs)] fn main() { - b::bar() + #[cfg(not(r#false))] + compile_error!(""); } diff --git a/tests/ui/check-cfg/invalid-arguments.boolean.stderr b/tests/ui/check-cfg/invalid-arguments.boolean.stderr deleted file mode 100644 index 18734de9dac0..000000000000 --- a/tests/ui/check-cfg/invalid-arguments.boolean.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: invalid `--check-cfg` argument: `cfg(true)` - | - = note: `true` is a boolean literal - = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)` - = note: visit for more details - diff --git a/tests/ui/check-cfg/invalid-arguments.boolean_after_values.stderr b/tests/ui/check-cfg/invalid-arguments.boolean_after_values.stderr new file mode 100644 index 000000000000..3aa2205d3b18 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.boolean_after_values.stderr @@ -0,0 +1,5 @@ +error: invalid `--check-cfg` argument: `cfg(values(),true)` + | + = note: `values()` cannot be specified before the names + = note: visit for more details + diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index c6b1218ce27c..229fb83c3fcc 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -2,7 +2,7 @@ // //@ check-fail //@ no-auto-check-cfg -//@ revisions: anything_else boolean +//@ revisions: anything_else boolean_after_values //@ revisions: string_for_name_1 string_for_name_2 multiple_any multiple_values //@ revisions: multiple_values_any not_empty_any not_empty_values_any //@ revisions: values_any_missing_values values_any_before_ident ident_in_values_1 @@ -11,7 +11,7 @@ //@ revisions: none_not_empty cfg_none unsafe_attr // //@ [anything_else]compile-flags: --check-cfg=anything_else(...) -//@ [boolean]compile-flags: --check-cfg=cfg(true) +//@ [boolean_after_values]compile-flags: --check-cfg=cfg(values(),true) //@ [string_for_name_1]compile-flags: --check-cfg=cfg("NOT_IDENT") //@ [string_for_name_2]compile-flags: --check-cfg=cfg(foo,"NOT_IDENT",bar) //@ [multiple_any]compile-flags: --check-cfg=cfg(any(),any()) From b310e8cd8f46aa1cb0358a6cdd63191c85fe43e4 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Thu, 3 Apr 2025 12:36:39 +0200 Subject: [PATCH 112/176] add Marco Ieni to mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index a791daa681d4..2f36588f54f1 100644 --- a/.mailmap +++ b/.mailmap @@ -412,6 +412,7 @@ Malo Jaffré Manish Goregaokar Mara Bos Marcell Pardavi +Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Marcus Klaas de Vries Margaret Meyerhofer Mark Mansi From 3e762b1897a71818ceb78707d0a734c7c3d45d70 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 3 Apr 2025 21:32:53 +1100 Subject: [PATCH 113/176] compiletest: Allow `--fail-fast` as a command-line option --- src/tools/compiletest/src/common.rs | 4 ++++ src/tools/compiletest/src/lib.rs | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 08d3c1c343e0..cee351cd8b31 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -178,6 +178,10 @@ pub struct Config { /// `true` to overwrite stderr/stdout files instead of complaining about changes in output. pub bless: bool, + /// Stop as soon as possible after any test fails. + /// May run a few more tests before stopping, due to threading. + pub fail_fast: bool, + /// The library paths required for running the compiler. pub compile_lib_path: PathBuf, diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 950566b2582a..01899c2c8a63 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -50,6 +50,12 @@ use crate::util::logv; /// some code here that inspects environment variables or even runs executables /// (e.g. when discovering debugger versions). pub fn parse_config(args: Vec) -> Config { + if env::var("RUST_TEST_NOCAPTURE").is_ok() { + eprintln!( + "WARNING: RUST_TEST_NOCAPTURE is not supported. Use the `--no-capture` flag instead." + ); + } + let mut opts = Options::new(); opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH") .reqopt("", "run-lib-path", "path to target shared libraries", "PATH") @@ -128,6 +134,7 @@ pub fn parse_config(args: Vec) -> Config { "bless", "overwrite stderr/stdout files instead of complaining about a mismatch", ) + .optflag("", "fail-fast", "stop as soon as possible after any test fails") .optflag("", "quiet", "print one character per test instead of one line") .optopt("", "color", "coloring: auto, always, never", "WHEN") .optflag("", "json", "emit json output instead of plaintext output") @@ -319,6 +326,9 @@ pub fn parse_config(args: Vec) -> Config { Config { bless: matches.opt_present("bless"), + fail_fast: matches.opt_present("fail-fast") + || env::var_os("RUSTC_TEST_FAIL_FAST").is_some(), + compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), rustc_path: opt_path(matches, "rustc-path"), @@ -603,13 +613,6 @@ pub fn run_tests(config: Arc) { } pub fn test_opts(config: &Config) -> test::TestOpts { - if env::var("RUST_TEST_NOCAPTURE").is_ok() { - eprintln!( - "WARNING: RUST_TEST_NOCAPTURE is no longer used. \ - Use the `--nocapture` flag instead." - ); - } - test::TestOpts { exclude_should_panic: false, filters: config.filters.clone(), @@ -629,7 +632,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts { options: test::Options::new(), time_options: None, force_run_in_process: false, - fail_fast: std::env::var_os("RUSTC_TEST_FAIL_FAST").is_some(), + fail_fast: config.fail_fast, } } From 581c5fbc40f9f242f75924153199759f0009e3ac Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Thu, 6 Mar 2025 20:36:44 +0300 Subject: [PATCH 114/176] Initial support for auto traits with default bounds --- compiler/rustc_hir/src/lang_items.rs | 6 + compiler/rustc_hir_analysis/src/check/mod.rs | 5 +- .../src/collect/item_bounds.rs | 9 +- .../src/collect/predicates_of.rs | 61 ++++- .../src/hir_ty_lowering/bounds.rs | 245 +++++++++++++++--- .../src/hir_ty_lowering/dyn_compatibility.rs | 12 + compiler/rustc_middle/src/ty/context.rs | 23 ++ .../src/solve/assembly/structural_traits.rs | 6 +- .../src/solve/trait_goals.rs | 42 +-- compiler/rustc_session/src/options.rs | 2 + compiler/rustc_span/src/symbol.rs | 9 + .../src/traits/select/candidate_assembly.rs | 38 ++- .../src/traits/select/mod.rs | 6 +- compiler/rustc_type_ir/src/interner.rs | 2 + .../backward-compatible-lazy-bounds-pass.rs | 25 ++ .../default_auto_traits/default-bounds.rs | 41 +++ .../default_auto_traits/default-bounds.stderr | 31 +++ .../extern-types.current.stderr | 17 ++ .../extern-types.next.stderr | 17 ++ .../default_auto_traits/extern-types.rs | 49 ++++ .../maybe-bounds-in-dyn-traits.rs | 61 +++++ .../maybe-bounds-in-dyn-traits.stderr | 23 ++ .../maybe-bounds-in-traits.rs | 115 ++++++++ .../maybe-bounds-in-traits.stderr | 71 +++++ 24 files changed, 830 insertions(+), 86 deletions(-) create mode 100644 tests/ui/traits/default_auto_traits/backward-compatible-lazy-bounds-pass.rs create mode 100644 tests/ui/traits/default_auto_traits/default-bounds.rs create mode 100644 tests/ui/traits/default_auto_traits/default-bounds.stderr create mode 100644 tests/ui/traits/default_auto_traits/extern-types.current.stderr create mode 100644 tests/ui/traits/default_auto_traits/extern-types.next.stderr create mode 100644 tests/ui/traits/default_auto_traits/extern-types.rs create mode 100644 tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs create mode 100644 tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr create mode 100644 tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs create mode 100644 tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index e625514e9ffa..90fab01ba2d4 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -433,6 +433,12 @@ language_item_table! { // Experimental lang items for implementing contract pre- and post-condition checking. ContractBuildCheckEnsures, sym::contract_build_check_ensures, contract_build_check_ensures_fn, Target::Fn, GenericRequirement::None; ContractCheckRequires, sym::contract_check_requires, contract_check_requires_fn, Target::Fn, GenericRequirement::None; + + // Experimental lang items for `MCP: Low level components for async drop`(https://github.com/rust-lang/compiler-team/issues/727) + DefaultTrait4, sym::default_trait4, default_trait4_trait, Target::Trait, GenericRequirement::None; + DefaultTrait3, sym::default_trait3, default_trait3_trait, Target::Trait, GenericRequirement::None; + DefaultTrait2, sym::default_trait2, default_trait2_trait, Target::Trait, GenericRequirement::None; + DefaultTrait1, sym::default_trait1, default_trait1_trait, Target::Trait, GenericRequirement::None; } /// The requirement imposed on the generics of a lang item diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index d8ae42145275..3e76d1027256 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -341,9 +341,8 @@ fn bounds_from_generic_predicates<'tcx>( ty::ClauseKind::Trait(trait_predicate) => { let entry = types.entry(trait_predicate.self_ty()).or_default(); let def_id = trait_predicate.def_id(); - if Some(def_id) != tcx.lang_items().sized_trait() { - // Type params are `Sized` by default, do not add that restriction to the list - // if it is a positive requirement. + if !tcx.is_default_trait(def_id) { + // Do not add that restriction to the list if it is a positive requirement. entry.push(trait_predicate.def_id()); } } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 6e07f0ff53c3..279b1e82a716 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -38,13 +38,13 @@ fn associated_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, assoc_item_def_id); let mut bounds = Vec::new(); icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); - // Associated types are implicitly sized unless a `?Sized` bound is found + // Implicit bounds are added to associated types unless a `?Trait` bound is found match filter { PredicateFilter::All | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { - icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); + icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span); } // `ConstIfConst` is only interested in `~const` bounds. PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} @@ -327,14 +327,13 @@ fn opaque_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = Vec::new(); icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); - // Opaque types are implicitly sized unless a `?Sized` bound is found + // Implicit bounds are added to opaque types unless a `?Trait` bound is found match filter { PredicateFilter::All | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { - // Associated types are implicitly sized unless a `?Sized` bound is found - icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); + icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span); } //`ConstIfConst` is only interested in `~const` bounds. PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 4bd89861a9e5..c83389d937e7 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -165,12 +165,42 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen ItemKind::Trait(_, _, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, _, self_bounds) => { - is_trait = Some(self_bounds); + is_trait = Some((self_bounds, item.span)); } _ => {} } }; + if let Node::TraitItem(item) = node { + let parent = tcx.local_parent(item.hir_id().owner.def_id); + let Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else { + unreachable!(); + }; + + let (trait_generics, trait_bounds) = match parent_trait.kind { + hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits), + hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), + _ => unreachable!(), + }; + + // Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if + // they are not added as super trait bounds to the trait itself. See comment on + // `requires_default_supertraits` for more details. + if !icx.lowerer().requires_default_supertraits(trait_bounds, trait_generics) { + let mut bounds = Vec::new(); + let self_ty_where_predicates = (parent, item.generics.predicates); + icx.lowerer().add_default_traits_with_filter( + &mut bounds, + tcx.types.self_param, + &[], + Some(self_ty_where_predicates), + item.span, + |tr| tr != hir::LangItem::Sized, + ); + predicates.extend(bounds); + } + } + let generics = tcx.generics_of(def_id); // Below we'll consider the bounds on the type parameters (including `Self`) @@ -181,11 +211,18 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let mut bounds = Vec::new(); icx.lowerer().lower_bounds( tcx.types.self_param, - self_bounds, + self_bounds.0, &mut bounds, ty::List::empty(), PredicateFilter::All, ); + icx.lowerer().add_default_super_traits( + def_id, + &mut bounds, + self_bounds.0, + hir_generics, + self_bounds.1, + ); predicates.extend(bounds); } @@ -210,8 +247,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen GenericParamKind::Type { .. } => { let param_ty = icx.lowerer().lower_ty_param(param.hir_id); let mut bounds = Vec::new(); - // Params are implicitly sized unless a `?Sized` bound is found - icx.lowerer().add_sized_bound( + // Implicit bounds are added to type params unless a `?Trait` bound is found + icx.lowerer().add_default_traits( &mut bounds, param_ty, &[], @@ -625,6 +662,22 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let self_param_ty = tcx.types.self_param; let mut bounds = Vec::new(); icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter); + match filter { + PredicateFilter::All + | PredicateFilter::SelfOnly + | PredicateFilter::SelfTraitThatDefines(_) + | PredicateFilter::SelfAndAssociatedTypeBounds => { + icx.lowerer().add_default_super_traits( + trait_def_id, + &mut bounds, + superbounds, + generics, + item.span, + ); + } + //`ConstIfConst` is only interested in `~const` bounds. + PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} + } let where_bounds_that_match = icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index f0dffd780bcc..dede5bd0a385 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -4,9 +4,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::{AmbigArg, HirId}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -24,25 +24,190 @@ use crate::hir_ty_lowering::{ }; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Add a `Sized` bound to the `bounds` if appropriate. - /// - /// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`. - pub(crate) fn add_sized_bound( + pub(crate) fn add_default_traits( &self, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, - hir_bounds: &'tcx [hir::GenericBound<'tcx>], + hir_bounds: &[hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, span: Span, ) { + self.add_default_traits_with_filter( + bounds, + self_ty, + hir_bounds, + self_ty_where_predicates, + span, + |_| true, + ); + } + + /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds + /// or associative items. + /// + /// To keep backward compatibility with existing code, `experimental_default_bounds` bounds + /// should be added everywhere, including super bounds. However this causes a huge performance + /// costs. For optimization purposes instead of adding default supertraits, bounds + /// are added to the associative items: + /// + /// ```ignore(illustrative) + /// // Default bounds are generated in the following way: + /// trait Trait { + /// fn foo(&self) where Self: Leak {} + /// } + /// + /// // instead of this: + /// trait Trait: Leak { + /// fn foo(&self) {} + /// } + /// ``` + /// It is not always possible to do this because of backward compatibility: + /// + /// ```ignore(illustrative) + /// pub trait Trait {} + /// pub trait Trait1 : Trait {} + /// //~^ ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait` + /// ``` + /// + /// or: + /// + /// ```ignore(illustrative) + /// trait Trait { + /// type Type where Self: Sized; + /// } + /// trait Trait2 : Trait {} + /// //~^ ERROR: `DefaultAutoTrait` required for `Trait2`, by implicit `Self: DefaultAutoTrait` in `Trait::Type` + /// ``` + /// + /// Therefore, `experimental_default_bounds` are still being added to supertraits if + /// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header. + pub(crate) fn requires_default_supertraits( + &self, + hir_bounds: &'tcx [hir::GenericBound<'tcx>], + hir_generics: &'tcx hir::Generics<'tcx>, + ) -> bool { + struct TraitInfoCollector; + + impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector { + type Result = ControlFlow<()>; + + fn visit_assoc_item_constraint( + &mut self, + _constraint: &'tcx hir::AssocItemConstraint<'tcx>, + ) -> Self::Result { + ControlFlow::Break(()) + } + + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { + if matches!( + &t.kind, + hir::TyKind::Path(hir::QPath::Resolved( + _, + hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. }, + )) + ) { + return ControlFlow::Break(()); + } + hir::intravisit::walk_ty(self, t) + } + } + + let mut found = false; + for bound in hir_bounds { + found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break(); + } + found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break(); + found + } + + /// Lazily sets `experimental_default_bounds` to true on trait super bounds. + /// See `requires_default_supertraits` for more information. + pub(crate) fn add_default_super_traits( + &self, + trait_def_id: LocalDefId, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + hir_bounds: &'tcx [hir::GenericBound<'tcx>], + hir_generics: &'tcx hir::Generics<'tcx>, + span: Span, + ) { + assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias)); + if self.requires_default_supertraits(hir_bounds, hir_generics) { + let self_ty_where_predicates = (trait_def_id, hir_generics.predicates); + self.add_default_traits_with_filter( + bounds, + self.tcx().types.self_param, + hir_bounds, + Some(self_ty_where_predicates), + span, + |default_trait| default_trait != hir::LangItem::Sized, + ); + } + } + + pub(crate) fn add_default_traits_with_filter( + &self, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + self_ty: Ty<'tcx>, + hir_bounds: &[hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + span: Span, + f: impl Fn(hir::LangItem) -> bool, + ) { + self.tcx().default_traits().iter().filter(|&&default_trait| f(default_trait)).for_each( + |default_trait| { + self.add_default_trait( + *default_trait, + bounds, + self_ty, + hir_bounds, + self_ty_where_predicates, + span, + ); + }, + ); + } + + /// Add a `Sized` or `experimental_default_bounds` bounds to the `bounds` if appropriate. + /// + /// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`. + pub(crate) fn add_default_trait( + &self, + trait_: hir::LangItem, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + self_ty: Ty<'tcx>, + hir_bounds: &[hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + span: Span, + ) { + let trait_id = self.tcx().lang_items().get(trait_); + if let Some(trait_id) = trait_id + && self.do_not_provide_default_trait_bound( + trait_id, + hir_bounds, + self_ty_where_predicates, + ) + { + // There was no `?Trait` or `!Trait` bound; + // add `Trait` if it's available. + let trait_ref = ty::TraitRef::new(self.tcx(), trait_id, [self_ty]); + // Preferable to put this obligation first, since we report better errors for sized ambiguity. + bounds.insert(0, (trait_ref.upcast(self.tcx()), span)); + } + } + + fn do_not_provide_default_trait_bound<'a>( + &self, + trait_def_id: DefId, + hir_bounds: &'a [hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + ) -> bool { let tcx = self.tcx(); - let sized_def_id = tcx.lang_items().sized_trait(); - let mut seen_negative_sized_bound = false; - let mut seen_positive_sized_bound = false; + let mut seen_negative_bound = false; + let mut seen_positive_bound = false; // Try to find an unbound in bounds. let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); - let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| { + let mut search_bounds = |hir_bounds: &'a [hir::GenericBound<'tcx>]| { for hir_bound in hir_bounds { let hir::GenericBound::Trait(ptr) = hir_bound else { continue; @@ -50,17 +215,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match ptr.modifiers.polarity { hir::BoundPolarity::Maybe(_) => unbounds.push(ptr), hir::BoundPolarity::Negative(_) => { - if let Some(sized_def_id) = sized_def_id - && ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) - { - seen_negative_sized_bound = true; + if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) { + seen_negative_bound = true; } } hir::BoundPolarity::Positive => { - if let Some(sized_def_id) = sized_def_id - && ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) - { - seen_positive_sized_bound = true; + if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) { + seen_positive_bound = true; } } } @@ -95,32 +256,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; } - let mut seen_sized_unbound = false; + let mut seen_unbound = false; for unbound in unbounds { - if let Some(sized_def_id) = sized_def_id - && unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) - { - seen_sized_unbound = true; - continue; + let unbound_def_id = unbound.trait_ref.trait_def_id(); + if unbound_def_id == Some(trait_def_id) { + seen_unbound = true; + } + let emit_relax_err = || { + let unbound_traits = + match self.tcx().sess.opts.unstable_opts.experimental_default_bounds { + true => "`?Sized` and `experimental_default_bounds`", + false => "`?Sized`", + }; + // There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`. + tcx.dcx().span_err( + unbound.span, + format!( + "relaxing a default bound only does something for {}; \ + all other traits are not bound by default", + unbound_traits + ), + ); + }; + match unbound_def_id { + Some(def_id) if !tcx.is_default_trait(def_id) => emit_relax_err(), + None => emit_relax_err(), + _ => {} } - // There was a `?Trait` bound, but it was not `?Sized` - self.dcx().span_err( - unbound.span, - "relaxing a default bound only does something for `?Sized`; \ - all other traits are not bound by default", - ); } - if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound { - // There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound; - // we don't need to do anything. - } else if let Some(sized_def_id) = sized_def_id { - // There was no `?Sized`, `!Sized` or explicit `Sized` bound; - // add `Sized` if it's available. - let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [self_ty]); - // Preferable to put this obligation first, since we report better errors for sized ambiguity. - bounds.insert(0, (trait_ref.upcast(tcx), span)); - } + !(seen_unbound || seen_negative_bound || seen_positive_bound) } /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 27643e715e6b..aeebe45f881f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -57,6 +57,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + let ast_bounds: Vec<_> = + hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect(); + + self.add_default_traits_with_filter( + &mut user_written_bounds, + dummy_self, + &ast_bounds, + None, + span, + |tr| tr != hir::LangItem::Sized, + ); + let (elaborated_trait_bounds, elaborated_projection_bounds) = traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied()); let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 618a65a01864..4302d66d0848 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -446,6 +446,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.is_lang_item(def_id, trait_lang_item_to_lang_item(lang_item)) } + fn is_default_trait(self, def_id: DefId) -> bool { + self.is_default_trait(def_id) + } + fn as_lang_item(self, def_id: DefId) -> Option { lang_item_to_trait_lang_item(self.lang_items().from_def_id(def_id)?) } @@ -1539,6 +1543,25 @@ impl<'tcx> TyCtxt<'tcx> { self.reserve_and_set_memory_dedup(alloc, salt) } + pub fn default_traits(self) -> &'static [rustc_hir::LangItem] { + match self.sess.opts.unstable_opts.experimental_default_bounds { + true => &[ + LangItem::Sized, + LangItem::DefaultTrait1, + LangItem::DefaultTrait2, + LangItem::DefaultTrait3, + LangItem::DefaultTrait4, + ], + false => &[LangItem::Sized], + } + } + + pub fn is_default_trait(self, def_id: DefId) -> bool { + self.default_traits() + .iter() + .any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id)) + } + /// Returns a range of the start/end indices specified with the /// `rustc_layout_scalar_valid_range` attribute. // FIXME(eddyb) this is an awkward spot for this method, maybe move it? diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index a5142de2d390..c2fb592c3f3a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -37,12 +37,16 @@ where | ty::Never | ty::Char => Ok(ty::Binder::dummy(vec![])), + // This branch is only for `experimental_default_bounds`. + // Other foreign types were rejected earlier in + // `disqualify_auto_trait_candidate_due_to_possible_impl`. + ty::Foreign(..) => Ok(ty::Binder::dummy(vec![])), + // Treat `str` like it's defined as `struct str([u8]);` ty::Str => Ok(ty::Binder::dummy(vec![Ty::new_slice(cx, Ty::new_u8(cx))])), ty::Dynamic(..) | ty::Param(..) - | ty::Foreign(..) | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Placeholder(..) | ty::Bound(..) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index b72f776e5cb4..b7ae96ec9d23 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1086,6 +1086,25 @@ where goal: Goal>, ) -> Option, NoSolution>> { let self_ty = goal.predicate.self_ty(); + let check_impls = || { + let mut disqualifying_impl = None; + self.cx().for_each_relevant_impl( + goal.predicate.def_id(), + goal.predicate.self_ty(), + |impl_def_id| { + disqualifying_impl = Some(impl_def_id); + }, + ); + if let Some(def_id) = disqualifying_impl { + trace!(?def_id, ?goal, "disqualified auto-trait implementation"); + // No need to actually consider the candidate here, + // since we do that in `consider_impl_candidate`. + return Some(Err(NoSolution)); + } else { + None + } + }; + match self_ty.kind() { // Stall int and float vars until they are resolved to a concrete // numerical type. That's because the check for impls below treats @@ -1096,6 +1115,10 @@ where Some(self.forced_ambiguity(MaybeCause::Ambiguity)) } + // Backward compatibility for default auto traits. + // Test: ui/traits/default_auto_traits/extern-types.rs + ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(), + // These types cannot be structurally decomposed into constituent // types, and therefore have no built-in auto impl. ty::Dynamic(..) @@ -1156,24 +1179,7 @@ where | ty::Never | ty::Tuple(_) | ty::Adt(_, _) - | ty::UnsafeBinder(_) => { - let mut disqualifying_impl = None; - self.cx().for_each_relevant_impl( - goal.predicate.def_id(), - goal.predicate.self_ty(), - |impl_def_id| { - disqualifying_impl = Some(impl_def_id); - }, - ); - if let Some(def_id) = disqualifying_impl { - trace!(?def_id, ?goal, "disqualified auto-trait implementation"); - // No need to actually consider the candidate here, - // since we do that in `consider_impl_candidate`. - return Some(Err(NoSolution)); - } else { - None - } - } + | ty::UnsafeBinder(_) => check_impls(), ty::Error(_) => None, } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index cd5e2c4173e7..eb513e00936c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2187,6 +2187,8 @@ options! { "Use WebAssembly error handling for wasm32-unknown-emscripten"), enforce_type_length_limit: bool = (false, parse_bool, [TRACKED], "enforce the type length limit when monomorphizing instances in codegen"), + experimental_default_bounds: bool = (false, parse_bool, [TRACKED], + "enable default bounds for experimental group of auto traits"), export_executable_symbols: bool = (false, parse_bool, [TRACKED], "export symbols from executables, as if they were dynamic libraries"), external_clangrt: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index bc853fe9079b..cbab63d981cc 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -800,6 +800,15 @@ symbols! { default_fn, default_lib_allocator, default_method_body_is_const, + // -------------------------- + // Lang items which are used only for experiments with auto traits with default bounds. + // These lang items are not actually defined in core/std. Experiment is a part of + // `MCP: Low level components for async drop`(https://github.com/rust-lang/compiler-team/issues/727) + default_trait1, + default_trait2, + default_trait3, + default_trait4, + // -------------------------- default_type_parameter_fallback, default_type_params, define_opaque, 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 d15c9afef3ab..cf6d2bc151fb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -692,6 +692,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let def_id = obligation.predicate.def_id(); + let mut check_impls = || { + // Only consider auto impls if there are no manual impls for the root of `self_ty`. + // + // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl + // for `&SomeType: Auto` exists. Due to E0321 the only crate where impls + // for `&SomeType: Auto` can be defined is the crate where `Auto` has been defined. + // + // Generally, we have to guarantee that for all `SimplifiedType`s the only crate + // which may define impls for that type is either the crate defining the type + // or the trait. This should be guaranteed by the orphan check. + let mut has_impl = false; + self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true); + if !has_impl { + candidates.vec.push(AutoImplCandidate) + } + }; + if self.tcx().trait_is_auto(def_id) { match *self_ty.kind() { ty::Dynamic(..) => { @@ -705,6 +722,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // we don't add any `..` impl. Default traits could // still be provided by a manual implementation for // this trait and type. + + // Backward compatibility for default auto traits. + // Test: ui/traits/default_auto_traits/extern-types.rs + if self.tcx().is_default_trait(def_id) { + check_impls() + } } ty::Param(..) | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) @@ -805,20 +828,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - // Only consider auto impls if there are no manual impls for the root of `self_ty`. - // - // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl - // for `&SomeType: Auto` exists. Due to E0321 the only crate where impls - // for `&SomeType: Auto` can be defined is the crate where `Auto` has been defined. - // - // Generally, we have to guarantee that for all `SimplifiedType`s the only crate - // which may define impls for that type is either the crate defining the type - // or the trait. This should be guaranteed by the orphan check. - let mut has_impl = false; - self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true); - if !has_impl { - candidates.vec.push(AutoImplCandidate) - } + check_impls(); } ty::Error(_) => { candidates.vec.push(AutoImplCandidate); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0679dbf1296a..42c598e538df 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2299,6 +2299,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::Never | ty::Char => ty::Binder::dummy(Vec::new()), + // This branch is only for `experimental_default_bounds`. + // Other foreign types were rejected earlier in + // `assemble_candidates_from_auto_impls`. + ty::Foreign(..) => ty::Binder::dummy(Vec::new()), + // FIXME(unsafe_binders): Squash the double binder for now, I guess. ty::UnsafeBinder(_) => return Err(SelectionError::Unimplemented), @@ -2308,7 +2313,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ty::Placeholder(..) | ty::Dynamic(..) | ty::Param(..) - | ty::Foreign(..) | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Bound(..) | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 8f86270d7dce..ff0d8cdd5850 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -259,6 +259,8 @@ pub trait Interner: fn is_lang_item(self, def_id: Self::DefId, lang_item: TraitSolverLangItem) -> bool; + fn is_default_trait(self, def_id: Self::DefId) -> bool; + fn as_lang_item(self, def_id: Self::DefId) -> Option; fn associated_type_def_ids(self, def_id: Self::DefId) -> impl IntoIterator; diff --git a/tests/ui/traits/default_auto_traits/backward-compatible-lazy-bounds-pass.rs b/tests/ui/traits/default_auto_traits/backward-compatible-lazy-bounds-pass.rs new file mode 100644 index 000000000000..3818456d3a67 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/backward-compatible-lazy-bounds-pass.rs @@ -0,0 +1,25 @@ +//@ check-pass +//@ compile-flags: -Zexperimental-default-bounds + +#![feature(auto_traits, lang_items, no_core, rustc_attrs, trait_alias)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "default_trait1"] +auto trait DefaultTrait1 {} + +#[lang = "default_trait2"] +auto trait DefaultTrait2 {} + +trait Trait {} +trait Trait1 : Trait {} + +trait Trait2 { + type Type; +} +trait Trait3 = Trait2; + +fn main() {} diff --git a/tests/ui/traits/default_auto_traits/default-bounds.rs b/tests/ui/traits/default_auto_traits/default-bounds.rs new file mode 100644 index 000000000000..64733a400340 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/default-bounds.rs @@ -0,0 +1,41 @@ +//@ compile-flags: -Zexperimental-default-bounds + +#![feature( + auto_traits, + lang_items, + negative_impls, + no_core, + rustc_attrs +)] +#![allow(incomplete_features)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +pub trait Copy {} + +#[lang = "default_trait1"] +auto trait Leak {} + +#[lang = "default_trait2"] +auto trait SyncDrop {} + +struct Forbidden; + +impl !Leak for Forbidden {} +impl !SyncDrop for Forbidden {} + +struct Accepted; + +fn bar(_: T) {} + +fn main() { + // checking that bounds can be added explicitly + bar(Forbidden); + //~^ ERROR the trait bound `Forbidden: Leak` is not satisfied + //~| ERROR the trait bound `Forbidden: SyncDrop` is not satisfied + bar(Accepted); +} diff --git a/tests/ui/traits/default_auto_traits/default-bounds.stderr b/tests/ui/traits/default_auto_traits/default-bounds.stderr new file mode 100644 index 000000000000..10fdcc43417d --- /dev/null +++ b/tests/ui/traits/default_auto_traits/default-bounds.stderr @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Forbidden: SyncDrop` is not satisfied + --> $DIR/default-bounds.rs:37:9 + | +LL | bar(Forbidden); + | --- ^^^^^^^^^ the trait `SyncDrop` is not implemented for `Forbidden` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/default-bounds.rs:33:8 + | +LL | fn bar(_: T) {} + | ^ required by this bound in `bar` + +error[E0277]: the trait bound `Forbidden: Leak` is not satisfied + --> $DIR/default-bounds.rs:37:9 + | +LL | bar(Forbidden); + | --- ^^^^^^^^^ the trait `Leak` is not implemented for `Forbidden` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/default-bounds.rs:33:11 + | +LL | fn bar(_: T) {} + | ^^^^ required by this bound in `bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/default_auto_traits/extern-types.current.stderr b/tests/ui/traits/default_auto_traits/extern-types.current.stderr new file mode 100644 index 000000000000..e1bd99b900f5 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/extern-types.current.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `extern_non_leak::Opaque: Leak` is not satisfied + --> $DIR/extern-types.rs:44:13 + | +LL | foo(x); + | --- ^ the trait `Leak` is not implemented for `extern_non_leak::Opaque` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/extern-types.rs:20:8 + | +LL | fn foo(_: &T) {} + | ^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/default_auto_traits/extern-types.next.stderr b/tests/ui/traits/default_auto_traits/extern-types.next.stderr new file mode 100644 index 000000000000..e1bd99b900f5 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/extern-types.next.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `extern_non_leak::Opaque: Leak` is not satisfied + --> $DIR/extern-types.rs:44:13 + | +LL | foo(x); + | --- ^ the trait `Leak` is not implemented for `extern_non_leak::Opaque` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/extern-types.rs:20:8 + | +LL | fn foo(_: &T) {} + | ^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/default_auto_traits/extern-types.rs b/tests/ui/traits/default_auto_traits/extern-types.rs new file mode 100644 index 000000000000..822d4c0637f0 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/extern-types.rs @@ -0,0 +1,49 @@ +//@ compile-flags: -Zexperimental-default-bounds +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver + +#![feature(auto_traits, extern_types, lang_items, negative_impls, no_core, rustc_attrs)] +#![allow(incomplete_features)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +pub trait Copy {} + +#[lang = "default_trait1"] +auto trait Leak {} + +// implicit T: Leak here +fn foo(_: &T) {} + +mod extern_leak { + use crate::*; + + extern "C" { + type Opaque; + } + + fn forward_extern_ty(x: &Opaque) { + // ok, extern type leak by default + crate::foo(x); + } +} + +mod extern_non_leak { + use crate::*; + + extern "C" { + type Opaque; + } + + impl !Leak for Opaque {} + fn forward_extern_ty(x: &Opaque) { + foo(x); + //~^ ERROR: the trait bound `extern_non_leak::Opaque: Leak` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs new file mode 100644 index 000000000000..49f2faba1468 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs @@ -0,0 +1,61 @@ +//@ compile-flags: -Zexperimental-default-bounds + +#![feature( + auto_traits, + lang_items, + more_maybe_bounds, + negative_impls, + no_core, + rustc_attrs +)] +#![allow(internal_features)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +pub trait Copy {} +impl<'a, T: ?Sized> Copy for &'a T {} + +#[lang = "legacy_receiver"] +trait Receiver {} +impl Receiver for &T {} + +#[lang = "unsize"] +trait Unsize {} + +#[lang = "coerce_unsized"] +trait CoerceUnsized {} +impl<'a, 'b: 'a, T: ?Sized + ?Leak + Unsize, U: ?Sized + ?Leak> CoerceUnsized<&'a U> for &'b T {} + +#[lang = "dispatch_from_dyn"] +trait DispatchFromDyn {} +impl<'a, T: ?Sized + ?Leak + Unsize, U: ?Sized + ?Leak> DispatchFromDyn<&'a U> for &'a T {} + +#[lang = "default_trait1"] +auto trait Leak {} + +struct NonLeakS; +impl !Leak for NonLeakS {} +struct LeakS; + +trait Trait { + fn leak_foo(&self) {} + fn maybe_leak_foo(&self) where Self: ?Leak {} +} + +impl Trait for NonLeakS {} +impl Trait for LeakS {} + +fn main() { + let _: &dyn Trait = &NonLeakS; + //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied + let _: &dyn Trait = &LeakS; + let _: &(dyn Trait + ?Leak) = &LeakS; + let x: &(dyn Trait + ?Leak) = &NonLeakS; + x.leak_foo(); + //~^ ERROR the trait bound `dyn Trait: Leak` is not satisfied + x.maybe_leak_foo(); +} diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr new file mode 100644 index 000000000000..b7ffb66e60bf --- /dev/null +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied + --> $DIR/maybe-bounds-in-dyn-traits.rs:53:25 + | +LL | let _: &dyn Trait = &NonLeakS; + | ^^^^^^^^^ the trait `Leak` is not implemented for `NonLeakS` + | + = note: required for the cast from `&NonLeakS` to `&dyn Trait + Leak` + +error[E0277]: the trait bound `dyn Trait: Leak` is not satisfied + --> $DIR/maybe-bounds-in-dyn-traits.rs:58:7 + | +LL | x.leak_foo(); + | ^^^^^^^^ the trait `Leak` is not implemented for `dyn Trait` + | +note: required by a bound in `Trait::leak_foo` + --> $DIR/maybe-bounds-in-dyn-traits.rs:45:5 + | +LL | fn leak_foo(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs new file mode 100644 index 000000000000..761f22d1be5e --- /dev/null +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs @@ -0,0 +1,115 @@ +//@ compile-flags: -Zexperimental-default-bounds + +#![feature( + auto_traits, + associated_type_defaults, + generic_const_items, + lang_items, + more_maybe_bounds, + negative_impls, + no_core, + rustc_attrs +)] +#![allow(incomplete_features)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "legacy_receiver"] +trait LegacyReceiver {} +impl LegacyReceiver for &T {} +impl LegacyReceiver for &mut T {} + +#[lang = "default_trait1"] +auto trait Leak {} + +struct NonLeakS; +impl !Leak for NonLeakS {} +struct LeakS; + +mod supertraits { + use crate::*; + + trait MaybeLeakT1: ?Leak {} + trait MaybeLeakT2 where Self: ?Leak {} + + impl MaybeLeakT1 for NonLeakS {} + impl MaybeLeakT2 for NonLeakS {} +} + +mod maybe_self_assoc_type { + use crate::*; + + trait TestBase1 {} + trait TestBase2 {} + + trait Test1 { + type MaybeLeakSelf: TestBase1 where Self: ?Leak; + //~^ ERROR the trait bound `Self: Leak` is not satisfied + type LeakSelf: TestBase1; + } + + trait Test2 { + type MaybeLeakSelf: TestBase2 where Self: ?Leak; + type LeakSelf: TestBase2; + } + + trait Test3 { + type Leak1 = LeakS; + type Leak2 = NonLeakS; + //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied + } + + trait Test4 { + type MaybeLeak1: ?Leak = LeakS; + type MaybeLeak2: ?Leak = NonLeakS; + } + + trait Test5: ?Leak { + // ok, because assoc types have implicit where Self: Leak + type MaybeLeakSelf1: TestBase1; + type MaybeLeakSelf2: TestBase2; + } +} + +mod maybe_self_assoc_const { + use crate::*; + + const fn size_of() -> usize { + 0 + } + + trait Trait { + const CLeak: usize = size_of::(); + const CNonLeak: usize = size_of::() where Self: ?Leak; + //~^ ERROR the trait bound `Self: Leak` is not satisfied + } +} + +mod methods { + use crate::*; + + trait Trait { + fn leak_foo(&self) {} + fn maybe_leak_foo(&self) where Self: ?Leak {} + fn mut_leak_foo(&mut self) {} + // there is no relax bound on corresponding Receiver impl + fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {} + //~^ `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` + } + + impl Trait for NonLeakS {} + impl Trait for LeakS {} + + fn foo() { + LeakS.leak_foo(); + LeakS.maybe_leak_foo(); + NonLeakS.leak_foo(); + //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied + NonLeakS.maybe_leak_foo(); + } +} + +fn main() {} diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr new file mode 100644 index 000000000000..3dd8418b100f --- /dev/null +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr @@ -0,0 +1,71 @@ +error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied + --> $DIR/maybe-bounds-in-traits.rs:61:22 + | +LL | type Leak2 = NonLeakS; + | ^^^^^^^^ the trait `Leak` is not implemented for `NonLeakS` + | +note: required by a bound in `Test3::Leak2` + --> $DIR/maybe-bounds-in-traits.rs:61:9 + | +LL | type Leak2 = NonLeakS; + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test3::Leak2` + +error[E0277]: the trait bound `Self: Leak` is not satisfied + --> $DIR/maybe-bounds-in-traits.rs:49:29 + | +LL | type MaybeLeakSelf: TestBase1 where Self: ?Leak; + | ^^^^^^^^^^^^^^^ the trait `Leak` is not implemented for `Self` + | +note: required by a bound in `TestBase1` + --> $DIR/maybe-bounds-in-traits.rs:45:21 + | +LL | trait TestBase1 {} + | ^ required by this bound in `TestBase1` +help: consider further restricting `Self` + | +LL | trait Test1: Leak { + | ++++++ + +error[E0658]: `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/maybe-bounds-in-traits.rs:99:31 + | +LL | fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {} + | ^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + +error[E0277]: the trait bound `Self: Leak` is not satisfied + --> $DIR/maybe-bounds-in-traits.rs:86:43 + | +LL | const CNonLeak: usize = size_of::() where Self: ?Leak; + | ^^^^ the trait `Leak` is not implemented for `Self` + | +note: required by a bound in `size_of` + --> $DIR/maybe-bounds-in-traits.rs:80:22 + | +LL | const fn size_of() -> usize { + | ^ required by this bound in `size_of` +help: consider further restricting `Self` + | +LL | trait Trait: Leak { + | ++++++ + +error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied + --> $DIR/maybe-bounds-in-traits.rs:109:18 + | +LL | NonLeakS.leak_foo(); + | ^^^^^^^^ the trait `Leak` is not implemented for `NonLeakS` + | +note: required by a bound in `methods::Trait::leak_foo` + --> $DIR/maybe-bounds-in-traits.rs:95:9 + | +LL | fn leak_foo(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. From 13970949d135f3b0e1b9ece433c5fc230804d657 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 13:54:08 +0000 Subject: [PATCH 115/176] Run coretests and alloctests with cg_clif in CI --- .../build_system/tests.rs | 47 ++++++++++--------- compiler/rustc_codegen_cranelift/config.txt | 2 +- library/coretests/Cargo.toml | 1 + 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index 122b541fa35f..eb15a3fc027e 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -99,6 +99,32 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ runner.run_out_command("gen_block_iterate", &[]); }), TestCase::build_bin_and_run("aot.raw-dylib", "example/raw-dylib.rs", &[]), + TestCase::custom("test.sysroot", &|runner| { + apply_patches( + &runner.dirs, + "sysroot_tests", + &runner.stdlib_source.join("library"), + &SYSROOT_TESTS_SRC.to_path(&runner.dirs), + ); + + SYSROOT_TESTS.clean(&runner.dirs); + + // coretests and alloctests produce a bunch of warnings. When running + // in rust's CI warnings are denied, so we have to override that here. + let mut target_compiler = runner.target_compiler.clone(); + target_compiler.rustflags.push("--cap-lints=allow".to_owned()); + + if runner.is_native { + let mut test_cmd = SYSROOT_TESTS.test(&target_compiler, &runner.dirs); + test_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests", "--", "-q"]); + spawn_and_wait(test_cmd); + } else { + eprintln!("Cross-Compiling: Not running tests"); + let mut build_cmd = SYSROOT_TESTS.build(&target_compiler, &runner.dirs); + build_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests"]); + spawn_and_wait(build_cmd); + } + }), ]; pub(crate) static RAND_REPO: GitRepo = GitRepo::github( @@ -146,27 +172,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(build_cmd); } }), - TestCase::custom("test.sysroot", &|runner| { - apply_patches( - &runner.dirs, - "sysroot_tests", - &runner.stdlib_source.join("library"), - &SYSROOT_TESTS_SRC.to_path(&runner.dirs), - ); - - SYSROOT_TESTS.clean(&runner.dirs); - - if runner.is_native { - let mut test_cmd = SYSROOT_TESTS.test(&runner.target_compiler, &runner.dirs); - test_cmd.args(["-p", "coretests", "-p", "alloctests", "--", "-q"]); - spawn_and_wait(test_cmd); - } else { - eprintln!("Cross-Compiling: Not running tests"); - let mut build_cmd = SYSROOT_TESTS.build(&runner.target_compiler, &runner.dirs); - build_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests"]); - spawn_and_wait(build_cmd); - } - }), TestCase::custom("test.regex", &|runner| { REGEX_REPO.patch(&runner.dirs); diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt index 714414fe8d68..6ae4767adfdf 100644 --- a/compiler/rustc_codegen_cranelift/config.txt +++ b/compiler/rustc_codegen_cranelift/config.txt @@ -32,9 +32,9 @@ aot.issue-59326 aot.neon aot.gen_block_iterate aot.raw-dylib +test.sysroot testsuite.extended_sysroot test.rust-random/rand -test.sysroot test.regex test.portable-simd diff --git a/library/coretests/Cargo.toml b/library/coretests/Cargo.toml index e44f01d347b3..7656388d24be 100644 --- a/library/coretests/Cargo.toml +++ b/library/coretests/Cargo.toml @@ -12,6 +12,7 @@ edition = "2024" path = "lib.rs" test = false bench = false +doc = false [[test]] name = "coretests" From ecf9e204c942b8e9bd4f04c9e2873ba04036e7e6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 3 Apr 2025 20:58:34 +1100 Subject: [PATCH 116/176] compiletest: Encapsulate all of the code that touches libtest --- src/tools/compiletest/src/common.rs | 2 +- src/tools/compiletest/src/executor.rs | 156 ++++++++++++++++++++++ src/tools/compiletest/src/header.rs | 33 ++--- src/tools/compiletest/src/header/tests.rs | 13 +- src/tools/compiletest/src/lib.rs | 88 +++--------- 5 files changed, 194 insertions(+), 98 deletions(-) create mode 100644 src/tools/compiletest/src/executor.rs diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index cee351cd8b31..9e35d2b46676 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -9,9 +9,9 @@ use std::{fmt, iter}; use build_helper::git::GitConfig; use semver::Version; use serde::de::{Deserialize, Deserializer, Error as _}; -use test::{ColorConfig, OutputFormat}; pub use self::Mode::*; +use crate::executor::{ColorConfig, OutputFormat}; use crate::util::{PathBufExt, add_dylib_path}; macro_rules! string_enum { diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs new file mode 100644 index 000000000000..7588fee2b2b0 --- /dev/null +++ b/src/tools/compiletest/src/executor.rs @@ -0,0 +1,156 @@ +//! This module encapsulates all of the code that interacts directly with +//! libtest, to execute the collected tests. +//! +//! This will hopefully make it easier to migrate away from libtest someday. + +use std::borrow::Cow; +use std::io; +use std::sync::Arc; + +use crate::common::{Config, TestPaths}; + +/// Delegates to libtest to run the list of collected tests. +/// +/// Returns `Ok(true)` if all tests passed, or `Ok(false)` if one or more tests failed. +pub(crate) fn execute_tests(config: &Config, tests: Vec) -> io::Result { + let opts = test_opts(config); + let tests = tests.into_iter().map(|t| t.into_libtest()).collect::>(); + + test::run_tests_console(&opts, tests) +} + +/// Information needed to create a `test::TestDescAndFn`. +pub(crate) struct CollectedTest { + pub(crate) desc: CollectedTestDesc, + pub(crate) config: Arc, + pub(crate) testpaths: TestPaths, + pub(crate) revision: Option, +} + +/// Information needed to create a `test::TestDesc`. +pub(crate) struct CollectedTestDesc { + pub(crate) name: String, + pub(crate) ignore: bool, + pub(crate) ignore_message: Option>, + pub(crate) should_panic: ShouldPanic, +} + +impl CollectedTest { + fn into_libtest(self) -> test::TestDescAndFn { + let Self { desc, config, testpaths, revision } = self; + let CollectedTestDesc { name, ignore, ignore_message, should_panic } = desc; + + // Libtest requires the ignore message to be a &'static str, so we might + // have to leak memory to create it. This is fine, as we only do so once + // per test, so the leak won't grow indefinitely. + let ignore_message = ignore_message.map(|msg| match msg { + Cow::Borrowed(s) => s, + Cow::Owned(s) => &*String::leak(s), + }); + + let desc = test::TestDesc { + name: test::DynTestName(name), + ignore, + ignore_message, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, + should_panic: should_panic.to_libtest(), + compile_fail: false, + no_run: false, + test_type: test::TestType::Unknown, + }; + + // This closure is invoked when libtest returns control to compiletest + // to execute the test. + let testfn = test::DynTestFn(Box::new(move || { + crate::runtest::run(config, &testpaths, revision.as_deref()); + Ok(()) + })); + + test::TestDescAndFn { desc, testfn } + } +} + +/// Whether console output should be colored or not. +#[derive(Copy, Clone, Default, Debug)] +pub enum ColorConfig { + #[default] + AutoColor, + AlwaysColor, + NeverColor, +} + +impl ColorConfig { + fn to_libtest(self) -> test::ColorConfig { + match self { + Self::AutoColor => test::ColorConfig::AutoColor, + Self::AlwaysColor => test::ColorConfig::AlwaysColor, + Self::NeverColor => test::ColorConfig::NeverColor, + } + } +} + +/// Format of the test results output. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum OutputFormat { + /// Verbose output + Pretty, + /// Quiet output + #[default] + Terse, + /// JSON output + Json, +} + +impl OutputFormat { + fn to_libtest(self) -> test::OutputFormat { + match self { + Self::Pretty => test::OutputFormat::Pretty, + Self::Terse => test::OutputFormat::Terse, + Self::Json => test::OutputFormat::Json, + } + } +} + +/// Whether test is expected to panic or not. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub(crate) enum ShouldPanic { + No, + Yes, +} + +impl ShouldPanic { + fn to_libtest(self) -> test::ShouldPanic { + match self { + Self::No => test::ShouldPanic::No, + Self::Yes => test::ShouldPanic::Yes, + } + } +} + +fn test_opts(config: &Config) -> test::TestOpts { + test::TestOpts { + exclude_should_panic: false, + filters: config.filters.clone(), + filter_exact: config.filter_exact, + run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No }, + format: config.format.to_libtest(), + logfile: config.logfile.clone(), + run_tests: true, + bench_benchmarks: true, + nocapture: config.nocapture, + color: config.color.to_libtest(), + shuffle: false, + shuffle_seed: None, + test_threads: None, + skip: config.skip.clone(), + list: false, + options: test::Options::new(), + time_options: None, + force_run_in_process: false, + fail_fast: config.fail_fast, + } +} diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index f654bd9c90b5..a0178f4bcc57 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -11,6 +11,7 @@ use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; use crate::debuggers::{extract_cdb_version, extract_gdb_version}; +use crate::executor::{CollectedTestDesc, ShouldPanic}; use crate::header::auxiliary::{AuxProps, parse_and_update_aux}; use crate::header::needs::CachedNeedsConditions; use crate::util::static_regex; @@ -1355,15 +1356,15 @@ where Some((min, max)) } -pub fn make_test_description( +pub(crate) fn make_test_description( config: &Config, cache: &HeadersCache, - name: test::TestName, + name: String, path: &Path, src: R, test_revision: Option<&str>, poisoned: &mut bool, -) -> test::TestDesc { +) -> CollectedTestDesc { let mut ignore = false; let mut ignore_message = None; let mut should_fail = false; @@ -1387,10 +1388,7 @@ pub fn make_test_description( match $e { IgnoreDecision::Ignore { reason } => { ignore = true; - // The ignore reason must be a &'static str, so we have to leak memory to - // create it. This is fine, as the header is parsed only at the start of - // compiletest so it won't grow indefinitely. - ignore_message = Some(&*Box::leak(Box::::from(reason))); + ignore_message = Some(reason.into()); } IgnoreDecision::Error { message } => { eprintln!("error: {}:{line_number}: {message}", path.display()); @@ -1431,25 +1429,12 @@ pub fn make_test_description( // since we run the pretty printer across all tests by default. // If desired, we could add a `should-fail-pretty` annotation. let should_panic = match config.mode { - crate::common::Pretty => test::ShouldPanic::No, - _ if should_fail => test::ShouldPanic::Yes, - _ => test::ShouldPanic::No, + crate::common::Pretty => ShouldPanic::No, + _ if should_fail => ShouldPanic::Yes, + _ => ShouldPanic::No, }; - test::TestDesc { - name, - ignore, - ignore_message, - source_file: "", - start_line: 0, - start_col: 0, - end_line: 0, - end_col: 0, - should_panic, - compile_fail: false, - no_run: false, - test_type: test::TestType::Unknown, - } + CollectedTestDesc { name, ignore, ignore_message, should_panic } } fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 4d90f152ee20..ff6bc49b72a1 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -8,14 +8,15 @@ use super::{ parse_normalize_rule, }; use crate::common::{Config, Debugger, Mode}; +use crate::executor::{CollectedTestDesc, ShouldPanic}; fn make_test_description( config: &Config, - name: test::TestName, + name: String, path: &Path, src: R, revision: Option<&str>, -) -> test::TestDesc { +) -> CollectedTestDesc { let cache = HeadersCache::load(config); let mut poisoned = false; let test = crate::header::make_test_description( @@ -233,7 +234,7 @@ fn parse_rs(config: &Config, contents: &str) -> EarlyProps { } fn check_ignore(config: &Config, contents: &str) -> bool { - let tn = test::DynTestName(String::new()); + let tn = String::new(); let p = Path::new("a.rs"); let d = make_test_description(&config, tn, p, std::io::Cursor::new(contents), None); d.ignore @@ -242,13 +243,13 @@ fn check_ignore(config: &Config, contents: &str) -> bool { #[test] fn should_fail() { let config: Config = cfg().build(); - let tn = test::DynTestName(String::new()); + let tn = String::new(); let p = Path::new("a.rs"); let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None); - assert_eq!(d.should_panic, test::ShouldPanic::No); + assert_eq!(d.should_panic, ShouldPanic::No); let d = make_test_description(&config, tn, p, std::io::Cursor::new("//@ should-fail"), None); - assert_eq!(d.should_panic, test::ShouldPanic::Yes); + assert_eq!(d.should_panic, ShouldPanic::Yes); } #[test] diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 01899c2c8a63..8145ae1c1bce 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -12,6 +12,7 @@ pub mod common; pub mod compute_diff; mod debuggers; pub mod errors; +mod executor; pub mod header; mod json; mod raise_fd_limit; @@ -32,7 +33,6 @@ use std::{env, fs, vec}; use build_helper::git::{get_git_modified_files, get_git_untracked_files}; use getopts::Options; -use test::ColorConfig; use tracing::*; use walkdir::WalkDir; @@ -41,6 +41,7 @@ use crate::common::{ CompareMode, Config, Debugger, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, output_base_dir, output_relative_path, }; +use crate::executor::{CollectedTest, ColorConfig, OutputFormat}; use crate::header::HeadersCache; use crate::util::logv; @@ -402,9 +403,9 @@ pub fn parse_config(args: Vec) -> Config { verbose: matches.opt_present("verbose"), format: match (matches.opt_present("quiet"), matches.opt_present("json")) { (true, true) => panic!("--quiet and --json are incompatible"), - (true, false) => test::OutputFormat::Terse, - (false, true) => test::OutputFormat::Json, - (false, false) => test::OutputFormat::Pretty, + (true, false) => OutputFormat::Terse, + (false, true) => OutputFormat::Json, + (false, false) => OutputFormat::Pretty, }, only_modified: matches.opt_present("only-modified"), color, @@ -535,8 +536,6 @@ pub fn run_tests(config: Arc) { // Let tests know which target they're running as env::set_var("TARGET", &config.target); - let opts = test_opts(&config); - let mut configs = Vec::new(); if let Mode::DebugInfo = config.mode { // Debugging emscripten code doesn't make sense today @@ -563,12 +562,12 @@ pub fn run_tests(config: Arc) { tests.extend(collect_and_make_tests(c)); } - tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice())); + tests.sort_by(|a, b| Ord::cmp(&a.desc.name, &b.desc.name)); // Delegate to libtest to filter and run the big list of structures created - // during test discovery. When libtest decides to run a test, it will invoke - // the corresponding closure created by `make_test_closure`. - let res = test::run_tests_console(&opts, tests); + // during test discovery. When libtest decides to run a test, it will + // return control to compiletest by invoking a closure. + let res = crate::executor::execute_tests(&config, tests); // Check the outcome reported by libtest. match res { @@ -612,30 +611,6 @@ pub fn run_tests(config: Arc) { } } -pub fn test_opts(config: &Config) -> test::TestOpts { - test::TestOpts { - exclude_should_panic: false, - filters: config.filters.clone(), - filter_exact: config.filter_exact, - run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No }, - format: config.format, - logfile: config.logfile.clone(), - run_tests: true, - bench_benchmarks: true, - nocapture: config.nocapture, - color: config.color, - shuffle: false, - shuffle_seed: None, - test_threads: None, - skip: config.skip.clone(), - list: false, - options: test::Options::new(), - time_options: None, - force_run_in_process: false, - fail_fast: config.fail_fast, - } -} - /// Read-only context data used during test collection. struct TestCollectorCx { config: Arc, @@ -646,17 +621,17 @@ struct TestCollectorCx { /// Mutable state used during test collection. struct TestCollector { - tests: Vec, + tests: Vec, found_path_stems: HashSet, poisoned: bool, } -/// Creates libtest structures for every test/revision in the test suite directory. +/// Creates test structures for every test/revision in the test suite directory. /// /// This always inspects _all_ test files in the suite (e.g. all 17k+ ui tests), /// regardless of whether any filters/tests were specified on the command-line, /// because filtering is handled later by libtest. -pub fn collect_and_make_tests(config: Arc) -> Vec { +pub(crate) fn collect_and_make_tests(config: Arc) -> Vec { debug!("making tests from {}", config.src_test_suite_root.display()); let common_inputs_stamp = common_inputs_stamp(&config); let modified_tests = @@ -885,7 +860,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te }; // For each revision (or the sole dummy revision), create and append a - // `test::TestDescAndFn` that can be handed over to libtest. + // `CollectedTest` that can be handed over to the test executor. collector.tests.extend(revisions.into_iter().map(|revision| { // Create a test name and description to hand over to libtest. let src_file = fs::File::open(&test_path).expect("open test file to parse ignores"); @@ -908,13 +883,14 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te if !cx.config.force_rerun && is_up_to_date(cx, testpaths, &early_props, revision) { desc.ignore = true; // Keep this in sync with the "up-to-date" message detected by bootstrap. - desc.ignore_message = Some("up-to-date"); + desc.ignore_message = Some("up-to-date".into()); } - // Create the callback that will run this test/revision when libtest calls it. - let testfn = make_test_closure(Arc::clone(&cx.config), testpaths, revision); + let config = Arc::clone(&cx.config); + let testpaths = testpaths.clone(); + let revision = revision.map(str::to_owned); - test::TestDescAndFn { desc, testfn } + CollectedTest { desc, config, testpaths, revision } })); } @@ -1046,11 +1022,7 @@ impl Stamp { } /// Creates a name for this test/revision that can be handed over to libtest. -fn make_test_name( - config: &Config, - testpaths: &TestPaths, - revision: Option<&str>, -) -> test::TestName { +fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> String { // Print the name of the file, relative to the sources root. let path = testpaths.file.strip_prefix(&config.src_root).unwrap(); let debugger = match config.debugger { @@ -1062,32 +1034,14 @@ fn make_test_name( None => String::new(), }; - test::DynTestName(format!( + format!( "[{}{}{}] {}{}", config.mode, debugger, mode_suffix, path.display(), revision.map_or("".to_string(), |rev| format!("#{}", rev)) - )) -} - -/// Creates a callback for this test/revision that libtest will call when it -/// decides to actually run the underlying test. -fn make_test_closure( - config: Arc, - testpaths: &TestPaths, - revision: Option<&str>, -) -> test::TestFn { - let testpaths = testpaths.clone(); - let revision = revision.map(str::to_owned); - - // This callback is the link between compiletest's test discovery code, - // and the parts of compiletest that know how to run an individual test. - test::DynTestFn(Box::new(move || { - runtest::run(config, &testpaths, revision.as_deref()); - Ok(()) - })) + ) } /// Checks that test discovery didn't find any tests whose name stem is a prefix From 6af96f873a20a6ffd582ee5b1f5475fc924d19e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 18 Mar 2025 08:00:10 +0100 Subject: [PATCH 117/176] Add a helper function for checking if LLD was used to `run-make-support` --- src/tools/run-make-support/src/lib.rs | 1 + src/tools/run-make-support/src/linker.rs | 36 ++++++++++ .../rust-lld-by-default-beta-stable/rmake.rs | 17 +---- .../rust-lld-by-default-nightly/rmake.rs | 27 +------- .../run-make/rust-lld-custom-target/rmake.rs | 39 +++-------- tests/run-make/rust-lld/rmake.rs | 66 +++++-------------- 6 files changed, 68 insertions(+), 118 deletions(-) create mode 100644 src/tools/run-make-support/src/linker.rs diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index fd22ff6c8bce..c75d500d2f06 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -17,6 +17,7 @@ pub mod assertion_helpers; pub mod diff; pub mod env; pub mod external_deps; +pub mod linker; pub mod path_helpers; pub mod run; pub mod scoped_run; diff --git a/src/tools/run-make-support/src/linker.rs b/src/tools/run-make-support/src/linker.rs new file mode 100644 index 000000000000..89093cf01139 --- /dev/null +++ b/src/tools/run-make-support/src/linker.rs @@ -0,0 +1,36 @@ +use regex::Regex; + +use crate::{Rustc, is_msvc}; + +/// Asserts that `rustc` uses LLD for linking when executed. +pub fn assert_rustc_uses_lld(rustc: &mut Rustc) { + let stderr = get_stderr_with_linker_messages(rustc); + assert!( + has_lld_version_in_logs(&stderr), + "LLD version should be present in rustc stderr:\n{stderr}" + ); +} + +/// Asserts that `rustc` doesn't use LLD for linking when executed. +pub fn assert_rustc_doesnt_use_lld(rustc: &mut Rustc) { + let stderr = get_stderr_with_linker_messages(rustc); + assert!( + !has_lld_version_in_logs(&stderr), + "LLD version should NOT be present in rustc stderr:\n{stderr}" + ); +} + +fn get_stderr_with_linker_messages(rustc: &mut Rustc) -> String { + // lld-link is used if msvc, otherwise a gnu-compatible lld is used. + let linker_version_flag = if is_msvc() { "--version" } else { "-Wl,-v" }; + + let output = rustc.arg("-Wlinker-messages").link_arg(linker_version_flag).run(); + output.stderr_utf8() +} + +fn has_lld_version_in_logs(stderr: &str) -> bool { + // Strip the `-Wlinker-messages` wrappers prefixing the linker output. + let stderr = Regex::new(r"warning: linker std(out|err):").unwrap().replace_all(&stderr, ""); + let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); + stderr.lines().any(|line| lld_version_re.is_match(line.trim())) +} diff --git a/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs index 263bb9b2e200..9a08991c4b89 100644 --- a/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs +++ b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs @@ -4,24 +4,11 @@ //@ ignore-nightly //@ only-x86_64-unknown-linux-gnu -use std::process::Output; - -use run_make_support::regex::Regex; +use run_make_support::linker::assert_rustc_doesnt_use_lld; use run_make_support::rustc; fn main() { // A regular compilation should not use rust-lld by default. We'll check that by asking the // linker to display its version number with a link-arg. - let output = rustc().arg("-Wlinker-messages").link_arg("-Wl,-v").input("main.rs").run(); - assert!( - !find_lld_version_in_logs(output.stderr_utf8()), - "the LLD version string should not be present in the output logs:\n{}", - output.stderr_utf8() - ); -} - -fn find_lld_version_in_logs(stderr: String) -> bool { - let lld_version_re = - Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); - stderr.lines().any(|line| lld_version_re.is_match(line.trim())) + assert_rustc_doesnt_use_lld(rustc().input("main.rs")); } diff --git a/tests/run-make/rust-lld-by-default-nightly/rmake.rs b/tests/run-make/rust-lld-by-default-nightly/rmake.rs index 7a0a08863dd3..3ff1e2770e65 100644 --- a/tests/run-make/rust-lld-by-default-nightly/rmake.rs +++ b/tests/run-make/rust-lld-by-default-nightly/rmake.rs @@ -6,35 +6,14 @@ //@ ignore-stable //@ only-x86_64-unknown-linux-gnu -use run_make_support::regex::Regex; +use run_make_support::linker::{assert_rustc_doesnt_use_lld, assert_rustc_uses_lld}; use run_make_support::rustc; fn main() { // A regular compilation should use rust-lld by default. We'll check that by asking the linker // to display its version number with a link-arg. - let output = rustc().arg("-Wlinker-messages").link_arg("-Wl,-v").input("main.rs").run(); - assert!( - find_lld_version_in_logs(output.stderr_utf8()), - "the LLD version string should be present in the output logs:\n{}", - output.stderr_utf8() - ); + assert_rustc_uses_lld(rustc().input("main.rs")); // But it can still be disabled by turning the linker feature off. - let output = rustc() - .arg("-Wlinker-messages") - .link_arg("-Wl,-v") - .arg("-Zlinker-features=-lld") - .input("main.rs") - .run(); - assert!( - !find_lld_version_in_logs(output.stderr_utf8()), - "the LLD version string should not be present in the output logs:\n{}", - output.stderr_utf8() - ); -} - -fn find_lld_version_in_logs(stderr: String) -> bool { - let lld_version_re = - Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); - stderr.lines().any(|line| lld_version_re.is_match(line.trim())) + assert_rustc_doesnt_use_lld(rustc().arg("-Zlinker-features=-lld").input("main.rs")); } diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs index 993a248ad00d..e2b065a10b17 100644 --- a/tests/run-make/rust-lld-custom-target/rmake.rs +++ b/tests/run-make/rust-lld-custom-target/rmake.rs @@ -8,43 +8,22 @@ //@ needs-rust-lld //@ only-x86_64-unknown-linux-gnu -use run_make_support::regex::Regex; +use run_make_support::linker::{assert_rustc_doesnt_use_lld, assert_rustc_uses_lld}; use run_make_support::rustc; fn main() { // Compile to a custom target spec with rust-lld enabled by default. We'll check that by asking // the linker to display its version number with a link-arg. - let output = rustc() - .crate_type("cdylib") - .arg("-Wlinker-messages") - .target("custom-target.json") - .link_arg("-Wl,-v") - .input("lib.rs") - .run(); - assert!( - find_lld_version_in_logs(output.stderr_utf8()), - "the LLD version string should be present in the output logs:\n{}", - output.stderr_utf8() + assert_rustc_uses_lld( + rustc().crate_type("cdylib").target("custom-target.json").input("lib.rs"), ); // But it can also be disabled via linker features. - let output = rustc() - .crate_type("cdylib") - .arg("-Wlinker-messages") - .target("custom-target.json") - .arg("-Zlinker-features=-lld") - .link_arg("-Wl,-v") - .input("lib.rs") - .run(); - assert!( - !find_lld_version_in_logs(output.stderr_utf8()), - "the LLD version string should not be present in the output logs:\n{}", - output.stderr_utf8() + assert_rustc_doesnt_use_lld( + rustc() + .crate_type("cdylib") + .target("custom-target.json") + .arg("-Zlinker-features=-lld") + .input("lib.rs"), ); } - -fn find_lld_version_in_logs(stderr: String) -> bool { - let lld_version_re = - Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); - stderr.lines().any(|line| lld_version_re.is_match(line.trim())) -} diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs index 35f716c24c71..aafd4b96d777 100644 --- a/tests/run-make/rust-lld/rmake.rs +++ b/tests/run-make/rust-lld/rmake.rs @@ -4,64 +4,32 @@ //@ needs-rust-lld //@ ignore-s390x lld does not yet support s390x as target -use run_make_support::regex::Regex; -use run_make_support::{is_msvc, rustc}; +use run_make_support::linker::{assert_rustc_doesnt_use_lld, assert_rustc_uses_lld}; +use run_make_support::rustc; fn main() { - // lld-link is used if msvc, otherwise a gnu-compatible lld is used. - let linker_version_flag = if is_msvc() { "--version" } else { "-Wl,-v" }; - // Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by // asking the linker to display its version number with a link-arg. - let output = rustc() - .arg("-Zlinker-features=+lld") - .arg("-Clink-self-contained=+linker") - .arg("-Zunstable-options") - .arg("-Wlinker-messages") - .link_arg(linker_version_flag) - .input("main.rs") - .run(); - assert!( - find_lld_version_in_logs(output.stderr_utf8()), - "the LLD version string should be present in the output logs:\n{}", - output.stderr_utf8() + assert_rustc_uses_lld( + rustc() + .arg("-Zlinker-features=+lld") + .arg("-Clink-self-contained=+linker") + .arg("-Zunstable-options") + .input("main.rs"), ); // It should not be used when we explicitly opt-out of lld. - let output = rustc() - .link_arg(linker_version_flag) - .arg("-Zlinker-features=-lld") - .arg("-Wlinker-messages") - .input("main.rs") - .run(); - assert!( - !find_lld_version_in_logs(output.stderr_utf8()), - "the LLD version string should not be present in the output logs:\n{}", - output.stderr_utf8() - ); + assert_rustc_doesnt_use_lld(rustc().arg("-Zlinker-features=-lld").input("main.rs")); // While we're here, also check that the last linker feature flag "wins" when passed multiple // times to rustc. - let output = rustc() - .link_arg(linker_version_flag) - .arg("-Clink-self-contained=+linker") - .arg("-Zunstable-options") - .arg("-Zlinker-features=-lld") - .arg("-Zlinker-features=+lld") - .arg("-Zlinker-features=-lld,+lld") - .arg("-Wlinker-messages") - .input("main.rs") - .run(); - assert!( - find_lld_version_in_logs(output.stderr_utf8()), - "the LLD version string should be present in the output logs:\n{}", - output.stderr_utf8() + assert_rustc_uses_lld( + rustc() + .arg("-Clink-self-contained=+linker") + .arg("-Zunstable-options") + .arg("-Zlinker-features=-lld") + .arg("-Zlinker-features=+lld") + .arg("-Zlinker-features=-lld,+lld") + .input("main.rs"), ); } - -fn find_lld_version_in_logs(stderr: String) -> bool { - // Strip the `-Wlinker-messages` wrappers prefixing the linker output. - let stderr = Regex::new(r"warning: linker std(out|err):").unwrap().replace_all(&stderr, ""); - let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); - stderr.lines().any(|line| lld_version_re.is_match(line.trim())) -} From 9ec11c246d616be224e963cafc8603b39e07926f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 24 Mar 2025 12:15:22 +0100 Subject: [PATCH 118/176] Move `link-self-contained-consistency` test to a more reasonable location --- tests/run-make/rust-lld/rmake.rs | 2 +- .../link-self-contained-consistency.many.stderr | 0 .../link-self-contained-consistency.one.stderr | 0 .../link-self-contained-consistency.rs | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename tests/ui/{linkage-attr => linking}/link-self-contained-consistency.many.stderr (100%) rename tests/ui/{linkage-attr => linking}/link-self-contained-consistency.one.stderr (100%) rename tests/ui/{linkage-attr => linking}/link-self-contained-consistency.rs (100%) diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs index aafd4b96d777..9470f5d0be18 100644 --- a/tests/run-make/rust-lld/rmake.rs +++ b/tests/run-make/rust-lld/rmake.rs @@ -18,7 +18,7 @@ fn main() { .input("main.rs"), ); - // It should not be used when we explicitly opt-out of lld. + // It should not be used when we explicitly opt out of lld. assert_rustc_doesnt_use_lld(rustc().arg("-Zlinker-features=-lld").input("main.rs")); // While we're here, also check that the last linker feature flag "wins" when passed multiple diff --git a/tests/ui/linkage-attr/link-self-contained-consistency.many.stderr b/tests/ui/linking/link-self-contained-consistency.many.stderr similarity index 100% rename from tests/ui/linkage-attr/link-self-contained-consistency.many.stderr rename to tests/ui/linking/link-self-contained-consistency.many.stderr diff --git a/tests/ui/linkage-attr/link-self-contained-consistency.one.stderr b/tests/ui/linking/link-self-contained-consistency.one.stderr similarity index 100% rename from tests/ui/linkage-attr/link-self-contained-consistency.one.stderr rename to tests/ui/linking/link-self-contained-consistency.one.stderr diff --git a/tests/ui/linkage-attr/link-self-contained-consistency.rs b/tests/ui/linking/link-self-contained-consistency.rs similarity index 100% rename from tests/ui/linkage-attr/link-self-contained-consistency.rs rename to tests/ui/linking/link-self-contained-consistency.rs From ac7dd7a1b3307ddfd6ad95a1b3f58830e0fdbf65 Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 24 Mar 2025 16:55:24 +0800 Subject: [PATCH 119/176] Remove `unsound-mir-opts` for `simplify_aggregate_to_copy` --- compiler/rustc_mir_transform/src/gvn.rs | 4 +- tests/codegen/clone_as_copy.rs | 2 - tests/codegen/try_question_mark_nop.rs | 38 ++++++++----- tests/mir-opt/gvn_clone.rs | 2 - .../mir-opt/gvn_clone.{impl#0}-clone.GVN.diff | 6 +-- tests/mir-opt/gvn_copy_aggregate.rs | 2 - tests/mir-opt/pre-codegen/clone_as_copy.rs | 2 - ..._clone.{impl#0}-clone.PreCodegen.after.mir | 6 +-- .../try_identity.old.PreCodegen.after.mir | 8 +-- ..._aggregate_to_copy_miscompile.foo.GVN.diff | 54 ++++++++----------- .../simplify_aggregate_to_copy_miscompile.rs | 12 +++-- 11 files changed, 65 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index a93fdff5817c..b6294f4ff8a2 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1098,9 +1098,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } - // unsound: https://github.com/rust-lang/rust/issues/132353 - if tcx.sess.opts.unstable_opts.unsound_mir_opts - && let AggregateTy::Def(_, _) = ty + if let AggregateTy::Def(_, _) = ty && let Some(value) = self.simplify_aggregate_to_copy(rvalue, location, &fields, variant_index) { diff --git a/tests/codegen/clone_as_copy.rs b/tests/codegen/clone_as_copy.rs index c39f120044c0..ef834ef59120 100644 --- a/tests/codegen/clone_as_copy.rs +++ b/tests/codegen/clone_as_copy.rs @@ -1,6 +1,4 @@ //@ revisions: DEBUGINFO NODEBUGINFO -//@ compile-flags: -Zunsound-mir-opts -// FIXME: see //@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes //@ [DEBUGINFO] compile-flags: -Cdebuginfo=full diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 3a3453b22b44..9430465a2860 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -16,12 +16,17 @@ use std::ptr::NonNull; #[no_mangle] pub fn option_nop_match_32(x: Option) -> Option { // CHECK: start: - // TWENTY-NEXT: %[[IS_SOME:.+]] = trunc nuw i32 %0 to i1 - // TWENTY-NEXT: %[[PAYLOAD:.+]] = select i1 %[[IS_SOME]], i32 %1, i32 undef - // CHECK-NEXT: [[REG1:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0 - // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %1, 1 - // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %[[PAYLOAD]], 1 - // CHECK-NEXT: ret { i32, i32 } [[REG2]] + // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i32 %0 to i1 + + // NINETEEN-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %0, i32 0 + // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 [[SELECT]], 0 + // NINETEEN-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 %1, 1 + + // TWENTY-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %1, i32 undef + // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0 + // TWENTY-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 [[SELECT]], 1 + + // CHECK-NEXT: ret { i32, i32 } [[REG3]] match x { Some(x) => Some(x), None => None, @@ -90,12 +95,17 @@ pub fn control_flow_nop_traits_32(x: ControlFlow) -> ControlFlow) -> Option { // CHECK: start: - // TWENTY-NEXT: %[[TRUNC:[0-9]+]] = trunc nuw i64 %0 to i1 - // TWENTY-NEXT: %[[SEL:\.[0-9]+]] = select i1 %[[TRUNC]], i64 %1, i64 undef - // CHECK-NEXT: [[REG1:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } poison, i64 %0, 0 - // NINETEEN-NEXT: [[REG2:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } [[REG1]], i64 %1, 1 - // TWENTY-NEXT: [[REG2:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } [[REG1]], i64 %[[SEL]], 1 - // CHECK-NEXT: ret { i64, i64 } [[REG2]] + // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i64 %0 to i1 + + // NINETEEN-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %0, i64 0 + // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 [[SELECT]], 0 + // NINETEEN-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 %1, 1 + + // TWENTY-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %1, i64 undef + // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 %0, 0 + // TWENTY-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 [[SELECT]], 1 + + // CHECK-NEXT: ret { i64, i64 } [[REG3]] match x { Some(x) => Some(x), None => None, @@ -164,8 +174,8 @@ pub fn control_flow_nop_traits_64(x: ControlFlow) -> ControlFlow) -> Result { // CHECK: start: - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 // CHECK-NEXT: ret void match x { @@ -189,8 +199,8 @@ pub fn result_nop_traits_128(x: Result) -> Result { #[no_mangle] pub fn control_flow_nop_match_128(x: ControlFlow) -> ControlFlow { // CHECK: start: - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 // CHECK-NEXT: ret void match x { diff --git a/tests/mir-opt/gvn_clone.rs b/tests/mir-opt/gvn_clone.rs index c16b665fbd39..08938c0e1b42 100644 --- a/tests/mir-opt/gvn_clone.rs +++ b/tests/mir-opt/gvn_clone.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Zunsound-mir-opts -// FIXME: see //@ test-mir-pass: GVN //@ compile-flags: -Zmir-enable-passes=+InstSimplify-before-inline diff --git a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff index 2a672e829707..0f23415ec53b 100644 --- a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff +++ b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff @@ -1,7 +1,7 @@ -- // MIR for `::clone` before GVN -+ // MIR for `::clone` after GVN +- // MIR for `::clone` before GVN ++ // MIR for `::clone` after GVN - fn ::clone(_1: &AllCopy) -> AllCopy { + fn ::clone(_1: &AllCopy) -> AllCopy { debug self => _1; let mut _0: AllCopy; let mut _2: i32; diff --git a/tests/mir-opt/gvn_copy_aggregate.rs b/tests/mir-opt/gvn_copy_aggregate.rs index 7c181d1ad378..c9473025a15f 100644 --- a/tests/mir-opt/gvn_copy_aggregate.rs +++ b/tests/mir-opt/gvn_copy_aggregate.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Zunsound-mir-opts -// FIXME: see //@ compile-flags: -Cdebuginfo=full // Check if we have transformed the nested clone to the copy in the complete pipeline. diff --git a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir index 62a9cd9131f0..9020cf1ef37f 100644 --- a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir @@ -3,13 +3,9 @@ fn ::clone(_1: &Foo) -> Foo { debug self => _1; let mut _0: Foo; - let mut _2: i32; bb0: { - StorageLive(_2); - _2 = copy ((*_1).0: i32); - _0 = Foo { a: move _2 }; - StorageDead(_2); + _0 = copy (*_1); return; } } diff --git a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir index ac485f485b1c..889e80d26e1c 100644 --- a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir @@ -19,14 +19,14 @@ fn old(_1: Result) -> Result { } bb1: { - _3 = move ((_1 as Ok).0: T); - _0 = Result::::Ok(copy _3); + _3 = copy ((_1 as Ok).0: T); + _0 = copy _1; goto -> bb3; } bb2: { - _4 = move ((_1 as Err).0: E); - _0 = Result::::Err(copy _4); + _4 = copy ((_1 as Err).0: E); + _0 = copy _1; goto -> bb3; } diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff index 2efc4ef56044..19a00f977eb1 100644 --- a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff @@ -6,60 +6,52 @@ let mut _0: std::option::Option; let mut _2: &std::option::Option; let mut _3: &std::option::Option; - let _4: &&mut std::option::Option; - let mut _5: isize; - let mut _7: !; - let mut _8: std::option::Option; - let mut _9: i32; - let mut _10: !; - let mut _11: &mut std::option::Option; + let mut _4: isize; + let mut _6: !; + let mut _7: std::option::Option; + let mut _8: i32; + let mut _9: !; scope 1 { - debug col => _6; - let _6: i32; + debug col => _5; + let _5: i32; } bb0: { StorageLive(_2); StorageLive(_3); - StorageLive(_4); - _4 = &_1; -- _11 = deref_copy (*_4); -- _3 = &(*_11); -+ _11 = copy _1; -+ _3 = &(*_1); + _3 = &(*_1); _2 = get(move _3) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_3); - _5 = discriminant((*_2)); - switchInt(move _5) -> [1: bb2, otherwise: bb3]; + _4 = discriminant((*_2)); + switchInt(move _4) -> [1: bb2, otherwise: bb3]; } bb2: { -- StorageLive(_6); +- StorageLive(_5); + nop; - _6 = copy (((*_2) as Some).0: i32); - StorageLive(_8); -- _8 = Option::::None; -- (*_1) = move _8; -+ _8 = const Option::::None; + _5 = copy (((*_2) as Some).0: i32); + StorageLive(_7); +- _7 = Option::::None; +- (*_1) = move _7; ++ _7 = const Option::::None; + (*_1) = const Option::::None; + StorageDead(_7); + StorageLive(_8); + _8 = copy _5; +- _0 = Option::::Some(move _8); ++ _0 = Option::::Some(copy _5); StorageDead(_8); - StorageLive(_9); - _9 = copy _6; -- _0 = Option::::Some(move _9); -+ _0 = Option::::Some(copy _6); - StorageDead(_9); -- StorageDead(_6); +- StorageDead(_5); + nop; - StorageDead(_4); StorageDead(_2); return; } bb3: { - StorageLive(_10); + StorageLive(_9); unreachable; } + } diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs index 47721b768be7..87b52ae48086 100644 --- a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs @@ -7,8 +7,6 @@ //! This test demonstrates the behavior, and should be adjusted or removed when fixing and relanding //! the mir-opt. #![crate_type = "lib"] -// skip-filecheck -//@ compile-flags: -O -Zunsound-mir-opts //@ test-mir-pass: GVN #![allow(internal_features)] #![feature(rustc_attrs, core_intrinsics)] @@ -16,7 +14,15 @@ // EMIT_MIR simplify_aggregate_to_copy_miscompile.foo.GVN.diff #[no_mangle] fn foo(v: &mut Option) -> Option { - if let &Some(col) = get(&v) { + // CHECK-LABEL: fn foo( + // CHECK-SAME: [[v:_.*]]: &mut Option + // CHECK: [[v_alias_1:_.*]] = &(*_1) + // CHECK-NEXT: [[v_alias_2:_.*]] = get(move [[v_alias_1]]) + // CHECK: (*[[v]]) = const Option::::None; + // CHECK-NOT: _0 = copy (*[[v_alias_2]]) + // CHECK: _0 = Option::::Some + // CHECK-NOT: _0 = copy (*[[v_alias_2]]) + if let &Some(col) = get(v) { *v = None; return Some(col); } else { From 4e05d858ad602de7d34054016c2277730789dcba Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 24 Mar 2025 16:55:24 +0800 Subject: [PATCH 120/176] Only preserving derefs for trivial terminators like SwitchInt and Goto --- compiler/rustc_mir_transform/src/gvn.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index b6294f4ff8a2..046f36bdeddf 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1779,8 +1779,14 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { let opaque = self.new_opaque(); self.assign(local, opaque); } - // Function calls maybe invalidate nested deref, and non-local assignments maybe invalidate deref. - // Currently, no distinction is made between these two cases. + } + // Function calls and ASM may invalidate (nested) derefs. We must handle them carefully. + // Currently, only preserving derefs for trivial terminators like SwitchInt and Goto. + let safe_to_preserve_derefs = matches!( + terminator.kind, + TerminatorKind::SwitchInt { .. } | TerminatorKind::Goto { .. } + ); + if !safe_to_preserve_derefs { self.invalidate_derefs(); } self.super_terminator(terminator, location); From 7d44887374ee667bd5aeb5e861032b8ce4093b29 Mon Sep 17 00:00:00 2001 From: dianqk Date: Tue, 25 Mar 2025 22:21:18 +0800 Subject: [PATCH 121/176] Invalid dereferences for all non-local mutations --- compiler/rustc_mir_transform/src/gvn.rs | 30 +++++++++-------- ...mute.undef_union_as_integer.GVN.32bit.diff | 3 +- ...mute.undef_union_as_integer.GVN.64bit.diff | 3 +- ...in.DestinationPropagation.panic-abort.diff | 10 ++---- ...n.DestinationPropagation.panic-unwind.diff | 10 ++---- ..._aggregate_to_copy_miscompile.foo.GVN.diff | 2 +- .../simplify_aggregate_to_copy_miscompile.rs | 33 ++++++++++++++++--- ..._copy_miscompile.set_discriminant.GVN.diff | 20 +++++++++++ 8 files changed, 75 insertions(+), 36 deletions(-) create mode 100644 tests/mir-opt/simplify_aggregate_to_copy_miscompile.set_discriminant.GVN.diff diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 046f36bdeddf..68bc0ffce6b5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1728,12 +1728,18 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { self.tcx } - fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, location: Location) { + fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { self.simplify_place_projection(place, location); + if context.is_mutating_use() && !place.projection.is_empty() { + // Non-local mutation maybe invalidate deref. + self.invalidate_derefs(); + } + self.super_place(place, context, location); } fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { self.simplify_operand(operand, location); + self.super_operand(operand, location); } fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) { @@ -1751,22 +1757,18 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { self.assign(local, value); Some(value) } else { - // Non-local assignments maybe invalidate deref. - self.invalidate_derefs(); value }; - let Some(value) = value else { return }; - - if let Some(const_) = self.try_as_constant(value) { - *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); - } else if let Some(local) = self.try_as_local(value, location) - && *rvalue != Rvalue::Use(Operand::Move(local.into())) - { - *rvalue = Rvalue::Use(Operand::Copy(local.into())); - self.reused_locals.insert(local); + if let Some(value) = value { + if let Some(const_) = self.try_as_constant(value) { + *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); + } else if let Some(local) = self.try_as_local(value, location) + && *rvalue != Rvalue::Use(Operand::Move(local.into())) + { + *rvalue = Rvalue::Use(Operand::Copy(local.into())); + self.reused_locals.insert(local); + } } - - return; } self.super_statement(stmt, location); } diff --git a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff index febb6bfb0a43..2ac9769a0e77 100644 --- a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff @@ -10,8 +10,9 @@ StorageLive(_1); StorageLive(_2); - _2 = (); +- _1 = Union32 { value: move _2 }; + _2 = const (); - _1 = Union32 { value: move _2 }; ++ _1 = Union32 { value: const () }; StorageDead(_2); _0 = move _1 as u32 (Transmute); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff index febb6bfb0a43..2ac9769a0e77 100644 --- a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff @@ -10,8 +10,9 @@ StorageLive(_1); StorageLive(_2); - _2 = (); +- _1 = Union32 { value: move _2 }; + _2 = const (); - _1 = Union32 { value: move _2 }; ++ _1 = Union32 { value: const () }; StorageDead(_2); _0 = move _1 as u32 (Transmute); StorageDead(_1); diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index 557320f01798..ef418798faaf 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -5,11 +5,10 @@ let mut _0: (); let _1: main::Un; let mut _2: u32; - let mut _3: u32; scope 1 { debug un => _1; scope 3 (inlined std::mem::drop::) { - debug _x => _3; + debug _x => _2; } } scope 2 (inlined val) { @@ -17,13 +16,10 @@ bb0: { StorageLive(_1); - StorageLive(_2); - nop; _1 = Un { us: const 1_u32 }; + StorageLive(_2); + _2 = copy (_1.0: u32); StorageDead(_2); - StorageLive(_3); - _3 = copy (_1.0: u32); - StorageDead(_3); StorageDead(_1); return; } diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index 557320f01798..ef418798faaf 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -5,11 +5,10 @@ let mut _0: (); let _1: main::Un; let mut _2: u32; - let mut _3: u32; scope 1 { debug un => _1; scope 3 (inlined std::mem::drop::) { - debug _x => _3; + debug _x => _2; } } scope 2 (inlined val) { @@ -17,13 +16,10 @@ bb0: { StorageLive(_1); - StorageLive(_2); - nop; _1 = Un { us: const 1_u32 }; + StorageLive(_2); + _2 = copy (_1.0: u32); StorageDead(_2); - StorageLive(_3); - _3 = copy (_1.0: u32); - StorageDead(_3); StorageDead(_1); return; } diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff index 19a00f977eb1..54c11679f0c6 100644 --- a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff @@ -20,7 +20,7 @@ StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = get(move _3) -> [return: bb1, unwind unreachable]; + _2 = get::>(move _3) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs index 87b52ae48086..33e31b569778 100644 --- a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs @@ -9,15 +9,16 @@ #![crate_type = "lib"] //@ test-mir-pass: GVN #![allow(internal_features)] -#![feature(rustc_attrs, core_intrinsics)] +#![feature(core_intrinsics, custom_mir, rustc_attrs)] + +use std::intrinsics::mir::*; // EMIT_MIR simplify_aggregate_to_copy_miscompile.foo.GVN.diff -#[no_mangle] fn foo(v: &mut Option) -> Option { // CHECK-LABEL: fn foo( // CHECK-SAME: [[v:_.*]]: &mut Option // CHECK: [[v_alias_1:_.*]] = &(*_1) - // CHECK-NEXT: [[v_alias_2:_.*]] = get(move [[v_alias_1]]) + // CHECK-NEXT: [[v_alias_2:_.*]] = get::>(move [[v_alias_1]]) // CHECK: (*[[v]]) = const Option::::None; // CHECK-NOT: _0 = copy (*[[v_alias_2]]) // CHECK: _0 = Option::::Some @@ -30,9 +31,31 @@ fn foo(v: &mut Option) -> Option { } } -#[no_mangle] +pub enum Value { + V0(i32), + V1(i32), +} + +// EMIT_MIR simplify_aggregate_to_copy_miscompile.set_discriminant.GVN.diff +#[custom_mir(dialect = "runtime", phase = "initial")] +fn set_discriminant(v: &mut Value) -> Value { + // CHECK-LABEL: fn set_discriminant( + mir! { + let v_: &Value; + { + Call(v_ = get(v), ReturnTo(ret), UnwindUnreachable()) + } + ret = { + let col: i32 = Field(Variant(*v_, 0), 0); + SetDiscriminant(*v, 1); + RET = Value::V0(col); + Return() + } + } +} + #[inline(never)] #[rustc_nounwind] -fn get(v: &Option) -> &Option { +fn get(v: &T) -> &T { v } diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.set_discriminant.GVN.diff b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.set_discriminant.GVN.diff new file mode 100644 index 000000000000..41f9763d0240 --- /dev/null +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.set_discriminant.GVN.diff @@ -0,0 +1,20 @@ +- // MIR for `set_discriminant` before GVN ++ // MIR for `set_discriminant` after GVN + + fn set_discriminant(_1: &mut Value) -> Value { + let mut _0: Value; + let mut _2: &Value; + let mut _3: i32; + + bb0: { + _2 = get::(copy _1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _3 = copy (((*_2) as variant#0).0: i32); + discriminant((*_1)) = 1; + _0 = Value::V0(copy _3); + return; + } + } + From a91e97c06c778b84663cfe4f2871b868d275a137 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 3 Apr 2025 17:20:45 +0200 Subject: [PATCH 122/176] Fix 2024 edition doctest panic output --- src/librustdoc/doctest/runner.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index f891505d2a60..09a3224a3c3f 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -113,6 +113,7 @@ impl DocTestRunner { mod __doctest_mod {{ use std::sync::OnceLock; use std::path::PathBuf; + use std::process::ExitCode; pub static BINARY_PATH: OnceLock = OnceLock::new(); pub const RUN_OPTION: &str = \"RUSTDOC_DOCTEST_RUN_NB_TEST\"; @@ -123,16 +124,17 @@ mod __doctest_mod {{ }} #[allow(unused)] - pub fn doctest_runner(bin: &std::path::Path, test_nb: usize) -> Result<(), String> {{ + pub fn doctest_runner(bin: &std::path::Path, test_nb: usize) -> ExitCode {{ let out = std::process::Command::new(bin) .env(self::RUN_OPTION, test_nb.to_string()) .args(std::env::args().skip(1).collect::>()) .output() .expect(\"failed to run command\"); if !out.status.success() {{ - Err(String::from_utf8_lossy(&out.stderr).to_string()) + eprintln!(\"{{}}\", String::from_utf8_lossy(&out.stderr)); + ExitCode::FAILURE }} else {{ - Ok(()) + ExitCode::SUCCESS }} }} }} From fff2484700bb7d1fa320a666109d1868767dfa6a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 3 Apr 2025 17:21:03 +0200 Subject: [PATCH 123/176] Add regression test for #137970 --- .../edition-2024-doctest-error-output.rs | 12 +++++++ .../edition-2024-doctest-error-output.stdout | 32 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/rustdoc-ui/edition-2024-doctest-error-output.rs create mode 100644 tests/rustdoc-ui/edition-2024-doctest-error-output.stdout diff --git a/tests/rustdoc-ui/edition-2024-doctest-error-output.rs b/tests/rustdoc-ui/edition-2024-doctest-error-output.rs new file mode 100644 index 000000000000..cabe5d1ae6ea --- /dev/null +++ b/tests/rustdoc-ui/edition-2024-doctest-error-output.rs @@ -0,0 +1,12 @@ +// This is a regression test for . +// The output must look nice and not like a `Debug` display of a `String`. + +//@ edition: 2024 +//@ compile-flags: --test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ failure-status: 101 + +//! ```rust +//! assert_eq!(2 + 2, 5); +//! ``` diff --git a/tests/rustdoc-ui/edition-2024-doctest-error-output.stdout b/tests/rustdoc-ui/edition-2024-doctest-error-output.stdout new file mode 100644 index 000000000000..5c4de44c21ab --- /dev/null +++ b/tests/rustdoc-ui/edition-2024-doctest-error-output.stdout @@ -0,0 +1,32 @@ + +running 1 test +test tests/rustdoc-ui/edition-2024-doctest-error-output.rs - (line 10) ... FAILED + +failures: + +---- tests/rustdoc-ui/edition-2024-doctest-error-output.rs - (line 10) stdout ---- + +thread 'main' panicked at /tmp/rustdoctestSZq9aS/doctest_bundle_2024.rs:6:1: +assertion `left == right` failed + left: 4 + right: 5 +stack backtrace: + 0: __rustc::rust_begin_unwind + 1: core::panicking::panic_fmt + 2: core::panicking::assert_failed_inner + 3: core::panicking::assert_failed + 4: doctest_bundle_2024::__doctest_0::main + 5: doctest_bundle_2024::__doctest_0::__main_fn + 6: doctest_runner_2024::__doctest_0::TEST::{{closure}} + 7: core::ops::function::FnOnce::call_once + 8: doctest_runner_2024::main + 9: core::ops::function::FnOnce::call_once +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. + + + +failures: + tests/rustdoc-ui/edition-2024-doctest-error-output.rs - (line 10) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From fde54c2c0301be851543220ce64c74a468a17311 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:30:01 +0000 Subject: [PATCH 124/176] Fix testing with randomized layouts enabled --- compiler/rustc_codegen_cranelift/build_system/tests.rs | 4 +++- library/alloc/Cargo.toml | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index eb15a3fc027e..eec89c026b26 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -109,10 +109,12 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ SYSROOT_TESTS.clean(&runner.dirs); + let mut target_compiler = runner.target_compiler.clone(); // coretests and alloctests produce a bunch of warnings. When running // in rust's CI warnings are denied, so we have to override that here. - let mut target_compiler = runner.target_compiler.clone(); target_compiler.rustflags.push("--cap-lints=allow".to_owned()); + // The standard library may have been compiled with -Zrandomize-layout. + target_compiler.rustflags.extend(["--cfg".to_owned(), "randomized_layouts".to_owned()]); if runner.is_native { let mut test_cmd = SYSROOT_TESTS.test(&target_compiler, &runner.dirs); diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index b729d5e116d2..1d2dd1e60819 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -36,5 +36,4 @@ check-cfg = [ 'cfg(no_global_oom_handling)', 'cfg(no_rc)', 'cfg(no_sync)', - 'cfg(randomized_layouts)', ] From 6189594c0a614432a4f099b15f176d57a46c257b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 3 Apr 2025 10:43:32 +0000 Subject: [PATCH 125/176] Deduplicate some `rustc_middle` function bodies by calling the `rustc_type_ir` equivalent --- compiler/rustc_middle/src/ty/sty.rs | 47 ++----------------- compiler/rustc_type_ir/src/inherent.rs | 57 +---------------------- compiler/rustc_type_ir/src/ty_kind.rs | 62 ++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 74a94d827845..27ee363f1c14 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -8,7 +8,7 @@ use std::iter; use std::ops::{ControlFlow, Range}; use hir::def::{CtorKind, DefKind}; -use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx}; +use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::LangItem; @@ -1441,23 +1441,7 @@ impl<'tcx> Ty<'tcx> { #[tracing::instrument(level = "trace", skip(tcx))] pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { - match self.kind() { - FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args), - FnPtr(sig_tys, hdr) => sig_tys.with(*hdr), - Error(_) => { - // ignore errors (#54954) - Binder::dummy(ty::FnSig { - inputs_and_output: ty::List::empty(), - c_variadic: false, - safety: hir::Safety::Safe, - abi: ExternAbi::Rust, - }) - } - Closure(..) => bug!( - "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", - ), - _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self), - } + self.kind().fn_sig(tcx) } #[inline] @@ -2043,32 +2027,7 @@ impl<'tcx> Ty<'tcx> { /// nested types may be further simplified, the outermost [`TyKind`] or /// type constructor remains the same. pub fn is_known_rigid(self) -> bool { - match self.kind() { - Bool - | Char - | Int(_) - | Uint(_) - | Float(_) - | Adt(_, _) - | Foreign(_) - | Str - | Array(_, _) - | Pat(_, _) - | Slice(_) - | RawPtr(_, _) - | Ref(_, _, _) - | FnDef(_, _) - | FnPtr(..) - | Dynamic(_, _, _) - | Closure(_, _) - | CoroutineClosure(_, _) - | Coroutine(_, _) - | CoroutineWitness(..) - | Never - | Tuple(_) - | UnsafeBinder(_) => true, - Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false, - } + self.kind().is_known_rigid() } } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index d4134bdf3a78..59c2d3c2fc8d 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -146,67 +146,14 @@ pub trait Ty>: fn has_unsafe_fields(self) -> bool; fn fn_sig(self, interner: I) -> ty::Binder> { - match self.kind() { - ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), - ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args), - ty::Error(_) => { - // ignore errors (#54954) - ty::Binder::dummy(ty::FnSig { - inputs_and_output: Default::default(), - c_variadic: false, - safety: I::Safety::safe(), - abi: I::Abi::rust(), - }) - } - ty::Closure(..) => panic!( - "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", - ), - _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self), - } + self.kind().fn_sig(interner) } fn discriminant_ty(self, interner: I) -> I::Ty; fn async_destructor_ty(self, interner: I) -> I::Ty; - - /// Returns `true` when the outermost type cannot be further normalized, - /// resolved, or instantiated. This includes all primitive types, but also - /// things like ADTs and trait objects, since even if their arguments or - /// nested types may be further simplified, the outermost [`ty::TyKind`] or - /// type constructor remains the same. fn is_known_rigid(self) -> bool { - match self.kind() { - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Adt(_, _) - | ty::Foreign(_) - | ty::Str - | ty::Array(_, _) - | ty::Pat(_, _) - | ty::Slice(_) - | ty::RawPtr(_, _) - | ty::Ref(_, _, _) - | ty::FnDef(_, _) - | ty::FnPtr(..) - | ty::UnsafeBinder(_) - | ty::Dynamic(_, _, _) - | ty::Closure(_, _) - | ty::CoroutineClosure(_, _) - | ty::Coroutine(_, _) - | ty::CoroutineWitness(..) - | ty::Never - | ty::Tuple(_) => true, - - ty::Error(_) - | ty::Infer(_) - | ty::Alias(_, _) - | ty::Param(_) - | ty::Bound(_, _) - | ty::Placeholder(_) => false, - } + self.kind().is_known_rigid() } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 9bea4482b550..d35b22d517c5 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -273,6 +273,68 @@ pub enum TyKind { Error(I::ErrorGuaranteed), } +impl TyKind { + pub fn fn_sig(self, interner: I) -> ty::Binder> { + match self { + ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), + ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args), + ty::Error(_) => { + // ignore errors (#54954) + ty::Binder::dummy(ty::FnSig { + inputs_and_output: Default::default(), + c_variadic: false, + safety: I::Safety::safe(), + abi: I::Abi::rust(), + }) + } + ty::Closure(..) => panic!( + "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", + ), + _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self), + } + } + + /// Returns `true` when the outermost type cannot be further normalized, + /// resolved, or instantiated. This includes all primitive types, but also + /// things like ADTs and trait objects, since even if their arguments or + /// nested types may be further simplified, the outermost [`ty::TyKind`] or + /// type constructor remains the same. + pub fn is_known_rigid(self) -> bool { + match self { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::Slice(_) + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(..) + | ty::UnsafeBinder(_) + | ty::Dynamic(_, _, _) + | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Tuple(_) => true, + + ty::Error(_) + | ty::Infer(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Placeholder(_) => false, + } + } +} + // This is manually implemented because a derive would require `I: Debug` impl fmt::Debug for TyKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { From f9927ee042f7d7418fbb64082272ce1feff4d895 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 3 Apr 2025 17:58:59 +0200 Subject: [PATCH 126/176] Use `eprint!` instead of `eprintln!` --- src/librustdoc/doctest/runner.rs | 2 +- .../edition-2024-error-output.rs} | 2 ++ .../doctest/edition-2024-error-output.stdout | 20 ++++++++++++ .../edition-2024-doctest-error-output.stdout | 32 ------------------- 4 files changed, 23 insertions(+), 33 deletions(-) rename tests/rustdoc-ui/{edition-2024-doctest-error-output.rs => doctest/edition-2024-error-output.rs} (80%) create mode 100644 tests/rustdoc-ui/doctest/edition-2024-error-output.stdout delete mode 100644 tests/rustdoc-ui/edition-2024-doctest-error-output.stdout diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index 09a3224a3c3f..5fd577e35315 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -131,7 +131,7 @@ mod __doctest_mod {{ .output() .expect(\"failed to run command\"); if !out.status.success() {{ - eprintln!(\"{{}}\", String::from_utf8_lossy(&out.stderr)); + eprint!(\"{{}}\", String::from_utf8_lossy(&out.stderr)); ExitCode::FAILURE }} else {{ ExitCode::SUCCESS diff --git a/tests/rustdoc-ui/edition-2024-doctest-error-output.rs b/tests/rustdoc-ui/doctest/edition-2024-error-output.rs similarity index 80% rename from tests/rustdoc-ui/edition-2024-doctest-error-output.rs rename to tests/rustdoc-ui/doctest/edition-2024-error-output.rs index cabe5d1ae6ea..82a85debcd19 100644 --- a/tests/rustdoc-ui/edition-2024-doctest-error-output.rs +++ b/tests/rustdoc-ui/doctest/edition-2024-error-output.rs @@ -4,7 +4,9 @@ //@ edition: 2024 //@ compile-flags: --test //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "panicked at .+rs:" -> "panicked at $$TMP:" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ rustc-env:RUST_BACKTRACE=0 //@ failure-status: 101 //! ```rust diff --git a/tests/rustdoc-ui/doctest/edition-2024-error-output.stdout b/tests/rustdoc-ui/doctest/edition-2024-error-output.stdout new file mode 100644 index 000000000000..8f056a5f703e --- /dev/null +++ b/tests/rustdoc-ui/doctest/edition-2024-error-output.stdout @@ -0,0 +1,20 @@ + +running 1 test +test $DIR/edition-2024-error-output.rs - (line 12) ... FAILED + +failures: + +---- $DIR/edition-2024-error-output.rs - (line 12) stdout ---- + +thread 'main' panicked at $TMP:6:1: +assertion `left == right` failed + left: 4 + right: 5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + + +failures: + $DIR/edition-2024-error-output.rs - (line 12) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/edition-2024-doctest-error-output.stdout b/tests/rustdoc-ui/edition-2024-doctest-error-output.stdout deleted file mode 100644 index 5c4de44c21ab..000000000000 --- a/tests/rustdoc-ui/edition-2024-doctest-error-output.stdout +++ /dev/null @@ -1,32 +0,0 @@ - -running 1 test -test tests/rustdoc-ui/edition-2024-doctest-error-output.rs - (line 10) ... FAILED - -failures: - ----- tests/rustdoc-ui/edition-2024-doctest-error-output.rs - (line 10) stdout ---- - -thread 'main' panicked at /tmp/rustdoctestSZq9aS/doctest_bundle_2024.rs:6:1: -assertion `left == right` failed - left: 4 - right: 5 -stack backtrace: - 0: __rustc::rust_begin_unwind - 1: core::panicking::panic_fmt - 2: core::panicking::assert_failed_inner - 3: core::panicking::assert_failed - 4: doctest_bundle_2024::__doctest_0::main - 5: doctest_bundle_2024::__doctest_0::__main_fn - 6: doctest_runner_2024::__doctest_0::TEST::{{closure}} - 7: core::ops::function::FnOnce::call_once - 8: doctest_runner_2024::main - 9: core::ops::function::FnOnce::call_once -note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. - - - -failures: - tests/rustdoc-ui/edition-2024-doctest-error-output.rs - (line 10) - -test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME - From 087ffd73bf43671db22087570c97e0afdde20f31 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Thu, 3 Apr 2025 17:19:11 -0400 Subject: [PATCH 127/176] add the autodiff batch mode frontend --- .../rustc_ast/src/expand/autodiff_attrs.rs | 13 + compiler/rustc_builtin_macros/messages.ftl | 1 + compiler/rustc_builtin_macros/src/autodiff.rs | 341 +++++++++++------- compiler/rustc_builtin_macros/src/errors.rs | 8 + .../rustc_codegen_ssa/src/codegen_attrs.rs | 2 +- 5 files changed, 237 insertions(+), 128 deletions(-) diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs index c8ec185ee5e2..f01c781f46c6 100644 --- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs +++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs @@ -77,6 +77,17 @@ pub struct AutoDiffAttrs { /// e.g. in the [JAX /// Documentation](https://jax.readthedocs.io/en/latest/_tutorials/advanced-autodiff.html#how-it-s-made-two-foundational-autodiff-functions). pub mode: DiffMode, + /// A user-provided, batching width. If not given, we will default to 1 (no batching). + /// Calling a differentiated, non-batched function through a loop 100 times is equivalent to: + /// - Calling the function 50 times with a batch size of 2 + /// - Calling the function 25 times with a batch size of 4, + /// etc. A batched function takes more (or longer) arguments, and might be able to benefit from + /// cache locality, better re-usal of primal values, and other optimizations. + /// We will (before LLVM's vectorizer runs) just generate most LLVM-IR instructions `width` + /// times, so this massively increases code size. As such, values like 1024 are unlikely to + /// work. We should consider limiting this to u8 or u16, but will leave it at u32 for + /// experiments for now and focus on documenting the implications of a large width. + pub width: u32, pub ret_activity: DiffActivity, pub input_activity: Vec, } @@ -222,6 +233,7 @@ impl AutoDiffAttrs { pub const fn error() -> Self { AutoDiffAttrs { mode: DiffMode::Error, + width: 0, ret_activity: DiffActivity::None, input_activity: Vec::new(), } @@ -229,6 +241,7 @@ impl AutoDiffAttrs { pub fn source() -> Self { AutoDiffAttrs { mode: DiffMode::Source, + width: 0, ret_activity: DiffActivity::None, input_activity: Vec::new(), } diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 3f03834f8d78..603dc90bafca 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -79,6 +79,7 @@ builtin_macros_autodiff_ret_activity = invalid return activity {$act} in {$mode} builtin_macros_autodiff_ty_activity = {$act} can not be used for this type builtin_macros_autodiff_unknown_activity = did not recognize Activity: `{$act}` +builtin_macros_autodiff_width = autodiff width must fit u32, but is {$width} builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s .label = not applicable here .label2 = not a `struct`, `enum` or `union` diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 6591ed151cf6..032ab82e9892 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -12,12 +12,12 @@ mod llvm_enzyme { valid_ty_for_activity, }; use rustc_ast::ptr::P; - use rustc_ast::token::{Token, TokenKind}; + use rustc_ast::token::{Lit, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::*; use rustc_ast::visit::AssocCtxt::*; use rustc_ast::{ - self as ast, AssocItemKind, BindingMode, FnRetTy, FnSig, Generics, ItemKind, MetaItemInner, - PatKind, TyKind, + self as ast, AssocItemKind, BindingMode, ExprKind, FnRetTy, FnSig, Generics, ItemKind, + MetaItemInner, PatKind, QSelf, TyKind, }; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::{Ident, Span, Symbol, kw, sym}; @@ -45,6 +45,16 @@ mod llvm_enzyme { } } fn first_ident(x: &MetaItemInner) -> rustc_span::Ident { + if let Some(l) = x.lit() { + match l.kind { + ast::LitKind::Int(val, _) => { + // get an Ident from a lit + return rustc_span::Ident::from_str(val.get().to_string().as_str()); + } + _ => {} + } + } + let segments = &x.meta_item().unwrap().path.segments; assert!(segments.len() == 1); segments[0].ident @@ -54,6 +64,14 @@ mod llvm_enzyme { first_ident(x).name.to_string() } + fn width(x: &MetaItemInner) -> Option { + let lit = x.lit()?; + match lit.kind { + ast::LitKind::Int(x, _) => Some(x.get()), + _ => return None, + } + } + pub(crate) fn from_ast( ecx: &mut ExtCtxt<'_>, meta_item: &ThinVec, @@ -65,9 +83,32 @@ mod llvm_enzyme { dcx.emit_err(errors::AutoDiffInvalidMode { span: meta_item[1].span(), mode }); return AutoDiffAttrs::error(); }; + + // Now we check, whether the user wants autodiff in batch/vector mode, or scalar mode. + // If he doesn't specify an integer (=width), we default to scalar mode, thus width=1. + let mut first_activity = 2; + + let width = if let [_, _, x, ..] = &meta_item[..] + && let Some(x) = width(x) + { + first_activity = 3; + match x.try_into() { + Ok(x) => x, + Err(_) => { + dcx.emit_err(errors::AutoDiffInvalidWidth { + span: meta_item[2].span(), + width: x, + }); + return AutoDiffAttrs::error(); + } + } + } else { + 1 + }; + let mut activities: Vec = vec![]; let mut errors = false; - for x in &meta_item[2..] { + for x in &meta_item[first_activity..] { let activity_str = name(&x); let res = DiffActivity::from_str(&activity_str); match res { @@ -98,7 +139,20 @@ mod llvm_enzyme { (&DiffActivity::None, activities.as_slice()) }; - AutoDiffAttrs { mode, ret_activity: *ret_activity, input_activity: input_activity.to_vec() } + AutoDiffAttrs { + mode, + width, + ret_activity: *ret_activity, + input_activity: input_activity.to_vec(), + } + } + + fn meta_item_inner_to_ts(t: &MetaItemInner, ts: &mut Vec) { + let comma: Token = Token::new(TokenKind::Comma, Span::default()); + let val = first_ident(t); + let t = Token::from_ast_ident(val); + ts.push(TokenTree::Token(t, Spacing::Joint)); + ts.push(TokenTree::Token(comma.clone(), Spacing::Alone)); } /// We expand the autodiff macro to generate a new placeholder function which passes @@ -197,27 +251,49 @@ mod llvm_enzyme { // create TokenStream from vec elemtents: // meta_item doesn't have a .tokens field - let comma: Token = Token::new(TokenKind::Comma, Span::default()); let mut ts: Vec = vec![]; if meta_item_vec.len() < 2 { // At the bare minimum, we need a fnc name and a mode, even for a dummy function with no // input and output args. dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() }); return vec![item]; - } else { - for t in meta_item_vec.clone()[1..].iter() { - let val = first_ident(t); - let t = Token::from_ast_ident(val); - ts.push(TokenTree::Token(t, Spacing::Joint)); - ts.push(TokenTree::Token(comma.clone(), Spacing::Alone)); - } } + + meta_item_inner_to_ts(&meta_item_vec[1], &mut ts); + + // Now, if the user gave a width (vector aka batch-mode ad), then we copy it. + // If it is not given, we default to 1 (scalar mode). + let start_position; + let kind: LitKind = LitKind::Integer; + let symbol; + if meta_item_vec.len() >= 3 + && let Some(width) = width(&meta_item_vec[2]) + { + start_position = 3; + symbol = Symbol::intern(&width.to_string()); + } else { + start_position = 2; + symbol = sym::integer(1); + } + let l: Lit = Lit { kind, symbol, suffix: None }; + let t = Token::new(TokenKind::Literal(l), Span::default()); + let comma = Token::new(TokenKind::Comma, Span::default()); + ts.push(TokenTree::Token(t, Spacing::Joint)); + ts.push(TokenTree::Token(comma.clone(), Spacing::Alone)); + + for t in meta_item_vec.clone()[start_position..].iter() { + meta_item_inner_to_ts(t, &mut ts); + } + if !has_ret { // We don't want users to provide a return activity if the function doesn't return anything. // For simplicity, we just add a dummy token to the end of the list. let t = Token::new(TokenKind::Ident(sym::None, false.into()), Span::default()); ts.push(TokenTree::Token(t, Spacing::Joint)); + ts.push(TokenTree::Token(comma, Spacing::Alone)); } + // We remove the last, trailing comma. + ts.pop(); let ts: TokenStream = TokenStream::from_iter(ts); let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret); @@ -475,6 +551,8 @@ mod llvm_enzyme { return body; } + // Everything from here onwards just tries to fullfil the return type. Fun! + // having an active-only return means we'll drop the original return type. // So that can be treated identical to not having one in the first place. let primal_ret = has_ret(&sig.decl.output) && !x.has_active_only_ret(); @@ -502,86 +580,65 @@ mod llvm_enzyme { return body; } - let mut exprs = ThinVec::>::new(); - if primal_ret { - // We have both primal ret and active floats. - // primal ret is first, by construction. - exprs.push(primal_call); - } - - // Now construct default placeholder for each active float. - // Is there something nicer than f32::default() and f64::default()? + let mut exprs: P = primal_call.clone(); let d_ret_ty = match d_sig.decl.output { FnRetTy::Ty(ref ty) => ty.clone(), FnRetTy::Default(span) => { panic!("Did not expect Default ret ty: {:?}", span); } }; - let mut d_ret_ty = match d_ret_ty.kind.clone() { - TyKind::Tup(ref tys) => tys.clone(), - TyKind::Path(_, rustc_ast::Path { segments, .. }) => { - if let [segment] = &segments[..] - && segment.args.is_none() - { - let id = vec![segments[0].ident]; - let kind = TyKind::Path(None, ecx.path(span, id)); - let ty = P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None }); - thin_vec![ty] - } else { - panic!("Expected tuple or simple path return type"); - } - } - _ => { - // We messed up construction of d_sig - panic!("Did not expect non-tuple ret ty: {:?}", d_ret_ty); - } - }; - if x.mode.is_fwd() && x.ret_activity == DiffActivity::Dual { - assert!(d_ret_ty.len() == 2); - // both should be identical, by construction - let arg = d_ret_ty[0].kind.is_simple_path().unwrap(); - let arg2 = d_ret_ty[1].kind.is_simple_path().unwrap(); - assert!(arg == arg2); - let sl: Vec = vec![arg, kw::Default]; - let tmp = ecx.def_site_path(&sl); - let default_call_expr = ecx.expr_path(ecx.path(span, tmp)); - let default_call_expr = ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); - exprs.push(default_call_expr); - } else if x.mode.is_rev() { - if primal_ret { - // We have extra handling above for the primal ret - d_ret_ty = d_ret_ty[1..].to_vec().into(); - } - - for arg in d_ret_ty.iter() { - let arg = arg.kind.is_simple_path().unwrap(); - let sl: Vec = vec![arg, kw::Default]; - let tmp = ecx.def_site_path(&sl); - let default_call_expr = ecx.expr_path(ecx.path(span, tmp)); + if x.mode.is_fwd() { + // Fwd mode is easy. If the return activity is Const, we support arbitrary types. + // Otherwise, we only support a scalar, a pair of scalars, or an array of scalars. + // We checked that (on a best-effort base) in the preceding gen_enzyme_decl function. + // In all three cases, we can return `std::hint::black_box(::default())`. + if x.ret_activity == DiffActivity::Const { + // Here we call the primal function, since our dummy function has the same return + // type due to the Const return activity. + exprs = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![exprs]); + } else { + let q = QSelf { ty: d_ret_ty.clone(), path_span: span, position: 0 }; + let y = + ExprKind::Path(Some(P(q)), ecx.path_ident(span, Ident::from_str("default"))); + let default_call_expr = ecx.expr(span, y); let default_call_expr = ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); - exprs.push(default_call_expr); + exprs = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![default_call_expr]); } + } else if x.mode.is_rev() { + if x.width == 1 { + // We either have `-> ArbitraryType` or `-> (ArbitraryType, repeated_float_scalars)`. + match d_ret_ty.kind { + TyKind::Tup(ref args) => { + // We have a tuple return type. We need to create a tuple of the same size + // and fill it with default values. + let mut exprs2 = thin_vec![exprs]; + for arg in args.iter().skip(1) { + let arg = arg.kind.is_simple_path().unwrap(); + let sl: Vec = vec![arg, kw::Default]; + let tmp = ecx.def_site_path(&sl); + let default_call_expr = ecx.expr_path(ecx.path(span, tmp)); + let default_call_expr = + ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); + exprs2.push(default_call_expr); + } + exprs = ecx.expr_tuple(new_decl_span, exprs2); + } + _ => { + // Interestingly, even the `-> ArbitraryType` case + // ends up getting matched and handled correctly above, + // so we don't have to handle any other case for now. + panic!("Unsupported return type: {:?}", d_ret_ty); + } + } + } + exprs = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![exprs]); + } else { + unreachable!("Unsupported mode: {:?}", x.mode); } - let ret: P; - match &exprs[..] { - [] => { - assert!(!has_ret(&d_sig.decl.output)); - // We don't have to match the return type. - return body; - } - [arg] => { - ret = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![arg.clone()]); - } - args => { - let ret_tuple: P = ecx.expr_tuple(span, args.into()); - ret = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![ret_tuple]); - } - } - assert!(has_ret(&d_sig.decl.output)); - body.stmts.push(ecx.stmt_expr(ret)); + body.stmts.push(ecx.stmt_expr(exprs)); body } @@ -689,50 +746,55 @@ mod llvm_enzyme { match activity { DiffActivity::Active => { act_ret.push(arg.ty.clone()); + // if width =/= 1, then push [arg.ty; width] to act_ret } DiffActivity::ActiveOnly => { // We will add the active scalar to the return type. // This is handled later. } DiffActivity::Duplicated | DiffActivity::DuplicatedOnly => { - let mut shadow_arg = arg.clone(); - // We += into the shadow in reverse mode. - shadow_arg.ty = P(assure_mut_ref(&arg.ty)); - let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind { - ident.name - } else { - debug!("{:#?}", &shadow_arg.pat); - panic!("not an ident?"); - }; - let name: String = format!("d{}", old_name); - new_inputs.push(name.clone()); - let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); - shadow_arg.pat = P(ast::Pat { - id: ast::DUMMY_NODE_ID, - kind: PatKind::Ident(BindingMode::NONE, ident, None), - span: shadow_arg.pat.span, - tokens: shadow_arg.pat.tokens.clone(), - }); - d_inputs.push(shadow_arg); + for i in 0..x.width { + let mut shadow_arg = arg.clone(); + // We += into the shadow in reverse mode. + shadow_arg.ty = P(assure_mut_ref(&arg.ty)); + let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind { + ident.name + } else { + debug!("{:#?}", &shadow_arg.pat); + panic!("not an ident?"); + }; + let name: String = format!("d{}_{}", old_name, i); + new_inputs.push(name.clone()); + let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); + shadow_arg.pat = P(ast::Pat { + id: ast::DUMMY_NODE_ID, + kind: PatKind::Ident(BindingMode::NONE, ident, None), + span: shadow_arg.pat.span, + tokens: shadow_arg.pat.tokens.clone(), + }); + d_inputs.push(shadow_arg.clone()); + } } DiffActivity::Dual | DiffActivity::DualOnly => { - let mut shadow_arg = arg.clone(); - let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind { - ident.name - } else { - debug!("{:#?}", &shadow_arg.pat); - panic!("not an ident?"); - }; - let name: String = format!("b{}", old_name); - new_inputs.push(name.clone()); - let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); - shadow_arg.pat = P(ast::Pat { - id: ast::DUMMY_NODE_ID, - kind: PatKind::Ident(BindingMode::NONE, ident, None), - span: shadow_arg.pat.span, - tokens: shadow_arg.pat.tokens.clone(), - }); - d_inputs.push(shadow_arg); + for i in 0..x.width { + let mut shadow_arg = arg.clone(); + let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind { + ident.name + } else { + debug!("{:#?}", &shadow_arg.pat); + panic!("not an ident?"); + }; + let name: String = format!("b{}_{}", old_name, i); + new_inputs.push(name.clone()); + let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); + shadow_arg.pat = P(ast::Pat { + id: ast::DUMMY_NODE_ID, + kind: PatKind::Ident(BindingMode::NONE, ident, None), + span: shadow_arg.pat.span, + tokens: shadow_arg.pat.tokens.clone(), + }); + d_inputs.push(shadow_arg.clone()); + } } DiffActivity::Const => { // Nothing to do here. @@ -788,23 +850,48 @@ mod llvm_enzyme { d_decl.inputs = d_inputs.into(); if x.mode.is_fwd() { + let ty = match d_decl.output { + FnRetTy::Ty(ref ty) => ty.clone(), + FnRetTy::Default(span) => { + // We want to return std::hint::black_box(()). + let kind = TyKind::Tup(ThinVec::new()); + let ty = P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None }); + d_decl.output = FnRetTy::Ty(ty.clone()); + assert!(matches!(x.ret_activity, DiffActivity::None)); + // this won't be used below, so any type would be fine. + ty + } + }; + if let DiffActivity::Dual = x.ret_activity { - let ty = match d_decl.output { - FnRetTy::Ty(ref ty) => ty.clone(), - FnRetTy::Default(span) => { - panic!("Did not expect Default ret ty: {:?}", span); - } + let kind = if x.width == 1 { + // Dual can only be used for f32/f64 ret. + // In that case we return now a tuple with two floats. + TyKind::Tup(thin_vec![ty.clone(), ty.clone()]) + } else { + // We have to return [T; width+1], +1 for the primal return. + let anon_const = rustc_ast::AnonConst { + id: ast::DUMMY_NODE_ID, + value: ecx.expr_usize(span, 1 + x.width as usize), + }; + TyKind::Array(ty.clone(), anon_const) }; - // Dual can only be used for f32/f64 ret. - // In that case we return now a tuple with two floats. - let kind = TyKind::Tup(thin_vec![ty.clone(), ty.clone()]); let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None }); d_decl.output = FnRetTy::Ty(ty); } if let DiffActivity::DualOnly = x.ret_activity { // No need to change the return type, - // we will just return the shadow in place - // of the primal return. + // we will just return the shadow in place of the primal return. + // However, if we have a width > 1, then we don't return -> T, but -> [T; width] + if x.width > 1 { + let anon_const = rustc_ast::AnonConst { + id: ast::DUMMY_NODE_ID, + value: ecx.expr_usize(span, x.width as usize), + }; + let kind = TyKind::Array(ty.clone(), anon_const); + let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None }); + d_decl.output = FnRetTy::Ty(ty); + } } } diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 30597944124c..4bbe212f4296 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -202,6 +202,14 @@ mod autodiff { pub(crate) mode: String, } + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_width)] + pub(crate) struct AutoDiffInvalidWidth { + #[primary_span] + pub(crate) span: Span, + pub(crate) width: u128, + } + #[derive(Diagnostic)] #[diag(builtin_macros_autodiff)] pub(crate) struct AutoDiffInvalidApplication { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index d16d4ed22838..4b2fd61442bd 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -860,7 +860,7 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option { } } - Some(AutoDiffAttrs { mode, ret_activity, input_activity: arg_activities }) + Some(AutoDiffAttrs { mode, width: 1, ret_activity, input_activity: arg_activities }) } pub(crate) fn provide(providers: &mut Providers) { From e0c8ead8802fcc314ec852a6641e08fd09307708 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Thu, 3 Apr 2025 17:21:21 -0400 Subject: [PATCH 128/176] add autodiff batching middle-end --- .../rustc_codegen_ssa/src/codegen_attrs.rs | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 4b2fd61442bd..02f631c7b39b 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use rustc_abi::ExternAbi; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; -use rustc_ast::{MetaItem, MetaItemInner, attr}; +use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; use rustc_attr_parsing::ReprAttr::ReprAlign; use rustc_attr_parsing::{AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_data_structures::fx::FxHashMap; @@ -805,8 +805,8 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option { return Some(AutoDiffAttrs::source()); } - let [mode, input_activities @ .., ret_activity] = &list[..] else { - span_bug!(attr.span(), "rustc_autodiff attribute must contain mode and activities"); + let [mode, width_meta, input_activities @ .., ret_activity] = &list[..] else { + span_bug!(attr.span(), "rustc_autodiff attribute must contain mode, width and activities"); }; let mode = if let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = mode { p1.segments.first().unwrap().ident @@ -823,6 +823,30 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option { } }; + let width: u32 = match width_meta { + MetaItemInner::MetaItem(MetaItem { path: p1, .. }) => { + let w = p1.segments.first().unwrap().ident; + match w.as_str().parse() { + Ok(val) => val, + Err(_) => { + span_bug!(w.span, "rustc_autodiff width should fit u32"); + } + } + } + MetaItemInner::Lit(lit) => { + if let LitKind::Int(val, _) = lit.kind { + match val.get().try_into() { + Ok(val) => val, + Err(_) => { + span_bug!(lit.span, "rustc_autodiff width should fit u32"); + } + } + } else { + span_bug!(lit.span, "rustc_autodiff width should be an integer"); + } + } + }; + // First read the ret symbol from the attribute let ret_symbol = if let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = ret_activity { p1.segments.first().unwrap().ident @@ -860,7 +884,7 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option { } } - Some(AutoDiffAttrs { mode, width: 1, ret_activity, input_activity: arg_activities }) + Some(AutoDiffAttrs { mode, width, ret_activity, input_activity: arg_activities }) } pub(crate) fn provide(providers: &mut Providers) { From 897f9e5985fb8a43fef6bbb40701efebc36bb9bc Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Fri, 4 Apr 2025 00:20:49 +0200 Subject: [PATCH 129/176] unstable book: document tait --- .../type-alias-impl-trait.md | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/type-alias-impl-trait.md diff --git a/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md b/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md new file mode 100644 index 000000000000..b91c553e8645 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md @@ -0,0 +1,159 @@ +# `type_alias_impl_trait` + +The tracking issue for this feature is: [#63063] + +------------------------ + +> This feature is not to be confused with [`trait_alias`] or [`impl_trait_in_assoc_type`]. + +### What is `impl Trait`? + +`impl Trait` in return position is useful for declaring types that are constrained by traits, but whose concrete type should be hidden: + +```rust +use std::fmt::Debug; + +fn new() -> impl Debug { + 42 +} + +fn main() { + let thing = new(); + // What actually is a `thing`? + // No idea but we know it implements `Debug`, so we can debug print it + println!("{thing:?}"); +} +``` + +See the [reference] for more information about `impl Trait` in return position. + +### `type_alias_impl_trait` + +However, we might want to use an `impl Trait` in multiple locations but actually use the same concrete type everywhere while keeping it hidden. +This can be useful in libraries where you want to hide implementation details. + +The `#[define_opaque]` attribute must be used to explicitly list opaque items constrained by the item it's on. + +```rust +#![feature(type_alias_impl_trait)] +# #![allow(unused_variables, dead_code)] +trait Trait {} + +struct MyType; + +impl Trait for MyType {} + +type Alias = impl Trait; + +#[define_opaque(Alias)] // To constrain the type alias to `MyType` +fn new() -> Alias { + MyType +} + +#[define_opaque(Alias)] // So we can name the concrete type inside this item +fn main() { + let thing: MyType = new(); +} + +// It can be a part of a struct too +struct HaveAlias { + stuff: String, + thing: Alias, +} +``` + +In this example, the concrete type referred to by `Alias` is guaranteed to be the same wherever `Alias` occurs. + +> Orginally this feature included type aliases as an associated type of a trait. In [#110237] this was split off to [`impl_trait_in_assoc_type`]. + +### `type_alias_impl_trait` in argument position. + +Note that using `Alias` as an argument type is *not* the same as argument-position `impl Trait`, as `Alias` refers to a unique type, whereas the concrete type for argument-position `impl Trait` is chosen by the caller. + +```rust +# #![feature(type_alias_impl_trait)] +# #![allow(unused_variables)] +# pub mod x { +# pub trait Trait {} +# +# struct MyType; +# +# impl Trait for MyType {} +# +# pub type Alias = impl Trait; +# +# #[define_opaque(Alias)] +# pub fn new() -> Alias { +# MyType +# } +# } +# use x::*; +// this... +pub fn take_alias(x: Alias) { + // ... +} + +// ...is *not* the same as +pub fn take_impl(x: impl Trait) { + // ... +} +# fn main(){} +``` + +```rust,compile_fail,E0308 +# #![feature(type_alias_impl_trait)] +# #![allow(unused_variables)] +# pub mod x { +# pub trait Trait {} +# +# struct MyType; +# +# impl Trait for MyType {} +# +# pub type Alias = impl Trait; +# +# #[define_opaque(Alias)] +# pub fn new() -> Alias { +# MyType +# } +# } +# use x::*; +# pub fn take_alias(x: Alias) { +# // ... +# } +# +# pub fn take_impl(x: impl Trait) { +# // ... +# } +# +// a user's crate using the trait and type alias +struct UserType; +impl Trait for UserType {} + +# fn main(){ +let x = UserType; +take_alias(x); +// ERROR expected opaque type, found `UserType` +// this function *actually* takes a `MyType` as is constrained in `new` + +let x = UserType; +take_impl(x); +// OK + +let x = new(); +take_alias(x); +// OK + +let x = new(); +take_impl(x); +// OK +# } +``` + +Note that the user cannot use `#[define_opaque(Alias)]` to reify the opaque type because only the crate where the type alias is declared may do so. But if this happened in the same crate and the opaque type was reified, they'd get a familiar error: "expected `MyType`, got `UserType`". + +[#63063]: https://github.com/rust-lang/rust/issues/63063 +[#110237]: (https://github.com/rust-lang/rust/pull/110237) +[reference]: (https://doc.rust-lang.org/stable/reference/types/impl-trait.html#abstract-return-types) +[`trait_alias`]: (./trait-alias.md) +[`impl_trait_in_assoc_type`]: (./impl-trait-in-assoc-type.md) From aa1b7bf070376b9b895d36a64263a5959eefebdd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Apr 2025 09:34:47 +1100 Subject: [PATCH 130/176] Remove an unwanted comment. I accidentally added this in #138740. --- compiler/rustc_ast_lowering/src/item.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 28f596ac0926..958a6917dff8 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -676,12 +676,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); let safety = self.lower_safety(*safety, hir::Safety::Unsafe); - - // njn: where for this? if define_opaque.is_some() { self.dcx().span_err(i.span, "foreign statics cannot define opaque types"); } - (ident, hir::ForeignItemKind::Static(ty, *mutability, safety)) } ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => { From b98760ba2dc4fffee19c75b83a472fe6f039f115 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Fri, 4 Apr 2025 01:23:01 +0200 Subject: [PATCH 131/176] Fix links --- .../src/language-features/type-alias-impl-trait.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md b/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md index b91c553e8645..a6fb25a55be2 100644 --- a/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md +++ b/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md @@ -153,7 +153,7 @@ take_impl(x); Note that the user cannot use `#[define_opaque(Alias)]` to reify the opaque type because only the crate where the type alias is declared may do so. But if this happened in the same crate and the opaque type was reified, they'd get a familiar error: "expected `MyType`, got `UserType`". [#63063]: https://github.com/rust-lang/rust/issues/63063 -[#110237]: (https://github.com/rust-lang/rust/pull/110237) -[reference]: (https://doc.rust-lang.org/stable/reference/types/impl-trait.html#abstract-return-types) -[`trait_alias`]: (./trait-alias.md) -[`impl_trait_in_assoc_type`]: (./impl-trait-in-assoc-type.md) +[#110237]: https://github.com/rust-lang/rust/pull/110237 +[reference]: https://doc.rust-lang.org/stable/reference/types/impl-trait.html#abstract-return-types +[`trait_alias`]: ./trait-alias.md +[`impl_trait_in_assoc_type`]: ./impl-trait-in-assoc-type.md From ad1fb1e2086d152a912a0be071584f15dac46470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Fri, 4 Apr 2025 01:34:35 +0200 Subject: [PATCH 132/176] Add a mailmap entry for myself --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index a791daa681d4..f4c8dab5a665 100644 --- a/.mailmap +++ b/.mailmap @@ -408,6 +408,8 @@ Luqman Aden Luqman Aden Lzu Tao Maik Klein +Maja Kądziołka +Maja Kądziołka Malo Jaffré Manish Goregaokar Mara Bos From b9e13cb539c23a320e3856eba82711cd6360407e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Apr 2025 09:34:01 +1100 Subject: [PATCH 133/176] Apply `Recovery::Forbidden` when reparsing pasted macro fragments. Fixes #137874. Removes `tests/crashes/137874.rs`; the new test is simpler (defines its own macro) but tests the same thing. The changes to the output of `tests/ui/associated-consts/issue-93835.rs` partly undo the changes seen when `NtTy` was removed in #133436, which is good. --- compiler/rustc_parse/src/parser/mod.rs | 17 +++++++++- tests/crashes/137874.rs | 4 --- tests/ui/associated-consts/issue-93835.rs | 3 +- tests/ui/associated-consts/issue-93835.stderr | 32 ++++++------------- .../macros/failed-to-reparse-issue-137874.rs | 12 +++++++ .../failed-to-reparse-issue-137874.stderr | 10 ++++++ 6 files changed, 48 insertions(+), 30 deletions(-) delete mode 100644 tests/crashes/137874.rs create mode 100644 tests/ui/macros/failed-to-reparse-issue-137874.rs create mode 100644 tests/ui/macros/failed-to-reparse-issue-137874.stderr diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 392a1c1057ab..3b0861a9942a 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -512,6 +512,14 @@ impl<'a> Parser<'a> { self } + #[inline] + fn with_recovery(&mut self, recovery: Recovery, f: impl FnOnce(&mut Self) -> T) -> T { + let old = mem::replace(&mut self.recovery, recovery); + let res = f(self); + self.recovery = old; + res + } + /// Whether the parser is allowed to recover from broken code. /// /// If this returns false, recovering broken code into valid code (especially if this recovery does lookahead) @@ -770,7 +778,14 @@ impl<'a> Parser<'a> { && match_mv_kind(mv_kind) { self.bump(); - let res = f(self).expect("failed to reparse {mv_kind:?}"); + + // Recovery is disabled when parsing macro arguments, so it must + // also be disabled when reparsing pasted macro arguments, + // otherwise we get inconsistent results (e.g. #137874). + let res = self.with_recovery(Recovery::Forbidden, |this| { + f(this).expect("failed to reparse {mv_kind:?}") + }); + if let token::CloseDelim(delim) = self.token.kind && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim && match_mv_kind(mv_kind) diff --git a/tests/crashes/137874.rs b/tests/crashes/137874.rs deleted file mode 100644 index 447188090245..000000000000 --- a/tests/crashes/137874.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #137874 -fn a() { - match b { deref !(0c) }; -} diff --git a/tests/ui/associated-consts/issue-93835.rs b/tests/ui/associated-consts/issue-93835.rs index 048681f04778..d6c2acaa9edc 100644 --- a/tests/ui/associated-consts/issue-93835.rs +++ b/tests/ui/associated-consts/issue-93835.rs @@ -3,11 +3,10 @@ fn e() { type_ascribe!(p, a>); //~^ ERROR cannot find type `a` in this scope - //~| ERROR path separator must be a double colon //~| ERROR cannot find value //~| ERROR associated const equality + //~| ERROR cannot find trait `p` in this scope //~| ERROR associated const equality - //~| ERROR failed to resolve: use of unresolved module or unlinked crate `p` } fn main() {} diff --git a/tests/ui/associated-consts/issue-93835.stderr b/tests/ui/associated-consts/issue-93835.stderr index e154ae25de26..551b50d0eb6b 100644 --- a/tests/ui/associated-consts/issue-93835.stderr +++ b/tests/ui/associated-consts/issue-93835.stderr @@ -1,15 +1,3 @@ -error: path separator must be a double colon - --> $DIR/issue-93835.rs:4:25 - | -LL | type_ascribe!(p, a>); - | ^ - | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 -help: use a double colon instead - | -LL | type_ascribe!(p, a>); - | + - error[E0425]: cannot find value `p` in this scope --> $DIR/issue-93835.rs:4:19 | @@ -22,6 +10,12 @@ error[E0412]: cannot find type `a` in this scope LL | type_ascribe!(p, a>); | ^ not found in this scope +error[E0405]: cannot find trait `p` in this scope + --> $DIR/issue-93835.rs:4:26 + | +LL | type_ascribe!(p, a>); + | ^ not found in this scope + error[E0658]: associated const equality is incomplete --> $DIR/issue-93835.rs:4:28 | @@ -43,15 +37,7 @@ LL | type_ascribe!(p, a>); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0433]: failed to resolve: use of unresolved module or unlinked crate `p` - --> $DIR/issue-93835.rs:4:24 - | -LL | type_ascribe!(p, a>); - | ^ use of unresolved module or unlinked crate `p` - | - = help: you might be missing a crate named `p` +error: aborting due to 5 previous errors -error: aborting due to 6 previous errors - -Some errors have detailed explanations: E0412, E0425, E0433, E0658. -For more information about an error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0405, E0412, E0425, E0658. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/macros/failed-to-reparse-issue-137874.rs b/tests/ui/macros/failed-to-reparse-issue-137874.rs new file mode 100644 index 000000000000..3e55ac376fea --- /dev/null +++ b/tests/ui/macros/failed-to-reparse-issue-137874.rs @@ -0,0 +1,12 @@ +// This originally crashed because `Recovery::Forbidden` wasn't being applied +// when fragments pasted by declarative macros were reparsed. + +macro_rules! m { + ($p:pat) => { + if let $p = 0 {} + } +} + +fn main() { + m!(0X0); //~ ERROR invalid base prefix for number literal +} diff --git a/tests/ui/macros/failed-to-reparse-issue-137874.stderr b/tests/ui/macros/failed-to-reparse-issue-137874.stderr new file mode 100644 index 000000000000..5bbb8b7f9e2f --- /dev/null +++ b/tests/ui/macros/failed-to-reparse-issue-137874.stderr @@ -0,0 +1,10 @@ +error: invalid base prefix for number literal + --> $DIR/failed-to-reparse-issue-137874.rs:11:8 + | +LL | m!(0X0); + | ^^^ help: try making the prefix lowercase (notice the capitalization): `0x0` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: aborting due to 1 previous error + From a2618e1af04401513252097235e99f8b81588b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Fri, 4 Apr 2025 04:56:18 +0200 Subject: [PATCH 134/176] AsyncDestructor: replace fields with impl_did MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The future and ctor fields aren't actually used, and the way they are extracted is obviously wrong – swapping the order of the items in the source code will give wrong results. Instead, store just the LocalDefId of the impl, which is enough for the only use of this data. --- compiler/rustc_middle/src/ty/mod.rs | 6 ++---- .../rustc_middle/src/ty/significant_drop_order.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 15 +++------------ 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 255d464d2654..23955f911184 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1124,10 +1124,8 @@ pub struct Destructor { // FIXME: consider combining this definition with regular `Destructor` #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] pub struct AsyncDestructor { - /// The `DefId` of the async destructor future constructor - pub ctor: DefId, - /// The `DefId` of the async destructor future type - pub future: DefId, + /// The `DefId` of the `impl AsyncDrop` + pub impl_did: LocalDefId, } #[derive(Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs index 2d9e0331451f..4881d611c128 100644 --- a/compiler/rustc_middle/src/ty/significant_drop_order.rs +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -154,7 +154,7 @@ pub fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { let dtor = if let Some(dtor) = tcx.adt_destructor(did) { dtor.did } else if let Some(dtor) = tcx.adt_async_destructor(did) { - dtor.future + return Some(tcx.source_span(dtor.impl_did)); } else { return Some(try_local_did_span(did)); }; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7743e202aae4..50efb57586c4 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -450,26 +450,17 @@ impl<'tcx> TyCtxt<'tcx> { continue; } - let [future, ctor] = self.associated_item_def_ids(impl_did) else { - self.dcx().span_delayed_bug( - self.def_span(impl_did), - "AsyncDrop impl without async_drop function or Dropper type", - ); - continue; - }; - - if let Some((_, _, old_impl_did)) = dtor_candidate { + if let Some(old_impl_did) = dtor_candidate { self.dcx() .struct_span_err(self.def_span(impl_did), "multiple async drop impls found") .with_span_note(self.def_span(old_impl_did), "other impl here") .delay_as_bug(); } - dtor_candidate = Some((*future, *ctor, impl_did)); + dtor_candidate = Some(impl_did); } - let (future, ctor, _) = dtor_candidate?; - Some(ty::AsyncDestructor { future, ctor }) + Some(ty::AsyncDestructor { impl_did: dtor_candidate? }) } /// Returns async drop glue morphology for a definition. To get async drop From a14e8f687c2f274548a20e01231b706d3c88790c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Fri, 4 Apr 2025 05:17:45 +0200 Subject: [PATCH 135/176] adt_destructor: sanity-check returned item Fixes #139278 --- compiler/rustc_middle/src/ty/util.rs | 5 +++++ .../ui/drop/nonsense-drop-impl-issue-139278.rs | 10 ++++++++++ .../nonsense-drop-impl-issue-139278.stderr | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 tests/ui/drop/nonsense-drop-impl-issue-139278.rs create mode 100644 tests/ui/drop/nonsense-drop-impl-issue-139278.stderr diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7743e202aae4..bebbe17d5187 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -414,6 +414,11 @@ impl<'tcx> TyCtxt<'tcx> { continue; }; + if self.def_kind(item_id) != DefKind::AssocFn { + self.dcx().span_delayed_bug(self.def_span(item_id), "drop is not a function"); + continue; + } + if let Some(old_item_id) = dtor_candidate { self.dcx() .struct_span_err(self.def_span(item_id), "multiple drop impls found") diff --git a/tests/ui/drop/nonsense-drop-impl-issue-139278.rs b/tests/ui/drop/nonsense-drop-impl-issue-139278.rs new file mode 100644 index 000000000000..86f4e4d86072 --- /dev/null +++ b/tests/ui/drop/nonsense-drop-impl-issue-139278.rs @@ -0,0 +1,10 @@ +//@ check-fail +struct Foo; + +impl Drop for Foo { //~ ERROR: not all trait items implemented + const SPLOK: u32 = 0; //~ ERROR: not a member of trait +} + +const X: Foo = Foo; + +fn main() {} diff --git a/tests/ui/drop/nonsense-drop-impl-issue-139278.stderr b/tests/ui/drop/nonsense-drop-impl-issue-139278.stderr new file mode 100644 index 000000000000..825e883fa6d8 --- /dev/null +++ b/tests/ui/drop/nonsense-drop-impl-issue-139278.stderr @@ -0,0 +1,18 @@ +error[E0438]: const `SPLOK` is not a member of trait `Drop` + --> $DIR/nonsense-drop-impl-issue-139278.rs:5:5 + | +LL | const SPLOK: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^^^ not a member of trait `Drop` + +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/nonsense-drop-impl-issue-139278.rs:4:1 + | +LL | impl Drop for Foo { + | ^^^^^^^^^^^^^^^^^ missing `drop` in implementation + | + = help: implement the missing item: `fn drop(&mut self) { todo!() }` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0046, E0438. +For more information about an error, try `rustc --explain E0046`. From c25207d8690a14c8d61aa215cd502d8ad581a0ea Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 4 Apr 2025 10:46:13 +0800 Subject: [PATCH 136/176] bootstrap: only build `rust_test_helpers` for `{incremental,ui}` suites --- src/bootstrap/src/core/build_steps/test.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 81f6b473c459..8e42e845a8cb 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1624,9 +1624,6 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the builder.tool_exe(Tool::RunMakeSupport); } - // Also provide `rust_test_helpers` for the host. - builder.ensure(TestHelpers { target: compiler.host }); - // ensure that `libproc_macro` is available on the host. if suite == "mir-opt" { builder.ensure(compile::Std::new(compiler, compiler.host).is_for_mir_opt_tests(true)); @@ -1634,11 +1631,6 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the builder.ensure(compile::Std::new(compiler, compiler.host)); } - // As well as the target - if suite != "mir-opt" { - builder.ensure(TestHelpers { target }); - } - let mut cmd = builder.tool_cmd(Tool::Compiletest); if suite == "mir-opt" { @@ -1804,11 +1796,18 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the } let mut hostflags = flags.clone(); - hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display())); hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No, compiler.stage)); let mut targetflags = flags; - targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display())); + + // Provide `rust_test_helpers` for both host and target. + if suite == "ui" || suite == "incremental" { + builder.ensure(TestHelpers { target: compiler.host }); + builder.ensure(TestHelpers { target }); + hostflags + .push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display())); + targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display())); + } for flag in hostflags { cmd.arg("--host-rustcflags").arg(flag); From fadf9105176d6ee6ec76c79447a0978b4819d26f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Apr 2025 16:50:56 +1100 Subject: [PATCH 137/176] Fix `Debug` impl for `LateParamRegionKind`. It uses `Br` prefixes which are inappropriate and appear to have been incorrectly copy/pasted from the `Debug` impl for `BoundRegionKind`. --- compiler/rustc_middle/src/ty/structural_impls.rs | 8 ++++---- tests/ui/nll/ty-outlives/impl-trait-captures.stderr | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 60fd531b4d0e..798ef352c408 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -86,15 +86,15 @@ impl fmt::Debug for ty::LateParamRegion { impl fmt::Debug for ty::LateParamRegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::LateParamRegionKind::Anon(idx) => write!(f, "BrAnon({idx})"), + ty::LateParamRegionKind::Anon(idx) => write!(f, "LateAnon({idx})"), ty::LateParamRegionKind::Named(did, name) => { if did.is_crate_root() { - write!(f, "BrNamed({name})") + write!(f, "LateNamed({name})") } else { - write!(f, "BrNamed({did:?}, {name})") + write!(f, "LateNamed({did:?}, {name})") } } - ty::LateParamRegionKind::ClosureEnv => write!(f, "BrEnv"), + ty::LateParamRegionKind::ClosureEnv => write!(f, "LateEnv"), } } } diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index 87bbd50a15c2..6fd41a761e99 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -4,14 +4,14 @@ error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[aeb9]::fo LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { | -- ------------ opaque type defined here | | - | hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here + | hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), LateNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here LL | x | ^ | -help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_))` +help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), LateNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_))` | -LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> { - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), LateNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> { + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error From aff2bc7a8815b89dd8dccf2564f5178118c1a3ec Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Apr 2025 14:44:45 +0200 Subject: [PATCH 138/176] Replace `rustc_lexer/unescape` with `rustc-literal-escaper` crate --- Cargo.lock | 10 +- compiler/rustc_ast/Cargo.toml | 2 +- compiler/rustc_ast/src/util/literal.rs | 2 +- compiler/rustc_lexer/src/lib.rs | 1 - compiler/rustc_lexer/src/unescape.rs | 438 ------------------ compiler/rustc_lexer/src/unescape/tests.rs | 286 ------------ compiler/rustc_parse/Cargo.toml | 1 + compiler/rustc_parse/src/lexer/mod.rs | 10 +- .../src/lexer/unescape_error_reporting.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse_format/Cargo.toml | 1 + compiler/rustc_parse_format/src/lib.rs | 10 +- 12 files changed, 22 insertions(+), 743 deletions(-) delete mode 100644 compiler/rustc_lexer/src/unescape.rs delete mode 100644 compiler/rustc_lexer/src/unescape/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 96526f7e9e7d..0bdddcc7a64d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3150,6 +3150,12 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc-literal-escaper" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdd0fcb1409d38cb2d940400497e2384a4a04b8685ee92a0a7a8986ccd72115" + [[package]] name = "rustc-main" version = "0.0.0" @@ -3242,10 +3248,10 @@ version = "0.0.0" dependencies = [ "bitflags", "memchr", + "rustc-literal-escaper", "rustc_ast_ir", "rustc_data_structures", "rustc_index", - "rustc_lexer", "rustc_macros", "rustc_serialize", "rustc_span", @@ -4200,6 +4206,7 @@ name = "rustc_parse" version = "0.0.0" dependencies = [ "bitflags", + "rustc-literal-escaper", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", @@ -4222,6 +4229,7 @@ dependencies = [ name = "rustc_parse_format" version = "0.0.0" dependencies = [ + "rustc-literal-escaper", "rustc_index", "rustc_lexer", ] diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 902287d03280..73b573272048 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -10,7 +10,7 @@ memchr = "2.7.4" rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } -rustc_lexer = { path = "../rustc_lexer" } +rustc-literal-escaper = "0.0.1" rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 6896ac723fa5..b8526cf9d952 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -2,7 +2,7 @@ use std::{ascii, fmt, str}; -use rustc_lexer::unescape::{ +use rustc_literal_escaper::{ MixedUnit, Mode, byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, }; use rustc_span::{Span, Symbol, kw, sym}; diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 61638e45253f..f9c71b2fa651 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -26,7 +26,6 @@ // tidy-alphabetical-end mod cursor; -pub mod unescape; #[cfg(test)] mod tests; diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs deleted file mode 100644 index d6ea4249247f..000000000000 --- a/compiler/rustc_lexer/src/unescape.rs +++ /dev/null @@ -1,438 +0,0 @@ -//! Utilities for validating string and char literals and turning them into -//! values they represent. - -use std::ops::Range; -use std::str::Chars; - -use Mode::*; - -#[cfg(test)] -mod tests; - -/// Errors and warnings that can occur during string unescaping. They mostly -/// relate to malformed escape sequences, but there are a few that are about -/// other problems. -#[derive(Debug, PartialEq, Eq)] -pub enum EscapeError { - /// Expected 1 char, but 0 were found. - ZeroChars, - /// Expected 1 char, but more than 1 were found. - MoreThanOneChar, - - /// Escaped '\' character without continuation. - LoneSlash, - /// Invalid escape character (e.g. '\z'). - InvalidEscape, - /// Raw '\r' encountered. - BareCarriageReturn, - /// Raw '\r' encountered in raw string. - BareCarriageReturnInRawString, - /// Unescaped character that was expected to be escaped (e.g. raw '\t'). - EscapeOnlyChar, - - /// Numeric character escape is too short (e.g. '\x1'). - TooShortHexEscape, - /// Invalid character in numeric escape (e.g. '\xz') - InvalidCharInHexEscape, - /// Character code in numeric escape is non-ascii (e.g. '\xFF'). - OutOfRangeHexEscape, - - /// '\u' not followed by '{'. - NoBraceInUnicodeEscape, - /// Non-hexadecimal value in '\u{..}'. - InvalidCharInUnicodeEscape, - /// '\u{}' - EmptyUnicodeEscape, - /// No closing brace in '\u{..}', e.g. '\u{12'. - UnclosedUnicodeEscape, - /// '\u{_12}' - LeadingUnderscoreUnicodeEscape, - /// More than 6 characters in '\u{..}', e.g. '\u{10FFFF_FF}' - OverlongUnicodeEscape, - /// Invalid in-bound unicode character code, e.g. '\u{DFFF}'. - LoneSurrogateUnicodeEscape, - /// Out of bounds unicode character code, e.g. '\u{FFFFFF}'. - OutOfRangeUnicodeEscape, - - /// Unicode escape code in byte literal. - UnicodeEscapeInByte, - /// Non-ascii character in byte literal, byte string literal, or raw byte string literal. - NonAsciiCharInByte, - - // `\0` in a C string literal. - NulInCStr, - - /// After a line ending with '\', the next line contains whitespace - /// characters that are not skipped. - UnskippedWhitespaceWarning, - - /// After a line ending with '\', multiple lines are skipped. - MultipleSkippedLinesWarning, -} - -impl EscapeError { - /// Returns true for actual errors, as opposed to warnings. - pub fn is_fatal(&self) -> bool { - !matches!( - self, - EscapeError::UnskippedWhitespaceWarning | EscapeError::MultipleSkippedLinesWarning - ) - } -} - -/// Takes the contents of a unicode-only (non-mixed-utf8) literal (without -/// quotes) and produces a sequence of escaped characters or errors. -/// -/// Values are returned by invoking `callback`. For `Char` and `Byte` modes, -/// the callback will be called exactly once. -pub fn unescape_unicode(src: &str, mode: Mode, callback: &mut F) -where - F: FnMut(Range, Result), -{ - match mode { - Char | Byte => { - let mut chars = src.chars(); - let res = unescape_char_or_byte(&mut chars, mode); - callback(0..(src.len() - chars.as_str().len()), res); - } - Str | ByteStr => unescape_non_raw_common(src, mode, callback), - RawStr | RawByteStr => check_raw_common(src, mode, callback), - RawCStr => check_raw_common(src, mode, &mut |r, mut result| { - if let Ok('\0') = result { - result = Err(EscapeError::NulInCStr); - } - callback(r, result) - }), - CStr => unreachable!(), - } -} - -/// Used for mixed utf8 string literals, i.e. those that allow both unicode -/// chars and high bytes. -pub enum MixedUnit { - /// Used for ASCII chars (written directly or via `\x00`..`\x7f` escapes) - /// and Unicode chars (written directly or via `\u` escapes). - /// - /// For example, if '¥' appears in a string it is represented here as - /// `MixedUnit::Char('¥')`, and it will be appended to the relevant byte - /// string as the two-byte UTF-8 sequence `[0xc2, 0xa5]` - Char(char), - - /// Used for high bytes (`\x80`..`\xff`). - /// - /// For example, if `\xa5` appears in a string it is represented here as - /// `MixedUnit::HighByte(0xa5)`, and it will be appended to the relevant - /// byte string as the single byte `0xa5`. - HighByte(u8), -} - -impl From for MixedUnit { - fn from(c: char) -> Self { - MixedUnit::Char(c) - } -} - -impl From for MixedUnit { - fn from(n: u8) -> Self { - if n.is_ascii() { MixedUnit::Char(n as char) } else { MixedUnit::HighByte(n) } - } -} - -/// Takes the contents of a mixed-utf8 literal (without quotes) and produces -/// a sequence of escaped characters or errors. -/// -/// Values are returned by invoking `callback`. -pub fn unescape_mixed(src: &str, mode: Mode, callback: &mut F) -where - F: FnMut(Range, Result), -{ - match mode { - CStr => unescape_non_raw_common(src, mode, &mut |r, mut result| { - if let Ok(MixedUnit::Char('\0')) = result { - result = Err(EscapeError::NulInCStr); - } - callback(r, result) - }), - Char | Byte | Str | RawStr | ByteStr | RawByteStr | RawCStr => unreachable!(), - } -} - -/// Takes a contents of a char literal (without quotes), and returns an -/// unescaped char or an error. -pub fn unescape_char(src: &str) -> Result { - unescape_char_or_byte(&mut src.chars(), Char) -} - -/// Takes a contents of a byte literal (without quotes), and returns an -/// unescaped byte or an error. -pub fn unescape_byte(src: &str) -> Result { - unescape_char_or_byte(&mut src.chars(), Byte).map(byte_from_char) -} - -/// What kind of literal do we parse. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Mode { - Char, - - Byte, - - Str, - RawStr, - - ByteStr, - RawByteStr, - - CStr, - RawCStr, -} - -impl Mode { - pub fn in_double_quotes(self) -> bool { - match self { - Str | RawStr | ByteStr | RawByteStr | CStr | RawCStr => true, - Char | Byte => false, - } - } - - /// Are `\x80`..`\xff` allowed? - fn allow_high_bytes(self) -> bool { - match self { - Char | Str => false, - Byte | ByteStr | CStr => true, - RawStr | RawByteStr | RawCStr => unreachable!(), - } - } - - /// Are unicode (non-ASCII) chars allowed? - #[inline] - fn allow_unicode_chars(self) -> bool { - match self { - Byte | ByteStr | RawByteStr => false, - Char | Str | RawStr | CStr | RawCStr => true, - } - } - - /// Are unicode escapes (`\u`) allowed? - fn allow_unicode_escapes(self) -> bool { - match self { - Byte | ByteStr => false, - Char | Str | CStr => true, - RawByteStr | RawStr | RawCStr => unreachable!(), - } - } - - pub fn prefix_noraw(self) -> &'static str { - match self { - Char | Str | RawStr => "", - Byte | ByteStr | RawByteStr => "b", - CStr | RawCStr => "c", - } - } -} - -fn scan_escape + From>( - chars: &mut Chars<'_>, - mode: Mode, -) -> Result { - // Previous character was '\\', unescape what follows. - let res: char = match chars.next().ok_or(EscapeError::LoneSlash)? { - '"' => '"', - 'n' => '\n', - 'r' => '\r', - 't' => '\t', - '\\' => '\\', - '\'' => '\'', - '0' => '\0', - 'x' => { - // Parse hexadecimal character code. - - let hi = chars.next().ok_or(EscapeError::TooShortHexEscape)?; - let hi = hi.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?; - - let lo = chars.next().ok_or(EscapeError::TooShortHexEscape)?; - let lo = lo.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?; - - let value = (hi * 16 + lo) as u8; - - return if !mode.allow_high_bytes() && !value.is_ascii() { - Err(EscapeError::OutOfRangeHexEscape) - } else { - // This may be a high byte, but that will only happen if `T` is - // `MixedUnit`, because of the `allow_high_bytes` check above. - Ok(T::from(value)) - }; - } - 'u' => return scan_unicode(chars, mode.allow_unicode_escapes()).map(T::from), - _ => return Err(EscapeError::InvalidEscape), - }; - Ok(T::from(res)) -} - -fn scan_unicode(chars: &mut Chars<'_>, allow_unicode_escapes: bool) -> Result { - // We've parsed '\u', now we have to parse '{..}'. - - if chars.next() != Some('{') { - return Err(EscapeError::NoBraceInUnicodeEscape); - } - - // First character must be a hexadecimal digit. - let mut n_digits = 1; - let mut value: u32 = match chars.next().ok_or(EscapeError::UnclosedUnicodeEscape)? { - '_' => return Err(EscapeError::LeadingUnderscoreUnicodeEscape), - '}' => return Err(EscapeError::EmptyUnicodeEscape), - c => c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?, - }; - - // First character is valid, now parse the rest of the number - // and closing brace. - loop { - match chars.next() { - None => return Err(EscapeError::UnclosedUnicodeEscape), - Some('_') => continue, - Some('}') => { - if n_digits > 6 { - return Err(EscapeError::OverlongUnicodeEscape); - } - - // Incorrect syntax has higher priority for error reporting - // than unallowed value for a literal. - if !allow_unicode_escapes { - return Err(EscapeError::UnicodeEscapeInByte); - } - - break std::char::from_u32(value).ok_or({ - if value > 0x10FFFF { - EscapeError::OutOfRangeUnicodeEscape - } else { - EscapeError::LoneSurrogateUnicodeEscape - } - }); - } - Some(c) => { - let digit: u32 = c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?; - n_digits += 1; - if n_digits > 6 { - // Stop updating value since we're sure that it's incorrect already. - continue; - } - value = value * 16 + digit; - } - }; - } -} - -#[inline] -fn ascii_check(c: char, allow_unicode_chars: bool) -> Result { - if allow_unicode_chars || c.is_ascii() { Ok(c) } else { Err(EscapeError::NonAsciiCharInByte) } -} - -fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result { - let c = chars.next().ok_or(EscapeError::ZeroChars)?; - let res = match c { - '\\' => scan_escape(chars, mode), - '\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar), - '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(c, mode.allow_unicode_chars()), - }?; - if chars.next().is_some() { - return Err(EscapeError::MoreThanOneChar); - } - Ok(res) -} - -/// Takes a contents of a string literal (without quotes) and produces a -/// sequence of escaped characters or errors. -fn unescape_non_raw_common + From>(src: &str, mode: Mode, callback: &mut F) -where - F: FnMut(Range, Result), -{ - let mut chars = src.chars(); - let allow_unicode_chars = mode.allow_unicode_chars(); // get this outside the loop - - // The `start` and `end` computation here is complicated because - // `skip_ascii_whitespace` makes us to skip over chars without counting - // them in the range computation. - while let Some(c) = chars.next() { - let start = src.len() - chars.as_str().len() - c.len_utf8(); - let res = match c { - '\\' => { - match chars.clone().next() { - Some('\n') => { - // Rust language specification requires us to skip whitespaces - // if unescaped '\' character is followed by '\n'. - // For details see [Rust language reference] - // (https://doc.rust-lang.org/reference/tokens.html#string-literals). - skip_ascii_whitespace(&mut chars, start, &mut |range, err| { - callback(range, Err(err)) - }); - continue; - } - _ => scan_escape::(&mut chars, mode), - } - } - '"' => Err(EscapeError::EscapeOnlyChar), - '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(c, allow_unicode_chars).map(T::from), - }; - let end = src.len() - chars.as_str().len(); - callback(start..end, res); - } -} - -fn skip_ascii_whitespace(chars: &mut Chars<'_>, start: usize, callback: &mut F) -where - F: FnMut(Range, EscapeError), -{ - let tail = chars.as_str(); - let first_non_space = tail - .bytes() - .position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r') - .unwrap_or(tail.len()); - if tail[1..first_non_space].contains('\n') { - // The +1 accounts for the escaping slash. - let end = start + first_non_space + 1; - callback(start..end, EscapeError::MultipleSkippedLinesWarning); - } - let tail = &tail[first_non_space..]; - if let Some(c) = tail.chars().next() { - if c.is_whitespace() { - // For error reporting, we would like the span to contain the character that was not - // skipped. The +1 is necessary to account for the leading \ that started the escape. - let end = start + first_non_space + c.len_utf8() + 1; - callback(start..end, EscapeError::UnskippedWhitespaceWarning); - } - } - *chars = tail.chars(); -} - -/// Takes a contents of a string literal (without quotes) and produces a -/// sequence of characters or errors. -/// NOTE: Raw strings do not perform any explicit character escaping, here we -/// only produce errors on bare CR. -fn check_raw_common(src: &str, mode: Mode, callback: &mut F) -where - F: FnMut(Range, Result), -{ - let mut chars = src.chars(); - let allow_unicode_chars = mode.allow_unicode_chars(); // get this outside the loop - - // The `start` and `end` computation here matches the one in - // `unescape_non_raw_common` for consistency, even though this function - // doesn't have to worry about skipping any chars. - while let Some(c) = chars.next() { - let start = src.len() - chars.as_str().len() - c.len_utf8(); - let res = match c { - '\r' => Err(EscapeError::BareCarriageReturnInRawString), - _ => ascii_check(c, allow_unicode_chars), - }; - let end = src.len() - chars.as_str().len(); - callback(start..end, res); - } -} - -#[inline] -pub fn byte_from_char(c: char) -> u8 { - let res = c as u32; - debug_assert!(res <= u8::MAX as u32, "guaranteed because of ByteStr"); - res as u8 -} diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs deleted file mode 100644 index 5b99495f4758..000000000000 --- a/compiler/rustc_lexer/src/unescape/tests.rs +++ /dev/null @@ -1,286 +0,0 @@ -use super::*; - -#[test] -fn test_unescape_char_bad() { - fn check(literal_text: &str, expected_error: EscapeError) { - assert_eq!(unescape_char(literal_text), Err(expected_error)); - } - - check("", EscapeError::ZeroChars); - check(r"\", EscapeError::LoneSlash); - - check("\n", EscapeError::EscapeOnlyChar); - check("\t", EscapeError::EscapeOnlyChar); - check("'", EscapeError::EscapeOnlyChar); - check("\r", EscapeError::BareCarriageReturn); - - check("spam", EscapeError::MoreThanOneChar); - check(r"\x0ff", EscapeError::MoreThanOneChar); - check(r#"\"a"#, EscapeError::MoreThanOneChar); - check(r"\na", EscapeError::MoreThanOneChar); - check(r"\ra", EscapeError::MoreThanOneChar); - check(r"\ta", EscapeError::MoreThanOneChar); - check(r"\\a", EscapeError::MoreThanOneChar); - check(r"\'a", EscapeError::MoreThanOneChar); - check(r"\0a", EscapeError::MoreThanOneChar); - check(r"\u{0}x", EscapeError::MoreThanOneChar); - check(r"\u{1F63b}}", EscapeError::MoreThanOneChar); - - check(r"\v", EscapeError::InvalidEscape); - check(r"\💩", EscapeError::InvalidEscape); - check(r"\●", EscapeError::InvalidEscape); - check("\\\r", EscapeError::InvalidEscape); - - check(r"\x", EscapeError::TooShortHexEscape); - check(r"\x0", EscapeError::TooShortHexEscape); - check(r"\xf", EscapeError::TooShortHexEscape); - check(r"\xa", EscapeError::TooShortHexEscape); - check(r"\xx", EscapeError::InvalidCharInHexEscape); - check(r"\xы", EscapeError::InvalidCharInHexEscape); - check(r"\x🦀", EscapeError::InvalidCharInHexEscape); - check(r"\xtt", EscapeError::InvalidCharInHexEscape); - check(r"\xff", EscapeError::OutOfRangeHexEscape); - check(r"\xFF", EscapeError::OutOfRangeHexEscape); - check(r"\x80", EscapeError::OutOfRangeHexEscape); - - check(r"\u", EscapeError::NoBraceInUnicodeEscape); - check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape); - check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape); - check(r"\u{", EscapeError::UnclosedUnicodeEscape); - check(r"\u{0000", EscapeError::UnclosedUnicodeEscape); - check(r"\u{}", EscapeError::EmptyUnicodeEscape); - check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape); - check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape); - check(r"\u{FFFFFF}", EscapeError::OutOfRangeUnicodeEscape); - check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape); - check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape); - - check(r"\u{DC00}", EscapeError::LoneSurrogateUnicodeEscape); - check(r"\u{DDDD}", EscapeError::LoneSurrogateUnicodeEscape); - check(r"\u{DFFF}", EscapeError::LoneSurrogateUnicodeEscape); - - check(r"\u{D800}", EscapeError::LoneSurrogateUnicodeEscape); - check(r"\u{DAAA}", EscapeError::LoneSurrogateUnicodeEscape); - check(r"\u{DBFF}", EscapeError::LoneSurrogateUnicodeEscape); -} - -#[test] -fn test_unescape_char_good() { - fn check(literal_text: &str, expected_char: char) { - assert_eq!(unescape_char(literal_text), Ok(expected_char)); - } - - check("a", 'a'); - check("ы", 'ы'); - check("🦀", '🦀'); - - check(r#"\""#, '"'); - check(r"\n", '\n'); - check(r"\r", '\r'); - check(r"\t", '\t'); - check(r"\\", '\\'); - check(r"\'", '\''); - check(r"\0", '\0'); - - check(r"\x00", '\0'); - check(r"\x5a", 'Z'); - check(r"\x5A", 'Z'); - check(r"\x7f", 127 as char); - - check(r"\u{0}", '\0'); - check(r"\u{000000}", '\0'); - check(r"\u{41}", 'A'); - check(r"\u{0041}", 'A'); - check(r"\u{00_41}", 'A'); - check(r"\u{4__1__}", 'A'); - check(r"\u{1F63b}", '😻'); -} - -#[test] -fn test_unescape_str_warn() { - fn check(literal: &str, expected: &[(Range, Result)]) { - let mut unescaped = Vec::with_capacity(literal.len()); - unescape_unicode(literal, Mode::Str, &mut |range, res| unescaped.push((range, res))); - assert_eq!(unescaped, expected); - } - - // Check we can handle escaped newlines at the end of a file. - check("\\\n", &[]); - check("\\\n ", &[]); - - check( - "\\\n \u{a0} x", - &[ - (0..5, Err(EscapeError::UnskippedWhitespaceWarning)), - (3..5, Ok('\u{a0}')), - (5..6, Ok(' ')), - (6..7, Ok('x')), - ], - ); - check("\\\n \n x", &[(0..7, Err(EscapeError::MultipleSkippedLinesWarning)), (7..8, Ok('x'))]); -} - -#[test] -fn test_unescape_str_good() { - fn check(literal_text: &str, expected: &str) { - let mut buf = Ok(String::with_capacity(literal_text.len())); - unescape_unicode(literal_text, Mode::Str, &mut |range, c| { - if let Ok(b) = &mut buf { - match c { - Ok(c) => b.push(c), - Err(e) => buf = Err((range, e)), - } - } - }); - assert_eq!(buf.as_deref(), Ok(expected)) - } - - check("foo", "foo"); - check("", ""); - check(" \t\n", " \t\n"); - - check("hello \\\n world", "hello world"); - check("thread's", "thread's") -} - -#[test] -fn test_unescape_byte_bad() { - fn check(literal_text: &str, expected_error: EscapeError) { - assert_eq!(unescape_byte(literal_text), Err(expected_error)); - } - - check("", EscapeError::ZeroChars); - check(r"\", EscapeError::LoneSlash); - - check("\n", EscapeError::EscapeOnlyChar); - check("\t", EscapeError::EscapeOnlyChar); - check("'", EscapeError::EscapeOnlyChar); - check("\r", EscapeError::BareCarriageReturn); - - check("spam", EscapeError::MoreThanOneChar); - check(r"\x0ff", EscapeError::MoreThanOneChar); - check(r#"\"a"#, EscapeError::MoreThanOneChar); - check(r"\na", EscapeError::MoreThanOneChar); - check(r"\ra", EscapeError::MoreThanOneChar); - check(r"\ta", EscapeError::MoreThanOneChar); - check(r"\\a", EscapeError::MoreThanOneChar); - check(r"\'a", EscapeError::MoreThanOneChar); - check(r"\0a", EscapeError::MoreThanOneChar); - - check(r"\v", EscapeError::InvalidEscape); - check(r"\💩", EscapeError::InvalidEscape); - check(r"\●", EscapeError::InvalidEscape); - - check(r"\x", EscapeError::TooShortHexEscape); - check(r"\x0", EscapeError::TooShortHexEscape); - check(r"\xa", EscapeError::TooShortHexEscape); - check(r"\xf", EscapeError::TooShortHexEscape); - check(r"\xx", EscapeError::InvalidCharInHexEscape); - check(r"\xы", EscapeError::InvalidCharInHexEscape); - check(r"\x🦀", EscapeError::InvalidCharInHexEscape); - check(r"\xtt", EscapeError::InvalidCharInHexEscape); - - check(r"\u", EscapeError::NoBraceInUnicodeEscape); - check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape); - check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape); - check(r"\u{", EscapeError::UnclosedUnicodeEscape); - check(r"\u{0000", EscapeError::UnclosedUnicodeEscape); - check(r"\u{}", EscapeError::EmptyUnicodeEscape); - check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape); - check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape); - - check("ы", EscapeError::NonAsciiCharInByte); - check("🦀", EscapeError::NonAsciiCharInByte); - - check(r"\u{0}", EscapeError::UnicodeEscapeInByte); - check(r"\u{000000}", EscapeError::UnicodeEscapeInByte); - check(r"\u{41}", EscapeError::UnicodeEscapeInByte); - check(r"\u{0041}", EscapeError::UnicodeEscapeInByte); - check(r"\u{00_41}", EscapeError::UnicodeEscapeInByte); - check(r"\u{4__1__}", EscapeError::UnicodeEscapeInByte); - check(r"\u{1F63b}", EscapeError::UnicodeEscapeInByte); - check(r"\u{0}x", EscapeError::UnicodeEscapeInByte); - check(r"\u{1F63b}}", EscapeError::UnicodeEscapeInByte); - check(r"\u{FFFFFF}", EscapeError::UnicodeEscapeInByte); - check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte); - check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte); - check(r"\u{DC00}", EscapeError::UnicodeEscapeInByte); - check(r"\u{DDDD}", EscapeError::UnicodeEscapeInByte); - check(r"\u{DFFF}", EscapeError::UnicodeEscapeInByte); - check(r"\u{D800}", EscapeError::UnicodeEscapeInByte); - check(r"\u{DAAA}", EscapeError::UnicodeEscapeInByte); - check(r"\u{DBFF}", EscapeError::UnicodeEscapeInByte); -} - -#[test] -fn test_unescape_byte_good() { - fn check(literal_text: &str, expected_byte: u8) { - assert_eq!(unescape_byte(literal_text), Ok(expected_byte)); - } - - check("a", b'a'); - - check(r#"\""#, b'"'); - check(r"\n", b'\n'); - check(r"\r", b'\r'); - check(r"\t", b'\t'); - check(r"\\", b'\\'); - check(r"\'", b'\''); - check(r"\0", b'\0'); - - check(r"\x00", b'\0'); - check(r"\x5a", b'Z'); - check(r"\x5A", b'Z'); - check(r"\x7f", 127); - check(r"\x80", 128); - check(r"\xff", 255); - check(r"\xFF", 255); -} - -#[test] -fn test_unescape_byte_str_good() { - fn check(literal_text: &str, expected: &[u8]) { - let mut buf = Ok(Vec::with_capacity(literal_text.len())); - unescape_unicode(literal_text, Mode::ByteStr, &mut |range, c| { - if let Ok(b) = &mut buf { - match c { - Ok(c) => b.push(byte_from_char(c)), - Err(e) => buf = Err((range, e)), - } - } - }); - assert_eq!(buf.as_deref(), Ok(expected)) - } - - check("foo", b"foo"); - check("", b""); - check(" \t\n", b" \t\n"); - - check("hello \\\n world", b"hello world"); - check("thread's", b"thread's") -} - -#[test] -fn test_unescape_raw_str() { - fn check(literal: &str, expected: &[(Range, Result)]) { - let mut unescaped = Vec::with_capacity(literal.len()); - unescape_unicode(literal, Mode::RawStr, &mut |range, res| unescaped.push((range, res))); - assert_eq!(unescaped, expected); - } - - check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]); - check("\rx", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString)), (1..2, Ok('x'))]); -} - -#[test] -fn test_unescape_raw_byte_str() { - fn check(literal: &str, expected: &[(Range, Result)]) { - let mut unescaped = Vec::with_capacity(literal.len()); - unescape_unicode(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res))); - assert_eq!(unescaped, expected); - } - - check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]); - check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByte))]); - check("🦀a", &[(0..4, Err(EscapeError::NonAsciiCharInByte)), (4..5, Ok('a'))]); -} diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index c9dcab0c871d..dec1e09d8dd8 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -15,6 +15,7 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } +rustc-literal-escaper = "0.0.1" rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 1d17290e1c70..4935fc03256f 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -6,8 +6,8 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, StashKey}; -use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, Cursor, DocStyle, LiteralKind, RawStrError}; +use rustc_literal_escaper::{EscapeError, Mode, unescape_mixed, unescape_unicode}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, @@ -970,9 +970,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { postfix_len: u32, ) -> (token::LitKind, Symbol) { self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| { - unescape::unescape_unicode(src, mode, &mut |span, result| { - callback(span, result.map(drop)) - }) + unescape_unicode(src, mode, &mut |span, result| callback(span, result.map(drop))) }) } @@ -986,9 +984,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { postfix_len: u32, ) -> (token::LitKind, Symbol) { self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| { - unescape::unescape_mixed(src, mode, &mut |span, result| { - callback(span, result.map(drop)) - }) + unescape_mixed(src, mode, &mut |span, result| callback(span, result.map(drop))) }) } } diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 2e066f0179c3..ec59a1a01314 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -4,7 +4,7 @@ use std::iter::once; use std::ops::Range; use rustc_errors::{Applicability, DiagCtxtHandle, ErrorGuaranteed}; -use rustc_lexer::unescape::{EscapeError, Mode}; +use rustc_literal_escaper::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; use tracing::debug; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 841d967d934b..9c457f150a32 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -21,7 +21,7 @@ use rustc_ast::{ }; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; -use rustc_lexer::unescape::unescape_char; +use rustc_literal_escaper::unescape_char; use rustc_macros::Subdiagnostic; use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error}; use rustc_session::lint::BuiltinLintDiag; diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index 289e062fb5e2..b0b70cefb596 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rustc_lexer = { path = "../rustc_lexer" } +rustc-literal-escaper = "0.0.1" # tidy-alphabetical-end [target.'cfg(target_pointer_width = "64")'.dev-dependencies] diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 97931742985e..c59e6cb5c33f 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -18,7 +18,7 @@ pub use Alignment::*; pub use Count::*; pub use Position::*; -use rustc_lexer::unescape; +use rustc_literal_escaper::{Mode, unescape_unicode}; // Note: copied from rustc_span /// Range inside of a `Span` used for diagnostics when we only have access to relative positions. @@ -1094,11 +1094,9 @@ fn find_width_map_from_snippet( fn unescape_string(string: &str) -> Option { let mut buf = String::new(); let mut ok = true; - unescape::unescape_unicode(string, unescape::Mode::Str, &mut |_, unescaped_char| { - match unescaped_char { - Ok(c) => buf.push(c), - Err(_) => ok = false, - } + unescape_unicode(string, Mode::Str, &mut |_, unescaped_char| match unescaped_char { + Ok(c) => buf.push(c), + Err(_) => ok = false, }); ok.then_some(buf) From 0f12a2c4ad6ebc7f74e682be819f0d61d8d27c57 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 4 Apr 2025 14:47:04 +0200 Subject: [PATCH 139/176] ToSocketAddrs: fix typo --- compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs | 2 +- library/std/src/net/socket_addr.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index fddddf404dbc..56cc43275851 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -969,7 +969,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } }; - // If we can detect the expression to be an function or method call where the closure was + // If we can detect the expression to be a function or method call where the closure was // an argument, we point at the function or method definition argument... if let Some((callee_def_id, call_span, call_args)) = get_call_details() { let arg_pos = call_args diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs index 4c8905c0d460..41e623e79ce2 100644 --- a/library/std/src/net/socket_addr.rs +++ b/library/std/src/net/socket_addr.rs @@ -101,7 +101,7 @@ use crate::{io, iter, option, slice, vec}; /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); /// ``` /// -/// [`TcpStream::connect`] is an example of an function that utilizes +/// [`TcpStream::connect`] is an example of a function that utilizes /// `ToSocketAddrs` as a trait bound on its parameter in order to accept /// different types: /// From bba0d57bb2773c0298e1b37456754610f069dd4a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Apr 2025 14:59:14 +0200 Subject: [PATCH 140/176] Remove usage of `rustc_lexer::unescape` in rust-analyzer --- src/tools/rust-analyzer/Cargo.lock | 8 ++++++++ src/tools/rust-analyzer/crates/parser/Cargo.toml | 1 + src/tools/rust-analyzer/crates/parser/src/lexed_str.rs | 10 +++++----- src/tools/rust-analyzer/crates/syntax/Cargo.toml | 1 + .../rust-analyzer/crates/syntax/src/ast/token_ext.rs | 2 +- src/tools/rust-analyzer/crates/syntax/src/lib.rs | 9 +-------- .../rust-analyzer/crates/syntax/src/validation.rs | 8 ++++---- 7 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 1e1d68f77824..2aa776b50878 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1270,6 +1270,7 @@ dependencies = [ "edition", "expect-test", "ra-ap-rustc_lexer", + "rustc-literal-escaper", "stdx", "tracing", ] @@ -1743,6 +1744,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +[[package]] +name = "rustc-literal-escaper" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdd0fcb1409d38cb2d940400497e2384a4a04b8685ee92a0a7a8986ccd72115" + [[package]] name = "rustc-stable-hash" version = "0.1.1" @@ -1982,6 +1989,7 @@ dependencies = [ "rayon", "rowan", "rustc-hash 2.0.0", + "rustc-literal-escaper", "rustc_apfloat", "smol_str", "stdx", diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml index a36a39dbee6c..292b7de255a8 100644 --- a/src/tools/rust-analyzer/crates/parser/Cargo.toml +++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml @@ -14,6 +14,7 @@ rust-version.workspace = true [dependencies] drop_bomb = "0.1.5" ra-ap-rustc_lexer.workspace = true +rustc-literal-escaper = "0.0.1" tracing = { workspace = true, optional = true } edition.workspace = true diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index c97596d5097e..b0bbc2fa5ff1 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -10,7 +10,7 @@ use std::ops; -use rustc_lexer::unescape::{EscapeError, Mode}; +use rustc_literal_escaper::{EscapeError, Mode, unescape_byte, unescape_char, unescape_mixed, unescape_unicode}; use crate::{ Edition, @@ -282,7 +282,7 @@ impl<'a> Converter<'a> { let text = &self.res.text[self.offset + 1..][..len - 1]; let i = text.rfind('\'').unwrap(); let text = &text[..i]; - if let Err(e) = rustc_lexer::unescape::unescape_char(text) { + if let Err(e) = unescape_char(text) { err = error_to_diagnostic_message(e, Mode::Char); } } @@ -295,7 +295,7 @@ impl<'a> Converter<'a> { let text = &self.res.text[self.offset + 2..][..len - 2]; let i = text.rfind('\'').unwrap(); let text = &text[..i]; - if let Err(e) = rustc_lexer::unescape::unescape_byte(text) { + if let Err(e) = unescape_byte(text) { err = error_to_diagnostic_message(e, Mode::Byte); } } @@ -402,14 +402,14 @@ fn unescape_string_error_message(text: &str, mode: Mode) -> &'static str { let mut error_message = ""; match mode { Mode::CStr => { - rustc_lexer::unescape::unescape_mixed(text, mode, &mut |_, res| { + unescape_mixed(text, mode, &mut |_, res| { if let Err(e) = res { error_message = error_to_diagnostic_message(e, mode); } }); } Mode::ByteStr | Mode::Str => { - rustc_lexer::unescape::unescape_unicode(text, mode, &mut |_, res| { + unescape_unicode(text, mode, &mut |_, res| { if let Err(e) = res { error_message = error_to_diagnostic_message(e, mode); } diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 3fe6e01dc3c9..4fb628685a1b 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -17,6 +17,7 @@ either.workspace = true itertools.workspace = true rowan = "=0.15.15" rustc-hash.workspace = true +rustc-literal-escaper = "0.0.1" indexmap.workspace = true smol_str.workspace = true triomphe.workspace = true diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs index df851ab5b252..08bffb9e3aad 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, num::ParseIntError}; -use rustc_lexer::unescape::{ +use rustc_literal_escaper::{ unescape_byte, unescape_char, unescape_mixed, unescape_unicode, EscapeError, MixedUnit, Mode, }; use stdx::always; diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs index c9e9f468dca7..21f1ea5f913a 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs @@ -19,13 +19,6 @@ //! [RFC]: //! [Swift]: -#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] - -#[cfg(not(feature = "in-rust-tree"))] -extern crate ra_ap_rustc_lexer as rustc_lexer; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_lexer; - mod parsing; mod ptr; mod syntax_error; @@ -64,7 +57,7 @@ pub use rowan::{ api::Preorder, Direction, GreenNode, NodeOrToken, SyntaxText, TextRange, TextSize, TokenAtOffset, WalkEvent, }; -pub use rustc_lexer::unescape; +pub use rustc_literal_escaper as unescape; pub use smol_str::{format_smolstr, SmolStr, SmolStrBuilder, ToSmolStr}; /// `Parse` is the result of the parsing: a syntax tree and a collection of diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 85eefac734b2..71c5f9a946db 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -5,7 +5,7 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{self, unescape_mixed, unescape_unicode, Mode}; +use rustc_literal_escaper::{unescape_mixed, unescape_unicode, EscapeError, Mode}; use crate::{ algo, @@ -44,8 +44,8 @@ pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec) { } } -fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, bool) { - use unescape::EscapeError as EE; +fn rustc_unescape_error_to_string(err: EscapeError) -> (&'static str, bool) { + use rustc_literal_escaper::EscapeError as EE; #[rustfmt::skip] let err_message = match err { @@ -127,7 +127,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { let text = token.text(); // FIXME: lift this lambda refactor to `fn` (https://github.com/rust-lang/rust-analyzer/pull/2834#discussion_r366199205) - let mut push_err = |prefix_len, off, err: unescape::EscapeError| { + let mut push_err = |prefix_len, off, err: EscapeError| { let off = token.text_range().start() + TextSize::try_from(off + prefix_len).unwrap(); let (message, is_err) = rustc_unescape_error_to_string(err); // FIXME: Emit lexer warnings From d74ce25b65e60cd5ccade3c6fd4234dbd201bda8 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 11 Feb 2025 10:43:25 +0100 Subject: [PATCH 141/176] refactor: Move Apple OSVersion (back) to rustc_target Also convert OSVersion into a proper struct for better type-safety. --- compiler/rustc_codegen_ssa/src/back/apple.rs | 91 ++--------------- .../rustc_codegen_ssa/src/back/apple/tests.rs | 12 +-- compiler/rustc_codegen_ssa/src/back/link.rs | 7 +- .../rustc_codegen_ssa/src/back/metadata.rs | 2 +- compiler/rustc_codegen_ssa/src/lib.rs | 1 - compiler/rustc_driver_impl/src/lib.rs | 2 +- compiler/rustc_target/src/lib.rs | 1 + .../rustc_target/src/spec/base/apple/mod.rs | 97 ++++++++++++++++++- .../rustc_target/src/spec/base/apple/tests.rs | 9 ++ compiler/rustc_target/src/spec/base/mod.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 1 + 11 files changed, 125 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 2c8b0ec418dd..8954ec0fcdd2 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -1,7 +1,6 @@ use std::env; use std::ffi::OsString; -use std::fmt::{Display, from_fn}; -use std::num::ParseIntError; +use std::str::FromStr; use std::path::PathBuf; use std::process::Command; @@ -9,6 +8,7 @@ use itertools::Itertools; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_session::Session; use rustc_target::spec::Target; +pub(super) use rustc_target::spec::apple::OSVersion; use tracing::debug; use crate::errors::{AppleDeploymentTarget, XcrunError, XcrunSdkPathWarning}; @@ -134,76 +134,6 @@ pub(super) fn add_data_and_relocation( Ok(()) } -/// Deployment target or SDK version. -/// -/// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`. -type OSVersion = (u16, u8, u8); - -/// Parse an OS version triple (SDK version or deployment target). -fn parse_version(version: &str) -> Result { - if let Some((major, minor)) = version.split_once('.') { - let major = major.parse()?; - if let Some((minor, patch)) = minor.split_once('.') { - Ok((major, minor.parse()?, patch.parse()?)) - } else { - Ok((major, minor.parse()?, 0)) - } - } else { - Ok((version.parse()?, 0, 0)) - } -} - -pub fn pretty_version(version: OSVersion) -> impl Display { - let (major, minor, patch) = version; - from_fn(move |f| { - write!(f, "{major}.{minor}")?; - if patch != 0 { - write!(f, ".{patch}")?; - } - Ok(()) - }) -} - -/// Minimum operating system versions currently supported by `rustc`. -fn os_minimum_deployment_target(os: &str) -> OSVersion { - // When bumping a version in here, remember to update the platform-support docs too. - // - // NOTE: The defaults may change in future `rustc` versions, so if you are looking for the - // default deployment target, prefer: - // ``` - // $ rustc --print deployment-target - // ``` - match os { - "macos" => (10, 12, 0), - "ios" => (10, 0, 0), - "tvos" => (10, 0, 0), - "watchos" => (5, 0, 0), - "visionos" => (1, 0, 0), - _ => unreachable!("tried to get deployment target for non-Apple platform"), - } -} - -/// The deployment target for the given target. -/// -/// This is similar to `os_minimum_deployment_target`, except that on certain targets it makes sense -/// to raise the minimum OS version. -/// -/// This matches what LLVM does, see in part: -/// -fn minimum_deployment_target(target: &Target) -> OSVersion { - match (&*target.os, &*target.arch, &*target.abi) { - ("macos", "aarch64", _) => (11, 0, 0), - ("ios", "aarch64", "macabi") => (14, 0, 0), - ("ios", "aarch64", "sim") => (14, 0, 0), - ("ios", _, _) if target.llvm_target.starts_with("arm64e") => (14, 0, 0), - // Mac Catalyst defaults to 13.1 in Clang. - ("ios", _, "macabi") => (13, 1, 0), - ("tvos", "aarch64", "sim") => (14, 0, 0), - ("watchos", "aarch64", "sim") => (7, 0, 0), - (os, _, _) => os_minimum_deployment_target(os), - } -} - /// Name of the environment variable used to fetch the deployment target on the given OS. pub fn deployment_target_env_var(os: &str) -> &'static str { match os { @@ -219,13 +149,13 @@ pub fn deployment_target_env_var(os: &str) -> &'static str { /// Get the deployment target based on the standard environment variables, or fall back to the /// minimum version supported by `rustc`. pub fn deployment_target(sess: &Session) -> OSVersion { - let min = minimum_deployment_target(&sess.target); + let min = OSVersion::minimum_deployment_target(&sess.target); let env_var = deployment_target_env_var(&sess.target.os); if let Ok(deployment_target) = env::var(env_var) { - match parse_version(&deployment_target) { + match OSVersion::from_str(&deployment_target) { Ok(version) => { - let os_min = os_minimum_deployment_target(&sess.target.os); + let os_min = OSVersion::os_minimum_deployment_target(&sess.target.os); // It is common that the deployment target is set a bit too low, for example on // macOS Aarch64 to also target older x86_64. So we only want to warn when variable // is lower than the minimum OS supported by rustc, not when the variable is lower @@ -233,8 +163,8 @@ pub fn deployment_target(sess: &Session) -> OSVersion { if version < os_min { sess.dcx().emit_warn(AppleDeploymentTarget::TooLow { env_var, - version: pretty_version(version).to_string(), - os_min: pretty_version(os_min).to_string(), + version: version.fmt_pretty().to_string(), + os_min: os_min.fmt_pretty().to_string(), }); } @@ -263,18 +193,17 @@ pub(super) fn add_version_to_llvm_target( let environment = components.next(); assert_eq!(components.next(), None, "too many LLVM triple components"); - let (major, minor, patch) = deployment_target; - assert!( !os.contains(|c: char| c.is_ascii_digit()), "LLVM target must not already be versioned" ); + let version = deployment_target.fmt_full(); if let Some(env) = environment { // Insert version into OS, before environment - format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}-{env}") + format!("{arch}-{vendor}-{os}{version}-{env}") } else { - format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}") + format!("{arch}-{vendor}-{os}{version}") } } diff --git a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs index 8df740a4bcf7..5afe79b71954 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs @@ -3,23 +3,15 @@ use super::*; #[test] fn test_add_version_to_llvm_target() { assert_eq!( - add_version_to_llvm_target("aarch64-apple-macosx", (10, 14, 1)), + add_version_to_llvm_target("aarch64-apple-macosx", OSVersion::new(10, 14, 1)), "aarch64-apple-macosx10.14.1" ); assert_eq!( - add_version_to_llvm_target("aarch64-apple-ios-simulator", (16, 1, 0)), + add_version_to_llvm_target("aarch64-apple-ios-simulator", OSVersion::new(16, 1, 0)), "aarch64-apple-ios16.1.0-simulator" ); } -#[test] -fn test_parse_version() { - assert_eq!(parse_version("10"), Ok((10, 0, 0))); - assert_eq!(parse_version("10.12"), Ok((10, 12, 0))); - assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6))); - assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99))); -} - #[test] #[cfg_attr(not(target_os = "macos"), ignore = "xcode-select is only available on macOS")] fn lookup_developer_dir() { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 1c885a2fd5ff..8ea8c5b01f46 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3115,8 +3115,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo _ => bug!("invalid OS/ABI combination for Apple target: {target_os}, {target_abi}"), }; - let (major, minor, patch) = apple::deployment_target(sess); - let min_version = format!("{major}.{minor}.{patch}"); + let min_version = apple::deployment_target(sess).fmt_full().to_string(); // The SDK version is used at runtime when compiling with a newer SDK / version of Xcode: // - By dyld to give extra warnings and errors, see e.g.: @@ -3185,10 +3184,10 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // The presence of `-mmacosx-version-min` makes CC default to // macOS, and it sets the deployment target. - let (major, minor, patch) = apple::deployment_target(sess); + let version = apple::deployment_target(sess).fmt_full(); // Intentionally pass this as a single argument, Clang doesn't // seem to like it otherwise. - cmd.cc_arg(&format!("-mmacosx-version-min={major}.{minor}.{patch}")); + cmd.cc_arg(&format!("-mmacosx-version-min={version}")); // macOS has no environment, so with these two, we've told CC the // four desired parameters. diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index e2c009712d17..aac2f2da0297 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -388,7 +388,7 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 { fn macho_object_build_version_for_target(sess: &Session) -> object::write::MachOBuildVersion { /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz" /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200 - fn pack_version((major, minor, patch): (u16, u8, u8)) -> u32 { + fn pack_version(apple::OSVersion { major, minor, patch }: apple::OSVersion) -> u32 { let (major, minor, patch) = (major as u32, minor as u32, patch as u32); (major << 16) | (minor << 8) | patch } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index f36e42cc6b95..67217927a872 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -7,7 +7,6 @@ #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] -#![feature(debug_closure_helpers)] #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 21b9542d0e1e..12f85c23a14a 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -811,7 +811,7 @@ fn print_crate_info( println_info!( "{}={}", apple::deployment_target_env_var(&sess.target.os), - apple::pretty_version(apple::deployment_target(sess)), + apple::deployment_target(sess).fmt_pretty(), ) } else { #[allow(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index a8d7da5692de..df99280f5712 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -12,6 +12,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] +#![feature(debug_closure_helpers)] #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index fd0e47b55aaa..dce1b9dab666 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,9 +1,12 @@ use std::borrow::Cow; use std::env; +use std::fmt::{Display, from_fn}; +use std::num::ParseIntError; +use std::str::FromStr; use crate::spec::{ BinaryFormat, Cc, DebuginfoKind, FloatAbi, FramePointer, LinkerFlavor, Lld, RustcAbi, - SplitDebuginfo, StackProbeType, StaticCow, TargetOptions, cvs, + SplitDebuginfo, StackProbeType, StaticCow, Target, TargetOptions, cvs, }; #[cfg(test)] @@ -222,3 +225,95 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow]> { cvs!["MACOSX_DEPLOYMENT_TARGET"] } } + +/// Deployment target or SDK version. +/// +/// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct OSVersion { + pub major: u16, + pub minor: u8, + pub patch: u8, +} + +impl FromStr for OSVersion { + type Err = ParseIntError; + + /// Parse an OS version triple (SDK version or deployment target). + fn from_str(version: &str) -> Result { + if let Some((major, minor)) = version.split_once('.') { + let major = major.parse()?; + if let Some((minor, patch)) = minor.split_once('.') { + Ok(Self { major, minor: minor.parse()?, patch: patch.parse()? }) + } else { + Ok(Self { major, minor: minor.parse()?, patch: 0 }) + } + } else { + Ok(Self { major: version.parse()?, minor: 0, patch: 0 }) + } + } +} + +impl OSVersion { + pub fn new(major: u16, minor: u8, patch: u8) -> Self { + Self { major, minor, patch } + } + + pub fn fmt_pretty(self) -> impl Display { + let Self { major, minor, patch } = self; + from_fn(move |f| { + write!(f, "{major}.{minor}")?; + if patch != 0 { + write!(f, ".{patch}")?; + } + Ok(()) + }) + } + + pub fn fmt_full(self) -> impl Display { + let Self { major, minor, patch } = self; + from_fn(move |f| write!(f, "{major}.{minor}.{patch}")) + } + + /// Minimum operating system versions currently supported by `rustc`. + pub fn os_minimum_deployment_target(os: &str) -> Self { + // When bumping a version in here, remember to update the platform-support docs too. + // + // NOTE: The defaults may change in future `rustc` versions, so if you are looking for the + // default deployment target, prefer: + // ``` + // $ rustc --print deployment-target + // ``` + let (major, minor, patch) = match os { + "macos" => (10, 12, 0), + "ios" => (10, 0, 0), + "tvos" => (10, 0, 0), + "watchos" => (5, 0, 0), + "visionos" => (1, 0, 0), + _ => unreachable!("tried to get deployment target for non-Apple platform"), + }; + Self { major, minor, patch } + } + + /// The deployment target for the given target. + /// + /// This is similar to `os_minimum_deployment_target`, except that on certain targets it makes sense + /// to raise the minimum OS version. + /// + /// This matches what LLVM does, see in part: + /// + pub fn minimum_deployment_target(target: &Target) -> Self { + let (major, minor, patch) = match (&*target.os, &*target.arch, &*target.abi) { + ("macos", "aarch64", _) => (11, 0, 0), + ("ios", "aarch64", "macabi") => (14, 0, 0), + ("ios", "aarch64", "sim") => (14, 0, 0), + ("ios", _, _) if target.llvm_target.starts_with("arm64e") => (14, 0, 0), + // Mac Catalyst defaults to 13.1 in Clang. + ("ios", _, "macabi") => (13, 1, 0), + ("tvos", "aarch64", "sim") => (14, 0, 0), + ("watchos", "aarch64", "sim") => (7, 0, 0), + (os, _, _) => return Self::os_minimum_deployment_target(os), + }; + Self { major, minor, patch } + } +} diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs index 7a985ad4dc05..391f34701043 100644 --- a/compiler/rustc_target/src/spec/base/apple/tests.rs +++ b/compiler/rustc_target/src/spec/base/apple/tests.rs @@ -1,3 +1,4 @@ +use super::OSVersion; use crate::spec::targets::{ aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_visionos_sim, aarch64_apple_watchos_sim, i686_apple_darwin, x86_64_apple_darwin, x86_64_apple_ios, @@ -42,3 +43,11 @@ fn macos_link_environment_unmodified() { ); } } + +#[test] +fn test_parse_version() { + assert_eq!("10".parse(), Ok(OSVersion::new(10, 0, 0))); + assert_eq!("10.12".parse(), Ok(OSVersion::new(10, 12, 0))); + assert_eq!("10.12.6".parse(), Ok(OSVersion::new(10, 12, 6))); + assert_eq!("9999.99.99".parse(), Ok(OSVersion::new(9999, 99, 99))); +} diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index e8fdc8717853..71b6528c2dd1 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -1,6 +1,6 @@ pub(crate) mod aix; pub(crate) mod android; -pub(crate) mod apple; +pub mod apple; pub(crate) mod avr; pub(crate) mod bpf; pub(crate) mod cygwin; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 981dded2601a..486bf9012ffa 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -60,6 +60,7 @@ pub mod crt_objects; mod base; mod json; +pub use base::apple; pub use base::avr::ef_avr_arch; /// Linker is called through a C/C++ compiler. From 7e4379c4eb25a423b8484d99b01bfc8f5bb7efd8 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 11 Feb 2025 11:02:36 +0100 Subject: [PATCH 142/176] refactor: Move env parsing of deployment target to rustc_session --- compiler/rustc_codegen_ssa/messages.ftl | 6 --- compiler/rustc_codegen_ssa/src/back/apple.rs | 52 +------------------ compiler/rustc_codegen_ssa/src/back/link.rs | 4 +- .../rustc_codegen_ssa/src/back/metadata.rs | 2 +- compiler/rustc_codegen_ssa/src/back/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/errors.rs | 9 ---- compiler/rustc_driver_impl/src/lib.rs | 5 +- compiler/rustc_session/messages.ftl | 6 +++ compiler/rustc_session/src/errors.rs | 10 +++- compiler/rustc_session/src/session.rs | 41 ++++++++++++++- .../rustc_target/src/spec/base/apple/mod.rs | 12 +++++ 11 files changed, 74 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 954a60148093..1dabf01ffd65 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -4,12 +4,6 @@ codegen_ssa_add_native_library = failed to add native library {$library_path}: { codegen_ssa_aix_strip_not_used = using host's `strip` binary to cross-compile to AIX which is not guaranteed to work -codegen_ssa_apple_deployment_target_invalid = - failed to parse deployment target specified in {$env_var}: {$error} - -codegen_ssa_apple_deployment_target_too_low = - deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min} - codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 8954ec0fcdd2..d242efaf4fd4 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -1,6 +1,4 @@ -use std::env; use std::ffi::OsString; -use std::str::FromStr; use std::path::PathBuf; use std::process::Command; @@ -11,7 +9,7 @@ use rustc_target::spec::Target; pub(super) use rustc_target::spec::apple::OSVersion; use tracing::debug; -use crate::errors::{AppleDeploymentTarget, XcrunError, XcrunSdkPathWarning}; +use crate::errors::{XcrunError, XcrunSdkPathWarning}; use crate::fluent_generated as fluent; #[cfg(test)] @@ -134,54 +132,6 @@ pub(super) fn add_data_and_relocation( Ok(()) } -/// Name of the environment variable used to fetch the deployment target on the given OS. -pub fn deployment_target_env_var(os: &str) -> &'static str { - match os { - "macos" => "MACOSX_DEPLOYMENT_TARGET", - "ios" => "IPHONEOS_DEPLOYMENT_TARGET", - "watchos" => "WATCHOS_DEPLOYMENT_TARGET", - "tvos" => "TVOS_DEPLOYMENT_TARGET", - "visionos" => "XROS_DEPLOYMENT_TARGET", - _ => unreachable!("tried to get deployment target env var for non-Apple platform"), - } -} - -/// Get the deployment target based on the standard environment variables, or fall back to the -/// minimum version supported by `rustc`. -pub fn deployment_target(sess: &Session) -> OSVersion { - let min = OSVersion::minimum_deployment_target(&sess.target); - let env_var = deployment_target_env_var(&sess.target.os); - - if let Ok(deployment_target) = env::var(env_var) { - match OSVersion::from_str(&deployment_target) { - Ok(version) => { - let os_min = OSVersion::os_minimum_deployment_target(&sess.target.os); - // It is common that the deployment target is set a bit too low, for example on - // macOS Aarch64 to also target older x86_64. So we only want to warn when variable - // is lower than the minimum OS supported by rustc, not when the variable is lower - // than the minimum for a specific target. - if version < os_min { - sess.dcx().emit_warn(AppleDeploymentTarget::TooLow { - env_var, - version: version.fmt_pretty().to_string(), - os_min: os_min.fmt_pretty().to_string(), - }); - } - - // Raise the deployment target to the minimum supported. - version.max(min) - } - Err(error) => { - sess.dcx().emit_err(AppleDeploymentTarget::Invalid { env_var, error }); - min - } - } - } else { - // If no deployment target variable is set, default to the minimum found above. - min - } -} - pub(super) fn add_version_to_llvm_target( llvm_target: &str, deployment_target: OSVersion, diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8ea8c5b01f46..1d05c4eee4d1 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3115,7 +3115,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo _ => bug!("invalid OS/ABI combination for Apple target: {target_os}, {target_abi}"), }; - let min_version = apple::deployment_target(sess).fmt_full().to_string(); + let min_version = sess.apple_deployment_target().fmt_full().to_string(); // The SDK version is used at runtime when compiling with a newer SDK / version of Xcode: // - By dyld to give extra warnings and errors, see e.g.: @@ -3184,7 +3184,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // The presence of `-mmacosx-version-min` makes CC default to // macOS, and it sets the deployment target. - let version = apple::deployment_target(sess).fmt_full(); + let version = sess.apple_deployment_target().fmt_full(); // Intentionally pass this as a single argument, Clang doesn't // seem to like it otherwise. cmd.cc_arg(&format!("-mmacosx-version-min={version}")); diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index aac2f2da0297..ebcccf1b97d9 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -394,7 +394,7 @@ fn macho_object_build_version_for_target(sess: &Session) -> object::write::MachO } let platform = apple::macho_platform(&sess.target); - let min_os = apple::deployment_target(sess); + let min_os = sess.apple_deployment_target(); let mut build_version = object::write::MachOBuildVersion::default(); build_version.platform = platform; diff --git a/compiler/rustc_codegen_ssa/src/back/mod.rs b/compiler/rustc_codegen_ssa/src/back/mod.rs index 875fa6cfa57b..8d1adb999303 100644 --- a/compiler/rustc_codegen_ssa/src/back/mod.rs +++ b/compiler/rustc_codegen_ssa/src/back/mod.rs @@ -20,7 +20,7 @@ pub mod write; /// Certain optimizations also depend on the deployment target. pub fn versioned_llvm_target(sess: &Session) -> Cow<'_, str> { if sess.target.is_like_darwin { - apple::add_version_to_llvm_target(&sess.target.llvm_target, apple::deployment_target(sess)) + apple::add_version_to_llvm_target(&sess.target.llvm_target, sess.apple_deployment_target()) .into() } else { // FIXME(madsmtm): Certain other targets also include a version, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index f52d29baf9dc..b33de8802d83 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -3,7 +3,6 @@ use std::borrow::Cow; use std::ffi::OsString; use std::io::Error; -use std::num::ParseIntError; use std::path::{Path, PathBuf}; use std::process::ExitStatus; @@ -738,14 +737,6 @@ pub enum ExtractBundledLibsError<'a> { ExtractSection { rlib: &'a Path, error: Box }, } -#[derive(Diagnostic)] -pub(crate) enum AppleDeploymentTarget { - #[diag(codegen_ssa_apple_deployment_target_invalid)] - Invalid { env_var: &'static str, error: ParseIntError }, - #[diag(codegen_ssa_apple_deployment_target_too_low)] - TooLow { env_var: &'static str, version: String, os_min: String }, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_read_file)] pub(crate) struct ReadFileError { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 12f85c23a14a..e7833e201a1c 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -34,7 +34,6 @@ use std::time::{Instant, SystemTime}; use std::{env, str}; use rustc_ast as ast; -use rustc_codegen_ssa::back::apple; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CodegenErrors, CodegenResults}; use rustc_data_structures::profiling::{ @@ -810,8 +809,8 @@ fn print_crate_info( if sess.target.is_like_darwin { println_info!( "{}={}", - apple::deployment_target_env_var(&sess.target.os), - apple::deployment_target(sess).fmt_pretty(), + rustc_target::spec::apple::deployment_target_env_var(&sess.target.os), + sess.apple_deployment_target().fmt_pretty(), ) } else { #[allow(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 74b8087e0776..2f1a918d3a67 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -1,3 +1,9 @@ +session_apple_deployment_target_invalid = + failed to parse deployment target specified in {$env_var}: {$error} + +session_apple_deployment_target_too_low = + deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min} + session_binary_float_literal_not_supported = binary float literal is not supported session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64 diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 71d8dbe44fed..c4e726613a07 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -1,4 +1,4 @@ -use std::num::NonZero; +use std::num::{NonZero, ParseIntError}; use rustc_ast::token; use rustc_ast::util::literal::LitError; @@ -14,6 +14,14 @@ use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTuple}; use crate::config::CrateType; use crate::parse::ParseSess; +#[derive(Diagnostic)] +pub(crate) enum AppleDeploymentTarget { + #[diag(session_apple_deployment_target_invalid)] + Invalid { env_var: &'static str, error: ParseIntError }, + #[diag(session_apple_deployment_target_too_low)] + TooLow { env_var: &'static str, version: String, os_min: String }, +} + pub(crate) struct FeatureGateError { pub(crate) span: MultiSpan, pub(crate) explain: DiagMessage, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a87b1961a995..cea82b359de3 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -29,7 +29,7 @@ use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{ CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SmallDataThresholdSupport, SplitDebuginfo, StackProtector, SymbolVisibility, Target, - TargetTuple, TlsModel, + TargetTuple, TlsModel, apple, }; use crate::code_stats::CodeStats; @@ -891,6 +891,45 @@ impl Session { FileNameDisplayPreference::Local } } + + /// Get the deployment target on Apple platforms based on the standard environment variables, + /// or fall back to the minimum version supported by `rustc`. + /// + /// This should be guarded behind `if sess.target.is_like_darwin`. + pub fn apple_deployment_target(&self) -> apple::OSVersion { + let min = apple::OSVersion::minimum_deployment_target(&self.target); + let env_var = apple::deployment_target_env_var(&self.target.os); + + // FIXME(madsmtm): Track changes to this. + if let Ok(deployment_target) = env::var(env_var) { + match apple::OSVersion::from_str(&deployment_target) { + Ok(version) => { + let os_min = apple::OSVersion::os_minimum_deployment_target(&self.target.os); + // It is common that the deployment target is set a bit too low, for example on + // macOS Aarch64 to also target older x86_64. So we only want to warn when variable + // is lower than the minimum OS supported by rustc, not when the variable is lower + // than the minimum for a specific target. + if version < os_min { + self.dcx().emit_warn(errors::AppleDeploymentTarget::TooLow { + env_var, + version: version.fmt_pretty().to_string(), + os_min: os_min.fmt_pretty().to_string(), + }); + } + + // Raise the deployment target to the minimum supported. + version.max(min) + } + Err(error) => { + self.dcx().emit_err(errors::AppleDeploymentTarget::Invalid { env_var, error }); + min + } + } + } else { + // If no deployment target variable is set, default to the minimum found above. + min + } + } } // JUSTIFICATION: part of session construction diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index dce1b9dab666..46fcd7d5c519 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -317,3 +317,15 @@ impl OSVersion { Self { major, minor, patch } } } + +/// Name of the environment variable used to fetch the deployment target on the given OS. +pub fn deployment_target_env_var(os: &str) -> &'static str { + match os { + "macos" => "MACOSX_DEPLOYMENT_TARGET", + "ios" => "IPHONEOS_DEPLOYMENT_TARGET", + "watchos" => "WATCHOS_DEPLOYMENT_TARGET", + "tvos" => "TVOS_DEPLOYMENT_TARGET", + "visionos" => "XROS_DEPLOYMENT_TARGET", + _ => unreachable!("tried to get deployment target env var for non-Apple platform"), + } +} From 13400c2c10f04fe49f1765ceb2de837c86b6f915 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Apr 2025 15:04:17 +0200 Subject: [PATCH 143/176] Add `_value` methods to proc_macro lib --- library/proc_macro/Cargo.toml | 1 + library/proc_macro/src/lib.rs | 114 ++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/library/proc_macro/Cargo.toml b/library/proc_macro/Cargo.toml index 72cb4e4166f8..f65c5e1a330c 100644 --- a/library/proc_macro/Cargo.toml +++ b/library/proc_macro/Cargo.toml @@ -9,3 +9,4 @@ std = { path = "../std" } # `core` when resolving doc links. Without this line a different `core` will be # loaded from sysroot causing duplicate lang items and other similar errors. core = { path = "../core" } +rustc-literal-escaper = "0.0.1" diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index d9141eab5919..35a8af03ba43 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -51,11 +51,24 @@ use std::{error, fmt}; #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level, MultiSpan}; +#[unstable(feature = "proc_macro_value", issue = "136652")] +pub use rustc_literal_escaper::EscapeError; +use rustc_literal_escaper::{MixedUnit, Mode, byte_from_char, unescape_mixed, unescape_unicode}; #[unstable(feature = "proc_macro_totokens", issue = "130977")] pub use to_tokens::ToTokens; use crate::escape::{EscapeOptions, escape_bytes}; +/// Errors returned when trying to retrieve a literal unescaped value. +#[unstable(feature = "proc_macro_value", issue = "136652")] +#[derive(Debug, PartialEq, Eq)] +pub enum ConversionErrorKind { + /// The literal failed to be escaped, take a look at [`EscapeError`] for more information. + FailedToUnescape(EscapeError), + /// Trying to convert a literal with the wrong type. + InvalidLiteralKind, +} + /// Determines whether proc_macro has been made accessible to the currently /// running program. /// @@ -1451,6 +1464,107 @@ impl Literal { } }) } + + /// Returns the unescaped string value if the current literal is a string or a string literal. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn str_value(&self) -> Result { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::Str => { + if symbol.contains('\\') { + let mut buf = String::with_capacity(symbol.len()); + let mut error = None; + // Force-inlining here is aggressive but the closure is + // called on every char in the string, so it can be hot in + // programs with many long strings containing escapes. + unescape_unicode( + symbol, + Mode::Str, + &mut #[inline(always)] + |_, c| match c { + Ok(c) => buf.push(c), + Err(err) => { + if err.is_fatal() { + error = Some(ConversionErrorKind::FailedToUnescape(err)); + } + } + }, + ); + if let Some(error) = error { Err(error) } else { Ok(buf) } + } else { + Ok(symbol.to_string()) + } + } + bridge::LitKind::StrRaw(_) => Ok(symbol.to_string()), + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } + + /// Returns the unescaped string value if the current literal is a c-string or a c-string + /// literal. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn cstr_value(&self) -> Result, ConversionErrorKind> { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::CStr => { + let mut error = None; + let mut buf = Vec::with_capacity(symbol.len()); + + unescape_mixed(symbol, Mode::CStr, &mut |_span, c| match c { + Ok(MixedUnit::Char(c)) => { + buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) + } + Ok(MixedUnit::HighByte(b)) => buf.push(b), + Err(err) => { + if err.is_fatal() { + error = Some(ConversionErrorKind::FailedToUnescape(err)); + } + } + }); + if let Some(error) = error { + Err(error) + } else { + buf.push(0); + Ok(buf) + } + } + bridge::LitKind::CStrRaw(_) => { + // Raw strings have no escapes so we can convert the symbol + // directly to a `Lrc` after appending the terminating NUL + // char. + let mut buf = symbol.to_owned().into_bytes(); + buf.push(0); + Ok(buf) + } + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } + + /// Returns the unescaped string value if the current literal is a byte string or a byte string + /// literal. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn byte_str_value(&self) -> Result, ConversionErrorKind> { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::ByteStr => { + let mut buf = Vec::with_capacity(symbol.len()); + let mut error = None; + + unescape_unicode(symbol, Mode::ByteStr, &mut |_, c| match c { + Ok(c) => buf.push(byte_from_char(c)), + Err(err) => { + if err.is_fatal() { + error = Some(ConversionErrorKind::FailedToUnescape(err)); + } + } + }); + if let Some(error) = error { Err(error) } else { Ok(buf) } + } + bridge::LitKind::ByteStrRaw(_) => { + // Raw strings have no escapes so we can convert the symbol + // directly to a `Lrc`. + Ok(symbol.to_owned().into_bytes()) + } + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } } /// Parse a single literal from its stringified representation. From a69a219f96454f59786b5983ce471aaeec1d77ed Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 1 Apr 2025 16:21:50 +0000 Subject: [PATCH 144/176] Use the span of the whole bound when the diagnostic talks about a bound --- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 4 ++-- tests/ui/consts/const-block-const-bound.stderr | 2 +- .../ui/traits/const-traits/assoc-type.current.stderr | 2 +- tests/ui/traits/const-traits/assoc-type.next.stderr | 2 +- .../const-traits/call-generic-method-nonconst.stderr | 2 +- .../const-traits/const-drop-fail-2.precise.stderr | 4 ++-- .../const-traits/const-drop-fail-2.stock.stderr | 4 ++-- .../const-traits/const-drop-fail.new_precise.stderr | 4 ++-- .../const-traits/const-drop-fail.new_stock.stderr | 4 ++-- .../const-traits/const-drop-fail.old_precise.stderr | 4 ++-- .../const-traits/const-drop-fail.old_stock.stderr | 4 ++-- tests/ui/traits/const-traits/const-opaque.no.stderr | 2 +- ...default-method-body-is-const-body-checking.stderr | 2 +- .../const-traits/item-bound-entailment-fails.stderr | 6 +++--- tests/ui/traits/const-traits/minicore-fn-fail.stderr | 2 +- .../const-traits/predicate-entailment-fails.stderr | 12 ++++++------ .../const-traits/trait-where-clause-const.stderr | 4 ++-- .../unsatisfied-const-trait-bound.stderr | 2 +- 18 files changed, 33 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 83925b5ec52c..b4a71edc118c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -838,7 +838,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | PredicateFilter::SelfOnly | PredicateFilter::SelfAndAssociatedTypeBounds => { match constness { - hir::BoundConstness::Always(span) => { + hir::BoundConstness::Always(_) => { if polarity == ty::PredicatePolarity::Positive { bounds.push(( poly_trait_ref @@ -864,7 +864,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // in `lower_assoc_item_constraint`. PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => { match constness { - hir::BoundConstness::Maybe(span) => { + hir::BoundConstness::Maybe(_) => { if polarity == ty::PredicatePolarity::Positive { bounds.push(( poly_trait_ref diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr index 14c62fb4d257..624772f5aedc 100644 --- a/tests/ui/consts/const-block-const-bound.stderr +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -10,7 +10,7 @@ note: required by a bound in `f` --> $DIR/const-block-const-bound.rs:6:15 | LL | const fn f(x: T) {} - | ^^^^^^ required by this bound in `f` + | ^^^^^^^^^^^^^^^ required by this bound in `f` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/assoc-type.current.stderr b/tests/ui/traits/const-traits/assoc-type.current.stderr index 4bf9acfbd650..7526369194b4 100644 --- a/tests/ui/traits/const-traits/assoc-type.current.stderr +++ b/tests/ui/traits/const-traits/assoc-type.current.stderr @@ -8,7 +8,7 @@ note: required by a bound in `Foo::Bar` --> $DIR/assoc-type.rs:33:15 | LL | type Bar: ~const Add; - | ^^^^^^ required by this bound in `Foo::Bar` + | ^^^^^^^^^^ required by this bound in `Foo::Bar` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/assoc-type.next.stderr b/tests/ui/traits/const-traits/assoc-type.next.stderr index 4bf9acfbd650..7526369194b4 100644 --- a/tests/ui/traits/const-traits/assoc-type.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type.next.stderr @@ -8,7 +8,7 @@ note: required by a bound in `Foo::Bar` --> $DIR/assoc-type.rs:33:15 | LL | type Bar: ~const Add; - | ^^^^^^ required by this bound in `Foo::Bar` + | ^^^^^^^^^^ required by this bound in `Foo::Bar` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr index 74a22186a163..11bbe8bbb408 100644 --- a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr @@ -10,7 +10,7 @@ note: required by a bound in `equals_self` --> $DIR/call-generic-method-nonconst.rs:17:25 | LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ required by this bound in `equals_self` + | ^^^^^^^^^^ required by this bound in `equals_self` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr index 2b5e66b1a086..76207ea0939b 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr @@ -8,14 +8,14 @@ note: required for `ConstDropImplWithBounds` to implement `const --> $DIR/const-drop-fail-2.rs:25:25 | LL | impl const Drop for ConstDropImplWithBounds { - | ------ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -------- ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | unsatisfied trait bound introduced here note: required by a bound in `check` --> $DIR/const-drop-fail-2.rs:21:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr index 2b5e66b1a086..76207ea0939b 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr @@ -8,14 +8,14 @@ note: required for `ConstDropImplWithBounds` to implement `const --> $DIR/const-drop-fail-2.rs:25:25 | LL | impl const Drop for ConstDropImplWithBounds { - | ------ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -------- ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | unsatisfied trait bound introduced here note: required by a bound in `check` --> $DIR/const-drop-fail-2.rs:21:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr index 682f48fe07af..f38e642bb63e 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr @@ -11,7 +11,7 @@ note: required by a bound in `check` --> $DIR/const-drop-fail.rs:24:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied --> $DIR/const-drop-fail.rs:35:5 @@ -26,7 +26,7 @@ note: required by a bound in `check` --> $DIR/const-drop-fail.rs:24:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr index 682f48fe07af..f38e642bb63e 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr @@ -11,7 +11,7 @@ note: required by a bound in `check` --> $DIR/const-drop-fail.rs:24:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied --> $DIR/const-drop-fail.rs:35:5 @@ -26,7 +26,7 @@ note: required by a bound in `check` --> $DIR/const-drop-fail.rs:24:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr index 682f48fe07af..f38e642bb63e 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr @@ -11,7 +11,7 @@ note: required by a bound in `check` --> $DIR/const-drop-fail.rs:24:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied --> $DIR/const-drop-fail.rs:35:5 @@ -26,7 +26,7 @@ note: required by a bound in `check` --> $DIR/const-drop-fail.rs:24:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr index 682f48fe07af..f38e642bb63e 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr @@ -11,7 +11,7 @@ note: required by a bound in `check` --> $DIR/const-drop-fail.rs:24:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied --> $DIR/const-drop-fail.rs:35:5 @@ -26,7 +26,7 @@ note: required by a bound in `check` --> $DIR/const-drop-fail.rs:24:19 | LL | const fn check(_: T) {} - | ^^^^^^ required by this bound in `check` + | ^^^^^^^^^^^^^^^ required by this bound in `check` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-opaque.no.stderr b/tests/ui/traits/const-traits/const-opaque.no.stderr index 1278e1257467..47e692936e04 100644 --- a/tests/ui/traits/const-traits/const-opaque.no.stderr +++ b/tests/ui/traits/const-traits/const-opaque.no.stderr @@ -10,7 +10,7 @@ note: required by a bound in `bar` --> $DIR/const-opaque.rs:26:17 | LL | const fn bar(t: T) -> impl ~const Foo { - | ^^^^^^ required by this bound in `bar` + | ^^^^^^^^^^ required by this bound in `bar` error[E0277]: the trait bound `(): const Foo` is not satisfied --> $DIR/const-opaque.rs:33:12 diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr index 8c284bde67e7..b3017523b27d 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr +++ b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr @@ -8,7 +8,7 @@ note: required by a bound in `foo` --> $DIR/default-method-body-is-const-body-checking.rs:7:28 | LL | const fn foo() where T: ~const Tr {} - | ^^^^^^ required by this bound in `foo` + | ^^^^^^^^^ required by this bound in `foo` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr index 0d53bc5897ef..7e72dc9abaa2 100644 --- a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr +++ b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr @@ -8,7 +8,7 @@ note: required by a bound in `Foo::Assoc` --> $DIR/item-bound-entailment-fails.rs:5:20 | LL | type Assoc: ~const Bar - | ^^^^^^ required by this bound in `Foo::Assoc` + | ^^^^^^^^^^ required by this bound in `Foo::Assoc` error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/item-bound-entailment-fails.rs:24:21 @@ -20,12 +20,12 @@ note: required for `C` to implement `~const Bar` --> $DIR/item-bound-entailment-fails.rs:14:15 | LL | impl const Bar for C where T: ~const Bar {} - | ^^^ ^^^^ ------ unsatisfied trait bound introduced here + | ^^^ ^^^^ ---------- unsatisfied trait bound introduced here note: required by a bound in `Foo::Assoc` --> $DIR/item-bound-entailment-fails.rs:5:20 | LL | type Assoc: ~const Bar - | ^^^^^^ required by this bound in `Foo::Assoc` + | ^^^^^^^^^^ required by this bound in `Foo::Assoc` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/minicore-fn-fail.stderr b/tests/ui/traits/const-traits/minicore-fn-fail.stderr index fa8be631a26b..03c7ade87c01 100644 --- a/tests/ui/traits/const-traits/minicore-fn-fail.stderr +++ b/tests/ui/traits/const-traits/minicore-fn-fail.stderr @@ -10,7 +10,7 @@ note: required by a bound in `call_indirect` --> $DIR/minicore-fn-fail.rs:11:27 | LL | const fn call_indirect(t: &T) { t() } - | ^^^^^^ required by this bound in `call_indirect` + | ^^^^^^^^^^^ required by this bound in `call_indirect` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/predicate-entailment-fails.stderr b/tests/ui/traits/const-traits/predicate-entailment-fails.stderr index 369e95688a9b..dfdc4d232508 100644 --- a/tests/ui/traits/const-traits/predicate-entailment-fails.stderr +++ b/tests/ui/traits/const-traits/predicate-entailment-fails.stderr @@ -5,7 +5,7 @@ LL | type Bar where T: ~const Bar; | ----------- definition of `Bar` from trait ... LL | type Bar = () where T: const Bar; - | ^^^^^ impl has extra requirement `T: const Bar` + | ^^^^^^^^^ impl has extra requirement `T: const Bar` error[E0276]: impl has stricter requirements than trait --> $DIR/predicate-entailment-fails.rs:17:26 @@ -14,7 +14,7 @@ LL | fn foo() where T: ~const Bar; | -------------------------------- definition of `foo` from trait ... LL | fn foo() where T: const Bar {} - | ^^^^^ impl has extra requirement `T: const Bar` + | ^^^^^^^^^ impl has extra requirement `T: const Bar` error[E0276]: impl has stricter requirements than trait --> $DIR/predicate-entailment-fails.rs:28:31 @@ -23,7 +23,7 @@ LL | type Bar where T: Bar; | ----------- definition of `Bar` from trait ... LL | type Bar = () where T: const Bar; - | ^^^^^ impl has extra requirement `T: const Bar` + | ^^^^^^^^^ impl has extra requirement `T: const Bar` error[E0276]: impl has stricter requirements than trait --> $DIR/predicate-entailment-fails.rs:31:26 @@ -32,7 +32,7 @@ LL | fn foo() where T: Bar; | ------------------------- definition of `foo` from trait ... LL | fn foo() where T: const Bar {} - | ^^^^^ impl has extra requirement `T: const Bar` + | ^^^^^^^^^ impl has extra requirement `T: const Bar` error[E0276]: impl has stricter requirements than trait --> $DIR/predicate-entailment-fails.rs:35:31 @@ -41,7 +41,7 @@ LL | type Bar where T: Bar; | ----------- definition of `Bar` from trait ... LL | type Bar = () where T: ~const Bar; - | ^^^^^^ impl has extra requirement `T: ~const Bar` + | ^^^^^^^^^^ impl has extra requirement `T: ~const Bar` error[E0276]: impl has stricter requirements than trait --> $DIR/predicate-entailment-fails.rs:38:26 @@ -50,7 +50,7 @@ LL | fn foo() where T: Bar; | ------------------------- definition of `foo` from trait ... LL | fn foo() where T: ~const Bar {} - | ^^^^^^ impl has extra requirement `T: ~const Bar` + | ^^^^^^^^^^ impl has extra requirement `T: ~const Bar` error: aborting due to 6 previous errors diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.stderr b/tests/ui/traits/const-traits/trait-where-clause-const.stderr index 4100ae1c6bfd..4ebd7b9757fe 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause-const.stderr @@ -8,7 +8,7 @@ note: required by a bound in `Foo::b` --> $DIR/trait-where-clause-const.rs:15:24 | LL | fn b() where Self: ~const Bar; - | ^^^^^^ required by this bound in `Foo::b` + | ^^^^^^^^^^ required by this bound in `Foo::b` error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause-const.rs:23:12 @@ -20,7 +20,7 @@ note: required by a bound in `Foo::c` --> $DIR/trait-where-clause-const.rs:16:13 | LL | fn c(); - | ^^^^^^ required by this bound in `Foo::c` + | ^^^^^^^^^^ required by this bound in `Foo::c` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index bda6a029cc2a..be761e49ba0c 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -28,7 +28,7 @@ note: required by a bound in `require` --> $DIR/unsatisfied-const-trait-bound.rs:8:15 | LL | fn require() {} - | ^^^^^ required by this bound in `require` + | ^^^^^^^^^^^ required by this bound in `require` error: aborting due to 4 previous errors From e6498670868810b7d232223487e8f2019a6ebdbb Mon Sep 17 00:00:00 2001 From: Kornel Date: Sun, 16 Mar 2025 16:17:33 +0000 Subject: [PATCH 145/176] Optimize slice Iter::nth --- library/core/src/slice/iter.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index d48248749c26..b1a19e3427d6 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -1536,17 +1536,15 @@ impl<'a, T> Iterator for Chunks<'a, T> { #[inline] fn nth(&mut self, n: usize) -> Option { let (start, overflow) = n.overflowing_mul(self.chunk_size); - if start >= self.v.len() || overflow { - self.v = &[]; - None - } else { - let end = match start.checked_add(self.chunk_size) { - Some(sum) => cmp::min(self.v.len(), sum), - None => self.v.len(), - }; - let nth = &self.v[start..end]; - self.v = &self.v[end..]; + // min(len) makes a wrong start harmless, but enables optimizing this to brachless code + let chunk_start = &self.v[start.min(self.v.len())..]; + let (nth, remainder) = chunk_start.split_at(self.chunk_size.min(chunk_start.len())); + if !overflow && start < self.v.len() { + self.v = remainder; Some(nth) + } else { + self.v = &self.v[..0]; // cheaper than &[] + None } } From 89477aff04a4d8f837a50deb62416cf33ecf766c Mon Sep 17 00:00:00 2001 From: Kornel Date: Sun, 16 Mar 2025 16:48:41 +0000 Subject: [PATCH 146/176] Optimize slice Windows::nth Generates branchless code --- library/core/src/slice/iter.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index b1a19e3427d6..e9c27ddbbbae 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -1380,14 +1380,16 @@ impl<'a, T> Iterator for Windows<'a, T> { #[inline] fn nth(&mut self, n: usize) -> Option { - let (end, overflow) = self.size.get().overflowing_add(n); - if end > self.v.len() || overflow { - self.v = &[]; - None - } else { - let nth = &self.v[n..end]; - self.v = &self.v[n + 1..]; + let size = self.size.get(); + if let Some(rest) = self.v.get(n..) + && let Some(nth) = rest.get(..size) + { + self.v = &rest[1..]; Some(nth) + } else { + // setting length to 0 is cheaper than overwriting the pointer when assigning &[] + self.v = &self.v[..0]; + None } } From 9f2f1aa08354019113f39672228fc62583e6a1ed Mon Sep 17 00:00:00 2001 From: Kornel Date: Sun, 16 Mar 2025 16:17:16 +0000 Subject: [PATCH 147/176] Optimize setting the slice to empty in slice Iter This avoids generating extra instructions that needlessly modify the slice's pointer --- library/core/src/slice/iter.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index e9c27ddbbbae..f507ee563ac0 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -1388,7 +1388,7 @@ impl<'a, T> Iterator for Windows<'a, T> { Some(nth) } else { // setting length to 0 is cheaper than overwriting the pointer when assigning &[] - self.v = &self.v[..0]; + self.v = &self.v[..0]; // cheaper than &[] None } } @@ -1429,7 +1429,7 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> { fn nth_back(&mut self, n: usize) -> Option { let (end, overflow) = self.v.len().overflowing_sub(n); if end < self.size.get() || overflow { - self.v = &[]; + self.v = &self.v[..0]; // cheaper than &[] None } else { let ret = &self.v[end - self.size.get()..end]; @@ -1609,7 +1609,7 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { fn nth_back(&mut self, n: usize) -> Option { let len = self.len(); if n >= len { - self.v = &[]; + self.v = &self.v[..0]; // cheaper than &[] None } else { let start = (len - 1 - n) * self.chunk_size; @@ -1933,7 +1933,7 @@ impl<'a, T> Iterator for ChunksExact<'a, T> { fn nth(&mut self, n: usize) -> Option { let (start, overflow) = n.overflowing_mul(self.chunk_size); if start >= self.v.len() || overflow { - self.v = &[]; + self.v = &self.v[..0]; // cheaper than &[] None } else { let (_, snd) = self.v.split_at(start); @@ -1971,7 +1971,7 @@ impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> { fn nth_back(&mut self, n: usize) -> Option { let len = self.len(); if n >= len { - self.v = &[]; + self.v = &self.v[..0]; // cheaper than &[] None } else { let start = (len - 1 - n) * self.chunk_size; @@ -2638,7 +2638,7 @@ impl<'a, T> Iterator for RChunks<'a, T> { fn nth(&mut self, n: usize) -> Option { let (end, overflow) = n.overflowing_mul(self.chunk_size); if end >= self.v.len() || overflow { - self.v = &[]; + self.v = &self.v[..0]; // cheaper than &[] None } else { // Can't underflow because of the check above @@ -2695,7 +2695,7 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> { fn nth_back(&mut self, n: usize) -> Option { let len = self.len(); if n >= len { - self.v = &[]; + self.v = &self.v[..0]; // cheaper than &[] None } else { // can't underflow because `n < len` @@ -3023,7 +3023,7 @@ impl<'a, T> Iterator for RChunksExact<'a, T> { fn nth(&mut self, n: usize) -> Option { let (end, overflow) = n.overflowing_mul(self.chunk_size); if end >= self.v.len() || overflow { - self.v = &[]; + self.v = &self.v[..0]; // cheaper than &[] None } else { let (fst, _) = self.v.split_at(self.v.len() - end); @@ -3062,7 +3062,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> { fn nth_back(&mut self, n: usize) -> Option { let len = self.len(); if n >= len { - self.v = &[]; + self.v = &self.v[..0]; // cheaper than &[] None } else { // now that we know that `n` corresponds to a chunk, From 76e13020767e7ff783284b5bcf7a7509259ceb51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 4 Apr 2025 18:29:20 +0200 Subject: [PATCH 148/176] Use target-agnostic LLD flags in bootstrap for use-lld --- src/bootstrap/src/utils/helpers.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index f8e4d4e04717..78dcdcbd1874 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -474,13 +474,13 @@ pub fn linker_flags( if stage == 0 && target.is_windows() { args.push("-Clink-arg=-fuse-ld=lld".to_string()); } else { - args.push("-Clinker-flavor=gnu-lld-cc".to_string()); + args.push("-Zlinker-features=+lld".to_string()); } // FIXME(kobzol): remove this flag once MCP510 gets stabilized args.push("-Zunstable-options".to_string()); } LldMode::SelfContained => { - args.push("-Clinker-flavor=gnu-lld-cc".to_string()); + args.push("-Zlinker-features=+lld".to_string()); args.push("-Clink-self-contained=+linker".to_string()); // FIXME(kobzol): remove this flag once MCP510 gets stabilized args.push("-Zunstable-options".to_string()); From 00f0ce26ac513fb858b74d526139846ee8a74866 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 5 Apr 2025 01:46:09 +0800 Subject: [PATCH 149/176] triagebot: add `compiletest` adhoc_group for `r? compiletest` --- triagebot.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index e2b9e321a488..422f5b82ad03 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1277,11 +1277,13 @@ project-stable-mir = [ "@oli-obk", "@scottmcm", ] - project-exploit-mitigations = [ "@cuviper", "@rcvalle", ] +compiletest = [ + "@jieyouxu", +] [assign.owners] "/.github/workflows" = ["infra-ci"] From b7c63a973fdfa317a01b9d676803c59edc31abdc Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 4 Apr 2025 14:24:23 -0400 Subject: [PATCH 150/176] add autodiff batching backend --- .../src/builder/autodiff.rs | 199 ++++++++++++++---- compiler/rustc_codegen_llvm/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/context.rs | 23 +- .../rustc_codegen_llvm/src/llvm/enzyme_ffi.rs | 4 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 10 + 6 files changed, 196 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 7cd4ee539d87..7d264ba4d00c 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -3,8 +3,10 @@ use std::ptr; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, AutoDiffItem, DiffActivity, DiffMode}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::back::write::ModuleConfig; -use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _; +use rustc_codegen_ssa::common::TypeKind; +use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; use rustc_errors::FatalError; +use rustc_middle::bug; use tracing::{debug, trace}; use crate::back::write::llvm_err; @@ -18,21 +20,42 @@ use crate::value::Value; use crate::{CodegenContext, LlvmCodegenBackend, ModuleLlvm, attributes, llvm}; fn get_params(fnc: &Value) -> Vec<&Value> { + let param_num = llvm::LLVMCountParams(fnc) as usize; + let mut fnc_args: Vec<&Value> = vec![]; + fnc_args.reserve(param_num); unsafe { - let param_num = llvm::LLVMCountParams(fnc) as usize; - let mut fnc_args: Vec<&Value> = vec![]; - fnc_args.reserve(param_num); llvm::LLVMGetParams(fnc, fnc_args.as_mut_ptr()); fnc_args.set_len(param_num); - fnc_args + } + fnc_args +} + +fn has_sret(fnc: &Value) -> bool { + let num_args = llvm::LLVMCountParams(fnc) as usize; + if num_args == 0 { + false + } else { + unsafe { llvm::LLVMRustHasAttributeAtIndex(fnc, 0, llvm::AttributeKind::StructRet) } } } +// When we call the `__enzyme_autodiff` or `__enzyme_fwddiff` function, we need to pass all the +// original inputs, as well as metadata and the additional shadow arguments. +// This function matches the arguments from the outer function to the inner enzyme call. +// +// This function also considers that Rust level arguments not always match the llvm-ir level +// arguments. A slice, `&[f32]`, for example, is represented as a pointer and a length on +// llvm-ir level. The number of activities matches the number of Rust level arguments, so we +// need to match those. +// FIXME(ZuseZ4): This logic is a bit more complicated than it should be, can we simplify it +// using iterators and peek()? fn match_args_from_caller_to_enzyme<'ll>( cx: &SimpleCx<'ll>, + width: u32, args: &mut Vec<&'ll llvm::Value>, inputs: &[DiffActivity], outer_args: &[&'ll llvm::Value], + has_sret: bool, ) { debug!("matching autodiff arguments"); // We now handle the issue that Rust level arguments not always match the llvm-ir level @@ -44,6 +67,14 @@ fn match_args_from_caller_to_enzyme<'ll>( let mut outer_pos: usize = 0; let mut activity_pos = 0; + if has_sret { + // Then the first outer arg is the sret pointer. Enzyme doesn't know about sret, so the + // inner function will still return something. We increase our outer_pos by one, + // and once we're done with all other args we will take the return of the inner call and + // update the sret pointer with it + outer_pos = 1; + } + let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap(); let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap(); let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap(); @@ -92,23 +123,20 @@ fn match_args_from_caller_to_enzyme<'ll>( // (..., metadata! enzyme_dup, ptr, ptr, int1, ...). // FIXME(ZuseZ4): We will upstream a safety check later which asserts that // int2 >= int1, which means the shadow vector is large enough to store the gradient. - assert!(unsafe { - llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Integer - }); - let next_outer_arg2 = outer_args[outer_pos + 2]; - let next_outer_ty2 = cx.val_ty(next_outer_arg2); - assert!(unsafe { - llvm::LLVMRustGetTypeKind(next_outer_ty2) == llvm::TypeKind::Pointer - }); - let next_outer_arg3 = outer_args[outer_pos + 3]; - let next_outer_ty3 = cx.val_ty(next_outer_arg3); - assert!(unsafe { - llvm::LLVMRustGetTypeKind(next_outer_ty3) == llvm::TypeKind::Integer - }); - args.push(next_outer_arg2); + assert_eq!(cx.type_kind(next_outer_ty), TypeKind::Integer); + + for i in 0..(width as usize) { + let next_outer_arg2 = outer_args[outer_pos + 2 * (i + 1)]; + let next_outer_ty2 = cx.val_ty(next_outer_arg2); + assert_eq!(cx.type_kind(next_outer_ty2), TypeKind::Pointer); + let next_outer_arg3 = outer_args[outer_pos + 2 * (i + 1) + 1]; + let next_outer_ty3 = cx.val_ty(next_outer_arg3); + assert_eq!(cx.type_kind(next_outer_ty3), TypeKind::Integer); + args.push(next_outer_arg2); + } args.push(cx.get_metadata_value(enzyme_const)); args.push(next_outer_arg); - outer_pos += 4; + outer_pos += 2 + 2 * width as usize; activity_pos += 2; } else { // A duplicated pointer will have the following two outer_fn arguments: @@ -116,15 +144,19 @@ fn match_args_from_caller_to_enzyme<'ll>( // (..., metadata! enzyme_dup, ptr, ptr, ...). if matches!(diff_activity, DiffActivity::Duplicated | DiffActivity::DuplicatedOnly) { - assert!( - unsafe { llvm::LLVMRustGetTypeKind(next_outer_ty) } - == llvm::TypeKind::Pointer - ); + assert_eq!(cx.type_kind(next_outer_ty), TypeKind::Pointer); } // In the case of Dual we don't have assumptions, e.g. f32 would be valid. args.push(next_outer_arg); outer_pos += 2; activity_pos += 1; + + // Now, if width > 1, we need to account for that + for _ in 1..width { + let next_outer_arg = outer_args[outer_pos]; + args.push(next_outer_arg); + outer_pos += 1; + } } } else { // We do not differentiate with resprect to this argument. @@ -135,6 +167,76 @@ fn match_args_from_caller_to_enzyme<'ll>( } } +// On LLVM-IR, we can luckily declare __enzyme_ functions without specifying the input +// arguments. We do however need to declare them with their correct return type. +// We already figured the correct return type out in our frontend, when generating the outer_fn, +// so we can now just go ahead and use that. This is not always trivial, e.g. because sret. +// Beyond sret, this article describes our challenges nicely: +// +// I.e. (i32, f32) will get merged into i64, but we don't handle that yet. +fn compute_enzyme_fn_ty<'ll>( + cx: &SimpleCx<'ll>, + attrs: &AutoDiffAttrs, + fn_to_diff: &'ll Value, + outer_fn: &'ll Value, +) -> &'ll llvm::Type { + let fn_ty = cx.get_type_of_global(outer_fn); + let mut ret_ty = cx.get_return_type(fn_ty); + + let has_sret = has_sret(outer_fn); + + if has_sret { + // Now we don't just forward the return type, so we have to figure it out based on the + // primal return type, in combination with the autodiff settings. + let fn_ty = cx.get_type_of_global(fn_to_diff); + let inner_ret_ty = cx.get_return_type(fn_ty); + + let void_ty = unsafe { llvm::LLVMVoidTypeInContext(cx.llcx) }; + if inner_ret_ty == void_ty { + // This indicates that even the inner function has an sret. + // Right now I only look for an sret in the outer function. + // This *probably* needs some extra handling, but I never ran + // into such a case. So I'll wait for user reports to have a test case. + bug!("sret in inner function"); + } + + if attrs.width == 1 { + todo!("Handle sret for scalar ad"); + } else { + // First we check if we also have to deal with the primal return. + match attrs.mode { + DiffMode::Forward => match attrs.ret_activity { + DiffActivity::Dual => { + let arr_ty = + unsafe { llvm::LLVMArrayType2(inner_ret_ty, attrs.width as u64 + 1) }; + ret_ty = arr_ty; + } + DiffActivity::DualOnly => { + let arr_ty = + unsafe { llvm::LLVMArrayType2(inner_ret_ty, attrs.width as u64) }; + ret_ty = arr_ty; + } + DiffActivity::Const => { + todo!("Not sure, do we need to do something here?"); + } + _ => { + bug!("unreachable"); + } + }, + DiffMode::Reverse => { + todo!("Handle sret for reverse mode"); + } + _ => { + bug!("unreachable"); + } + } + } + } + + // LLVM can figure out the input types on it's own, so we take a shortcut here. + unsafe { llvm::LLVMFunctionType(ret_ty, ptr::null(), 0, True) } +} + /// When differentiating `fn_to_diff`, take a `outer_fn` and generate another /// function with expected naming and calling conventions[^1] which will be /// discovered by the enzyme LLVM pass and its body populated with the differentiated @@ -197,17 +299,9 @@ fn generate_enzyme_call<'ll>( // } // ``` unsafe { - // On LLVM-IR, we can luckily declare __enzyme_ functions without specifying the input - // arguments. We do however need to declare them with their correct return type. - // We already figured the correct return type out in our frontend, when generating the outer_fn, - // so we can now just go ahead and use that. FIXME(ZuseZ4): This doesn't handle sret yet. - let fn_ty = llvm::LLVMGlobalGetValueType(outer_fn); - let ret_ty = llvm::LLVMGetReturnType(fn_ty); + let enzyme_ty = compute_enzyme_fn_ty(cx, &attrs, fn_to_diff, outer_fn); - // LLVM can figure out the input types on it's own, so we take a shortcut here. - let enzyme_ty = llvm::LLVMFunctionType(ret_ty, ptr::null(), 0, True); - - //FIXME(ZuseZ4): the CC/Addr/Vis values are best effort guesses, we should look at tests and + // FIXME(ZuseZ4): the CC/Addr/Vis values are best effort guesses, we should look at tests and // think a bit more about what should go here. let cc = llvm::LLVMGetFunctionCallConv(outer_fn); let ad_fn = declare_simple_fn( @@ -240,14 +334,27 @@ fn generate_enzyme_call<'ll>( if matches!(attrs.ret_activity, DiffActivity::Dual | DiffActivity::Active) { args.push(cx.get_metadata_value(enzyme_primal_ret)); } + if attrs.width > 1 { + let enzyme_width = cx.create_metadata("enzyme_width".to_string()).unwrap(); + args.push(cx.get_metadata_value(enzyme_width)); + args.push(cx.get_const_i64(attrs.width as u64)); + } + let has_sret = has_sret(outer_fn); let outer_args: Vec<&llvm::Value> = get_params(outer_fn); - match_args_from_caller_to_enzyme(&cx, &mut args, &attrs.input_activity, &outer_args); + match_args_from_caller_to_enzyme( + &cx, + attrs.width, + &mut args, + &attrs.input_activity, + &outer_args, + has_sret, + ); let call = builder.call(enzyme_ty, ad_fn, &args, None); // This part is a bit iffy. LLVM requires that a call to an inlineable function has some - // metadata attachted to it, but we just created this code oota. Given that the + // metadata attached to it, but we just created this code oota. Given that the // differentiated function already has partly confusing metadata, and given that this // affects nothing but the auttodiff IR, we take a shortcut and just steal metadata from the // dummy code which we inserted at a higher level. @@ -268,7 +375,22 @@ fn generate_enzyme_call<'ll>( // Now that we copied the metadata, get rid of dummy code. llvm::LLVMRustEraseInstUntilInclusive(entry, last_inst); - if cx.val_ty(call) == cx.type_void() { + if cx.val_ty(call) == cx.type_void() || has_sret { + if has_sret { + // This is what we already have in our outer_fn (shortened): + // define void @_foo(ptr <..> sret([32 x i8]) initializes((0, 32)) %0, <...>) { + // %7 = call [4 x double] (...) @__enzyme_fwddiff_foo(ptr @square, metadata !"enzyme_width", i64 4, <...>) + // + // store [4 x double] %7, ptr %0, align 8 + // ret void + // } + + // now store the result of the enzyme call into the sret pointer. + let sret_ptr = outer_args[0]; + let call_ty = cx.val_ty(call); + assert_eq!(cx.type_kind(call_ty), TypeKind::Array); + llvm::LLVMBuildStore(&builder.llbuilder, call, sret_ptr); + } builder.ret_void(); } else { builder.ret(call); @@ -300,8 +422,7 @@ pub(crate) fn differentiate<'ll>( if !diff_items.is_empty() && !cgcx.opts.unstable_opts.autodiff.contains(&rustc_session::config::AutoDiff::Enable) { - let dcx = cgcx.create_dcx(); - return Err(dcx.handle().emit_almost_fatal(AutoDiffWithoutEnable)); + return Err(diag_handler.handle().emit_almost_fatal(AutoDiffWithoutEnable)); } // Before dumping the module, we want all the TypeTrees to become part of the module. diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 62fa2884e0f6..d5acfe205311 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -425,7 +425,7 @@ impl<'ll> CodegenCx<'ll, '_> { let val_llty = self.val_ty(v); let g = self.get_static_inner(def_id, val_llty); - let llty = llvm::LLVMGlobalGetValueType(g); + let llty = self.get_type_of_global(g); let g = if val_llty == llty { g diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 926445c780b5..d163fa981179 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -8,6 +8,7 @@ use std::str; use rustc_abi::{HasDataLayout, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; +use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; @@ -38,7 +39,7 @@ use crate::debuginfo::metadata::apply_vcall_visibility_metadata; use crate::llvm::Metadata; use crate::type_::Type; use crate::value::Value; -use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util}; +use crate::{attributes, common, coverageinfo, debuginfo, llvm, llvm_util}; /// `TyCtxt` (and related cache datastructures) can't be move between threads. /// However, there are various cx related functions which we want to be available to the builder and @@ -643,7 +644,18 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { llvm::set_section(g, c"llvm.metadata"); } } - +impl<'ll> SimpleCx<'ll> { + pub(crate) fn get_return_type(&self, ty: &'ll Type) -> &'ll Type { + assert_eq!(self.type_kind(ty), TypeKind::Function); + unsafe { llvm::LLVMGetReturnType(ty) } + } + pub(crate) fn get_type_of_global(&self, val: &'ll Value) -> &'ll Type { + unsafe { llvm::LLVMGlobalGetValueType(val) } + } + pub(crate) fn val_ty(&self, v: &'ll Value) -> &'ll Type { + common::val_ty(v) + } +} impl<'ll> SimpleCx<'ll> { pub(crate) fn new( llmod: &'ll llvm::Module, @@ -660,6 +672,13 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { llvm::LLVMMetadataAsValue(self.llcx(), metadata) } + // FIXME(autodiff): We should split `ConstCodegenMethods` to pull the reusable parts + // onto a trait that is also implemented for GenericCx. + pub(crate) fn get_const_i64(&self, n: u64) -> &'ll Value { + let ty = unsafe { llvm::LLVMInt64TypeInContext(self.llcx()) }; + unsafe { llvm::LLVMConstInt(ty, n, llvm::False) } + } + pub(crate) fn get_function(&self, name: &str) -> Option<&'ll Value> { let name = SmallCStr::new(name); unsafe { llvm::LLVMGetNamedFunction((**self).borrow().llmod, name.as_ptr()) } diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index f6b238629075..9e495586db07 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -4,7 +4,7 @@ use libc::{c_char, c_uint}; use super::MetadataKindId; -use super::ffi::{BasicBlock, Metadata, Module, Type, Value}; +use super::ffi::{AttributeKind, BasicBlock, Metadata, Module, Type, Value}; use crate::llvm::Bool; #[link(name = "llvm-wrapper", kind = "static")] @@ -17,6 +17,8 @@ unsafe extern "C" { pub(crate) fn LLVMRustEraseInstFromParent(V: &Value); pub(crate) fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value; pub(crate) fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool; + pub(crate) fn LLVMRustHasAttributeAtIndex(V: &Value, i: c_uint, Kind: AttributeKind) -> bool; + pub(crate) fn LLVMRustGetArrayNumElements(Ty: &Type) -> u64; } unsafe extern "C" { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 83efb3ea6603..d861e635fc5d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1172,7 +1172,7 @@ unsafe extern "C" { // Operations on parameters pub(crate) fn LLVMIsAArgument(Val: &Value) -> Option<&Value>; - pub(crate) fn LLVMCountParams(Fn: &Value) -> c_uint; + pub(crate) safe fn LLVMCountParams(Fn: &Value) -> c_uint; pub(crate) fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value; // Operations on basic blocks diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 53df59930f4f..32e6da446d72 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -384,6 +384,12 @@ static inline void AddAttributes(T *t, unsigned Index, LLVMAttributeRef *Attrs, t->setAttributes(PALNew); } +extern "C" bool LLVMRustHasAttributeAtIndex(LLVMValueRef Fn, unsigned Index, + LLVMRustAttributeKind RustAttr) { + Function *F = unwrap(Fn); + return F->hasParamAttribute(Index, fromRust(RustAttr)); +} + extern "C" void LLVMRustAddFunctionAttributes(LLVMValueRef Fn, unsigned Index, LLVMAttributeRef *Attrs, size_t AttrsLen) { @@ -636,6 +642,10 @@ static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) { } } +extern "C" uint64_t LLVMRustGetArrayNumElements(LLVMTypeRef Ty) { + return unwrap(Ty)->getArrayNumElements(); +} + extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen, char *Constraints, size_t ConstraintsLen, From 79e17bc71e98cd5da6e0dd9815f2a719e61af663 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 4 Apr 2025 14:24:46 -0400 Subject: [PATCH 151/176] add new tests for autodiff batching and update old ones --- tests/codegen/autodiff.rs | 4 +- tests/codegen/autodiffv.rs | 116 ++++++++++++++++++++++ tests/pretty/autodiff_forward.pp | 100 +++++++++++++++---- tests/pretty/autodiff_forward.rs | 18 ++++ tests/pretty/autodiff_reverse.pp | 22 ++-- tests/ui/autodiff/autodiff_illegal.rs | 7 ++ tests/ui/autodiff/autodiff_illegal.stderr | 38 ++++--- 7 files changed, 251 insertions(+), 54 deletions(-) create mode 100644 tests/codegen/autodiffv.rs diff --git a/tests/codegen/autodiff.rs b/tests/codegen/autodiff.rs index cace0edb2b54..85358f5fcb69 100644 --- a/tests/codegen/autodiff.rs +++ b/tests/codegen/autodiff.rs @@ -11,7 +11,7 @@ fn square(x: &f64) -> f64 { x * x } -// CHECK:define internal fastcc double @diffesquare(double %x.0.val, ptr nocapture align 8 %"x'" +// CHECK:define internal fastcc double @diffesquare(double %x.0.val, ptr nocapture nonnull align 8 %"x'" // CHECK-NEXT:invertstart: // CHECK-NEXT: %_0 = fmul double %x.0.val, %x.0.val // CHECK-NEXT: %0 = fadd fast double %x.0.val, %x.0.val @@ -22,7 +22,7 @@ fn square(x: &f64) -> f64 { // CHECK-NEXT:} fn main() { - let x = 3.0; + let x = std::hint::black_box(3.0); let output = square(&x); assert_eq!(9.0, output); diff --git a/tests/codegen/autodiffv.rs b/tests/codegen/autodiffv.rs new file mode 100644 index 000000000000..e00471164055 --- /dev/null +++ b/tests/codegen/autodiffv.rs @@ -0,0 +1,116 @@ +//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat +//@ no-prefer-dynamic +//@ needs-enzyme +// +// In Enzyme, we test against a large range of LLVM versions (5+) and don't have overly many +// breakages. One benefit is that we match the IR generated by Enzyme only after running it +// through LLVM's O3 pipeline, which will remove most of the noise. +// However, our integration test could also be affected by changes in how rustc lowers MIR into +// LLVM-IR, which could cause additional noise and thus breakages. If that's the case, we should +// reduce this test to only match the first lines and the ret instructions. + +#![feature(autodiff)] + +use std::autodiff::autodiff; + +#[autodiff(d_square3, Forward, Dual, DualOnly)] +#[autodiff(d_square2, Forward, 4, Dual, DualOnly)] +#[autodiff(d_square1, Forward, 4, Dual, Dual)] +#[no_mangle] +fn square(x: &f32) -> f32 { + x * x +} + +// d_sqaure2 +// CHECK: define internal fastcc [4 x float] @fwddiffe4square(float %x.0.val, [4 x ptr] %"x'") +// CHECK-NEXT: start: +// CHECK-NEXT: %0 = extractvalue [4 x ptr] %"x'", 0 +// CHECK-NEXT: %"_2'ipl" = load float, ptr %0, align 4 +// CHECK-NEXT: %1 = extractvalue [4 x ptr] %"x'", 1 +// CHECK-NEXT: %"_2'ipl1" = load float, ptr %1, align 4 +// CHECK-NEXT: %2 = extractvalue [4 x ptr] %"x'", 2 +// CHECK-NEXT: %"_2'ipl2" = load float, ptr %2, align 4 +// CHECK-NEXT: %3 = extractvalue [4 x ptr] %"x'", 3 +// CHECK-NEXT: %"_2'ipl3" = load float, ptr %3, align 4 +// CHECK-NEXT: %4 = insertelement <4 x float> poison, float %"_2'ipl", i64 0 +// CHECK-NEXT: %5 = insertelement <4 x float> %4, float %"_2'ipl1", i64 1 +// CHECK-NEXT: %6 = insertelement <4 x float> %5, float %"_2'ipl2", i64 2 +// CHECK-NEXT: %7 = insertelement <4 x float> %6, float %"_2'ipl3", i64 3 +// CHECK-NEXT: %8 = fadd fast <4 x float> %7, %7 +// CHECK-NEXT: %9 = insertelement <4 x float> poison, float %x.0.val, i64 0 +// CHECK-NEXT: %10 = shufflevector <4 x float> %9, <4 x float> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: %11 = fmul fast <4 x float> %8, %10 +// CHECK-NEXT: %12 = extractelement <4 x float> %11, i64 0 +// CHECK-NEXT: %13 = insertvalue [4 x float] undef, float %12, 0 +// CHECK-NEXT: %14 = extractelement <4 x float> %11, i64 1 +// CHECK-NEXT: %15 = insertvalue [4 x float] %13, float %14, 1 +// CHECK-NEXT: %16 = extractelement <4 x float> %11, i64 2 +// CHECK-NEXT: %17 = insertvalue [4 x float] %15, float %16, 2 +// CHECK-NEXT: %18 = extractelement <4 x float> %11, i64 3 +// CHECK-NEXT: %19 = insertvalue [4 x float] %17, float %18, 3 +// CHECK-NEXT: ret [4 x float] %19 +// CHECK-NEXT: } + +// d_square3, the extra float is the original return value (x * x) +// CHECK: define internal fastcc { float, [4 x float] } @fwddiffe4square.1(float %x.0.val, [4 x ptr] %"x'") +// CHECK-NEXT: start: +// CHECK-NEXT: %0 = extractvalue [4 x ptr] %"x'", 0 +// CHECK-NEXT: %"_2'ipl" = load float, ptr %0, align 4 +// CHECK-NEXT: %1 = extractvalue [4 x ptr] %"x'", 1 +// CHECK-NEXT: %"_2'ipl1" = load float, ptr %1, align 4 +// CHECK-NEXT: %2 = extractvalue [4 x ptr] %"x'", 2 +// CHECK-NEXT: %"_2'ipl2" = load float, ptr %2, align 4 +// CHECK-NEXT: %3 = extractvalue [4 x ptr] %"x'", 3 +// CHECK-NEXT: %"_2'ipl3" = load float, ptr %3, align 4 +// CHECK-NEXT: %_0 = fmul float %x.0.val, %x.0.val +// CHECK-NEXT: %4 = insertelement <4 x float> poison, float %"_2'ipl", i64 0 +// CHECK-NEXT: %5 = insertelement <4 x float> %4, float %"_2'ipl1", i64 1 +// CHECK-NEXT: %6 = insertelement <4 x float> %5, float %"_2'ipl2", i64 2 +// CHECK-NEXT: %7 = insertelement <4 x float> %6, float %"_2'ipl3", i64 3 +// CHECK-NEXT: %8 = fadd fast <4 x float> %7, %7 +// CHECK-NEXT: %9 = insertelement <4 x float> poison, float %x.0.val, i64 0 +// CHECK-NEXT: %10 = shufflevector <4 x float> %9, <4 x float> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: %11 = fmul fast <4 x float> %8, %10 +// CHECK-NEXT: %12 = extractelement <4 x float> %11, i64 0 +// CHECK-NEXT: %13 = insertvalue [4 x float] undef, float %12, 0 +// CHECK-NEXT: %14 = extractelement <4 x float> %11, i64 1 +// CHECK-NEXT: %15 = insertvalue [4 x float] %13, float %14, 1 +// CHECK-NEXT: %16 = extractelement <4 x float> %11, i64 2 +// CHECK-NEXT: %17 = insertvalue [4 x float] %15, float %16, 2 +// CHECK-NEXT: %18 = extractelement <4 x float> %11, i64 3 +// CHECK-NEXT: %19 = insertvalue [4 x float] %17, float %18, 3 +// CHECK-NEXT: %20 = insertvalue { float, [4 x float] } undef, float %_0, 0 +// CHECK-NEXT: %21 = insertvalue { float, [4 x float] } %20, [4 x float] %19, 1 +// CHECK-NEXT: ret { float, [4 x float] } %21 +// CHECK-NEXT: } + +fn main() { + let x = std::hint::black_box(3.0); + let output = square(&x); + dbg!(&output); + assert_eq!(9.0, output); + dbg!(square(&x)); + + let mut df_dx1 = 1.0; + let mut df_dx2 = 2.0; + let mut df_dx3 = 3.0; + let mut df_dx4 = 0.0; + let [o1, o2, o3, o4] = d_square2(&x, &mut df_dx1, &mut df_dx2, &mut df_dx3, &mut df_dx4); + dbg!(o1, o2, o3, o4); + let [output2, o1, o2, o3, o4] = + d_square1(&x, &mut df_dx1, &mut df_dx2, &mut df_dx3, &mut df_dx4); + dbg!(o1, o2, o3, o4); + assert_eq!(output, output2); + assert!((6.0 - o1).abs() < 1e-10); + assert!((12.0 - o2).abs() < 1e-10); + assert!((18.0 - o3).abs() < 1e-10); + assert!((0.0 - o4).abs() < 1e-10); + assert_eq!(1.0, df_dx1); + assert_eq!(2.0, df_dx2); + assert_eq!(3.0, df_dx3); + assert_eq!(0.0, df_dx4); + assert_eq!(d_square3(&x, &mut df_dx1), 2.0 * o1); + assert_eq!(d_square3(&x, &mut df_dx2), 2.0 * o2); + assert_eq!(d_square3(&x, &mut df_dx3), 2.0 * o3); + assert_eq!(d_square3(&x, &mut df_dx4), 2.0 * o4); +} diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff_forward.pp index dc7a2712f423..4b2fb6166ff7 100644 --- a/tests/pretty/autodiff_forward.pp +++ b/tests/pretty/autodiff_forward.pp @@ -25,27 +25,31 @@ pub fn f1(x: &[f64], y: f64) -> f64 { // We want to be sure that the same function can be differentiated in different ways + + // Make sure, that we add the None for the default return. + + ::core::panicking::panic("not implemented") } -#[rustc_autodiff(Forward, Dual, Const, Dual,)] +#[rustc_autodiff(Forward, 1, Dual, Const, Dual)] #[inline(never)] -pub fn df1(x: &[f64], bx: &[f64], y: f64) -> (f64, f64) { +pub fn df1(x: &[f64], bx_0: &[f64], y: f64) -> (f64, f64) { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f1(x, y)); - ::core::hint::black_box((bx,)); - ::core::hint::black_box((f1(x, y), f64::default())) + ::core::hint::black_box((bx_0,)); + ::core::hint::black_box(<(f64, f64)>::default()) } #[rustc_autodiff] #[inline(never)] pub fn f2(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(Forward, Dual, Const, Const,)] +#[rustc_autodiff(Forward, 1, Dual, Const, Const)] #[inline(never)] -pub fn df2(x: &[f64], bx: &[f64], y: f64) -> f64 { +pub fn df2(x: &[f64], bx_0: &[f64], y: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f2(x, y)); - ::core::hint::black_box((bx,)); + ::core::hint::black_box((bx_0,)); ::core::hint::black_box(f2(x, y)) } #[rustc_autodiff] @@ -53,20 +57,20 @@ pub fn df2(x: &[f64], bx: &[f64], y: f64) -> f64 { pub fn f3(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(Forward, Dual, Const, Const,)] +#[rustc_autodiff(Forward, 1, Dual, Const, Const)] #[inline(never)] -pub fn df3(x: &[f64], bx: &[f64], y: f64) -> f64 { +pub fn df3(x: &[f64], bx_0: &[f64], y: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f3(x, y)); - ::core::hint::black_box((bx,)); + ::core::hint::black_box((bx_0,)); ::core::hint::black_box(f3(x, y)) } #[rustc_autodiff] #[inline(never)] pub fn f4() {} -#[rustc_autodiff(Forward, None)] +#[rustc_autodiff(Forward, 1, None)] #[inline(never)] -pub fn df4() { +pub fn df4() -> () { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f4()); ::core::hint::black_box(()); @@ -76,28 +80,82 @@ pub fn df4() { pub fn f5(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(Forward, Const, Dual, Const,)] +#[rustc_autodiff(Forward, 1, Const, Dual, Const)] #[inline(never)] -pub fn df5_y(x: &[f64], y: f64, by: f64) -> f64 { +pub fn df5_y(x: &[f64], y: f64, by_0: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f5(x, y)); - ::core::hint::black_box((by,)); + ::core::hint::black_box((by_0,)); ::core::hint::black_box(f5(x, y)) } -#[rustc_autodiff(Forward, Dual, Const, Const,)] +#[rustc_autodiff(Forward, 1, Dual, Const, Const)] #[inline(never)] -pub fn df5_x(x: &[f64], bx: &[f64], y: f64) -> f64 { +pub fn df5_x(x: &[f64], bx_0: &[f64], y: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f5(x, y)); - ::core::hint::black_box((bx,)); + ::core::hint::black_box((bx_0,)); ::core::hint::black_box(f5(x, y)) } -#[rustc_autodiff(Reverse, Duplicated, Const, Active,)] +#[rustc_autodiff(Reverse, 1, Duplicated, Const, Active)] #[inline(never)] -pub fn df5_rev(x: &[f64], dx: &mut [f64], y: f64, dret: f64) -> f64 { +pub fn df5_rev(x: &[f64], dx_0: &mut [f64], y: f64, dret: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f5(x, y)); - ::core::hint::black_box((dx, dret)); + ::core::hint::black_box((dx_0, dret)); ::core::hint::black_box(f5(x, y)) } +struct DoesNotImplDefault; +#[rustc_autodiff] +#[inline(never)] +pub fn f6() -> DoesNotImplDefault { + ::core::panicking::panic("not implemented") +} +#[rustc_autodiff(Forward, 1, Const)] +#[inline(never)] +pub fn df6() -> DoesNotImplDefault { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f6()); + ::core::hint::black_box(()); + ::core::hint::black_box(f6()) +} +#[rustc_autodiff] +#[inline(never)] +pub fn f7(x: f32) -> () {} +#[rustc_autodiff(Forward, 1, Const, None)] +#[inline(never)] +pub fn df7(x: f32) -> () { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f7(x)); + ::core::hint::black_box(()); +} +#[no_mangle] +#[rustc_autodiff] +#[inline(never)] +fn f8(x: &f32) -> f32 { ::core::panicking::panic("not implemented") } +#[rustc_autodiff(Forward, 4, Dual, Dual)] +#[inline(never)] +fn f8_3(x: &f32, bx_0: &f32, bx_1: &f32, bx_2: &f32, bx_3: &f32) + -> [f32; 5usize] { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f8(x)); + ::core::hint::black_box((bx_0, bx_1, bx_2, bx_3)); + ::core::hint::black_box(<[f32; 5usize]>::default()) +} +#[rustc_autodiff(Forward, 4, Dual, DualOnly)] +#[inline(never)] +fn f8_2(x: &f32, bx_0: &f32, bx_1: &f32, bx_2: &f32, bx_3: &f32) + -> [f32; 4usize] { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f8(x)); + ::core::hint::black_box((bx_0, bx_1, bx_2, bx_3)); + ::core::hint::black_box(<[f32; 4usize]>::default()) +} +#[rustc_autodiff(Forward, 1, Dual, DualOnly)] +#[inline(never)] +fn f8_1(x: &f32, bx_0: &f32) -> f32 { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f8(x)); + ::core::hint::black_box((bx_0,)); + ::core::hint::black_box(::default()) +} fn main() {} diff --git a/tests/pretty/autodiff_forward.rs b/tests/pretty/autodiff_forward.rs index bc5582116322..a765738c2a81 100644 --- a/tests/pretty/autodiff_forward.rs +++ b/tests/pretty/autodiff_forward.rs @@ -36,4 +36,22 @@ pub fn f5(x: &[f64], y: f64) -> f64 { unimplemented!() } +struct DoesNotImplDefault; +#[autodiff(df6, Forward, Const)] +pub fn f6() -> DoesNotImplDefault { + unimplemented!() +} + +// Make sure, that we add the None for the default return. +#[autodiff(df7, Forward, Const)] +pub fn f7(x: f32) -> () {} + +#[autodiff(f8_1, Forward, Dual, DualOnly)] +#[autodiff(f8_2, Forward, 4, Dual, DualOnly)] +#[autodiff(f8_3, Forward, 4, Dual, Dual)] +#[no_mangle] +fn f8(x: &f32) -> f32 { + unimplemented!() +} + fn main() {} diff --git a/tests/pretty/autodiff_reverse.pp b/tests/pretty/autodiff_reverse.pp index b2cf0244af4c..31920694a3ad 100644 --- a/tests/pretty/autodiff_reverse.pp +++ b/tests/pretty/autodiff_reverse.pp @@ -28,18 +28,18 @@ pub fn f1(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(Reverse, Duplicated, Const, Active,)] +#[rustc_autodiff(Reverse, 1, Duplicated, Const, Active)] #[inline(never)] -pub fn df1(x: &[f64], dx: &mut [f64], y: f64, dret: f64) -> f64 { +pub fn df1(x: &[f64], dx_0: &mut [f64], y: f64, dret: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f1(x, y)); - ::core::hint::black_box((dx, dret)); + ::core::hint::black_box((dx_0, dret)); ::core::hint::black_box(f1(x, y)) } #[rustc_autodiff] #[inline(never)] pub fn f2() {} -#[rustc_autodiff(Reverse, None)] +#[rustc_autodiff(Reverse, 1, None)] #[inline(never)] pub fn df2() { unsafe { asm!("NOP", options(pure, nomem)); }; @@ -51,12 +51,12 @@ pub fn df2() { pub fn f3(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(Reverse, Duplicated, Const, Active,)] +#[rustc_autodiff(Reverse, 1, Duplicated, Const, Active)] #[inline(never)] -pub fn df3(x: &[f64], dx: &mut [f64], y: f64, dret: f64) -> f64 { +pub fn df3(x: &[f64], dx_0: &mut [f64], y: f64, dret: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f3(x, y)); - ::core::hint::black_box((dx, dret)); + ::core::hint::black_box((dx_0, dret)); ::core::hint::black_box(f3(x, y)) } enum Foo { Reverse, } @@ -64,7 +64,7 @@ use Foo::Reverse; #[rustc_autodiff] #[inline(never)] pub fn f4(x: f32) { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(Reverse, Const, None)] +#[rustc_autodiff(Reverse, 1, Const, None)] #[inline(never)] pub fn df4(x: f32) { unsafe { asm!("NOP", options(pure, nomem)); }; @@ -76,11 +76,11 @@ pub fn df4(x: f32) { pub fn f5(x: *const f32, y: &f32) { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(Reverse, DuplicatedOnly, Duplicated, None)] +#[rustc_autodiff(Reverse, 1, DuplicatedOnly, Duplicated, None)] #[inline(never)] -pub unsafe fn df5(x: *const f32, dx: *mut f32, y: &f32, dy: &mut f32) { +pub unsafe fn df5(x: *const f32, dx_0: *mut f32, y: &f32, dy_0: &mut f32) { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(f5(x, y)); - ::core::hint::black_box((dx, dy)); + ::core::hint::black_box((dx_0, dy_0)); } fn main() {} diff --git a/tests/ui/autodiff/autodiff_illegal.rs b/tests/ui/autodiff/autodiff_illegal.rs index e810b9ba565b..2f2cd8d93532 100644 --- a/tests/ui/autodiff/autodiff_illegal.rs +++ b/tests/ui/autodiff/autodiff_illegal.rs @@ -177,4 +177,11 @@ fn f21(x: f32) -> f32 { unimplemented!() } +struct DoesNotImplDefault; +#[autodiff(df22, Forward, Dual)] +pub fn f22() -> DoesNotImplDefault { + //~^^ ERROR the function or associated item `default` exists for tuple `(DoesNotImplDefault, DoesNotImplDefault)`, but its trait bounds were not satisfied + unimplemented!() +} + fn main() {} diff --git a/tests/ui/autodiff/autodiff_illegal.stderr b/tests/ui/autodiff/autodiff_illegal.stderr index 47d53492700b..3752b27e7dd1 100644 --- a/tests/ui/autodiff/autodiff_illegal.stderr +++ b/tests/ui/autodiff/autodiff_illegal.stderr @@ -19,32 +19,24 @@ error: expected 1 activities, but found 2 | LL | #[autodiff(df3, Reverse, Duplicated, Const)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected 1 activities, but found 0 --> $DIR/autodiff_illegal.rs:27:1 | LL | #[autodiff(df4, Reverse)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) error: Dual can not be used in Reverse Mode --> $DIR/autodiff_illegal.rs:34:1 | LL | #[autodiff(df5, Reverse, Dual)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) error: Duplicated can not be used in Forward Mode --> $DIR/autodiff_illegal.rs:41:1 | LL | #[autodiff(df6, Forward, Duplicated)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) error: Duplicated can not be used for this type --> $DIR/autodiff_illegal.rs:42:14 @@ -107,7 +99,6 @@ LL | #[autodiff(fn_exists, Reverse, Active)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fn_exists` redefined here | = note: `fn_exists` must be defined only once in the value namespace of this module - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) error: autodiff requires at least a name and mode --> $DIR/autodiff_illegal.rs:95:1 @@ -135,42 +126,49 @@ error: invalid return activity Active in Forward Mode | LL | #[autodiff(df19, Forward, Dual, Active)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid return activity Dual in Reverse Mode --> $DIR/autodiff_illegal.rs:167:1 | LL | #[autodiff(df20, Reverse, Active, Dual)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid return activity Duplicated in Reverse Mode --> $DIR/autodiff_illegal.rs:174:1 | LL | #[autodiff(df21, Reverse, Active, Duplicated)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared type `MyFloat` --> $DIR/autodiff_illegal.rs:130:1 | LL | #[autodiff(df15, Reverse, Active, Active)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `MyFloat` - | - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared type `F64Trans` --> $DIR/autodiff_illegal.rs:154:1 | LL | #[autodiff(df18, Reverse, Active, Active)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `F64Trans` + +error[E0599]: the function or associated item `default` exists for tuple `(DoesNotImplDefault, DoesNotImplDefault)`, but its trait bounds were not satisfied + --> $DIR/autodiff_illegal.rs:181:1 + | +LL | struct DoesNotImplDefault; + | ------------------------- doesn't satisfy `DoesNotImplDefault: Default` +LL | #[autodiff(df22, Forward, Dual)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item cannot be called on `(DoesNotImplDefault, DoesNotImplDefault)` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `DoesNotImplDefault: Default` + which is required by `(DoesNotImplDefault, DoesNotImplDefault): Default` +help: consider annotating `DoesNotImplDefault` with `#[derive(Default)]` + | +LL + #[derive(Default)] +LL | struct DoesNotImplDefault; | - = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 22 previous errors +error: aborting due to 23 previous errors -Some errors have detailed explanations: E0428, E0433, E0658. +Some errors have detailed explanations: E0428, E0433, E0599, E0658. For more information about an error, try `rustc --explain E0428`. From 89d8948835c603ec0c8234cd94772b6ac8ef9a34 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 4 Apr 2025 14:25:23 -0400 Subject: [PATCH 152/176] add new flag to print the module post-AD, before opts --- compiler/rustc_codegen_llvm/src/back/lto.rs | 12 ++++++++++-- compiler/rustc_session/src/config.rs | 6 ++++-- compiler/rustc_session/src/options.rs | 4 +++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 668795191a29..158275a559be 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -610,6 +610,8 @@ fn enable_autodiff_settings(ad: &[config::AutoDiff], module: &mut ModuleCodegen< } // We handle this below config::AutoDiff::PrintModAfter => {} + // We handle this below + config::AutoDiff::PrintModFinal => {} // This is required and already checked config::AutoDiff::Enable => {} } @@ -657,14 +659,20 @@ pub(crate) fn run_pass_manager( } if cfg!(llvm_enzyme) && enable_ad { + // This is the post-autodiff IR, mainly used for testing and educational purposes. + if config.autodiff.contains(&config::AutoDiff::PrintModAfter) { + unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) }; + } + let opt_stage = llvm::OptStage::FatLTO; let stage = write::AutodiffStage::PostAD; unsafe { write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?; } - // This is the final IR, so people should be able to inspect the optimized autodiff output. - if config.autodiff.contains(&config::AutoDiff::PrintModAfter) { + // This is the final IR, so people should be able to inspect the optimized autodiff output, + // for manual inspection. + if config.autodiff.contains(&config::AutoDiff::PrintModFinal) { unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) }; } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 43b78423c727..39d6a24d0817 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -235,10 +235,12 @@ pub enum AutoDiff { PrintPerf, /// Print intermediate IR generation steps PrintSteps, - /// Print the whole module, before running opts. + /// Print the module, before running autodiff. PrintModBefore, - /// Print the module after Enzyme differentiated everything. + /// Print the module after running autodiff. PrintModAfter, + /// Print the module after running autodiff and optimizations. + PrintModFinal, /// Enzyme's loose type debug helper (can cause incorrect gradients!!) /// Usable in cases where Enzyme errors with `can not deduce type of X`. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b3be4b611f03..45cce29799f0 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -707,7 +707,7 @@ mod desc { pub(crate) const parse_list: &str = "a space-separated list of strings"; pub(crate) const parse_list_with_polarity: &str = "a comma-separated list of strings, with elements beginning with + or -"; - pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Enable`, `PrintSteps`, `PrintTA`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfter`, `LooseTypes`, `Inline`"; + pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Enable`, `PrintSteps`, `PrintTA`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfter`, `PrintModFinal`, `LooseTypes`, `Inline`"; pub(crate) const parse_comma_list: &str = "a comma-separated list of strings"; pub(crate) const parse_opt_comma_list: &str = parse_comma_list; pub(crate) const parse_number: &str = "a number"; @@ -1355,6 +1355,7 @@ pub mod parse { "PrintSteps" => AutoDiff::PrintSteps, "PrintModBefore" => AutoDiff::PrintModBefore, "PrintModAfter" => AutoDiff::PrintModAfter, + "PrintModFinal" => AutoDiff::PrintModFinal, "LooseTypes" => AutoDiff::LooseTypes, "Inline" => AutoDiff::Inline, _ => { @@ -2088,6 +2089,7 @@ options! { `=PrintSteps` `=PrintModBefore` `=PrintModAfter` + `=PrintModFinal` `=LooseTypes` `=Inline` Multiple options can be combined with commas."), From cfcc47ea540750dac30010edb42c4fa21efd577a Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Fri, 4 Apr 2025 21:43:03 +0200 Subject: [PATCH 153/176] make `Arguments::as_statically_known_str` doc(hidden) --- library/core/src/fmt/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 30fd2d7815f5..0c8e1495c62d 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -743,6 +743,7 @@ impl<'a> Arguments<'a> { #[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")] #[must_use] #[inline] + #[doc(hidden)] pub fn as_statically_known_str(&self) -> Option<&'static str> { let s = self.as_str(); if core::intrinsics::is_val_statically_known(s.is_some()) { s } else { None } From 2b533e6b49e6c918389f7a38e6b6e7e030f30fed Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Apr 2025 15:05:44 +0200 Subject: [PATCH 154/176] bootstrap: Only add `rustc_randomized_layouts` if the crate has it --- library/Cargo.lock | 5 +++++ library/proc_macro/Cargo.toml | 2 +- library/proc_macro/src/lib.rs | 1 + src/bootstrap/src/lib.rs | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 23d9d926eba3..c45a84b2e340 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -235,6 +235,7 @@ name = "proc_macro" version = "0.0.0" dependencies = [ "core", + "rustc-literal-escaper", "std", ] @@ -310,6 +311,10 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "rustc-literal-escaper" +version = "0.0.1" + [[package]] name = "rustc-std-workspace-alloc" version = "1.99.0" diff --git a/library/proc_macro/Cargo.toml b/library/proc_macro/Cargo.toml index f65c5e1a330c..b8bc2a3af4cd 100644 --- a/library/proc_macro/Cargo.toml +++ b/library/proc_macro/Cargo.toml @@ -9,4 +9,4 @@ std = { path = "../std" } # `core` when resolving doc links. Without this line a different `core` will be # loaded from sysroot causing duplicate lang items and other similar errors. core = { path = "../core" } -rustc-literal-escaper = "0.0.1" +rustc-literal-escaper = { version = "0.0.2", features = ["rustc-dep-of-std"] } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 35a8af03ba43..f1cf0c5a2db7 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -27,6 +27,7 @@ #![feature(panic_can_unwind)] #![feature(restricted_std)] #![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] #![feature(extend_one)] #![recursion_limit = "256"] #![allow(internal_features)] diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 843d474f92de..7c60e0421421 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -748,7 +748,7 @@ impl Build { features.push("llvm"); } // keep in sync with `bootstrap/compile.rs:rustc_cargo_env` - if self.config.rust_randomize_layout { + if self.config.rust_randomize_layout && check("rustc_randomized_layouts") { features.push("rustc_randomized_layouts"); } From 2e3a16187189ae8e7bdb2ac98a237e11540f993a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Apr 2025 22:06:10 +0200 Subject: [PATCH 155/176] Update `rustc-literal-escaper` version to `0.0.2` --- Cargo.lock | 4 ++-- compiler/rustc_ast/Cargo.toml | 2 +- compiler/rustc_parse/Cargo.toml | 2 +- compiler/rustc_parse_format/Cargo.toml | 2 +- library/Cargo.lock | 7 ++++++- src/tools/rust-analyzer/Cargo.lock | 4 ++-- src/tools/rust-analyzer/crates/parser/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/syntax/Cargo.toml | 2 +- 8 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0bdddcc7a64d..699dd375dd25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3152,9 +3152,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc-literal-escaper" -version = "0.0.1" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdd0fcb1409d38cb2d940400497e2384a4a04b8685ee92a0a7a8986ccd72115" +checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04" [[package]] name = "rustc-main" diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 73b573272048..b2d3b90fc449 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -7,10 +7,10 @@ edition = "2024" # tidy-alphabetical-start bitflags = "2.4.1" memchr = "2.7.4" +rustc-literal-escaper = "0.0.2" rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } -rustc-literal-escaper = "0.0.1" rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index dec1e09d8dd8..6504081f0b9c 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" +rustc-literal-escaper = "0.0.2" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -15,7 +16,6 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } -rustc-literal-escaper = "0.0.1" rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index b0b70cefb596..52f23c00d4bc 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -5,8 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start +rustc-literal-escaper = "0.0.2" rustc_lexer = { path = "../rustc_lexer" } -rustc-literal-escaper = "0.0.1" # tidy-alphabetical-end [target.'cfg(target_pointer_width = "64")'.dev-dependencies] diff --git a/library/Cargo.lock b/library/Cargo.lock index c45a84b2e340..589d8e5fd55f 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -313,7 +313,12 @@ dependencies = [ [[package]] name = "rustc-literal-escaper" -version = "0.0.1" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04" +dependencies = [ + "rustc-std-workspace-std", +] [[package]] name = "rustc-std-workspace-alloc" diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 2aa776b50878..be6391152665 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1746,9 +1746,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc-literal-escaper" -version = "0.0.1" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdd0fcb1409d38cb2d940400497e2384a4a04b8685ee92a0a7a8986ccd72115" +checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04" [[package]] name = "rustc-stable-hash" diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml index 292b7de255a8..40c1e9fa7bdd 100644 --- a/src/tools/rust-analyzer/crates/parser/Cargo.toml +++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml @@ -14,7 +14,7 @@ rust-version.workspace = true [dependencies] drop_bomb = "0.1.5" ra-ap-rustc_lexer.workspace = true -rustc-literal-escaper = "0.0.1" +rustc-literal-escaper = "0.0.2" tracing = { workspace = true, optional = true } edition.workspace = true diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 4fb628685a1b..23e1917922b7 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -17,7 +17,7 @@ either.workspace = true itertools.workspace = true rowan = "=0.15.15" rustc-hash.workspace = true -rustc-literal-escaper = "0.0.1" +rustc-literal-escaper = "0.0.2" indexmap.workspace = true smol_str.workspace = true triomphe.workspace = true From 017e99b53b528609b68a45e20ac6f6fb4b61cded Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Apr 2025 22:25:10 +0200 Subject: [PATCH 156/176] Add `rustc-literal-escaper` to allowed crates lists --- src/tools/tidy/src/deps.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 8f761d349cca..682ab4875a12 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -361,6 +361,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "regex-syntax", "rustc-demangle", "rustc-hash", + "rustc-literal-escaper", "rustc-rayon", "rustc-rayon-core", "rustc-stable-hash", @@ -486,6 +487,7 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[ "rand_core", "rand_xorshift", "rustc-demangle", + "rustc-literal-escaper", "shlex", "syn", "unicode-ident", From 6b5ccfc87f59ab017032e430d4d358b4989735da Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 5 Apr 2025 06:09:14 +0900 Subject: [PATCH 157/176] check if merged attributes list is empty --- compiler/rustc_ast_lowering/src/expr.rs | 16 +++++++----- tests/ui/attributes/invalid-reprs.rs | 6 +++++ tests/ui/attributes/invalid-reprs.stderr | 33 ++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 tests/ui/attributes/invalid-reprs.rs create mode 100644 tests/ui/attributes/invalid-reprs.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 52291fdfb302..fc2aae5b27f7 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -74,14 +74,16 @@ impl<'hir> LoweringContext<'_, 'hir> { // Merge attributes into the inner expression. if !e.attrs.is_empty() { let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]); - self.attrs.insert( - ex.hir_id.local_id, - &*self.arena.alloc_from_iter( - self.lower_attrs_vec(&e.attrs, e.span) - .into_iter() - .chain(old_attrs.iter().cloned()), - ), + let attrs = &*self.arena.alloc_from_iter( + self.lower_attrs_vec(&e.attrs, e.span) + .into_iter() + .chain(old_attrs.iter().cloned()), ); + if attrs.is_empty() { + return ex; + } + + self.attrs.insert(ex.hir_id.local_id, attrs); } return ex; } diff --git a/tests/ui/attributes/invalid-reprs.rs b/tests/ui/attributes/invalid-reprs.rs new file mode 100644 index 000000000000..95ed14b54916 --- /dev/null +++ b/tests/ui/attributes/invalid-reprs.rs @@ -0,0 +1,6 @@ +fn main() { + let y = #[repr(uwu(4))] + //~^ ERROR attributes on expressions are experimental + //~| ERROR unrecognized representation hint + (&id(5)); //~ ERROR: cannot find function `id` in this scope +} diff --git a/tests/ui/attributes/invalid-reprs.stderr b/tests/ui/attributes/invalid-reprs.stderr new file mode 100644 index 000000000000..415b969b2440 --- /dev/null +++ b/tests/ui/attributes/invalid-reprs.stderr @@ -0,0 +1,33 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/invalid-reprs.rs:2:13 + | +LL | let y = #[repr(uwu(4))] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0425]: cannot find function `id` in this scope + --> $DIR/invalid-reprs.rs:5:7 + | +LL | (&id(5)); + | ^^ not found in this scope + | +help: consider importing this function + | +LL + use std::process::id; + | + +error[E0552]: unrecognized representation hint + --> $DIR/invalid-reprs.rs:2:20 + | +LL | let y = #[repr(uwu(4))] + | ^^^^^^ + | + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0552, E0658. +For more information about an error, try `rustc --explain E0425`. From 8ff70529f22158dab9a06c7b2e79e1d460d24c61 Mon Sep 17 00:00:00 2001 From: Calder Coalson Date: Wed, 19 Feb 2025 12:08:31 -0800 Subject: [PATCH 158/176] Expose algebraic floating point intrinsics --- library/core/src/intrinsics/mod.rs | 10 +- library/core/src/num/f128.rs | 50 +++++++++ library/core/src/num/f16.rs | 50 +++++++++ library/core/src/num/f32.rs | 50 +++++++++ library/core/src/num/f64.rs | 50 +++++++++ library/core/src/primitive_docs.rs | 45 ++++++++ library/std/src/lib.rs | 1 + library/std/tests/floats/f128.rs | 19 ++++ library/std/tests/floats/f16.rs | 21 ++++ library/std/tests/floats/f32.rs | 21 ++++ library/std/tests/floats/f64.rs | 19 ++++ library/std/tests/floats/lib.rs | 4 +- src/tools/miri/src/intrinsics/mod.rs | 8 +- tests/codegen/float/algebraic.rs | 149 +++++++++++++++++++++++++++ tests/codegen/float_math.rs | 71 ++++++++++--- 15 files changed, 544 insertions(+), 24 deletions(-) create mode 100644 tests/codegen/float/algebraic.rs diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 81e59a1f349e..afd6192d7c47 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2475,35 +2475,35 @@ pub unsafe fn float_to_int_unchecked(value: Float) -> In /// Float addition that allows optimizations based on algebraic rules. /// -/// This intrinsic does not have a stable counterpart. +/// Stabilized as [`f16::algebraic_add`], [`f32::algebraic_add`], [`f64::algebraic_add`] and [`f128::algebraic_add`]. #[rustc_nounwind] #[rustc_intrinsic] pub fn fadd_algebraic(a: T, b: T) -> T; /// Float subtraction that allows optimizations based on algebraic rules. /// -/// This intrinsic does not have a stable counterpart. +/// Stabilized as [`f16::algebraic_sub`], [`f32::algebraic_sub`], [`f64::algebraic_sub`] and [`f128::algebraic_sub`]. #[rustc_nounwind] #[rustc_intrinsic] pub fn fsub_algebraic(a: T, b: T) -> T; /// Float multiplication that allows optimizations based on algebraic rules. /// -/// This intrinsic does not have a stable counterpart. +/// Stabilized as [`f16::algebraic_mul`], [`f32::algebraic_mul`], [`f64::algebraic_mul`] and [`f128::algebraic_mul`]. #[rustc_nounwind] #[rustc_intrinsic] pub fn fmul_algebraic(a: T, b: T) -> T; /// Float division that allows optimizations based on algebraic rules. /// -/// This intrinsic does not have a stable counterpart. +/// Stabilized as [`f16::algebraic_div`], [`f32::algebraic_div`], [`f64::algebraic_div`] and [`f128::algebraic_div`]. #[rustc_nounwind] #[rustc_intrinsic] pub fn fdiv_algebraic(a: T, b: T) -> T; /// Float remainder that allows optimizations based on algebraic rules. /// -/// This intrinsic does not have a stable counterpart. +/// Stabilized as [`f16::algebraic_rem`], [`f32::algebraic_rem`], [`f64::algebraic_rem`] and [`f128::algebraic_rem`]. #[rustc_nounwind] #[rustc_intrinsic] pub fn frem_algebraic(a: T, b: T) -> T; diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index b17190971c3e..08c34e852da4 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -1362,4 +1362,54 @@ impl f128 { // SAFETY: this is actually a safe intrinsic unsafe { intrinsics::copysignf128(self, sign) } } + + /// Float addition that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_add(self, rhs: f128) -> f128 { + intrinsics::fadd_algebraic(self, rhs) + } + + /// Float subtraction that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_sub(self, rhs: f128) -> f128 { + intrinsics::fsub_algebraic(self, rhs) + } + + /// Float multiplication that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_mul(self, rhs: f128) -> f128 { + intrinsics::fmul_algebraic(self, rhs) + } + + /// Float division that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_div(self, rhs: f128) -> f128 { + intrinsics::fdiv_algebraic(self, rhs) + } + + /// Float remainder that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_rem(self, rhs: f128) -> f128 { + intrinsics::frem_algebraic(self, rhs) + } } diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index d20677f43b41..a33e5f530146 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -1338,4 +1338,54 @@ impl f16 { // SAFETY: this is actually a safe intrinsic unsafe { intrinsics::copysignf16(self, sign) } } + + /// Float addition that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_add(self, rhs: f16) -> f16 { + intrinsics::fadd_algebraic(self, rhs) + } + + /// Float subtraction that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_sub(self, rhs: f16) -> f16 { + intrinsics::fsub_algebraic(self, rhs) + } + + /// Float multiplication that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_mul(self, rhs: f16) -> f16 { + intrinsics::fmul_algebraic(self, rhs) + } + + /// Float division that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_div(self, rhs: f16) -> f16 { + intrinsics::fdiv_algebraic(self, rhs) + } + + /// Float remainder that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_rem(self, rhs: f16) -> f16 { + intrinsics::frem_algebraic(self, rhs) + } } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 53373584d555..e473fac03935 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1504,4 +1504,54 @@ impl f32 { // SAFETY: this is actually a safe intrinsic unsafe { intrinsics::copysignf32(self, sign) } } + + /// Float addition that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_add(self, rhs: f32) -> f32 { + intrinsics::fadd_algebraic(self, rhs) + } + + /// Float subtraction that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_sub(self, rhs: f32) -> f32 { + intrinsics::fsub_algebraic(self, rhs) + } + + /// Float multiplication that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_mul(self, rhs: f32) -> f32 { + intrinsics::fmul_algebraic(self, rhs) + } + + /// Float division that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_div(self, rhs: f32) -> f32 { + intrinsics::fdiv_algebraic(self, rhs) + } + + /// Float remainder that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_rem(self, rhs: f32) -> f32 { + intrinsics::frem_algebraic(self, rhs) + } } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index ca28b40bb3ad..6522a80b0b7e 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1503,4 +1503,54 @@ impl f64 { // SAFETY: this is actually a safe intrinsic unsafe { intrinsics::copysignf64(self, sign) } } + + /// Float addition that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_add(self, rhs: f64) -> f64 { + intrinsics::fadd_algebraic(self, rhs) + } + + /// Float subtraction that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_sub(self, rhs: f64) -> f64 { + intrinsics::fsub_algebraic(self, rhs) + } + + /// Float multiplication that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_mul(self, rhs: f64) -> f64 { + intrinsics::fmul_algebraic(self, rhs) + } + + /// Float division that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_div(self, rhs: f64) -> f64 { + intrinsics::fdiv_algebraic(self, rhs) + } + + /// Float remainder that allows optimizations based on algebraic rules. + /// + /// See [algebraic operators](primitive@f32#algebraic-operators) for more info. + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_algebraic", issue = "136469")] + #[inline] + pub fn algebraic_rem(self, rhs: f64) -> f64 { + intrinsics::frem_algebraic(self, rhs) + } } diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 89c856fe1074..f12d204f3846 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1315,6 +1315,51 @@ mod prim_f16 {} /// | `wasm32`, `wasm64` | If all input NaNs are quiet with all-zero payload: None.
Otherwise: all possible payloads. | /// /// For targets not in this table, all payloads are possible. +/// +/// # Algebraic operators +/// +/// Algebraic operators of the form `a.algebraic_*(b)` allow the compiler to optimize +/// floating point operations using all the usual algebraic properties of real numbers -- +/// despite the fact that those properties do *not* hold on floating point numbers. +/// This can give a great performance boost since it may unlock vectorization. +/// +/// The exact set of optimizations is unspecified but typically allows combining operations, +/// rearranging series of operations based on mathematical properties, converting between division +/// and reciprocal multiplication, and disregarding the sign of zero. This means that the results of +/// elementary operations may have undefined precision, and "non-mathematical" values +/// such as NaN, +/-Inf, or -0.0 may behave in unexpected ways, but these operations +/// will never cause undefined behavior. +/// +/// Because of the unpredictable nature of compiler optimizations, the same inputs may produce +/// different results even within a single program run. **Unsafe code must not rely on any property +/// of the return value for soundness.** However, implementations will generally do their best to +/// pick a reasonable tradeoff between performance and accuracy of the result. +/// +/// For example: +/// +/// ``` +/// # #![feature(float_algebraic)] +/// # #![allow(unused_assignments)] +/// # let mut x: f32 = 0.0; +/// # let a: f32 = 1.0; +/// # let b: f32 = 2.0; +/// # let c: f32 = 3.0; +/// # let d: f32 = 4.0; +/// x = a.algebraic_add(b).algebraic_add(c).algebraic_add(d); +/// ``` +/// +/// May be rewritten as: +/// +/// ``` +/// # #![allow(unused_assignments)] +/// # let mut x: f32 = 0.0; +/// # let a: f32 = 1.0; +/// # let b: f32 = 2.0; +/// # let c: f32 = 3.0; +/// # let d: f32 = 4.0; +/// x = a + b + c + d; // As written +/// x = (a + c) + (b + d); // Reordered to shorten critical path and enable vectorization +/// ``` #[stable(feature = "rust1", since = "1.0.0")] mod prim_f32 {} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ad005833ad53..e2bb2e704316 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -340,6 +340,7 @@ #![feature(exact_size_is_empty)] #![feature(exclusive_wrapper)] #![feature(extend_one)] +#![feature(float_algebraic)] #![feature(float_gamma)] #![feature(float_minimum_maximum)] #![feature(fmt_internals)] diff --git a/library/std/tests/floats/f128.rs b/library/std/tests/floats/f128.rs index b4a6c672bf05..df28e8129ddd 100644 --- a/library/std/tests/floats/f128.rs +++ b/library/std/tests/floats/f128.rs @@ -984,6 +984,25 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } +#[test] +fn test_algebraic() { + let a: f128 = 123.0; + let b: f128 = 456.0; + + // Check that individual operations match their primitive counterparts. + // + // This is a check of current implementations and does NOT imply any form of + // guarantee about future behavior. The compiler reserves the right to make + // these operations inexact matches in the future. + let eps = if cfg!(miri) { 1e-6 } else { 0.0 }; + + assert_approx_eq!(a.algebraic_add(b), a + b, eps); + assert_approx_eq!(a.algebraic_sub(b), a - b, eps); + assert_approx_eq!(a.algebraic_mul(b), a * b, eps); + assert_approx_eq!(a.algebraic_div(b), a / b, eps); + assert_approx_eq!(a.algebraic_rem(b), a % b, eps); +} + #[test] fn test_from() { assert_eq!(f128::from(false), 0.0); diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs index ca0b8efbe83b..1a90f00aecce 100644 --- a/library/std/tests/floats/f16.rs +++ b/library/std/tests/floats/f16.rs @@ -954,6 +954,27 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } +#[test] +fn test_algebraic() { + let a: f16 = 123.0; + let b: f16 = 456.0; + + // Check that individual operations match their primitive counterparts. + // + // This is a check of current implementations and does NOT imply any form of + // guarantee about future behavior. The compiler reserves the right to make + // these operations inexact matches in the future. + let eps_add = if cfg!(miri) { 1e1 } else { 0.0 }; + let eps_mul = if cfg!(miri) { 1e3 } else { 0.0 }; + let eps_div = if cfg!(miri) { 1e0 } else { 0.0 }; + + assert_approx_eq!(a.algebraic_add(b), a + b, eps_add); + assert_approx_eq!(a.algebraic_sub(b), a - b, eps_add); + assert_approx_eq!(a.algebraic_mul(b), a * b, eps_mul); + assert_approx_eq!(a.algebraic_div(b), a / b, eps_div); + assert_approx_eq!(a.algebraic_rem(b), a % b, eps_div); +} + #[test] fn test_from() { assert_eq!(f16::from(false), 0.0); diff --git a/library/std/tests/floats/f32.rs b/library/std/tests/floats/f32.rs index bf7641986ada..d99b03cb255f 100644 --- a/library/std/tests/floats/f32.rs +++ b/library/std/tests/floats/f32.rs @@ -915,3 +915,24 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } + +#[test] +fn test_algebraic() { + let a: f32 = 123.0; + let b: f32 = 456.0; + + // Check that individual operations match their primitive counterparts. + // + // This is a check of current implementations and does NOT imply any form of + // guarantee about future behavior. The compiler reserves the right to make + // these operations inexact matches in the future. + let eps_add = if cfg!(miri) { 1e-3 } else { 0.0 }; + let eps_mul = if cfg!(miri) { 1e-1 } else { 0.0 }; + let eps_div = if cfg!(miri) { 1e-4 } else { 0.0 }; + + assert_approx_eq!(a.algebraic_add(b), a + b, eps_add); + assert_approx_eq!(a.algebraic_sub(b), a - b, eps_add); + assert_approx_eq!(a.algebraic_mul(b), a * b, eps_mul); + assert_approx_eq!(a.algebraic_div(b), a / b, eps_div); + assert_approx_eq!(a.algebraic_rem(b), a % b, eps_div); +} diff --git a/library/std/tests/floats/f64.rs b/library/std/tests/floats/f64.rs index cbbfcd15efd2..611670751bb5 100644 --- a/library/std/tests/floats/f64.rs +++ b/library/std/tests/floats/f64.rs @@ -894,3 +894,22 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } + +#[test] +fn test_algebraic() { + let a: f64 = 123.0; + let b: f64 = 456.0; + + // Check that individual operations match their primitive counterparts. + // + // This is a check of current implementations and does NOT imply any form of + // guarantee about future behavior. The compiler reserves the right to make + // these operations inexact matches in the future. + let eps = if cfg!(miri) { 1e-6 } else { 0.0 }; + + assert_approx_eq!(a.algebraic_add(b), a + b, eps); + assert_approx_eq!(a.algebraic_sub(b), a - b, eps); + assert_approx_eq!(a.algebraic_mul(b), a * b, eps); + assert_approx_eq!(a.algebraic_div(b), a / b, eps); + assert_approx_eq!(a.algebraic_rem(b), a % b, eps); +} diff --git a/library/std/tests/floats/lib.rs b/library/std/tests/floats/lib.rs index ad82f1a44e71..de5a3cdbd0f9 100644 --- a/library/std/tests/floats/lib.rs +++ b/library/std/tests/floats/lib.rs @@ -1,4 +1,4 @@ -#![feature(f16, f128, float_gamma, float_minimum_maximum)] +#![feature(f16, f128, float_algebraic, float_gamma, float_minimum_maximum)] use std::fmt; use std::ops::{Add, Div, Mul, Rem, Sub}; @@ -10,7 +10,7 @@ macro_rules! assert_approx_eq { let (a, b) = (&$a, &$b); let diff = (*a - *b).abs(); assert!( - diff < $lim, + diff <= $lim, "{a:?} is not approximately equal to {b:?} (threshold {lim:?}, difference {diff:?})", lim = $lim ); diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 85fb280a9a90..a3525dcc77ae 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -411,9 +411,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; let res = this.binary_op(op, &a, &b)?; // `binary_op` already called `generate_nan` if needed. - // Apply a relative error of 16ULP to simulate non-deterministic precision loss + // Apply a relative error of 4ULP to simulate non-deterministic precision loss // due to optimizations. - let res = apply_random_float_error_to_imm(this, res, 4 /* log2(16) */)?; + let res = apply_random_float_error_to_imm(this, res, 2 /* log2(4) */)?; this.write_immediate(*res, dest)?; } @@ -464,9 +464,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if !float_finite(&res)? { throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result"); } - // Apply a relative error of 16ULP to simulate non-deterministic precision loss + // Apply a relative error of 4ULP to simulate non-deterministic precision loss // due to optimizations. - let res = apply_random_float_error_to_imm(this, res, 4 /* log2(16) */)?; + let res = apply_random_float_error_to_imm(this, res, 2 /* log2(4) */)?; this.write_immediate(*res, dest)?; } diff --git a/tests/codegen/float/algebraic.rs b/tests/codegen/float/algebraic.rs new file mode 100644 index 000000000000..818a4bcdfe3f --- /dev/null +++ b/tests/codegen/float/algebraic.rs @@ -0,0 +1,149 @@ +// Verify that algebraic intrinsics generate the correct LLVM calls + +// Ensure operations get inlined +//@ compile-flags: -Copt-level=1 + +#![crate_type = "lib"] +#![feature(f16)] +#![feature(f128)] +#![feature(float_algebraic)] + +// CHECK-LABEL: @f16_algebraic_add +#[no_mangle] +pub fn f16_algebraic_add(a: f16, b: f16) -> f16 { + // CHECK: fadd reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_add(b) +} + +// CHECK-LABEL: @f16_algebraic_sub +#[no_mangle] +pub fn f16_algebraic_sub(a: f16, b: f16) -> f16 { + // CHECK: fsub reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_sub(b) +} + +// CHECK-LABEL: @f16_algebraic_mul +#[no_mangle] +pub fn f16_algebraic_mul(a: f16, b: f16) -> f16 { + // CHECK: fmul reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_mul(b) +} + +// CHECK-LABEL: @f16_algebraic_div +#[no_mangle] +pub fn f16_algebraic_div(a: f16, b: f16) -> f16 { + // CHECK: fdiv reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_div(b) +} + +// CHECK-LABEL: @f16_algebraic_rem +#[no_mangle] +pub fn f16_algebraic_rem(a: f16, b: f16) -> f16 { + // CHECK: frem reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_rem(b) +} + +// CHECK-LABEL: @f32_algebraic_add +#[no_mangle] +pub fn f32_algebraic_add(a: f32, b: f32) -> f32 { + // CHECK: fadd reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_add(b) +} + +// CHECK-LABEL: @f32_algebraic_sub +#[no_mangle] +pub fn f32_algebraic_sub(a: f32, b: f32) -> f32 { + // CHECK: fsub reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_sub(b) +} + +// CHECK-LABEL: @f32_algebraic_mul +#[no_mangle] +pub fn f32_algebraic_mul(a: f32, b: f32) -> f32 { + // CHECK: fmul reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_mul(b) +} + +// CHECK-LABEL: @f32_algebraic_div +#[no_mangle] +pub fn f32_algebraic_div(a: f32, b: f32) -> f32 { + // CHECK: fdiv reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_div(b) +} + +// CHECK-LABEL: @f32_algebraic_rem +#[no_mangle] +pub fn f32_algebraic_rem(a: f32, b: f32) -> f32 { + // CHECK: frem reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_rem(b) +} + +// CHECK-LABEL: @f64_algebraic_add +#[no_mangle] +pub fn f64_algebraic_add(a: f64, b: f64) -> f64 { + // CHECK: fadd reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_add(b) +} + +// CHECK-LABEL: @f64_algebraic_sub +#[no_mangle] +pub fn f64_algebraic_sub(a: f64, b: f64) -> f64 { + // CHECK: fsub reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_sub(b) +} + +// CHECK-LABEL: @f64_algebraic_mul +#[no_mangle] +pub fn f64_algebraic_mul(a: f64, b: f64) -> f64 { + // CHECK: fmul reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_mul(b) +} + +// CHECK-LABEL: @f64_algebraic_div +#[no_mangle] +pub fn f64_algebraic_div(a: f64, b: f64) -> f64 { + // CHECK: fdiv reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_div(b) +} + +// CHECK-LABEL: @f64_algebraic_rem +#[no_mangle] +pub fn f64_algebraic_rem(a: f64, b: f64) -> f64 { + // CHECK: frem reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_rem(b) +} + +// CHECK-LABEL: @f128_algebraic_add +#[no_mangle] +pub fn f128_algebraic_add(a: f128, b: f128) -> f128 { + // CHECK: fadd reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_add(b) +} + +// CHECK-LABEL: @f128_algebraic_sub +#[no_mangle] +pub fn f128_algebraic_sub(a: f128, b: f128) -> f128 { + // CHECK: fsub reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_sub(b) +} + +// CHECK-LABEL: @f128_algebraic_mul +#[no_mangle] +pub fn f128_algebraic_mul(a: f128, b: f128) -> f128 { + // CHECK: fmul reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_mul(b) +} + +// CHECK-LABEL: @f128_algebraic_div +#[no_mangle] +pub fn f128_algebraic_div(a: f128, b: f128) -> f128 { + // CHECK: fdiv reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_div(b) +} + +// CHECK-LABEL: @f128_algebraic_rem +#[no_mangle] +pub fn f128_algebraic_rem(a: f128, b: f128) -> f128 { + // CHECK: frem reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_rem(b) +} diff --git a/tests/codegen/float_math.rs b/tests/codegen/float_math.rs index 31387ec82b92..9a1e0b4d2d06 100644 --- a/tests/codegen/float_math.rs +++ b/tests/codegen/float_math.rs @@ -3,7 +3,10 @@ #![crate_type = "lib"] #![feature(core_intrinsics)] -use std::intrinsics::{fadd_fast, fdiv_fast, fmul_fast, frem_fast, fsub_fast}; +use std::intrinsics::{ + fadd_algebraic, fadd_fast, fdiv_algebraic, fdiv_fast, fmul_algebraic, fmul_fast, + frem_algebraic, frem_fast, fsub_algebraic, fsub_fast, +}; // CHECK-LABEL: @add #[no_mangle] @@ -13,30 +16,72 @@ pub fn add(x: f32, y: f32) -> f32 { x + y } -// CHECK-LABEL: @addition +// CHECK-LABEL: @test_fadd_algebraic #[no_mangle] -pub fn addition(x: f32, y: f32) -> f32 { - // CHECK: fadd fast float +pub fn test_fadd_algebraic(x: f32, y: f32) -> f32 { + // CHECK: fadd reassoc nsz arcp contract float %x, %y + fadd_algebraic(x, y) +} + +// CHECK-LABEL: @test_fsub_algebraic +#[no_mangle] +pub fn test_fsub_algebraic(x: f32, y: f32) -> f32 { + // CHECK: fsub reassoc nsz arcp contract float %x, %y + fsub_algebraic(x, y) +} + +// CHECK-LABEL: @test_fmul_algebraic +#[no_mangle] +pub fn test_fmul_algebraic(x: f32, y: f32) -> f32 { + // CHECK: fmul reassoc nsz arcp contract float %x, %y + fmul_algebraic(x, y) +} + +// CHECK-LABEL: @test_fdiv_algebraic +#[no_mangle] +pub fn test_fdiv_algebraic(x: f32, y: f32) -> f32 { + // CHECK: fdiv reassoc nsz arcp contract float %x, %y + fdiv_algebraic(x, y) +} + +// CHECK-LABEL: @test_frem_algebraic +#[no_mangle] +pub fn test_frem_algebraic(x: f32, y: f32) -> f32 { + // CHECK: frem reassoc nsz arcp contract float %x, %y + frem_algebraic(x, y) +} + +// CHECK-LABEL: @test_fadd_fast +#[no_mangle] +pub fn test_fadd_fast(x: f32, y: f32) -> f32 { + // CHECK: fadd fast float %x, %y unsafe { fadd_fast(x, y) } } -// CHECK-LABEL: @subtraction +// CHECK-LABEL: @test_fsub_fast #[no_mangle] -pub fn subtraction(x: f32, y: f32) -> f32 { - // CHECK: fsub fast float +pub fn test_fsub_fast(x: f32, y: f32) -> f32 { + // CHECK: fsub fast float %x, %y unsafe { fsub_fast(x, y) } } -// CHECK-LABEL: @multiplication +// CHECK-LABEL: @test_fmul_fast #[no_mangle] -pub fn multiplication(x: f32, y: f32) -> f32 { - // CHECK: fmul fast float +pub fn test_fmul_fast(x: f32, y: f32) -> f32 { + // CHECK: fmul fast float %x, %y unsafe { fmul_fast(x, y) } } -// CHECK-LABEL: @division +// CHECK-LABEL: @test_fdiv_fast #[no_mangle] -pub fn division(x: f32, y: f32) -> f32 { - // CHECK: fdiv fast float +pub fn test_fdiv_fast(x: f32, y: f32) -> f32 { + // CHECK: fdiv fast float %x, %y unsafe { fdiv_fast(x, y) } } + +// CHECK-LABEL: @test_frem_fast +#[no_mangle] +pub fn test_frem_fast(x: f32, y: f32) -> f32 { + // CHECK: frem fast float %x, %y + unsafe { frem_fast(x, y) } +} From 8c891ba2223a5eaa6ef1d9faf2b392e2cd3677d0 Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Sat, 5 Apr 2025 03:03:10 +0000 Subject: [PATCH 159/176] Change notifications for Exploit Mitigations PG Reduce the amount of notifications sent to all the Exploit Mitigations PG by removing it from some of the paths. --- triagebot.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index c2a0ea3068f5..756536dc2e7b 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1002,7 +1002,7 @@ message = "Changes to the size of AST and/or HIR nodes." cc = ["@nnethercote"] [mentions."compiler/rustc_sanitizers"] -cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] +cc = ["@rcvalle"] [mentions."src/doc/rustc/src/exploit-mitigations.md"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] @@ -1038,7 +1038,7 @@ cc = ["@Urgau"] cc = ["@Noratrieb"] [mentions."tests/codegen/sanitizer"] -cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] +cc = ["@rcvalle"] [mentions."tests/codegen/split-lto-unit.rs"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] @@ -1050,7 +1050,7 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] [mentions."tests/ui/sanitizer"] -cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] +cc = ["@rcvalle"] [mentions."tests/ui/stack-protector"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] From 4085af01836c3af3bd7c68060274ba7a0c334261 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Mon, 24 Mar 2025 23:01:13 -0700 Subject: [PATCH 160/176] Move fd into sys --- .../sys/{pal/hermit/fd.rs => fd/hermit.rs} | 2 +- library/std/src/sys/fd/mod.rs | 19 +++++++++++++++++++ .../std/src/sys/{pal/sgx/fd.rs => fd/sgx.rs} | 2 +- .../src/sys/{pal/unix/fd.rs => fd/unix.rs} | 17 +++++++++++------ .../src/sys/{pal/unix/fd => fd/unix}/tests.rs | 3 ++- .../src/sys/{pal/wasi/fd.rs => fd/wasi.rs} | 5 ++--- library/std/src/sys/fs/hermit.rs | 2 +- library/std/src/sys/mod.rs | 1 + library/std/src/sys/pal/hermit/mod.rs | 1 - library/std/src/sys/pal/sgx/mod.rs | 1 - library/std/src/sys/pal/unix/linux/pidfd.rs | 2 +- library/std/src/sys/pal/unix/mod.rs | 1 - library/std/src/sys/pal/wasi/mod.rs | 1 - library/std/src/sys/pal/wasip2/mod.rs | 5 +---- library/std/src/sys/stdio/wasi.rs | 2 +- src/bootstrap/mk/Makefile.in | 4 ++-- 16 files changed, 43 insertions(+), 25 deletions(-) rename library/std/src/sys/{pal/hermit/fd.rs => fd/hermit.rs} (99%) create mode 100644 library/std/src/sys/fd/mod.rs rename library/std/src/sys/{pal/sgx/fd.rs => fd/sgx.rs} (97%) rename library/std/src/sys/{pal/unix/fd.rs => fd/unix.rs} (98%) rename library/std/src/sys/{pal/unix/fd => fd/unix}/tests.rs (86%) rename library/std/src/sys/{pal/wasi/fd.rs => fd/wasi.rs} (99%) diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/fd/hermit.rs similarity index 99% rename from library/std/src/sys/pal/hermit/fd.rs rename to library/std/src/sys/fd/hermit.rs index edd984d920a1..7e8ba065f1b9 100644 --- a/library/std/src/sys/pal/hermit/fd.rs +++ b/library/std/src/sys/fd/hermit.rs @@ -1,8 +1,8 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] -use super::hermit_abi; use crate::cmp; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, SeekFrom}; +use crate::os::hermit::hermit_abi; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::{cvt, unsupported}; use crate::sys_common::{AsInner, FromInner, IntoInner}; diff --git a/library/std/src/sys/fd/mod.rs b/library/std/src/sys/fd/mod.rs new file mode 100644 index 000000000000..86cfa44c39dc --- /dev/null +++ b/library/std/src/sys/fd/mod.rs @@ -0,0 +1,19 @@ +//! Platform-dependent file descriptor abstraction. + +#![deny(unsafe_op_in_unsafe_fn)] + +cfg_if::cfg_if! { + if #[cfg(target_family = "unix")] { + mod unix; + pub use unix::*; + } else if #[cfg(target_os = "hermit")] { + mod hermit; + pub use hermit::*; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + mod sgx; + pub use sgx::*; + } else if #[cfg(target_os = "wasi")] { + mod wasi; + pub use wasi::*; + } +} diff --git a/library/std/src/sys/pal/sgx/fd.rs b/library/std/src/sys/fd/sgx.rs similarity index 97% rename from library/std/src/sys/pal/sgx/fd.rs rename to library/std/src/sys/fd/sgx.rs index 399f6a164898..1ef768db64c7 100644 --- a/library/std/src/sys/pal/sgx/fd.rs +++ b/library/std/src/sys/fd/sgx.rs @@ -1,8 +1,8 @@ use fortanix_sgx_abi::Fd; -use super::abi::usercalls; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; +use crate::sys::pal::abi::usercalls; use crate::sys::{AsInner, FromInner, IntoInner}; #[derive(Debug)] diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/fd/unix.rs similarity index 98% rename from library/std/src/sys/pal/unix/fd.rs rename to library/std/src/sys/fd/unix.rs index 2ec8d01c13f4..3fd92ccbff3a 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/fd/unix.rs @@ -1,4 +1,5 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] +#![allow(unsafe_op_in_unsafe_fn)] #[cfg(test)] mod tests; @@ -22,6 +23,10 @@ use crate::cmp; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::cvt; +#[cfg(all(target_os = "android", target_pointer_width = "64"))] +use crate::sys::pal::weak::syscall; +#[cfg(any(all(target_os = "android", target_pointer_width = "32"), target_vendor = "apple"))] +use crate::sys::pal::weak::weak; use crate::sys_common::{AsInner, FromInner, IntoInner}; #[derive(Debug)] @@ -232,7 +237,7 @@ impl FileDesc { // implementation if `preadv` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::syscall!( + syscall!( fn preadv( fd: libc::c_int, iovec: *const libc::iovec, @@ -257,7 +262,7 @@ impl FileDesc { // and its metadata from LLVM IR. #[no_sanitize(cfi)] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::weak!( + weak!( fn preadv64( fd: libc::c_int, iovec: *const libc::iovec, @@ -293,7 +298,7 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::weak!( + weak!( fn preadv( fd: libc::c_int, iovec: *const libc::iovec, @@ -442,7 +447,7 @@ impl FileDesc { // implementation if `pwritev` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::syscall!( + syscall!( fn pwritev( fd: libc::c_int, iovec: *const libc::iovec, @@ -464,7 +469,7 @@ impl FileDesc { #[cfg(all(target_os = "android", target_pointer_width = "32"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::weak!( + weak!( fn pwritev64( fd: libc::c_int, iovec: *const libc::iovec, @@ -500,7 +505,7 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::weak!( + weak!( fn pwritev( fd: libc::c_int, iovec: *const libc::iovec, diff --git a/library/std/src/sys/pal/unix/fd/tests.rs b/library/std/src/sys/fd/unix/tests.rs similarity index 86% rename from library/std/src/sys/pal/unix/fd/tests.rs rename to library/std/src/sys/fd/unix/tests.rs index c5301ce65578..fcd66c71707d 100644 --- a/library/std/src/sys/pal/unix/fd/tests.rs +++ b/library/std/src/sys/fd/unix/tests.rs @@ -1,6 +1,7 @@ use core::mem::ManuallyDrop; -use super::{FileDesc, IoSlice}; +use super::FileDesc; +use crate::io::IoSlice; use crate::os::unix::io::FromRawFd; #[test] diff --git a/library/std/src/sys/pal/wasi/fd.rs b/library/std/src/sys/fd/wasi.rs similarity index 99% rename from library/std/src/sys/pal/wasi/fd.rs rename to library/std/src/sys/fd/wasi.rs index 4b3dd1ce49ef..80a5143ff0b0 100644 --- a/library/std/src/sys/pal/wasi/fd.rs +++ b/library/std/src/sys/fd/wasi.rs @@ -1,11 +1,10 @@ -#![forbid(unsafe_op_in_unsafe_fn)] -#![allow(dead_code)] +#![expect(dead_code)] -use super::err2io; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; +use crate::sys::pal::err2io; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; #[derive(Debug)] diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index f83a2f90ed22..99690abe8ed2 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs @@ -9,8 +9,8 @@ use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Raw use crate::path::{Path, PathBuf}; use crate::sync::Arc; use crate::sys::common::small_c_string::run_path_with_cstr; +use crate::sys::fd::FileDesc; pub use crate::sys::fs::common::{copy, exists}; -use crate::sys::pal::fd::FileDesc; use crate::sys::time::SystemTime; use crate::sys::{cvt, unsupported}; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index f0cfb9b27736..f8f220fafd1d 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -12,6 +12,7 @@ pub mod anonymous_pipe; pub mod backtrace; pub mod cmath; pub mod exit_guard; +pub mod fd; pub mod fs; pub mod io; pub mod net; diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 67eab96fa403..26211bcb1520 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -20,7 +20,6 @@ use crate::os::raw::c_char; pub mod args; pub mod env; -pub mod fd; pub mod futex; pub mod os; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index fe43cfd2caf7..52684e18ac27 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -11,7 +11,6 @@ use crate::sync::atomic::{AtomicBool, Ordering}; pub mod abi; pub mod args; pub mod env; -pub mod fd; mod libunwind_integration; pub mod os; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs index 78744430f3b5..2d949ec9e91f 100644 --- a/library/std/src/sys/pal/unix/linux/pidfd.rs +++ b/library/std/src/sys/pal/unix/linux/pidfd.rs @@ -1,7 +1,7 @@ use crate::io; use crate::os::fd::{AsRawFd, FromRawFd, RawFd}; use crate::sys::cvt; -use crate::sys::pal::unix::fd::FileDesc; +use crate::sys::fd::FileDesc; use crate::sys::process::ExitStatus; use crate::sys_common::{AsInner, FromInner, IntoInner}; diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 413fda1d8d8e..d7106c339747 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -8,7 +8,6 @@ pub mod weak; pub mod args; pub mod env; -pub mod fd; #[cfg(target_os = "fuchsia")] pub mod fuchsia; pub mod futex; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index cdd613f76b63..80853e7b5a26 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -15,7 +15,6 @@ pub mod args; pub mod env; -pub mod fd; #[allow(unused)] #[path = "../wasm/atomics/futex.rs"] pub mod futex; diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index 6ac28f1bf4fc..504b947d09e2 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -10,8 +10,6 @@ pub mod args; #[path = "../wasi/env.rs"] pub mod env; -#[path = "../wasi/fd.rs"] -pub mod fd; #[allow(unused)] #[path = "../wasm/atomics/futex.rs"] pub mod futex; @@ -39,7 +37,6 @@ mod helpers; // import conflict rules. If we glob export `helpers` and `common` together, // then the compiler complains about conflicts. -use helpers::err2io; -pub use helpers::{abort_internal, decode_error_kind, is_interrupted}; +pub(crate) use helpers::{abort_internal, decode_error_kind, err2io, is_interrupted}; mod cabi_realloc; diff --git a/library/std/src/sys/stdio/wasi.rs b/library/std/src/sys/stdio/wasi.rs index 8105b0cfa2f1..b70efd026f94 100644 --- a/library/std/src/sys/stdio/wasi.rs +++ b/library/std/src/sys/stdio/wasi.rs @@ -4,7 +4,7 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; use crate::os::raw; use crate::os::wasi::io::{AsRawFd, FromRawFd}; -use crate::sys::pal::fd::WasiFd; +use crate::sys::fd::WasiFd; pub struct Stdin; pub struct Stdout; diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 6cb0b19d7632..c441b6a16cd2 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -73,12 +73,12 @@ check-aux: $(BOOTSTRAP) miri --stage 2 library/std \ $(BOOTSTRAP_ARGS) \ --no-doc -- \ - --skip fs:: --skip net:: --skip process:: --skip sys::pal:: + --skip fs:: --skip net:: --skip process:: --skip sys::fd:: --skip sys::pal:: $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 library/std \ $(BOOTSTRAP_ARGS) \ --doc -- \ - --skip fs:: --skip net:: --skip process:: --skip sys::pal:: + --skip fs:: --skip net:: --skip process:: --skip sys::fd:: --skip sys::pal:: # Also test some very target-specific modules on other targets # (making sure to cover an i686 target as well). $(Q)MIRIFLAGS="-Zmiri-disable-isolation" BOOTSTRAP_SKIP_TARGET_SANITY=1 \ From 3ab22fabf1a21077556c708633ceaefbb678c178 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Fri, 28 Mar 2025 18:19:46 -0700 Subject: [PATCH 161/176] Fix unsafe_op_in_unsafe_fn for Unix fd and weak --- library/std/src/sys/fd/mod.rs | 2 +- library/std/src/sys/fd/unix.rs | 3 +-- library/std/src/sys/pal/unix/weak.rs | 19 ++++++++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/library/std/src/sys/fd/mod.rs b/library/std/src/sys/fd/mod.rs index 86cfa44c39dc..e0f5eab69514 100644 --- a/library/std/src/sys/fd/mod.rs +++ b/library/std/src/sys/fd/mod.rs @@ -1,6 +1,6 @@ //! Platform-dependent file descriptor abstraction. -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] cfg_if::cfg_if! { if #[cfg(target_family = "unix")] { diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index 3fd92ccbff3a..2042ea2c73d0 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -1,5 +1,4 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] -#![allow(unsafe_op_in_unsafe_fn)] #[cfg(test)] mod tests; @@ -674,6 +673,6 @@ impl IntoRawFd for FileDesc { impl FromRawFd for FileDesc { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self(FromRawFd::from_raw_fd(raw_fd)) + Self(unsafe { FromRawFd::from_raw_fd(raw_fd) }) } } diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index e7f4e005cc48..e4c814fba8ce 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -20,6 +20,7 @@ // each instance of `weak!` and `syscall!`. Rather than trying to unify all of // that, we'll just allow that some unix targets don't use this module at all. #![allow(dead_code, unused_macros)] +#![forbid(unsafe_op_in_unsafe_fn)] use crate::ffi::CStr; use crate::marker::PhantomData; @@ -131,11 +132,15 @@ impl DlsymWeak { unsafe fn initialize(&self) -> Option { assert_eq!(size_of::(), size_of::<*mut libc::c_void>()); - let val = fetch(self.name); + let val = unsafe { fetch(self.name) }; // This synchronizes with the acquire fence in `get`. self.func.store(val, Ordering::Release); - if val.is_null() { None } else { Some(mem::transmute_copy::<*mut libc::c_void, F>(&val)) } + if val.is_null() { + None + } else { + Some(unsafe { mem::transmute_copy::<*mut libc::c_void, F>(&val) }) + } } } @@ -144,7 +149,7 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void { Ok(cstr) => cstr, Err(..) => return ptr::null_mut(), }; - libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) + unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) } } #[cfg(not(any(target_os = "linux", target_os = "android")))] @@ -157,7 +162,7 @@ pub(crate) macro syscall { weak!(fn $name($($param: $t),*) -> $ret;); if let Some(fun) = $name.get() { - fun($($param),*) + unsafe { fun($($param),*) } } else { super::os::set_errno(libc::ENOSYS); -1 @@ -177,9 +182,9 @@ pub(crate) macro syscall { // Use a weak symbol from libc when possible, allowing `LD_PRELOAD` // interposition, but if it's not found just use a raw syscall. if let Some(fun) = $name.get() { - fun($($param),*) + unsafe { fun($($param),*) } } else { - libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret + unsafe { libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } } } ) @@ -189,7 +194,7 @@ pub(crate) macro syscall { pub(crate) macro raw_syscall { (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( unsafe fn $name($($param: $t),*) -> $ret { - libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret + unsafe { libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } } ) } From 9b889e919807c7f5c377c9c6b17d55276c8e3351 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sat, 29 Mar 2025 14:43:32 -0700 Subject: [PATCH 162/176] Rename internal module from statik to no_threads This module is named in reference to the keyword, but the term is somewhat overloaded. Rename it to more clearly describe it and avoid the misspelling. --- library/std/src/sys/thread_local/mod.rs | 6 +++--- .../std/src/sys/thread_local/{statik.rs => no_threads.rs} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename library/std/src/sys/thread_local/{statik.rs => no_threads.rs} (100%) diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index 1ff13154b7b3..fb7cb40625d9 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -30,9 +30,9 @@ cfg_if::cfg_if! { target_os = "zkvm", target_os = "trusty", ))] { - mod statik; - pub use statik::{EagerStorage, LazyStorage, thread_local_inner}; - pub(crate) use statik::{LocalPointer, local_pointer}; + mod no_threads; + pub use no_threads::{EagerStorage, LazyStorage, thread_local_inner}; + pub(crate) use no_threads::{LocalPointer, local_pointer}; } else if #[cfg(target_thread_local)] { mod native; pub use native::{EagerStorage, LazyStorage, thread_local_inner}; diff --git a/library/std/src/sys/thread_local/statik.rs b/library/std/src/sys/thread_local/no_threads.rs similarity index 100% rename from library/std/src/sys/thread_local/statik.rs rename to library/std/src/sys/thread_local/no_threads.rs From a98546b961a7fc707155aecbde094fbcecce81fd Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Tue, 11 Mar 2025 19:04:35 +0000 Subject: [PATCH 163/176] KCFI: Add KCFI arity indicator support Adds KCFI arity indicator support to the Rust compiler (see rust-lang/rust#138311, https://github.com/llvm/llvm-project/pull/121070, and https://lore.kernel.org/lkml/CANiq72=3ghFxy8E=AU9p+0imFxKr5iU3sd0hVUXed5BA+KjdNQ@mail.gmail.com/). --- compiler/rustc_codegen_llvm/messages.ftl | 2 + compiler/rustc_codegen_llvm/src/context.rs | 16 +++++ compiler/rustc_codegen_llvm/src/errors.rs | 4 ++ compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/messages.ftl | 2 + compiler/rustc_session/src/errors.rs | 4 ++ compiler/rustc_session/src/options.rs | 2 + compiler/rustc_session/src/session.rs | 9 +++ .../sanitizer/kcfi/emit-arity-indicator.rs | 61 +++++++++++++++++++ .../sanitizer/kcfi/add-kcfi-arity-flag.rs | 19 ++++++ .../ui/sanitizer/kcfi-arity-requires-kcfi.rs | 9 +++ .../sanitizer/kcfi-arity-requires-kcfi.stderr | 4 ++ .../kcfi-arity-requires-llvm-21-0-0.rs | 11 ++++ .../kcfi-arity-requires-llvm-21-0-0.stderr | 4 ++ 14 files changed, 148 insertions(+) create mode 100644 tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs create mode 100644 tests/codegen/sanitizer/kcfi/add-kcfi-arity-flag.rs create mode 100644 tests/ui/sanitizer/kcfi-arity-requires-kcfi.rs create mode 100644 tests/ui/sanitizer/kcfi-arity-requires-kcfi.stderr create mode 100644 tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs create mode 100644 tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.stderr diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index 17f2e7ca9f70..41391b096cca 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -56,6 +56,8 @@ codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO codegen_llvm_run_passes = failed to run LLVM passes codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err} +codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0 = `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later. + codegen_llvm_sanitizer_memtag_requires_mte = `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte` diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index f7b096ff976a..ad98e506690e 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -327,6 +327,22 @@ pub(crate) unsafe fn create_module<'ll>( pfe.prefix().into(), ); } + + // Add "kcfi-arity" module flag if KCFI arity indicator is enabled. (See + // https://github.com/llvm/llvm-project/pull/117121.) + if sess.is_sanitizer_kcfi_arity_enabled() { + // KCFI arity indicator requires LLVM 21.0.0 or later. + if llvm_version < (21, 0, 0) { + tcx.dcx().emit_err(crate::errors::SanitizerKcfiArityRequiresLLVM2100); + } + + llvm::add_module_flag_u32( + llmod, + llvm::ModuleFlagMergeBehavior::Override, + "kcfi-arity", + 1, + ); + } } // Control Flow Guard is currently only supported by MSVC and LLVM on Windows. diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 4c5a78ca74fe..ecf108f988f0 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -217,3 +217,7 @@ pub(crate) struct MismatchedDataLayout<'a> { pub(crate) struct FixedX18InvalidArch<'a> { pub arch: &'a str, } + +#[derive(Diagnostic)] +#[diag(codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0)] +pub(crate) struct SanitizerKcfiArityRequiresLLVM2100; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 4592e0144388..a8e556632572 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -853,6 +853,7 @@ fn test_unstable_options_tracking_hash() { tracked!(sanitizer_cfi_generalize_pointers, Some(true)); tracked!(sanitizer_cfi_normalize_integers, Some(true)); tracked!(sanitizer_dataflow_abilist, vec![String::from("/rustc/abc")]); + tracked!(sanitizer_kcfi_arity, Some(true)); tracked!(sanitizer_memory_track_origins, 2); tracked!(sanitizer_recover, SanitizerSet::ADDRESS); tracked!(saturating_float_casts, Some(true)); diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 74b8087e0776..a0f873f3cf66 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -94,6 +94,8 @@ session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto` or `-Cli session_sanitizer_cfi_requires_single_codegen_unit = `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1` +session_sanitizer_kcfi_arity_requires_kcfi = `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi` + session_sanitizer_kcfi_requires_panic_abort = `-Z sanitizer=kcfi` requires `-C panic=abort` session_sanitizer_not_supported = {$us} sanitizer is not supported for this target diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 71d8dbe44fed..3979aea70d33 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -147,6 +147,10 @@ pub(crate) struct SanitizerCfiGeneralizePointersRequiresCfi; #[diag(session_sanitizer_cfi_normalize_integers_requires_cfi)] pub(crate) struct SanitizerCfiNormalizeIntegersRequiresCfi; +#[derive(Diagnostic)] +#[diag(session_sanitizer_kcfi_arity_requires_kcfi)] +pub(crate) struct SanitizerKcfiArityRequiresKcfi; + #[derive(Diagnostic)] #[diag(session_sanitizer_kcfi_requires_panic_abort)] pub(crate) struct SanitizerKcfiRequiresPanicAbort; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4f544d2c16b7..720bc3f61e42 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2443,6 +2443,8 @@ written to standard error output)"), "enable normalizing integer types (default: no)"), sanitizer_dataflow_abilist: Vec = (Vec::new(), parse_comma_list, [TRACKED], "additional ABI list files that control how shadow parameters are passed (comma separated)"), + sanitizer_kcfi_arity: Option = (None, parse_opt_bool, [TRACKED], + "enable KCFI arity indicator (default: no)"), sanitizer_memory_track_origins: usize = (0, parse_sanitizer_memory_track_origins, [TRACKED], "enable origins tracking in MemorySanitizer"), sanitizer_recover: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a87b1961a995..2c6b6eb619b3 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -381,6 +381,10 @@ impl Session { self.opts.unstable_opts.sanitizer_cfi_normalize_integers == Some(true) } + pub fn is_sanitizer_kcfi_arity_enabled(&self) -> bool { + self.opts.unstable_opts.sanitizer_kcfi_arity == Some(true) + } + pub fn is_sanitizer_kcfi_enabled(&self) -> bool { self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI) } @@ -1211,6 +1215,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } + // KCFI arity indicator requires KCFI. + if sess.is_sanitizer_kcfi_arity_enabled() && !sess.is_sanitizer_kcfi_enabled() { + sess.dcx().emit_err(errors::SanitizerKcfiArityRequiresKcfi); + } + // LLVM CFI pointer generalization requires CFI or KCFI. if sess.is_sanitizer_cfi_generalize_pointers_enabled() { if !(sess.is_sanitizer_cfi_enabled() || sess.is_sanitizer_kcfi_enabled()) { diff --git a/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs b/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs new file mode 100644 index 000000000000..b3b623b509b4 --- /dev/null +++ b/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs @@ -0,0 +1,61 @@ +// Verifies that KCFI arity indicator is emitted. +// +//@ add-core-stubs +//@ revisions: x86_64 +//@ assembly-output: emit-asm +//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -Cllvm-args=-x86-asm-syntax=intel -Ctarget-feature=-crt-static -Cpanic=abort -Zsanitizer=kcfi -Zsanitizer-kcfi-arity -Copt-level=0 +//@ [x86_64] needs-llvm-components: x86 +//@ min-llvm-version: 21.0.0 + +#![crate_type = "lib"] + +pub fn add_one(x: i32) -> i32 { + // CHECK-LABEL: __cfi__{{.*}}7add_one{{.*}}: + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: mov ecx, 2628068948 + x + 1 +} + +pub fn add_two(x: i32, _y: i32) -> i32 { + // CHECK-LABEL: __cfi__{{.*}}7add_two{{.*}}: + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: mov edx, 2505940310 + x + 2 +} + +pub fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { + // CHECK-LABEL: __cfi__{{.*}}8do_twice{{.*}}: + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: nop + // CHECK-NEXT: mov edx, 653723426 + f(arg) + f(arg) +} diff --git a/tests/codegen/sanitizer/kcfi/add-kcfi-arity-flag.rs b/tests/codegen/sanitizer/kcfi/add-kcfi-arity-flag.rs new file mode 100644 index 000000000000..9a2290901d64 --- /dev/null +++ b/tests/codegen/sanitizer/kcfi/add-kcfi-arity-flag.rs @@ -0,0 +1,19 @@ +// Verifies that "kcfi-arity" module flag is added. +// +//@ add-core-stubs +//@ revisions: x86_64 +//@ [x86_64] compile-flags: --target x86_64-unknown-none +//@ [x86_64] needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-crt-static -Cpanic=abort -Zsanitizer=kcfi -Zsanitizer-kcfi-arity +//@ min-llvm-version: 21.0.0 + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::*; + +pub fn foo() {} + +// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi-arity", i32 1} diff --git a/tests/ui/sanitizer/kcfi-arity-requires-kcfi.rs b/tests/ui/sanitizer/kcfi-arity-requires-kcfi.rs new file mode 100644 index 000000000000..12aabb3b8623 --- /dev/null +++ b/tests/ui/sanitizer/kcfi-arity-requires-kcfi.rs @@ -0,0 +1,9 @@ +// Verifies that `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`. +// +//@ needs-sanitizer-kcfi +//@ compile-flags: -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-kcfi-arity + +//~? ERROR `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi` +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/tests/ui/sanitizer/kcfi-arity-requires-kcfi.stderr b/tests/ui/sanitizer/kcfi-arity-requires-kcfi.stderr new file mode 100644 index 000000000000..4ed1b754fd43 --- /dev/null +++ b/tests/ui/sanitizer/kcfi-arity-requires-kcfi.stderr @@ -0,0 +1,4 @@ +error: `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi` + +error: aborting due to 1 previous error + diff --git a/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs b/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs new file mode 100644 index 000000000000..8a724b853e13 --- /dev/null +++ b/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs @@ -0,0 +1,11 @@ +// Verifies that `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later. +// +//@ needs-sanitizer-kcfi +//@ compile-flags: -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Cpanic=abort -Zsanitizer=kcfi -Zsanitizer-kcfi-arity +//@ build-fail +//@ max-llvm-major-version: 20 + +//~? ERROR `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later. +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.stderr b/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.stderr new file mode 100644 index 000000000000..ac6bd7411fd8 --- /dev/null +++ b/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.stderr @@ -0,0 +1,4 @@ +error: `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later. + +error: aborting due to 1 previous error + From 89d9dd6e158c18a79cd547dc172ba5739203097b Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 5 Apr 2025 08:59:13 +0000 Subject: [PATCH 164/176] Only `format!` error message on failure --- compiler/rustc_smir/src/rustc_smir/alloc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index 52c5b425c14f..0dedb55f6fc1 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -27,7 +27,7 @@ pub(crate) fn new_allocation<'tcx>( tables: &mut Tables<'tcx>, ) -> Allocation { try_new_allocation(ty, const_value, tables) - .expect(&format!("Failed to convert: {const_value:?} to {ty:?}")) + .unwrap_or_else(|_| panic!("Failed to convert: {const_value:?} to {ty:?}")) } #[allow(rustc::usage_of_qualified_ty)] From 33d62dd208bcb9049a128bbc241508e7e12c96c9 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 5 Apr 2025 08:59:49 +0000 Subject: [PATCH 165/176] Dedup call to layout query --- compiler/rustc_smir/src/rustc_smir/alloc.rs | 36 +++++++-------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index 0dedb55f6fc1..26dfd2fbe448 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -36,39 +36,30 @@ pub(crate) fn try_new_allocation<'tcx>( const_value: ConstValue<'tcx>, tables: &mut Tables<'tcx>, ) -> Result { + let layout = tables + .tcx + .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + .map_err(|e| e.stable(tables))?; Ok(match const_value { ConstValue::Scalar(scalar) => { let size = scalar.size(); - let align = tables - .tcx - .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) - .map_err(|e| e.stable(tables))? - .align; - let mut allocation = - rustc_middle::mir::interpret::Allocation::new(size, align.abi, AllocInit::Uninit); + let mut allocation = rustc_middle::mir::interpret::Allocation::new( + size, + layout.align.abi, + AllocInit::Uninit, + ); allocation .write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar) .map_err(|e| e.stable(tables))?; allocation.stable(tables) } - ConstValue::ZeroSized => { - let align = tables - .tcx - .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) - .map_err(|e| e.stable(tables))? - .align; - new_empty_allocation(align.abi) - } + ConstValue::ZeroSized => new_empty_allocation(layout.align.abi), ConstValue::Slice { data, meta } => { let alloc_id = tables.tcx.reserve_and_set_memory_alloc(data); let ptr = Pointer::new(alloc_id.into(), Size::ZERO); let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx); let scalar_meta = rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx); - let layout = tables - .tcx - .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) - .map_err(|e| e.stable(tables))?; let mut allocation = rustc_middle::mir::interpret::Allocation::new( layout.size, layout.align.abi, @@ -92,12 +83,7 @@ pub(crate) fn try_new_allocation<'tcx>( } ConstValue::Indirect { alloc_id, offset } => { let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory(); - let ty_size = tables - .tcx - .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) - .map_err(|e| e.stable(tables))? - .size; - allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables) + allocation_filter(&alloc.0, alloc_range(offset, layout.size), tables) } }) } From 707d356d004029a7e5300ce51e5aed330aa4a1a7 Mon Sep 17 00:00:00 2001 From: Makai Date: Sat, 5 Apr 2025 18:23:07 +0800 Subject: [PATCH 166/176] let `rustc_smir` host `stable_mir` for refactoring --- Cargo.lock | 5 +- compiler/rustc_smir/Cargo.toml | 2 +- compiler/rustc_smir/src/lib.rs | 2 + .../rustc_smir/src/rustc_internal/internal.rs | 1 + compiler/rustc_smir/src/rustc_internal/mod.rs | 1 + .../rustc_smir/src/rustc_internal/pretty.rs | 1 + compiler/rustc_smir/src/rustc_smir/alloc.rs | 1 + compiler/rustc_smir/src/rustc_smir/builder.rs | 1 + compiler/rustc_smir/src/rustc_smir/context.rs | 1 + .../rustc_smir/src/rustc_smir/convert/abi.rs | 1 + .../src/rustc_smir/convert/error.rs | 1 + .../rustc_smir/src/rustc_smir/convert/mir.rs | 1 + .../rustc_smir/src/rustc_smir/convert/mod.rs | 1 + .../rustc_smir/src/rustc_smir/convert/ty.rs | 1 + compiler/rustc_smir/src/rustc_smir/mod.rs | 1 + .../src => rustc_smir/src/stable_mir}/abi.rs | 13 +- .../src/stable_mir}/compiler_interface.rs | 18 +- .../src/stable_mir}/crate_def.rs | 5 +- .../src/stable_mir}/error.rs | 0 .../src => rustc_smir/src/stable_mir}/mir.rs | 0 .../src/stable_mir}/mir/alloc.rs | 9 +- .../src/stable_mir}/mir/body.rs | 13 +- .../src/stable_mir}/mir/mono.rs | 43 ++-- .../src/stable_mir}/mir/pretty.rs | 11 +- .../src/stable_mir}/mir/visit.rs | 8 +- compiler/rustc_smir/src/stable_mir/mod.rs | 239 ++++++++++++++++++ .../src/stable_mir}/target.rs | 3 +- .../src => rustc_smir/src/stable_mir}/ty.rs | 17 +- .../src/stable_mir}/visitor.rs | 14 +- compiler/stable_mir/Cargo.toml | 3 +- compiler/stable_mir/src/lib.rs | 234 +---------------- 31 files changed, 346 insertions(+), 305 deletions(-) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/abi.rs (97%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/compiler_interface.rs (96%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/crate_def.rs (97%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/error.rs (100%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/mir.rs (100%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/mir/alloc.rs (92%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/mir/body.rs (99%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/mir/mono.rs (90%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/mir/pretty.rs (98%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/mir/visit.rs (99%) create mode 100644 compiler/rustc_smir/src/stable_mir/mod.rs rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/target.rs (95%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/ty.rs (98%) rename compiler/{stable_mir/src => rustc_smir/src/stable_mir}/visitor.rs (95%) diff --git a/Cargo.lock b/Cargo.lock index 96526f7e9e7d..99bd1bff0204 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4432,7 +4432,7 @@ dependencies = [ "rustc_span", "rustc_target", "scoped-tls", - "stable_mir", + "serde", "tracing", ] @@ -4990,8 +4990,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "stable_mir" version = "0.1.0-preview" dependencies = [ - "scoped-tls", - "serde", + "rustc_smir", ] [[package]] diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index b2149a03a8ef..fc9f411ac3cd 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -14,6 +14,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } scoped-tls = "1.0" -stable_mir = {path = "../stable_mir" } +serde = { version = "1.0.125", features = [ "derive" ] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index eaba14bbf30f..5d465bca4eef 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -22,3 +22,5 @@ pub mod rustc_internal; // Make this module private for now since external users should not call these directly. mod rustc_smir; + +pub mod stable_mir; diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index bb2b2dea2f37..36b68cc13982 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -21,6 +21,7 @@ use stable_mir::{CrateItem, CrateNum, DefId}; use super::RustcInternal; use crate::rustc_smir::Tables; +use crate::stable_mir; impl RustcInternal for CrateItem { type T<'tcx> = rustc_span::def_id::DefId; diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 30e9b2e72f73..a546a44c8700 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -22,6 +22,7 @@ use stable_mir::ty::IndexedVal; use crate::rustc_smir::context::TablesWrapper; use crate::rustc_smir::{Stable, Tables}; +use crate::stable_mir; mod internal; pub mod pretty; diff --git a/compiler/rustc_smir/src/rustc_internal/pretty.rs b/compiler/rustc_smir/src/rustc_internal/pretty.rs index b752ad71ecc6..0710c18746af 100644 --- a/compiler/rustc_smir/src/rustc_internal/pretty.rs +++ b/compiler/rustc_smir/src/rustc_internal/pretty.rs @@ -3,6 +3,7 @@ use std::io; use rustc_middle::ty::TyCtxt; use super::run; +use crate::stable_mir; pub fn write_smir_pretty<'tcx, W: io::Write>(tcx: TyCtxt<'tcx>, w: &mut W) -> io::Result<()> { writeln!( diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index 52c5b425c14f..212138576621 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -6,6 +6,7 @@ use stable_mir::mir::Mutability; use stable_mir::ty::{Allocation, ProvenanceMap}; use crate::rustc_smir::{Stable, Tables}; +use crate::stable_mir; /// Creates new empty `Allocation` from given `Align`. fn new_empty_allocation(align: Align) -> Allocation { diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs index 2eb0cea0e853..64763b71d303 100644 --- a/compiler/rustc_smir/src/rustc_smir/builder.rs +++ b/compiler/rustc_smir/src/rustc_smir/builder.rs @@ -10,6 +10,7 @@ use rustc_middle::mir::visit::MutVisitor; use rustc_middle::ty::{self, TyCtxt}; use crate::rustc_smir::{Stable, Tables}; +use crate::stable_mir; /// Builds a monomorphic body for a given instance. pub(crate) struct BodyBuilder<'tcx> { diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 322e86147c19..240f6f7fe45a 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -35,6 +35,7 @@ use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, I use crate::rustc_internal::RustcInternal; use crate::rustc_smir::builder::BodyBuilder; use crate::rustc_smir::{Stable, Tables, alloc, filter_def_ids, new_item_kind, smir_crate}; +use crate::stable_mir; impl<'tcx> Context for TablesWrapper<'tcx> { fn target_info(&self) -> MachineInfo { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index 62cbab9b723c..7ccc785a4002 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -14,6 +14,7 @@ use stable_mir::target::MachineSize as Size; use stable_mir::ty::{Align, IndexedVal, VariantIdx}; use crate::rustc_smir::{Stable, Tables}; +use crate::stable_mir; impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx { type T = VariantIdx; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/error.rs b/compiler/rustc_smir/src/rustc_smir/convert/error.rs index 82ecfa630ddb..2cde5542483d 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/error.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/error.rs @@ -6,6 +6,7 @@ use rustc_middle::mir::interpret::AllocError; use rustc_middle::ty::layout::LayoutError; use crate::rustc_smir::{Stable, Tables}; +use crate::stable_mir; impl<'tcx> Stable<'tcx> for LayoutError<'tcx> { type T = stable_mir::Error; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index bdd6e16a7c17..61b769bce083 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -9,6 +9,7 @@ use stable_mir::ty::{Allocation, ConstantKind, MirConst}; use stable_mir::{Error, opaque}; use crate::rustc_smir::{Stable, Tables, alloc}; +use crate::stable_mir; impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { type T = stable_mir::mir::Body; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index a3da563af50d..3494de62d835 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -3,6 +3,7 @@ use rustc_abi::FieldIdx; use crate::rustc_smir::{Stable, Tables}; +use crate::stable_mir; mod abi; mod error; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 8309809d7b51..1ba25aa0e971 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -7,6 +7,7 @@ use stable_mir::ty::{ }; use crate::rustc_smir::{Stable, Tables, alloc}; +use crate::stable_mir; impl<'tcx> Stable<'tcx> for ty::AliasTyKind { type T = stable_mir::ty::AliasKind; diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index c5d33f090a05..dea8f54a6709 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -21,6 +21,7 @@ use stable_mir::{CtorKind, ItemKind}; use tracing::debug; use crate::rustc_internal::IndexMap; +use crate::stable_mir; mod alloc; mod builder; diff --git a/compiler/stable_mir/src/abi.rs b/compiler/rustc_smir/src/stable_mir/abi.rs similarity index 97% rename from compiler/stable_mir/src/abi.rs rename to compiler/rustc_smir/src/stable_mir/abi.rs index 091f3e1a95e9..3842cb7e653e 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/rustc_smir/src/stable_mir/abi.rs @@ -3,12 +3,13 @@ use std::num::NonZero; use std::ops::RangeInclusive; use serde::Serialize; +use stable_mir::compiler_interface::with; +use stable_mir::mir::FieldIdx; +use stable_mir::target::{MachineInfo, MachineSize as Size}; +use stable_mir::ty::{Align, IndexedVal, Ty, VariantIdx}; +use stable_mir::{Error, Opaque, error}; -use crate::compiler_interface::with; -use crate::mir::FieldIdx; -use crate::target::{MachineInfo, MachineSize as Size}; -use crate::ty::{Align, IndexedVal, Ty, VariantIdx}; -use crate::{Error, Opaque, error}; +use crate::stable_mir; /// A function ABI definition. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] @@ -149,7 +150,7 @@ pub enum FieldsShape { Arbitrary { /// Offsets for the first byte of each field, /// ordered to match the source definition order. - /// I.e.: It follows the same order as [crate::ty::VariantDef::fields()]. + /// I.e.: It follows the same order as [super::ty::VariantDef::fields()]. /// This vector does not go in increasing order. offsets: Vec, }, diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs similarity index 96% rename from compiler/stable_mir/src/compiler_interface.rs rename to compiler/rustc_smir/src/stable_mir/compiler_interface.rs index 46154da36ca0..33d950bb951c 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs @@ -5,23 +5,25 @@ use std::cell::Cell; -use crate::abi::{FnAbi, Layout, LayoutShape}; -use crate::crate_def::Attribute; -use crate::mir::alloc::{AllocId, GlobalAlloc}; -use crate::mir::mono::{Instance, InstanceDef, StaticDef}; -use crate::mir::{BinOp, Body, Place, UnOp}; -use crate::target::MachineInfo; -use crate::ty::{ +use stable_mir::abi::{FnAbi, Layout, LayoutShape}; +use stable_mir::crate_def::Attribute; +use stable_mir::mir::alloc::{AllocId, GlobalAlloc}; +use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef}; +use stable_mir::mir::{BinOp, Body, Place, UnOp}; +use stable_mir::target::MachineInfo; +use stable_mir::ty::{ AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, }; -use crate::{ +use stable_mir::{ AssocItems, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, Symbol, TraitDecls, mir, }; +use crate::stable_mir; + /// This trait defines the interface between stable_mir and the Rust compiler. /// Do not use this directly. pub trait Context { diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/rustc_smir/src/stable_mir/crate_def.rs similarity index 97% rename from compiler/stable_mir/src/crate_def.rs rename to compiler/rustc_smir/src/stable_mir/crate_def.rs index 75228135e4cb..64f7ef9b314f 100644 --- a/compiler/stable_mir/src/crate_def.rs +++ b/compiler/rustc_smir/src/stable_mir/crate_def.rs @@ -2,9 +2,10 @@ //! such as, a function, a trait, an enum, and any other definitions. use serde::Serialize; +use stable_mir::ty::{GenericArgs, Span, Ty}; +use stable_mir::{AssocItems, Crate, Symbol, with}; -use crate::ty::{GenericArgs, Span, Ty}; -use crate::{AssocItems, Crate, Symbol, with}; +use crate::stable_mir; /// A unique identification number for each item accessible for the current compilation unit. #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)] diff --git a/compiler/stable_mir/src/error.rs b/compiler/rustc_smir/src/stable_mir/error.rs similarity index 100% rename from compiler/stable_mir/src/error.rs rename to compiler/rustc_smir/src/stable_mir/error.rs diff --git a/compiler/stable_mir/src/mir.rs b/compiler/rustc_smir/src/stable_mir/mir.rs similarity index 100% rename from compiler/stable_mir/src/mir.rs rename to compiler/rustc_smir/src/stable_mir/mir.rs diff --git a/compiler/stable_mir/src/mir/alloc.rs b/compiler/rustc_smir/src/stable_mir/mir/alloc.rs similarity index 92% rename from compiler/stable_mir/src/mir/alloc.rs rename to compiler/rustc_smir/src/stable_mir/mir/alloc.rs index 023807b76aec..782f52888b73 100644 --- a/compiler/stable_mir/src/mir/alloc.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/alloc.rs @@ -3,11 +3,12 @@ use std::io::Read; use serde::Serialize; +use stable_mir::mir::mono::{Instance, StaticDef}; +use stable_mir::target::{Endian, MachineInfo}; +use stable_mir::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty}; +use stable_mir::{Error, with}; -use crate::mir::mono::{Instance, StaticDef}; -use crate::target::{Endian, MachineInfo}; -use crate::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty}; -use crate::{Error, with}; +use crate::stable_mir; /// An allocation in the SMIR global memory can be either a function pointer, /// a static, or a "real" allocation with some data in it. diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs similarity index 99% rename from compiler/stable_mir/src/mir/body.rs rename to compiler/rustc_smir/src/stable_mir/mir/body.rs index 2a1c163de3c4..b23605454246 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -1,14 +1,15 @@ use std::io; use serde::Serialize; - -use crate::compiler_interface::with; -use crate::mir::pretty::function_body; -use crate::ty::{ +use stable_mir::compiler_interface::with; +use stable_mir::mir::pretty::function_body; +use stable_mir::ty::{ AdtDef, ClosureDef, CoroutineClosureDef, CoroutineDef, GenericArgs, MirConst, Movability, Region, RigidTy, Ty, TyConst, TyKind, VariantIdx, }; -use crate::{Error, Opaque, Span, Symbol}; +use stable_mir::{Error, Opaque, Span, Symbol}; + +use crate::stable_mir; /// The SMIR representation of a single function. #[derive(Clone, Debug, Serialize)] @@ -565,7 +566,7 @@ pub enum Rvalue { /// /// **Needs clarification**: Are there weird additional semantics here related to the runtime /// nature of this operation? - ThreadLocalRef(crate::CrateItem), + ThreadLocalRef(stable_mir::CrateItem), /// Computes a value as described by the operation. NullaryOp(NullOp, Ty), diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/rustc_smir/src/stable_mir/mir/mono.rs similarity index 90% rename from compiler/stable_mir/src/mir/mono.rs rename to compiler/rustc_smir/src/stable_mir/mir/mono.rs index 22507a49411f..0c3e4fb7c90b 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/mono.rs @@ -2,12 +2,13 @@ use std::fmt::{Debug, Formatter}; use std::io; use serde::Serialize; +use stable_mir::abi::FnAbi; +use stable_mir::crate_def::CrateDef; +use stable_mir::mir::Body; +use stable_mir::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty}; +use stable_mir::{CrateItem, DefId, Error, ItemKind, Opaque, Symbol, with}; -use crate::abi::FnAbi; -use crate::crate_def::CrateDef; -use crate::mir::Body; -use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty}; -use crate::{CrateItem, DefId, Error, ItemKind, Opaque, Symbol, with}; +use crate::stable_mir; #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum MonoItem { @@ -117,11 +118,11 @@ impl Instance { } /// Resolve an instance starting from a function definition and generic arguments. - pub fn resolve(def: FnDef, args: &GenericArgs) -> Result { + pub fn resolve(def: FnDef, args: &GenericArgs) -> Result { with(|context| { - context.resolve_instance(def, args).ok_or_else(|| { - crate::Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`")) - }) + context + .resolve_instance(def, args) + .ok_or_else(|| Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`"))) }) } @@ -131,11 +132,11 @@ impl Instance { } /// Resolve an instance for a given function pointer. - pub fn resolve_for_fn_ptr(def: FnDef, args: &GenericArgs) -> Result { + pub fn resolve_for_fn_ptr(def: FnDef, args: &GenericArgs) -> Result { with(|context| { - context.resolve_for_fn_ptr(def, args).ok_or_else(|| { - crate::Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`")) - }) + context + .resolve_for_fn_ptr(def, args) + .ok_or_else(|| Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`"))) }) } @@ -144,11 +145,11 @@ impl Instance { def: ClosureDef, args: &GenericArgs, kind: ClosureKind, - ) -> Result { + ) -> Result { with(|context| { - context.resolve_closure(def, args, kind).ok_or_else(|| { - crate::Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`")) - }) + context + .resolve_closure(def, args, kind) + .ok_or_else(|| Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`"))) }) } @@ -195,7 +196,7 @@ impl Debug for Instance { /// Try to convert a crate item into an instance. /// The item cannot be generic in order to be converted into an instance. impl TryFrom for Instance { - type Error = crate::Error; + type Error = stable_mir::Error; fn try_from(item: CrateItem) -> Result { with(|context| { @@ -212,7 +213,7 @@ impl TryFrom for Instance { /// Try to convert an instance into a crate item. /// Only user defined instances can be converted. impl TryFrom for CrateItem { - type Error = crate::Error; + type Error = stable_mir::Error; fn try_from(value: Instance) -> Result { with(|context| { @@ -259,7 +260,7 @@ crate_def! { } impl TryFrom for StaticDef { - type Error = crate::Error; + type Error = stable_mir::Error; fn try_from(value: CrateItem) -> Result { if matches!(value.kind(), ItemKind::Static) { @@ -271,7 +272,7 @@ impl TryFrom for StaticDef { } impl TryFrom for StaticDef { - type Error = crate::Error; + type Error = stable_mir::Error; fn try_from(value: Instance) -> Result { StaticDef::try_from(CrateItem::try_from(value)?) diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs similarity index 98% rename from compiler/stable_mir/src/mir/pretty.rs rename to compiler/rustc_smir/src/stable_mir/mir/pretty.rs index 65d9f20f0a3b..439ebe978e59 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs @@ -4,13 +4,14 @@ use std::io::Write; use std::{fmt, io, iter}; use fmt::{Display, Formatter}; - -use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind}; -use crate::mir::{ +use stable_mir::mir::{ Operand, Place, RawPtrKind, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents, }; -use crate::ty::{AdtKind, AssocKind, IndexedVal, MirConst, Ty, TyConst}; -use crate::{Body, CrateDef, Mutability, with}; +use stable_mir::ty::{AdtKind, AssocKind, IndexedVal, MirConst, Ty, TyConst}; +use stable_mir::{Body, CrateDef, Mutability, with}; + +use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind}; +use crate::stable_mir; impl Display for Ty { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/rustc_smir/src/stable_mir/mir/visit.rs similarity index 99% rename from compiler/stable_mir/src/mir/visit.rs rename to compiler/rustc_smir/src/stable_mir/mir/visit.rs index 9d2368ba3320..786693ea98d3 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/visit.rs @@ -35,9 +35,11 @@ //! The only place that `_` is acceptable is to match a field (or //! variant argument) that does not require visiting. -use crate::mir::*; -use crate::ty::{GenericArgs, MirConst, Region, Ty, TyConst}; -use crate::{Error, Opaque, Span}; +use stable_mir::mir::*; +use stable_mir::ty::{GenericArgs, MirConst, Region, Ty, TyConst}; +use stable_mir::{Error, Opaque, Span}; + +use crate::stable_mir; macro_rules! make_mir_visitor { ($visitor_trait_name:ident, $($mutability:ident)?) => { diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs new file mode 100644 index 000000000000..c59758d4ad3f --- /dev/null +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -0,0 +1,239 @@ +//! Module that is temporarily parasitic on the `rustc_smir` crate, +//! +//! This module is designed to resolve circular dependency that would happen +//! if we gradually invert the dependency order between `rustc_smir` and `stable_mir`. +//! +//! Once refactoring is complete, we will migrate it back to the `stable_mir` crate. + +//! The WIP stable interface to rustc internals. +//! +//! For more information see +//! +//! # Note +//! +//! This API is still completely unstable and subject to change. + +// #![doc( +// html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", +// test(attr(allow(unused_variables), deny(warnings))) +// )] +//! +//! This crate shall contain all type definitions and APIs that we expect third-party tools to invoke to +//! interact with the compiler. +//! +//! The goal is to eventually be published on +//! [crates.io](https://crates.io). + +use std::fmt::Debug; +use std::{fmt, io}; + +use serde::Serialize; +use stable_mir::compiler_interface::with; +pub use stable_mir::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId}; +pub use stable_mir::error::*; +use stable_mir::mir::mono::StaticDef; +use stable_mir::mir::{Body, Mutability}; +use stable_mir::ty::{AssocItem, FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; + +use crate::stable_mir; + +pub mod abi; +#[macro_use] +pub mod crate_def; +pub mod compiler_interface; +#[macro_use] +pub mod error; +pub mod mir; +pub mod target; +pub mod ty; +pub mod visitor; + +/// Use String for now but we should replace it. +pub type Symbol = String; + +/// The number that identifies a crate. +pub type CrateNum = usize; + +impl Debug for DefId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DefId").field("id", &self.0).field("name", &self.name()).finish() + } +} + +impl IndexedVal for DefId { + fn to_val(index: usize) -> Self { + DefId(index) + } + + fn to_index(&self) -> usize { + self.0 + } +} + +/// A list of crate items. +pub type CrateItems = Vec; + +/// A list of trait decls. +pub type TraitDecls = Vec; + +/// A list of impl trait decls. +pub type ImplTraitDecls = Vec; + +/// A list of associated items. +pub type AssocItems = Vec; + +/// Holds information about a crate. +#[derive(Clone, PartialEq, Eq, Debug, Serialize)] +pub struct Crate { + pub id: CrateNum, + pub name: Symbol, + pub is_local: bool, +} + +impl Crate { + /// The list of foreign modules in this crate. + pub fn foreign_modules(&self) -> Vec { + with(|cx| cx.foreign_modules(self.id)) + } + + /// The list of traits declared in this crate. + pub fn trait_decls(&self) -> TraitDecls { + with(|cx| cx.trait_decls(self.id)) + } + + /// The list of trait implementations in this crate. + pub fn trait_impls(&self) -> ImplTraitDecls { + with(|cx| cx.trait_impls(self.id)) + } + + /// Return a list of function definitions from this crate independent on their visibility. + pub fn fn_defs(&self) -> Vec { + with(|cx| cx.crate_functions(self.id)) + } + + /// Return a list of static items defined in this crate independent on their visibility. + pub fn statics(&self) -> Vec { + with(|cx| cx.crate_statics(self.id)) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] +pub enum ItemKind { + Fn, + Static, + Const, + Ctor(CtorKind), +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] +pub enum CtorKind { + Const, + Fn, +} + +pub type Filename = String; + +crate_def_with_ty! { + /// Holds information about an item in a crate. + #[derive(Serialize)] + pub CrateItem; +} + +impl CrateItem { + /// This will return the body of an item or panic if it's not available. + pub fn expect_body(&self) -> mir::Body { + with(|cx| cx.mir_body(self.0)) + } + + /// Return the body of an item if available. + pub fn body(&self) -> Option { + with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0))) + } + + /// Check if a body is available for this item. + pub fn has_body(&self) -> bool { + with(|cx| cx.has_body(self.0)) + } + + pub fn span(&self) -> Span { + with(|cx| cx.span_of_an_item(self.0)) + } + + pub fn kind(&self) -> ItemKind { + with(|cx| cx.item_kind(*self)) + } + + pub fn requires_monomorphization(&self) -> bool { + with(|cx| cx.requires_monomorphization(self.0)) + } + + pub fn ty(&self) -> Ty { + with(|cx| cx.def_ty(self.0)) + } + + pub fn is_foreign_item(&self) -> bool { + with(|cx| cx.is_foreign_item(self.0)) + } + + /// Emit MIR for this item body. + pub fn emit_mir(&self, w: &mut W) -> io::Result<()> { + self.body() + .ok_or_else(|| io::Error::other(format!("No body found for `{}`", self.name())))? + .dump(w, &self.name()) + } +} + +/// Return the function where execution starts if the current +/// crate defines that. This is usually `main`, but could be +/// `start` if the crate is a no-std crate. +pub fn entry_fn() -> Option { + with(|cx| cx.entry_fn()) +} + +/// Access to the local crate. +pub fn local_crate() -> Crate { + with(|cx| cx.local_crate()) +} + +/// Try to find a crate or crates if multiple crates exist from given name. +pub fn find_crates(name: &str) -> Vec { + with(|cx| cx.find_crates(name)) +} + +/// Try to find a crate with the given name. +pub fn external_crates() -> Vec { + with(|cx| cx.external_crates()) +} + +/// Retrieve all items in the local crate that have a MIR associated with them. +pub fn all_local_items() -> CrateItems { + with(|cx| cx.all_local_items()) +} + +pub fn all_trait_decls() -> TraitDecls { + with(|cx| cx.all_trait_decls()) +} + +pub fn all_trait_impls() -> ImplTraitDecls { + with(|cx| cx.all_trait_impls()) +} + +/// A type that provides internal information but that can still be used for debug purpose. +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub struct Opaque(String); + +impl std::fmt::Display for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl std::fmt::Debug for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +pub fn opaque(value: &T) -> Opaque { + Opaque(format!("{value:?}")) +} diff --git a/compiler/stable_mir/src/target.rs b/compiler/rustc_smir/src/stable_mir/target.rs similarity index 95% rename from compiler/stable_mir/src/target.rs rename to compiler/rustc_smir/src/stable_mir/target.rs index 32c3a2a9122e..6cf1e9feb015 100644 --- a/compiler/stable_mir/src/target.rs +++ b/compiler/rustc_smir/src/stable_mir/target.rs @@ -1,8 +1,9 @@ //! Provide information about the machine that this is being compiled into. use serde::Serialize; +use stable_mir::compiler_interface::with; -use crate::compiler_interface::with; +use crate::stable_mir; /// The properties of the target machine being compiled into. #[derive(Clone, PartialEq, Eq, Serialize)] diff --git a/compiler/stable_mir/src/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs similarity index 98% rename from compiler/stable_mir/src/ty.rs rename to compiler/rustc_smir/src/stable_mir/ty.rs index 25ec4a440d6e..1efa2fe13c56 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -2,15 +2,16 @@ use std::fmt::{self, Debug, Display, Formatter}; use std::ops::Range; use serde::Serialize; +use stable_mir::abi::{FnAbi, Layout}; +use stable_mir::crate_def::{CrateDef, CrateDefItems, CrateDefType}; +use stable_mir::mir::alloc::{AllocId, read_target_int, read_target_uint}; +use stable_mir::mir::mono::StaticDef; +use stable_mir::target::MachineInfo; +use stable_mir::{Filename, Opaque}; use super::mir::{Body, Mutability, Safety}; use super::{DefId, Error, Symbol, with}; -use crate::abi::{FnAbi, Layout}; -use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType}; -use crate::mir::alloc::{AllocId, read_target_int, read_target_uint}; -use crate::mir::mono::StaticDef; -use crate::target::MachineInfo; -use crate::{Filename, Opaque}; +use crate::stable_mir; #[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)] pub struct Ty(usize); @@ -588,7 +589,7 @@ pub enum IntTy { impl IntTy { pub fn num_bytes(self) -> usize { match self { - IntTy::Isize => crate::target::MachineInfo::target_pointer_width().bytes(), + IntTy::Isize => MachineInfo::target_pointer_width().bytes(), IntTy::I8 => 1, IntTy::I16 => 2, IntTy::I32 => 4, @@ -611,7 +612,7 @@ pub enum UintTy { impl UintTy { pub fn num_bytes(self) -> usize { match self { - UintTy::Usize => crate::target::MachineInfo::target_pointer_width().bytes(), + UintTy::Usize => MachineInfo::target_pointer_width().bytes(), UintTy::U8 => 1, UintTy::U16 => 2, UintTy::U32 => 4, diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/rustc_smir/src/stable_mir/visitor.rs similarity index 95% rename from compiler/stable_mir/src/visitor.rs rename to compiler/rustc_smir/src/stable_mir/visitor.rs index 8463174f9a46..31a53d1b19d9 100644 --- a/compiler/stable_mir/src/visitor.rs +++ b/compiler/rustc_smir/src/stable_mir/visitor.rs @@ -1,11 +1,13 @@ use std::ops::ControlFlow; +use stable_mir::Opaque; +use stable_mir::ty::TyConst; + use super::ty::{ Allocation, Binder, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, MirConst, Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, }; -use crate::Opaque; -use crate::ty::TyConst; +use crate::stable_mir; pub trait Visitor: Sized { type Break; @@ -47,13 +49,13 @@ impl Visitable for TyConst { } fn super_visit(&self, visitor: &mut V) -> ControlFlow { match &self.kind { - crate::ty::TyConstKind::Param(_) | crate::ty::TyConstKind::Bound(_, _) => {} - crate::ty::TyConstKind::Unevaluated(_, args) => args.visit(visitor)?, - crate::ty::TyConstKind::Value(ty, alloc) => { + super::ty::TyConstKind::Param(_) | super::ty::TyConstKind::Bound(_, _) => {} + super::ty::TyConstKind::Unevaluated(_, args) => args.visit(visitor)?, + super::ty::TyConstKind::Value(ty, alloc) => { alloc.visit(visitor)?; ty.visit(visitor)?; } - crate::ty::TyConstKind::ZSTValue(ty) => ty.visit(visitor)?, + super::ty::TyConstKind::ZSTValue(ty) => ty.visit(visitor)?, } ControlFlow::Continue(()) } diff --git a/compiler/stable_mir/Cargo.toml b/compiler/stable_mir/Cargo.toml index d691a0e4f22f..3a01ee5783ee 100644 --- a/compiler/stable_mir/Cargo.toml +++ b/compiler/stable_mir/Cargo.toml @@ -4,5 +4,4 @@ version = "0.1.0-preview" edition = "2024" [dependencies] -scoped-tls = "1.0" -serde = { version = "1.0.125", features = [ "derive" ] } +rustc_smir = { path = "../rustc_smir" } diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index df90d3e5a084..cc0fb52433d9 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -1,231 +1,7 @@ -//! The WIP stable interface to rustc internals. +//! We've temporarily moved the `stable_mir` implementation to [`rustc_smir::stable_mir`], +//! during refactoring to break the circular dependency between `rustc_smir` and `stable_mir`, //! -//! For more information see -//! -//! # Note -//! -//! This API is still completely unstable and subject to change. +//! This is a transitional measure as described in [PR #139319](https://github.com/rust-lang/rust/pull/139319). +//! Once the refactoring is complete, the `stable_mir` implementation will be moved back here. -#![doc( - html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", - test(attr(allow(unused_variables), deny(warnings))) -)] -//! -//! This crate shall contain all type definitions and APIs that we expect third-party tools to invoke to -//! interact with the compiler. -//! -//! The goal is to eventually be published on -//! [crates.io](https://crates.io). - -use std::fmt::Debug; -use std::{fmt, io}; - -use serde::Serialize; - -use crate::compiler_interface::with; -pub use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId}; -pub use crate::error::*; -use crate::mir::mono::StaticDef; -use crate::mir::{Body, Mutability}; -use crate::ty::{AssocItem, FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; - -pub mod abi; -#[macro_use] -pub mod crate_def; -pub mod compiler_interface; -#[macro_use] -pub mod error; -pub mod mir; -pub mod target; -pub mod ty; -pub mod visitor; - -/// Use String for now but we should replace it. -pub type Symbol = String; - -/// The number that identifies a crate. -pub type CrateNum = usize; - -impl Debug for DefId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("DefId").field("id", &self.0).field("name", &self.name()).finish() - } -} - -impl IndexedVal for DefId { - fn to_val(index: usize) -> Self { - DefId(index) - } - - fn to_index(&self) -> usize { - self.0 - } -} - -/// A list of crate items. -pub type CrateItems = Vec; - -/// A list of trait decls. -pub type TraitDecls = Vec; - -/// A list of impl trait decls. -pub type ImplTraitDecls = Vec; - -/// A list of associated items. -pub type AssocItems = Vec; - -/// Holds information about a crate. -#[derive(Clone, PartialEq, Eq, Debug, Serialize)] -pub struct Crate { - pub id: CrateNum, - pub name: Symbol, - pub is_local: bool, -} - -impl Crate { - /// The list of foreign modules in this crate. - pub fn foreign_modules(&self) -> Vec { - with(|cx| cx.foreign_modules(self.id)) - } - - /// The list of traits declared in this crate. - pub fn trait_decls(&self) -> TraitDecls { - with(|cx| cx.trait_decls(self.id)) - } - - /// The list of trait implementations in this crate. - pub fn trait_impls(&self) -> ImplTraitDecls { - with(|cx| cx.trait_impls(self.id)) - } - - /// Return a list of function definitions from this crate independent on their visibility. - pub fn fn_defs(&self) -> Vec { - with(|cx| cx.crate_functions(self.id)) - } - - /// Return a list of static items defined in this crate independent on their visibility. - pub fn statics(&self) -> Vec { - with(|cx| cx.crate_statics(self.id)) - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] -pub enum ItemKind { - Fn, - Static, - Const, - Ctor(CtorKind), -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] -pub enum CtorKind { - Const, - Fn, -} - -pub type Filename = String; - -crate_def_with_ty! { - /// Holds information about an item in a crate. - #[derive(Serialize)] - pub CrateItem; -} - -impl CrateItem { - /// This will return the body of an item or panic if it's not available. - pub fn expect_body(&self) -> mir::Body { - with(|cx| cx.mir_body(self.0)) - } - - /// Return the body of an item if available. - pub fn body(&self) -> Option { - with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0))) - } - - /// Check if a body is available for this item. - pub fn has_body(&self) -> bool { - with(|cx| cx.has_body(self.0)) - } - - pub fn span(&self) -> Span { - with(|cx| cx.span_of_an_item(self.0)) - } - - pub fn kind(&self) -> ItemKind { - with(|cx| cx.item_kind(*self)) - } - - pub fn requires_monomorphization(&self) -> bool { - with(|cx| cx.requires_monomorphization(self.0)) - } - - pub fn ty(&self) -> Ty { - with(|cx| cx.def_ty(self.0)) - } - - pub fn is_foreign_item(&self) -> bool { - with(|cx| cx.is_foreign_item(self.0)) - } - - /// Emit MIR for this item body. - pub fn emit_mir(&self, w: &mut W) -> io::Result<()> { - self.body() - .ok_or_else(|| io::Error::other(format!("No body found for `{}`", self.name())))? - .dump(w, &self.name()) - } -} - -/// Return the function where execution starts if the current -/// crate defines that. This is usually `main`, but could be -/// `start` if the crate is a no-std crate. -pub fn entry_fn() -> Option { - with(|cx| cx.entry_fn()) -} - -/// Access to the local crate. -pub fn local_crate() -> Crate { - with(|cx| cx.local_crate()) -} - -/// Try to find a crate or crates if multiple crates exist from given name. -pub fn find_crates(name: &str) -> Vec { - with(|cx| cx.find_crates(name)) -} - -/// Try to find a crate with the given name. -pub fn external_crates() -> Vec { - with(|cx| cx.external_crates()) -} - -/// Retrieve all items in the local crate that have a MIR associated with them. -pub fn all_local_items() -> CrateItems { - with(|cx| cx.all_local_items()) -} - -pub fn all_trait_decls() -> TraitDecls { - with(|cx| cx.all_trait_decls()) -} - -pub fn all_trait_impls() -> ImplTraitDecls { - with(|cx| cx.all_trait_impls()) -} - -/// A type that provides internal information but that can still be used for debug purpose. -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub struct Opaque(String); - -impl std::fmt::Display for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl std::fmt::Debug for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -pub fn opaque(value: &T) -> Opaque { - Opaque(format!("{value:?}")) -} +pub use rustc_smir::stable_mir::*; From 5b596cd28b9ca38f8541aff1b05ec26c6207797b Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 5 Apr 2025 13:58:34 +0000 Subject: [PATCH 167/176] In `simplify_repeated_aggregate`, don't test first element against itself --- compiler/rustc_mir_transform/src/instsimplify.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index da346dfc48c1..2eff6b31372f 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -78,20 +78,20 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { /// GVN can also do this optimization, but GVN is only run at mir-opt-level 2 so having this in /// InstSimplify helps unoptimized builds. fn simplify_repeated_aggregate(&self, rvalue: &mut Rvalue<'tcx>) { - let Rvalue::Aggregate(box AggregateKind::Array(_), fields) = rvalue else { + let Rvalue::Aggregate(box AggregateKind::Array(_), fields) = &*rvalue else { return; }; if fields.len() < 5 { return; } - let first = &fields[rustc_abi::FieldIdx::ZERO]; + let (first, rest) = fields[..].split_first().unwrap(); let Operand::Constant(first) = first else { return; }; let Ok(first_val) = first.const_.eval(self.tcx, self.typing_env, first.span) else { return; }; - if fields.iter().all(|field| { + if rest.iter().all(|field| { let Operand::Constant(field) = field else { return false; }; From 66a273083c5cb833ad9341cd9f0690caf89e5bb1 Mon Sep 17 00:00:00 2001 From: Adam Kobzan Date: Sat, 5 Apr 2025 08:40:21 -0700 Subject: [PATCH 168/176] Fix Typo --- compiler/rustc_middle/src/ty/generic_args.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index e87859a55edd..439a2f3e1616 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -396,12 +396,12 @@ impl<'tcx> GenericArgs<'tcx> { InlineConstArgs { args: self } } - /// Creates an `GenericArgs` that maps each generic parameter to itself. + /// Creates a `GenericArgs` that maps each generic parameter to itself. pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into) -> GenericArgsRef<'tcx> { Self::for_item(tcx, def_id.into(), |param, _| tcx.mk_param_from_def(param)) } - /// Creates an `GenericArgs` for generic parameter definitions, + /// Creates a `GenericArgs` for generic parameter definitions, /// by calling closures to obtain each kind. /// The closures get to observe the `GenericArgs` as they're /// being built, which can be used to correctly From e31d1d51e4fca3642bd2fcd474ccffcc6b36bb00 Mon Sep 17 00:00:00 2001 From: Adam Kobzan Date: Sat, 5 Apr 2025 09:09:28 -0700 Subject: [PATCH 169/176] format --- compiler/rustc_middle/src/ty/generic_args.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 439a2f3e1616..9c1ff134f0fd 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -396,14 +396,14 @@ impl<'tcx> GenericArgs<'tcx> { InlineConstArgs { args: self } } - /// Creates a `GenericArgs` that maps each generic parameter to itself. + /// Creates a [`GenericArgs`] that maps each generic parameter to itself. pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into) -> GenericArgsRef<'tcx> { Self::for_item(tcx, def_id.into(), |param, _| tcx.mk_param_from_def(param)) } - /// Creates a `GenericArgs` for generic parameter definitions, + /// Creates a [`GenericArgs`] for generic parameter definitions, /// by calling closures to obtain each kind. - /// The closures get to observe the `GenericArgs` as they're + /// The closures get to observe the [`GenericArgs`] as they're /// being built, which can be used to correctly /// replace defaults of generic parameters. pub fn for_item(tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> GenericArgsRef<'tcx> From 89d0e7c03391efda88f4736f3f04f4c5a8ae71d3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 5 Apr 2025 16:16:50 +0000 Subject: [PATCH 170/176] Fix ProvenVia for global where clauses --- .../rustc_next_trait_solver/src/solve/trait_goals.rs | 12 ++++++++++-- tests/ui/codegen/mono-impossible-drop.rs | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index c46169a26c1c..d42c9980f463 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1301,7 +1301,6 @@ where .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_))) .map(|c| c.result) .collect(); - return if let Some(response) = self.try_merge_responses(&where_bounds) { Ok((response, Some(TraitGoalProvenVia::ParamEnv))) } else { @@ -1322,9 +1321,18 @@ where }; } + // If there are *only* global where bounds, then make sure to return that this + // is still reported as being proven-via the param-env so that rigid projections + // operate correctly. + let proven_via = + if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) { + TraitGoalProvenVia::ParamEnv + } else { + TraitGoalProvenVia::Misc + }; let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect(); if let Some(response) = self.try_merge_responses(&all_candidates) { - Ok((response, Some(TraitGoalProvenVia::Misc))) + Ok((response, Some(proven_via))) } else { self.flounder(&all_candidates).map(|r| (r, None)) } diff --git a/tests/ui/codegen/mono-impossible-drop.rs b/tests/ui/codegen/mono-impossible-drop.rs index dec013cfe54b..c8a9554da436 100644 --- a/tests/ui/codegen/mono-impossible-drop.rs +++ b/tests/ui/codegen/mono-impossible-drop.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ compile-flags: -Clink-dead-code=on --crate-type=lib //@ build-pass From 579753294041fe1a6085acb2a1b924d73c0c8ec8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 5 Apr 2025 20:06:52 +0200 Subject: [PATCH 171/176] Clean up `rustc-literal-escaper` usage in rust-analyzer --- src/tools/rust-analyzer/Cargo.lock | 1 - src/tools/rust-analyzer/Cargo.toml | 1 + src/tools/rust-analyzer/crates/parser/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/syntax/Cargo.toml | 4 +--- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index be6391152665..745a8097c8a5 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1985,7 +1985,6 @@ dependencies = [ "indexmap", "itertools", "parser", - "ra-ap-rustc_lexer", "rayon", "rowan", "rustc-hash 2.0.0", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index ce2d66000e39..e22191397655 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -136,6 +136,7 @@ pulldown-cmark-to-cmark = "10.0.4" pulldown-cmark = { version = "0.9.0", default-features = false } rayon = "1.8.0" rustc-hash = "2.0.0" +rustc-literal-escaper = "0.0.2" semver = "1.0.14" serde = { version = "1.0.192" } serde_derive = { version = "1.0.192" } diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml index 40c1e9fa7bdd..114a66add63b 100644 --- a/src/tools/rust-analyzer/crates/parser/Cargo.toml +++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml @@ -14,7 +14,7 @@ rust-version.workspace = true [dependencies] drop_bomb = "0.1.5" ra-ap-rustc_lexer.workspace = true -rustc-literal-escaper = "0.0.2" +rustc-literal-escaper.workspace = true tracing = { workspace = true, optional = true } edition.workspace = true diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 23e1917922b7..6b356398204e 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -17,14 +17,12 @@ either.workspace = true itertools.workspace = true rowan = "=0.15.15" rustc-hash.workspace = true -rustc-literal-escaper = "0.0.2" +rustc-literal-escaper.workspace = true indexmap.workspace = true smol_str.workspace = true triomphe.workspace = true tracing.workspace = true -ra-ap-rustc_lexer.workspace = true - parser.workspace = true stdx.workspace = true From 12167d7064597993355e41d3a8c20654bccaf0be Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 2 Apr 2025 12:08:01 -0700 Subject: [PATCH 172/176] Update the minimum external LLVM to 19 --- compiler/rustc_codegen_llvm/src/abi.rs | 17 +- compiler/rustc_codegen_llvm/src/attributes.rs | 50 ++- compiler/rustc_codegen_llvm/src/builder.rs | 30 +- compiler/rustc_codegen_llvm/src/context.rs | 23 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 17 +- .../llvm-wrapper/CoverageMappingWrapper.cpp | 4 - .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 58 +--- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 81 ----- src/bootstrap/src/core/build_steps/llvm.rs | 6 +- src/ci/docker/README.md | 8 +- .../host-x86_64/x86_64-gnu-llvm-18/Dockerfile | 69 ---- .../host-x86_64/x86_64-gnu-llvm-19/Dockerfile | 1 + src/ci/github-actions/jobs.yml | 30 +- tests/assembly/aarch64-pointer-auth.rs | 1 - tests/assembly/static-relocation-model.rs | 2 +- tests/codegen/branch-protection-old-llvm.rs | 46 --- tests/codegen/branch-protection.rs | 1 - tests/codegen/call-metadata.rs | 18 -- tests/codegen/cast-target-abi.rs | 1 - tests/codegen/cffi/ffi-const.rs | 3 +- tests/codegen/cffi/ffi-out-of-bounds-loads.rs | 1 - tests/codegen/cffi/ffi-pure.rs | 3 +- .../mir_inlined_twice_var_locs.rs | 1 - tests/codegen/dont-shuffle-bswaps.rs | 1 - tests/codegen/enum/enum-two-variants-match.rs | 1 - tests/codegen/intrinsics/carrying_mul_add.rs | 1 - tests/codegen/intrinsics/transmute.rs | 11 +- .../issues/issue-107681-unwrap_unchecked.rs | 1 - tests/codegen/issues/issue-118306.rs | 1 - .../issue-122600-ptr-discriminant-update.rs | 1 - tests/codegen/issues/issue-126585.rs | 1 - tests/codegen/range-attribute.rs | 1 - tests/codegen/tied-features-strength.rs | 12 +- tests/codegen/try_question_mark_nop.rs | 2 - tests/codegen/unchecked_shifts.rs | 15 +- tests/codegen/vec_pop_push_noop.rs | 3 - tests/coverage/mcdc/condition-limit.cov-map | 4 +- tests/coverage/mcdc/condition-limit.coverage | 1 - tests/coverage/mcdc/condition-limit.rs | 1 - tests/coverage/mcdc/if.cov-map | 28 +- tests/coverage/mcdc/if.coverage | 1 - tests/coverage/mcdc/if.rs | 1 - .../coverage/mcdc/inlined_expressions.cov-map | 4 +- .../mcdc/inlined_expressions.coverage | 1 - tests/coverage/mcdc/inlined_expressions.rs | 1 - tests/coverage/mcdc/nested_if.cov-map | 16 +- tests/coverage/mcdc/nested_if.coverage | 1 - tests/coverage/mcdc/nested_if.rs | 1 - tests/coverage/mcdc/non_control_flow.cov-map | 28 +- tests/coverage/mcdc/non_control_flow.coverage | 1 - tests/coverage/mcdc/non_control_flow.rs | 1 - tests/ui/abi/large-byval-align.rs | 1 - tests/ui/asm/aarch64/srcloc.old.stderr | 290 ----------------- tests/ui/asm/aarch64/srcloc.rs | 3 - .../{srcloc.new.stderr => srcloc.stderr} | 48 +-- tests/ui/asm/inline-syntax.arm.stderr | 12 +- tests/ui/asm/inline-syntax.arm_llvm_18.stderr | 90 ------ tests/ui/asm/inline-syntax.rs | 15 +- tests/ui/asm/inline-syntax.x86_64.stderr | 14 +- .../riscv/riscv32e-registers.riscv32e.stderr | 32 +- ...riscv32e-registers.riscv32e_llvm_18.stderr | 194 ----------- .../riscv/riscv32e-registers.riscv32em.stderr | 32 +- ...iscv32e-registers.riscv32em_llvm_18.stderr | 194 ----------- .../riscv32e-registers.riscv32emc.stderr | 32 +- ...scv32e-registers.riscv32emc_llvm_18.stderr | 194 ----------- tests/ui/asm/riscv/riscv32e-registers.rs | 14 +- tests/ui/asm/x86_64/srcloc.old.stderr | 302 ------------------ tests/ui/asm/x86_64/srcloc.rs | 3 - .../{srcloc.new.stderr => srcloc.stderr} | 50 +-- .../mcdc-condition-limit.rs | 1 - 70 files changed, 222 insertions(+), 1911 deletions(-) delete mode 100644 src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile delete mode 100644 tests/codegen/branch-protection-old-llvm.rs delete mode 100644 tests/codegen/call-metadata.rs delete mode 100644 tests/ui/asm/aarch64/srcloc.old.stderr rename tests/ui/asm/aarch64/{srcloc.new.stderr => srcloc.stderr} (91%) delete mode 100644 tests/ui/asm/inline-syntax.arm_llvm_18.stderr delete mode 100644 tests/ui/asm/riscv/riscv32e-registers.riscv32e_llvm_18.stderr delete mode 100644 tests/ui/asm/riscv/riscv32e-registers.riscv32em_llvm_18.stderr delete mode 100644 tests/ui/asm/riscv/riscv32e-registers.riscv32emc_llvm_18.stderr delete mode 100644 tests/ui/asm/x86_64/srcloc.old.stderr rename tests/ui/asm/x86_64/{srcloc.new.stderr => srcloc.stderr} (92%) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 710593381513..8294e29d07df 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -17,14 +17,13 @@ use rustc_target::callconv::{ use rustc_target::spec::SanitizerSet; use smallvec::SmallVec; -use crate::attributes::llfn_attrs_from_instance; +use crate::attributes::{self, llfn_attrs_from_instance}; use crate::builder::Builder; use crate::context::CodegenCx; use crate::llvm::{self, Attribute, AttributePlace}; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; -use crate::{attributes, llvm_util}; trait ArgAttributesExt { fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value); @@ -437,7 +436,6 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { let apply_range_attr = |idx: AttributePlace, scalar: rustc_abi::Scalar| { if cx.sess().opts.optimize != config::OptLevel::No - && llvm_util::get_version() >= (19, 0, 0) && matches!(scalar.primitive(), Primitive::Int(..)) // If the value is a boolean, the range is 0..2 and that ultimately // become 0..0 when the type becomes i1, which would be rejected @@ -571,19 +569,6 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } _ => {} } - if bx.cx.sess().opts.optimize != config::OptLevel::No - && llvm_util::get_version() < (19, 0, 0) - && let BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr - && matches!(scalar.primitive(), Primitive::Int(..)) - // If the value is a boolean, the range is 0..2 and that ultimately - // become 0..0 when the type becomes i1, which would be rejected - // by the LLVM verifier. - && !scalar.is_bool() - // LLVM also rejects full range. - && !scalar.is_always_valid(bx) - { - bx.range_metadata(callsite, scalar.valid_range(bx)); - } for arg in self.args.iter() { match &arg.mode { PassMode::Ignore => {} diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 3d7afa17bdf3..e8c42d16733e 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -407,30 +407,28 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( // Do not set sanitizer attributes for naked functions. to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize)); - if llvm_util::get_version() >= (19, 0, 0) { - // For non-naked functions, set branch protection attributes on aarch64. - if let Some(BranchProtection { bti, pac_ret }) = - cx.sess().opts.unstable_opts.branch_protection - { - assert!(cx.sess().target.arch == "aarch64"); - if bti { - to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement")); - } - if let Some(PacRet { leaf, pc, key }) = pac_ret { - if pc { - to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr")); - } - to_add.push(llvm::CreateAttrStringValue( - cx.llcx, - "sign-return-address", - if leaf { "all" } else { "non-leaf" }, - )); - to_add.push(llvm::CreateAttrStringValue( - cx.llcx, - "sign-return-address-key", - if key == PAuthKey::A { "a_key" } else { "b_key" }, - )); + // For non-naked functions, set branch protection attributes on aarch64. + if let Some(BranchProtection { bti, pac_ret }) = + cx.sess().opts.unstable_opts.branch_protection + { + assert!(cx.sess().target.arch == "aarch64"); + if bti { + to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement")); + } + if let Some(PacRet { leaf, pc, key }) = pac_ret { + if pc { + to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr")); } + to_add.push(llvm::CreateAttrStringValue( + cx.llcx, + "sign-return-address", + if leaf { "all" } else { "non-leaf" }, + )); + to_add.push(llvm::CreateAttrStringValue( + cx.llcx, + "sign-return-address-key", + if key == PAuthKey::A { "a_key" } else { "b_key" }, + )); } } } @@ -510,12 +508,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(), InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(), })) - // HACK: LLVM versions 19+ do not have the FPMR feature and treat it as always enabled - // It only exists as a feature in LLVM 18, cannot be passed down for any other version - .chain(match &*cx.tcx.sess.target.arch { - "aarch64" if llvm_util::get_version().0 == 18 => vec!["+fpmr".to_string()], - _ => vec![], - }) .collect::>(); if cx.tcx.sess.target.is_like_wasm { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 297f104d124a..35134e9f5a05 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -30,6 +30,7 @@ use smallvec::SmallVec; use tracing::{debug, instrument}; use crate::abi::FnAbiLlvmExt; +use crate::attributes; use crate::common::Funclet; use crate::context::{CodegenCx, FullCx, GenericCx, SCx}; use crate::llvm::{ @@ -38,7 +39,6 @@ use crate::llvm::{ use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; -use crate::{attributes, llvm_util}; #[must_use] pub(crate) struct GenericBuilder<'a, 'll, CX: Borrow>> { @@ -927,11 +927,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { debug_assert_ne!(self.val_ty(val), dest_ty); let trunc = self.trunc(val, dest_ty); - if llvm_util::get_version() >= (19, 0, 0) { - unsafe { - if llvm::LLVMIsAInstruction(trunc).is_some() { - llvm::LLVMSetNUW(trunc, True); - } + unsafe { + if llvm::LLVMIsAInstruction(trunc).is_some() { + llvm::LLVMSetNUW(trunc, True); } } trunc @@ -941,11 +939,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { debug_assert_ne!(self.val_ty(val), dest_ty); let trunc = self.trunc(val, dest_ty); - if llvm_util::get_version() >= (19, 0, 0) { - unsafe { - if llvm::LLVMIsAInstruction(trunc).is_some() { - llvm::LLVMSetNSW(trunc, True); - } + unsafe { + if llvm::LLVMIsAInstruction(trunc).is_some() { + llvm::LLVMSetNSW(trunc, True); } } trunc @@ -1899,10 +1895,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { hash: &'ll Value, bitmap_bits: &'ll Value, ) { - assert!( - crate::llvm_util::get_version() >= (19, 0, 0), - "MCDC intrinsics require LLVM 19 or later" - ); self.call_intrinsic("llvm.instrprof.mcdc.parameters", &[fn_name, hash, bitmap_bits]); } @@ -1914,10 +1906,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { bitmap_index: &'ll Value, mcdc_temp: &'ll Value, ) { - assert!( - crate::llvm_util::get_version() >= (19, 0, 0), - "MCDC intrinsics require LLVM 19 or later" - ); let args = &[fn_name, hash, bitmap_index, mcdc_temp]; self.call_intrinsic("llvm.instrprof.mcdc.tvbitmap.update", args); } @@ -1929,10 +1917,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn mcdc_condbitmap_update(&mut self, cond_index: &'ll Value, mcdc_temp: &'ll Value) { - assert!( - crate::llvm_util::get_version() >= (19, 0, 0), - "MCDC intrinsics require LLVM 19 or later" - ); let align = self.tcx.data_layout.i32_align.abi; let current_tv_index = self.load(self.cx.type_i32(), mcdc_temp, align); let new_tv_index = self.add(current_tv_index, cond_index); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1e8861116e22..4ec699955189 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -164,23 +164,6 @@ pub(crate) unsafe fn create_module<'ll>( let mut target_data_layout = sess.target.data_layout.to_string(); let llvm_version = llvm_util::get_version(); - if llvm_version < (19, 0, 0) { - if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") { - // LLVM 19 sets -Fn32 in its data layout string for 64-bit ARM - // Earlier LLVMs leave this default, so remove it. - // See https://github.com/llvm/llvm-project/pull/90702 - target_data_layout = target_data_layout.replace("-Fn32", ""); - } - } - - if llvm_version < (19, 0, 0) { - if sess.target.arch == "loongarch64" { - // LLVM 19 updates the LoongArch64 data layout. - // See https://github.com/llvm/llvm-project/pull/93814 - target_data_layout = target_data_layout.replace("-n32:64", "-n64"); - } - } - if llvm_version < (20, 0, 0) { if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") { // LLVM 20 defines three additional address spaces for alternate @@ -1218,10 +1201,8 @@ impl<'ll> CodegenCx<'ll, '_> { if self.sess().instrument_coverage() { ifn!("llvm.instrprof.increment", fn(ptr, t_i64, t_i32, t_i32) -> void); - if crate::llvm_util::get_version() >= (19, 0, 0) { - ifn!("llvm.instrprof.mcdc.parameters", fn(ptr, t_i64, t_i32) -> void); - ifn!("llvm.instrprof.mcdc.tvbitmap.update", fn(ptr, t_i64, t_i32, ptr) -> void); - } + ifn!("llvm.instrprof.mcdc.parameters", fn(ptr, t_i64, t_i32) -> void); + ifn!("llvm.instrprof.mcdc.tvbitmap.update", fn(ptr, t_i64, t_i32, ptr) -> void); } ifn!("llvm.type.test", fn(ptr, t_metadata) -> i1); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 4e85286ed55c..36e35f81392b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -256,7 +256,6 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::new("perfmon")), ("aarch64", "paca") => Some(LLVMFeature::new("pauth")), ("aarch64", "pacg") => Some(LLVMFeature::new("pauth")), - ("aarch64", "pauth-lr") if get_version().0 < 19 => None, // Before LLVM 20 those two features were packaged together as b16b16 ("aarch64", "sve-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")), ("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")), @@ -270,20 +269,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::new("fp16fml")), ("aarch64", "fp16") => Some(LLVMFeature::new("fullfp16")), // Filter out features that are not supported by the current LLVM version - ("aarch64", "fpmr") if get_version().0 != 18 => None, + ("aarch64", "fpmr") => None, // only existed in 18 ("arm", "fp16") => Some(LLVMFeature::new("fullfp16")), - // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single - // feature called `fast-unaligned-access`. In LLVM 19, it was split back out. - ("riscv32" | "riscv64", "unaligned-scalar-mem" | "unaligned-vector-mem") - if get_version().0 == 18 => - { - Some(LLVMFeature::new("fast-unaligned-access")) - } // Filter out features that are not supported by the current LLVM version - ("riscv32" | "riscv64", "zaamo") if get_version().0 < 19 => None, - ("riscv32" | "riscv64", "zabha") if get_version().0 < 19 => None, - ("riscv32" | "riscv64", "zalrsc") if get_version().0 < 19 => None, - ("riscv32" | "riscv64", "zama16b") if get_version().0 < 19 => None, ("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None, // Enable the evex512 target feature if an avx512 target feature is enabled. ("x86", s) if s.starts_with("avx512") => { @@ -295,10 +283,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::new("hasleoncasa")), // In LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available and SPARC-V8+ ABI used". // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L27-L28 - // Before LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available". + // Before LLVM 19, there was no `v8plus` feature and `v9` means "SPARC-V9 instruction available". // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L26 ("sparc", "v8plus") if get_version().0 == 19 => Some(LLVMFeature::new("v9")), - ("sparc", "v8plus") if get_version().0 < 19 => None, ("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")), // These new `amx` variants and `movrs` were introduced in LLVM20 ("x86", "amx-avx512" | "amx-fp8" | "amx-movrs" | "amx-tf32" | "amx-transpose") diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index b8884486c333..4695de8ea09a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -47,7 +47,6 @@ struct LLVMRustMCDCBranchParameters { int16_t ConditionIDs[2]; }; -#if LLVM_VERSION_GE(19, 0) static coverage::mcdc::BranchParameters fromRust(LLVMRustMCDCBranchParameters Params) { return coverage::mcdc::BranchParameters( @@ -59,7 +58,6 @@ fromRust(LLVMRustMCDCDecisionParameters Params) { return coverage::mcdc::DecisionParameters(Params.BitmapIdx, Params.NumConditions); } -#endif // Must match the layout of // `rustc_codegen_llvm::coverageinfo::ffi::CoverageSpan`. @@ -203,7 +201,6 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer( Region.Span.LineEnd, Region.Span.ColumnEnd)); } -#if LLVM_VERSION_GE(19, 0) // MC/DC branch regions: for (const auto &Region : ArrayRef(MCDCBranchRegions, NumMCDCBranchRegions)) { MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion( @@ -221,7 +218,6 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer( Region.Span.LineStart, Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd)); } -#endif // Write the converted expressions and mappings to a byte buffer. auto CoverageMappingWriter = coverage::CoverageMappingWriter( diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 257bdc01993f..e02c80c50b14 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -47,10 +47,7 @@ #include // Conditional includes prevent clang-format from fully sorting the list, -// so keep them separate. -#if LLVM_VERSION_GE(19, 0) -#include "llvm/Support/PGOOptions.h" -#endif +// so if any are needed, keep them separate down here. using namespace llvm; @@ -432,31 +429,15 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( } if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) { -#if LLVM_VERSION_GE(19, 0) Options.MCOptions.CompressDebugSections = DebugCompressionType::Zlib; -#else - Options.CompressDebugSections = DebugCompressionType::Zlib; -#endif } else if (!strcmp("zstd", DebugInfoCompression) && llvm::compression::zstd::isAvailable()) { -#if LLVM_VERSION_GE(19, 0) Options.MCOptions.CompressDebugSections = DebugCompressionType::Zstd; -#else - Options.CompressDebugSections = DebugCompressionType::Zstd; -#endif } else if (!strcmp("none", DebugInfoCompression)) { -#if LLVM_VERSION_GE(19, 0) Options.MCOptions.CompressDebugSections = DebugCompressionType::None; -#else - Options.CompressDebugSections = DebugCompressionType::None; -#endif } -#if LLVM_VERSION_GE(19, 0) Options.MCOptions.X86RelaxRelocations = RelaxELFRelocations; -#else - Options.RelaxELFRelocations = RelaxELFRelocations; -#endif Options.UseInitArray = UseInitArray; Options.EmulatedTLS = UseEmulatedTls; @@ -753,34 +734,23 @@ extern "C" LLVMRustResult LLVMRustOptimize( auto FS = vfs::getRealFileSystem(); if (PGOGenPath) { assert(!PGOUsePath && !PGOSampleUsePath); - PGOOpt = PGOOptions(PGOGenPath, "", "", "", FS, PGOOptions::IRInstr, - PGOOptions::NoCSAction, -#if LLVM_VERSION_GE(19, 0) - PGOOptions::ColdFuncOpt::Default, -#endif - DebugInfoForProfiling); + PGOOpt = PGOOptions( + PGOGenPath, "", "", "", FS, PGOOptions::IRInstr, PGOOptions::NoCSAction, + PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling); } else if (PGOUsePath) { assert(!PGOSampleUsePath); - PGOOpt = PGOOptions(PGOUsePath, "", "", "", FS, PGOOptions::IRUse, - PGOOptions::NoCSAction, -#if LLVM_VERSION_GE(19, 0) - PGOOptions::ColdFuncOpt::Default, -#endif - DebugInfoForProfiling); + PGOOpt = PGOOptions( + PGOUsePath, "", "", "", FS, PGOOptions::IRUse, PGOOptions::NoCSAction, + PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling); } else if (PGOSampleUsePath) { - PGOOpt = PGOOptions(PGOSampleUsePath, "", "", "", FS, PGOOptions::SampleUse, - PGOOptions::NoCSAction, -#if LLVM_VERSION_GE(19, 0) - PGOOptions::ColdFuncOpt::Default, -#endif - DebugInfoForProfiling); + PGOOpt = + PGOOptions(PGOSampleUsePath, "", "", "", FS, PGOOptions::SampleUse, + PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default, + DebugInfoForProfiling); } else if (DebugInfoForProfiling) { - PGOOpt = PGOOptions("", "", "", "", FS, PGOOptions::NoAction, - PGOOptions::NoCSAction, -#if LLVM_VERSION_GE(19, 0) - PGOOptions::ColdFuncOpt::Default, -#endif - DebugInfoForProfiling); + PGOOpt = PGOOptions( + "", "", "", "", FS, PGOOptions::NoAction, PGOOptions::NoCSAction, + PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling); } auto PB = PassBuilder(TM, PTO, PGOOpt, &PIC); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 32e6da446d72..5f0e4d745e83 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -473,12 +473,8 @@ extern "C" LLVMAttributeRef LLVMRustCreateRangeAttribute(LLVMContextRef C, unsigned NumBits, const uint64_t LowerWords[], const uint64_t UpperWords[]) { -#if LLVM_VERSION_GE(19, 0) return LLVMCreateConstantRangeAttribute(C, Attribute::Range, NumBits, LowerWords, UpperWords); -#else - report_fatal_error("LLVM 19.0 is required for Range Attribute"); -#endif } // These values **must** match ffi::AllocKindFlags. @@ -1601,43 +1597,6 @@ extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst, MaybeAlign(DstAlign), IsVolatile)); } -// Polyfill for `LLVMBuildCallBr`, which was added in LLVM 19. -// -// FIXME: Remove when Rust's minimum supported LLVM version reaches 19. -#if LLVM_VERSION_LT(19, 0) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef) - -extern "C" LLVMValueRef -LLVMBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, - LLVMBasicBlockRef DefaultDest, LLVMBasicBlockRef *IndirectDests, - unsigned NumIndirectDests, LLVMValueRef *Args, unsigned NumArgs, - LLVMOperandBundleRef *Bundles, unsigned NumBundles, - const char *Name) { - Value *Callee = unwrap(Fn); - FunctionType *FTy = unwrap(Ty); - - // FIXME: Is there a way around this? - std::vector IndirectDestsUnwrapped; - IndirectDestsUnwrapped.reserve(NumIndirectDests); - for (unsigned i = 0; i < NumIndirectDests; ++i) { - IndirectDestsUnwrapped.push_back(unwrap(IndirectDests[i])); - } - - // FIXME: Is there a way around this? - SmallVector OpBundles; - OpBundles.reserve(NumBundles); - for (unsigned i = 0; i < NumBundles; ++i) { - OpBundles.push_back(*unwrap(Bundles[i])); - } - - return wrap( - unwrap(B)->CreateCallBr(FTy, Callee, unwrap(DefaultDest), - ArrayRef(IndirectDestsUnwrapped), - ArrayRef(unwrap(Args), NumArgs), - ArrayRef(OpBundles), Name)); -} -#endif - extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, LLVMBasicBlockRef BB) { auto Point = unwrap(BB)->getFirstInsertionPt(); @@ -1781,24 +1740,6 @@ extern "C" LLVMValueRef LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS))); } -#if LLVM_VERSION_LT(19, 0) -enum { - LLVMGEPFlagInBounds = (1 << 0), - LLVMGEPFlagNUSW = (1 << 1), - LLVMGEPFlagNUW = (1 << 2), -}; -extern "C" LLVMValueRef -LLVMBuildGEPWithNoWrapFlags(LLVMBuilderRef B, LLVMTypeRef Ty, - LLVMValueRef Pointer, LLVMValueRef *Indices, - unsigned NumIndices, const char *Name, - unsigned NoWrapFlags) { - if (NoWrapFlags & LLVMGEPFlagInBounds) - return LLVMBuildInBoundsGEP2(B, Ty, Pointer, Indices, NumIndices, Name); - else - return LLVMBuildGEP2(B, Ty, Pointer, Indices, NumIndices, Name); -} -#endif - // Transfers ownership of DiagnosticHandler unique_ptr to the caller. extern "C" DiagnosticHandler * LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) { @@ -1866,11 +1807,7 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( } } if (DiagnosticHandlerCallback) { -#if LLVM_VERSION_GE(19, 0) DiagnosticHandlerCallback(&DI, DiagnosticHandlerContext); -#else - DiagnosticHandlerCallback(DI, DiagnosticHandlerContext); -#endif return true; } return false; @@ -2018,21 +1955,3 @@ extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) { MD.NoHWAddress = true; GV.setSanitizerMetadata(MD); } - -// 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 diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index e21804fa3c07..69a8bd59f16c 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -346,8 +346,6 @@ impl Step for Llvm { .define("LLVM_INCLUDE_DOCS", "OFF") .define("LLVM_INCLUDE_BENCHMARKS", "OFF") .define("LLVM_INCLUDE_TESTS", enable_tests) - // FIXME: remove this when minimal llvm is 19 - .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") .define("LLVM_ENABLE_BINDINGS", "OFF") .define("LLVM_ENABLE_Z3_SOLVER", "OFF") @@ -610,11 +608,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) { let version = get_llvm_version(builder, llvm_config); let mut parts = version.split('.').take(2).filter_map(|s| s.parse::().ok()); if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) { - if major >= 18 { + if major >= 19 { return; } } - panic!("\n\nbad LLVM version: {version}, need >=18\n\n") + panic!("\n\nbad LLVM version: {version}, need >=19\n\n") } fn configure_cmake( diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 20b6f7d10ef5..488a6a2bce12 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -14,9 +14,9 @@ To run a specific CI job locally, you can use the `citool` Rust crate: cargo run --manifest-path src/ci/citool/Cargo.toml run-local ``` -For example, to run the `x86_64-gnu-llvm-18-1` job: +For example, to run the `x86_64-gnu-llvm-19-1` job: ``` -cargo run --manifest-path src/ci/citool/Cargo.toml run-local x86_64-gnu-llvm-18-1 +cargo run --manifest-path src/ci/citool/Cargo.toml run-local x86_64-gnu-llvm-19-1 ``` The job will output artifacts in an `obj/` dir at the root of a repository. Note @@ -27,10 +27,10 @@ Docker image executed in the given CI job. while locally, to the `obj/` directory. This is primarily to prevent strange linker errors when using multiple Docker images. -For some Linux workflows (for example `x86_64-gnu-llvm-18-N`), the process is more involved. You will need to see which script is executed for the given workflow inside the [`jobs.yml`](../github-actions/jobs.yml) file and pass it through the `DOCKER_SCRIPT` environment variable. For example, to reproduce the `x86_64-gnu-llvm-18-3` workflow, you can run the following script: +For some Linux workflows (for example `x86_64-gnu-llvm-19-N`), the process is more involved. You will need to see which script is executed for the given workflow inside the [`jobs.yml`](../github-actions/jobs.yml) file and pass it through the `DOCKER_SCRIPT` environment variable. For example, to reproduce the `x86_64-gnu-llvm-19-3` workflow, you can run the following script: ``` -DOCKER_SCRIPT=x86_64-gnu-llvm3.sh ./src/ci/docker/run.sh x86_64-gnu-llvm-18 +DOCKER_SCRIPT=x86_64-gnu-llvm3.sh ./src/ci/docker/run.sh x86_64-gnu-llvm-19 ``` ## Local Development diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile deleted file mode 100644 index aefc0f376f68..000000000000 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile +++ /dev/null @@ -1,69 +0,0 @@ -FROM ubuntu:24.04 - -ARG DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y --no-install-recommends \ - bzip2 \ - g++ \ - gcc-multilib \ - make \ - ninja-build \ - file \ - curl \ - ca-certificates \ - python3 \ - git \ - cmake \ - sudo \ - gdb \ - llvm-18-tools \ - llvm-18-dev \ - libedit-dev \ - libssl-dev \ - pkg-config \ - zlib1g-dev \ - xz-utils \ - nodejs \ - mingw-w64 \ - # libgccjit dependencies - flex \ - libmpfr-dev \ - libgmp-dev \ - libmpc3 \ - libmpc-dev \ - && rm -rf /var/lib/apt/lists/* - -# Install powershell (universal package) so we can test x.ps1 on Linux -# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep. -RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ - dpkg --ignore-depends=libicu72 -i powershell.deb && \ - rm -f powershell.deb - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -# We are disabling CI LLVM since this builder is intentionally using a host -# LLVM, rather than the typical src/llvm-project LLVM. -ENV NO_DOWNLOAD_CI_LLVM 1 -ENV EXTERNAL_LLVM 1 - -# Using llvm-link-shared due to libffi issues -- see #34486 -ENV RUST_CONFIGURE_ARGS \ - --build=x86_64-unknown-linux-gnu \ - --llvm-root=/usr/lib/llvm-18 \ - --enable-llvm-link-shared \ - --set rust.randomize-layout=true \ - --set rust.thin-lto-import-instr-limit=10 - -COPY scripts/shared.sh /scripts/ - -ARG SCRIPT_ARG - -COPY scripts/add_dummy_commit.sh /tmp/ -COPY scripts/x86_64-gnu-llvm.sh /tmp/ -COPY scripts/x86_64-gnu-llvm2.sh /tmp/ -COPY scripts/x86_64-gnu-llvm3.sh /tmp/ -COPY scripts/stage_2_test_set1.sh /tmp/ -COPY scripts/stage_2_test_set2.sh /tmp/ - -ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}" diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile index e0ed2e227f81..be235f648b52 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile @@ -3,6 +3,7 @@ FROM ubuntu:24.10 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ + bzip2 \ g++ \ gcc-multilib \ make \ diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 26ff17e423b5..68e680a1b1b7 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -105,7 +105,7 @@ pr: - name: mingw-check-tidy continue_on_error: true <<: *job-linux-4c - - name: x86_64-gnu-llvm-18 + - name: x86_64-gnu-llvm-19 env: ENABLE_GCC_CODEGEN: "1" # We are adding (temporarily) a dummy commit on the compiler @@ -329,34 +329,6 @@ auto: DOCKER_SCRIPT: x86_64-gnu-llvm3.sh <<: *job-linux-4c - # The x86_64-gnu-llvm-18 job is split into multiple jobs to run tests in parallel. - # x86_64-gnu-llvm-18-1 skips tests that run in x86_64-gnu-llvm-18-{2,3}. - - name: x86_64-gnu-llvm-18-1 - env: - RUST_BACKTRACE: 1 - READ_ONLY_SRC: "0" - IMAGE: x86_64-gnu-llvm-18 - DOCKER_SCRIPT: stage_2_test_set1.sh - <<: *job-linux-4c - - # Skip tests that run in x86_64-gnu-llvm-18-{1,3} - - name: x86_64-gnu-llvm-18-2 - env: - RUST_BACKTRACE: 1 - READ_ONLY_SRC: "0" - IMAGE: x86_64-gnu-llvm-18 - DOCKER_SCRIPT: x86_64-gnu-llvm2.sh - <<: *job-linux-4c - - # Skip tests that run in x86_64-gnu-llvm-18-{1,2} - - name: x86_64-gnu-llvm-18-3 - env: - RUST_BACKTRACE: 1 - READ_ONLY_SRC: "0" - IMAGE: x86_64-gnu-llvm-18 - DOCKER_SCRIPT: x86_64-gnu-llvm3.sh - <<: *job-linux-4c - - name: x86_64-gnu-nopt <<: *job-linux-4c diff --git a/tests/assembly/aarch64-pointer-auth.rs b/tests/assembly/aarch64-pointer-auth.rs index 8c0069826795..56a26df469f3 100644 --- a/tests/assembly/aarch64-pointer-auth.rs +++ b/tests/assembly/aarch64-pointer-auth.rs @@ -8,7 +8,6 @@ //@ [PACRET] compile-flags: -Z branch-protection=pac-ret,leaf //@ [PAUTHLR_NOP] compile-flags: -Z branch-protection=pac-ret,pc,leaf //@ [PAUTHLR] compile-flags: -C target-feature=+pauth-lr -Z branch-protection=pac-ret,pc,leaf -//@ min-llvm-version: 19 #![feature(no_core, lang_items)] #![no_std] diff --git a/tests/assembly/static-relocation-model.rs b/tests/assembly/static-relocation-model.rs index 53fa18852b69..35ad94133b2c 100644 --- a/tests/assembly/static-relocation-model.rs +++ b/tests/assembly/static-relocation-model.rs @@ -25,7 +25,7 @@ extern "C" { } // CHECK-LABEL: banana: -// On the next line LLVM 14 produces a `movb`, whereas LLVM 15+ produces a `movzbl`. +// LLVM may produce either kind of `mov` here, depending on version and optimization level. // x64: {{movb|movzbl}} chaenomeles{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}} // A64: adrp [[REG:[a-z0-9]+]], chaenomeles // A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles] diff --git a/tests/codegen/branch-protection-old-llvm.rs b/tests/codegen/branch-protection-old-llvm.rs deleted file mode 100644 index 14b34ac50188..000000000000 --- a/tests/codegen/branch-protection-old-llvm.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Test that the correct module flags are emitted with different branch protection flags. - -//@ add-core-stubs -//@ revisions: BTI PACRET LEAF BKEY NONE -//@ needs-llvm-components: aarch64 -//@ [BTI] compile-flags: -Z branch-protection=bti -//@ [PACRET] compile-flags: -Z branch-protection=pac-ret -//@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf -//@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key -//@ compile-flags: --target aarch64-unknown-linux-gnu -//@ max-llvm-major-version: 18 - -#![crate_type = "lib"] -#![feature(no_core, lang_items)] -#![no_core] - -extern crate minicore; -use minicore::*; - -// A basic test function. -pub fn test() {} - -// BTI: !"branch-target-enforcement", i32 1 -// BTI: !"sign-return-address", i32 0 -// BTI: !"sign-return-address-all", i32 0 -// BTI: !"sign-return-address-with-bkey", i32 0 - -// PACRET: !"branch-target-enforcement", i32 0 -// PACRET: !"sign-return-address", i32 1 -// PACRET: !"sign-return-address-all", i32 0 -// PACRET: !"sign-return-address-with-bkey", i32 0 - -// LEAF: !"branch-target-enforcement", i32 0 -// LEAF: !"sign-return-address", i32 1 -// LEAF: !"sign-return-address-all", i32 1 -// LEAF: !"sign-return-address-with-bkey", i32 0 - -// BKEY: !"branch-target-enforcement", i32 0 -// BKEY: !"sign-return-address", i32 1 -// BKEY: !"sign-return-address-all", i32 0 -// BKEY: !"sign-return-address-with-bkey", i32 1 - -// NONE-NOT: branch-target-enforcement -// NONE-NOT: sign-return-address -// NONE-NOT: sign-return-address-all -// NONE-NOT: sign-return-address-with-bkey diff --git a/tests/codegen/branch-protection.rs b/tests/codegen/branch-protection.rs index ae14eae9ae0d..d67e494cc0d6 100644 --- a/tests/codegen/branch-protection.rs +++ b/tests/codegen/branch-protection.rs @@ -12,7 +12,6 @@ //@ [PAUTHLR_LEAF] compile-flags: -Z branch-protection=pac-ret,pc,leaf //@ [PAUTHLR_BTI] compile-flags: -Z branch-protection=bti,pac-ret,pc //@ compile-flags: --target aarch64-unknown-linux-gnu -//@ min-llvm-version: 19 #![crate_type = "lib"] #![feature(no_core, lang_items)] diff --git a/tests/codegen/call-metadata.rs b/tests/codegen/call-metadata.rs deleted file mode 100644 index 7ad3ded2f09d..000000000000 --- a/tests/codegen/call-metadata.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Checks that range metadata gets emitted on calls to functions returning a -// scalar value. - -//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@ max-llvm-major-version: 18 - -#![crate_type = "lib"] - -pub fn test() { - // CHECK: call noundef i8 @some_true(){{( #[0-9]+)?}}, !range [[R0:![0-9]+]] - // CHECK: [[R0]] = !{i8 0, i8 3} - some_true(); -} - -#[no_mangle] -fn some_true() -> Option { - Some(true) -} diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs index e1a7ad718a06..cbd49e2f022a 100644 --- a/tests/codegen/cast-target-abi.rs +++ b/tests/codegen/cast-target-abi.rs @@ -1,7 +1,6 @@ // ignore-tidy-linelength //@ add-core-stubs //@ revisions:aarch64 loongarch64 powerpc64 sparc64 x86_64 -//@ min-llvm-version: 19 //@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu diff --git a/tests/codegen/cffi/ffi-const.rs b/tests/codegen/cffi/ffi-const.rs index 564b8f7f8d8d..6c90902e89fe 100644 --- a/tests/codegen/cffi/ffi-const.rs +++ b/tests/codegen/cffi/ffi-const.rs @@ -9,8 +9,7 @@ pub fn bar() { extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] - // The attribute changed from `readnone` to `memory(none)` with LLVM 16.0. - // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readnone|memory\(none\)}}{{.*}} } + // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(none){{.*}} } #[ffi_const] pub fn foo(); } diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs index 73bc7ef6b77d..859386d2df87 100644 --- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs +++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs @@ -1,6 +1,5 @@ //@ add-core-stubs //@ revisions: linux apple -//@ min-llvm-version: 19 //@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir //@[linux] compile-flags: --target x86_64-unknown-linux-gnu diff --git a/tests/codegen/cffi/ffi-pure.rs b/tests/codegen/cffi/ffi-pure.rs index 601509d5c90f..2c5d5f5b4b12 100644 --- a/tests/codegen/cffi/ffi-pure.rs +++ b/tests/codegen/cffi/ffi-pure.rs @@ -9,8 +9,7 @@ pub fn bar() { extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] - // The attribute changed from `readonly` to `memory(read)` with LLVM 16.0. - // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readonly|memory\(read\)}}{{.*}} } + // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(read){{.*}} } #[ffi_pure] pub fn foo(); } diff --git a/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs index 0f6e99f9b1ee..7530689d5747 100644 --- a/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs +++ b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs @@ -1,4 +1,3 @@ -//@ min-llvm-version: 19 //@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Zmir-enable-passes=+Inline // MSVC is different because of the individual allocas. //@ ignore-msvc diff --git a/tests/codegen/dont-shuffle-bswaps.rs b/tests/codegen/dont-shuffle-bswaps.rs index 0e712bc3a4eb..e100474f606f 100644 --- a/tests/codegen/dont-shuffle-bswaps.rs +++ b/tests/codegen/dont-shuffle-bswaps.rs @@ -3,7 +3,6 @@ //@[OPT3] compile-flags: -C opt-level=3 // some targets don't do the opt we are looking for //@[OPT3] only-64bit -//@ min-llvm-version: 18.1.3 #![crate_type = "lib"] #![no_std] diff --git a/tests/codegen/enum/enum-two-variants-match.rs b/tests/codegen/enum/enum-two-variants-match.rs index c1f208d79091..21ae1f96bca7 100644 --- a/tests/codegen/enum/enum-two-variants-match.rs +++ b/tests/codegen/enum/enum-two-variants-match.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@ min-llvm-version: 19 (for trunc nuw) //@ only-x86_64 (because these discriminants are isize) #![crate_type = "lib"] diff --git a/tests/codegen/intrinsics/carrying_mul_add.rs b/tests/codegen/intrinsics/carrying_mul_add.rs index b53585a8a6ee..21fb49a3786a 100644 --- a/tests/codegen/intrinsics/carrying_mul_add.rs +++ b/tests/codegen/intrinsics/carrying_mul_add.rs @@ -1,7 +1,6 @@ //@ revisions: RAW OPT //@ compile-flags: -C opt-level=1 //@[RAW] compile-flags: -C no-prepopulate-passes -//@[OPT] min-llvm-version: 19 #![crate_type = "lib"] #![feature(core_intrinsics)] diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index 4849b88c09c2..560ebcccdd02 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -12,9 +12,6 @@ use std::intrinsics::{transmute, transmute_unchecked}; use std::mem::MaybeUninit; use std::num::NonZero; -// FIXME(LLVM18REMOVED): `trunc nuw` doesn't exist in LLVM 18, so once we no -// longer support it the optional flag checks can be changed to required. - pub enum ZstNever {} #[repr(align(2))] @@ -157,7 +154,7 @@ pub unsafe fn check_from_newtype(x: Scalar64) -> u64 { pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool { // CHECK: %x = alloca [1 x i8], align 1 // CHECK: %[[BYTE:.+]] = load i8, ptr %x, align 1 - // CHECK: %[[BOOL:.+]] = trunc{{( nuw)?}} i8 %[[BYTE]] to i1 + // CHECK: %[[BOOL:.+]] = trunc nuw i8 %[[BYTE]] to i1 // CHECK: ret i1 %[[BOOL]] transmute(x) } @@ -175,7 +172,7 @@ pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 { #[no_mangle] pub unsafe fn check_byte_to_bool(x: u8) -> bool { // CHECK-NOT: alloca - // CHECK: %[[R:.+]] = trunc{{( nuw)?}} i8 %x to i1 + // CHECK: %[[R:.+]] = trunc nuw i8 %x to i1 // CHECK: ret i1 %[[R]] transmute(x) } @@ -288,7 +285,7 @@ pub unsafe fn check_long_array_more_aligned(x: [u8; 100]) -> [u32; 25] { #[no_mangle] pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) { // CHECK-NOT: alloca - // CHECK: trunc{{( nuw)?}} i8 %x.0 to i1 + // CHECK: trunc nuw i8 %x.0 to i1 // CHECK: zext i1 %x.1 to i8 transmute(x) } @@ -342,7 +339,7 @@ pub unsafe fn check_heterogeneous_integer_pair(x: (i32, bool)) -> (bool, u32) { // CHECK: store i8 %[[WIDER]] // CHECK: %[[BYTE:.+]] = load i8 - // CHECK: trunc{{( nuw)?}} i8 %[[BYTE:.+]] to i1 + // CHECK: trunc nuw i8 %[[BYTE:.+]] to i1 // CHECK: load i32 transmute(x) } diff --git a/tests/codegen/issues/issue-107681-unwrap_unchecked.rs b/tests/codegen/issues/issue-107681-unwrap_unchecked.rs index fd7296de4c86..69aefc6b1fb5 100644 --- a/tests/codegen/issues/issue-107681-unwrap_unchecked.rs +++ b/tests/codegen/issues/issue-107681-unwrap_unchecked.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ min-llvm-version: 19 // Test for #107681. // Make sure we don't create `br` or `select` instructions. diff --git a/tests/codegen/issues/issue-118306.rs b/tests/codegen/issues/issue-118306.rs index f9f3e0c0529c..f12dc7cdfe2c 100644 --- a/tests/codegen/issues/issue-118306.rs +++ b/tests/codegen/issues/issue-118306.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ min-llvm-version: 19 //@ only-x86_64 // Test for #118306. diff --git a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs index fbea4ee8979f..2414c54e4b79 100644 --- a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs +++ b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ min-llvm-version: 19 #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-126585.rs b/tests/codegen/issues/issue-126585.rs index a468efd728d1..466dab64cdc1 100644 --- a/tests/codegen/issues/issue-126585.rs +++ b/tests/codegen/issues/issue-126585.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=s -//@ min-llvm-version: 19 //@ only-x86_64 // Test for #126585. diff --git a/tests/codegen/range-attribute.rs b/tests/codegen/range-attribute.rs index e23f5e6bb748..b81ff9ab3e2b 100644 --- a/tests/codegen/range-attribute.rs +++ b/tests/codegen/range-attribute.rs @@ -6,7 +6,6 @@ //@[bit32] only-32bit //@[bit64] only-64bit //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@ min-llvm-version: 19 #![crate_type = "lib"] diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 8b1f3b14fc30..6be0e21e0ef3 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -4,21 +4,17 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 -// The "+fpmr" feature is matched as optional as it is only an explicit -// feature in LLVM 18. Once the min supported version is LLVM-19 the optional -// regex matching for this feature can be removed. - //@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0 -// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } +// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 -// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?))*}}" } +// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(-sve,?)|(\+neon,?))*}}" } //@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(-fp-armv8,?)|(-neon,?))*}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 -// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } +// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fp-armv8,?)|(\+neon,?))*}}" } #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 9430465a2860..9f68d742a75e 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -1,10 +1,8 @@ //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled --edition=2021 //@ only-x86_64 -// FIXME: Remove the `min-llvm-version`. //@ revisions: NINETEEN TWENTY //@[NINETEEN] exact-llvm-major-version: 19 //@[TWENTY] min-llvm-version: 20 -//@ min-llvm-version: 19 #![crate_type = "lib"] #![feature(try_blocks)] diff --git a/tests/codegen/unchecked_shifts.rs b/tests/codegen/unchecked_shifts.rs index 9fccaf2252e0..3f533718a2d0 100644 --- a/tests/codegen/unchecked_shifts.rs +++ b/tests/codegen/unchecked_shifts.rs @@ -1,7 +1,4 @@ -//@ revisions: LLVM18 LLVM19PLUS //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@[LLVM18] exact-llvm-major-version: 18 -//@[LLVM19PLUS] min-llvm-version: 19 // This runs mir-opts to inline the standard library call, but doesn't run LLVM // optimizations so it doesn't need to worry about them adding more flags. @@ -24,8 +21,7 @@ pub unsafe fn unchecked_shl_unsigned_same(a: u32, b: u32) -> u32 { #[no_mangle] pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 { // CHECK-NOT: assume - // LLVM18: %[[TRUNC:.+]] = trunc i32 %b to i16 - // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i32 %b to i16 + // CHECK: %[[TRUNC:.+]] = trunc nuw i32 %b to i16 // CHECK: shl i16 %a, %[[TRUNC]] a.unchecked_shl(b) } @@ -53,8 +49,7 @@ pub unsafe fn unchecked_shr_signed_same(a: i32, b: u32) -> i32 { #[no_mangle] pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 { // CHECK-NOT: assume - // LLVM18: %[[TRUNC:.+]] = trunc i32 %b to i16 - // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i32 %b to i16 + // CHECK: %[[TRUNC:.+]] = trunc nuw i32 %b to i16 // CHECK: ashr i16 %a, %[[TRUNC]] a.unchecked_shr(b) } @@ -90,8 +85,7 @@ pub unsafe fn unchecked_shl_i128_u8(a: i128, b: u8) -> i128 { #[no_mangle] pub unsafe fn unchecked_shl_u8_i128(a: u8, b: i128) -> u8 { // CHECK-NOT: assume - // LLVM18: %[[TRUNC:.+]] = trunc i128 %b to i8 - // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i128 %b to i8 + // CHECK: %[[TRUNC:.+]] = trunc nuw i128 %b to i8 // CHECK: shl i8 %a, %[[TRUNC]] std::intrinsics::unchecked_shl(a, b) } @@ -100,8 +94,7 @@ pub unsafe fn unchecked_shl_u8_i128(a: u8, b: i128) -> u8 { #[no_mangle] pub unsafe fn unchecked_shr_i8_u128(a: i8, b: u128) -> i8 { // CHECK-NOT: assume - // LLVM18: %[[TRUNC:.+]] = trunc i128 %b to i8 - // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i128 %b to i8 + // CHECK: %[[TRUNC:.+]] = trunc nuw i128 %b to i8 // CHECK: ashr i8 %a, %[[TRUNC]] std::intrinsics::unchecked_shr(a, b) } diff --git a/tests/codegen/vec_pop_push_noop.rs b/tests/codegen/vec_pop_push_noop.rs index 2635660596ab..3e375219fe01 100644 --- a/tests/codegen/vec_pop_push_noop.rs +++ b/tests/codegen/vec_pop_push_noop.rs @@ -1,6 +1,3 @@ -//@ revisions: llvm-pre-19 llvm-19 -//@ [llvm-19] min-llvm-version: 19 -//@ [llvm-pre-19] max-llvm-major-version: 18 //@ compile-flags: -Copt-level=3 #![crate_type = "lib"] diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map index 8ff5d6360f67..befe8866a592 100644 --- a/tests/coverage/mcdc/condition-limit.cov-map +++ b/tests/coverage/mcdc/condition-limit.cov-map @@ -1,5 +1,5 @@ Function name: condition_limit::accept_7_conditions -Raw bytes (147): 0x[01, 01, 08, 01, 05, 05, 09, 09, 0d, 0d, 11, 11, 15, 15, 19, 19, 1d, 01, 1d, 12, 01, 07, 01, 02, 09, 28, 08, 07, 02, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 07, 06, 00, 00, 0d, 00, 0e, 09, 00, 12, 00, 13, 30, 0d, 0a, 06, 05, 00, 00, 12, 00, 13, 0d, 00, 17, 00, 18, 30, 11, 0e, 05, 04, 00, 00, 17, 00, 18, 11, 00, 1c, 00, 1d, 30, 15, 12, 04, 03, 00, 00, 1c, 00, 1d, 15, 00, 21, 00, 22, 30, 19, 16, 03, 02, 00, 00, 21, 00, 22, 19, 00, 26, 00, 27, 30, 1d, 1a, 02, 00, 00, 00, 26, 00, 27, 1d, 00, 28, 02, 06, 1e, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (147): 0x[01, 01, 08, 01, 05, 05, 09, 09, 0d, 0d, 11, 11, 15, 15, 19, 19, 1d, 01, 1d, 12, 01, 06, 01, 02, 09, 28, 08, 07, 02, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 07, 06, 00, 00, 0d, 00, 0e, 09, 00, 12, 00, 13, 30, 0d, 0a, 06, 05, 00, 00, 12, 00, 13, 0d, 00, 17, 00, 18, 30, 11, 0e, 05, 04, 00, 00, 17, 00, 18, 11, 00, 1c, 00, 1d, 30, 15, 12, 04, 03, 00, 00, 1c, 00, 1d, 15, 00, 21, 00, 22, 30, 19, 16, 03, 02, 00, 00, 21, 00, 22, 19, 00, 26, 00, 27, 30, 1d, 1a, 02, 00, 00, 00, 26, 00, 27, 1d, 00, 28, 02, 06, 1e, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -12,7 +12,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Counter(6), rhs = Counter(7) - expression 7 operands: lhs = Counter(0), rhs = Counter(7) Number of file 0 mappings: 18 -- Code(Counter(0)) at (prev + 7, 1) to (start + 2, 9) +- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 9) - MCDCDecision { bitmap_idx: 8, conditions_num: 7 } at (prev + 2, 8) to (start + 0, 39) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 7, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 diff --git a/tests/coverage/mcdc/condition-limit.coverage b/tests/coverage/mcdc/condition-limit.coverage index d11b8a17710b..04ccd6497c3d 100644 --- a/tests/coverage/mcdc/condition-limit.coverage +++ b/tests/coverage/mcdc/condition-limit.coverage @@ -1,6 +1,5 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/condition-limit.rs b/tests/coverage/mcdc/condition-limit.rs index 2e8f16193793..867636cdaed2 100644 --- a/tests/coverage/mcdc/condition-limit.rs +++ b/tests/coverage/mcdc/condition-limit.rs @@ -1,6 +1,5 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map index 771351f649f1..1b038f48429e 100644 --- a/tests/coverage/mcdc/if.cov-map +++ b/tests/coverage/mcdc/if.cov-map @@ -1,5 +1,5 @@ Function name: if::mcdc_check_a -Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 0f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 0e, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -7,7 +7,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -23,7 +23,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::mcdc_check_b -Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 17, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 16, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -31,7 +31,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 23, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 22, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -47,7 +47,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::mcdc_check_both -Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 1f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 1e, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -55,7 +55,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -71,7 +71,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::mcdc_check_neither -Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 07, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (62): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 06, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 06, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -79,7 +79,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -95,7 +95,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::mcdc_check_not_tree_decision -Raw bytes (85): 0x[01, 01, 07, 01, 05, 01, 17, 05, 09, 05, 09, 17, 0d, 05, 09, 01, 0d, 0a, 01, 31, 01, 03, 0a, 28, 05, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 06, 03, 02, 00, 00, 0e, 00, 0f, 17, 00, 14, 00, 15, 30, 0d, 12, 02, 00, 00, 00, 14, 00, 15, 0d, 00, 16, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (85): 0x[01, 01, 07, 01, 05, 01, 17, 05, 09, 05, 09, 17, 0d, 05, 09, 01, 0d, 0a, 01, 30, 01, 03, 0a, 28, 05, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 06, 03, 02, 00, 00, 0e, 00, 0f, 17, 00, 14, 00, 15, 30, 0d, 12, 02, 00, 00, 00, 14, 00, 15, 0d, 00, 16, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -107,7 +107,7 @@ Number of expressions: 7 - expression 5 operands: lhs = Counter(1), rhs = Counter(2) - expression 6 operands: lhs = Counter(0), rhs = Counter(3) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 49, 1) to (start + 3, 10) +- Code(Counter(0)) at (prev + 48, 1) to (start + 3, 10) - MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 3 } at (prev + 0, 9) to (start + 0, 10) true = c1 @@ -129,7 +129,7 @@ Number of file 0 mappings: 10 Highest counter ID seen: c3 Function name: if::mcdc_check_tree_decision -Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 09, 05, 09, 05, 1f, 09, 0d, 09, 0d, 01, 1f, 09, 0d, 0a, 01, 27, 01, 03, 09, 28, 04, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 09, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 0d, 0e, 03, 00, 00, 00, 13, 00, 14, 1f, 00, 16, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 09, 05, 09, 05, 1f, 09, 0d, 09, 0d, 01, 1f, 09, 0d, 0a, 01, 26, 01, 03, 09, 28, 04, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 09, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 0d, 0e, 03, 00, 00, 00, 13, 00, 14, 1f, 00, 16, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -142,7 +142,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Counter(0), rhs = Expression(7, Add) - expression 7 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 39, 1) to (start + 3, 9) +- Code(Counter(0)) at (prev + 38, 1) to (start + 3, 9) - MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -164,7 +164,7 @@ Number of file 0 mappings: 10 Highest counter ID seen: c3 Function name: if::mcdc_nested_if -Raw bytes (120): 0x[01, 01, 0b, 01, 05, 01, 2b, 05, 09, 05, 09, 2b, 0d, 05, 09, 0d, 11, 2b, 11, 05, 09, 01, 2b, 05, 09, 0e, 01, 3b, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 26, 02, 00, 00, 00, 0d, 00, 0e, 2b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 0d, 12, 01, 02, 00, 00, 0c, 00, 0d, 0d, 00, 11, 00, 12, 30, 11, 1a, 02, 00, 00, 00, 11, 00, 12, 11, 00, 13, 02, 0a, 1e, 02, 09, 00, 0a, 26, 01, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (120): 0x[01, 01, 0b, 01, 05, 01, 2b, 05, 09, 05, 09, 2b, 0d, 05, 09, 0d, 11, 2b, 11, 05, 09, 01, 2b, 05, 09, 0e, 01, 3a, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 26, 02, 00, 00, 00, 0d, 00, 0e, 2b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 0d, 12, 01, 02, 00, 00, 0c, 00, 0d, 0d, 00, 11, 00, 12, 30, 11, 1a, 02, 00, 00, 00, 11, 00, 12, 11, 00, 13, 02, 0a, 1e, 02, 09, 00, 0a, 26, 01, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 11 @@ -180,7 +180,7 @@ Number of expressions: 11 - expression 9 operands: lhs = Counter(0), rhs = Expression(10, Add) - expression 10 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 59, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 58, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 8) to (start + 0, 9) true = c1 diff --git a/tests/coverage/mcdc/if.coverage b/tests/coverage/mcdc/if.coverage index b000c7d5d2f8..51917d060454 100644 --- a/tests/coverage/mcdc/if.coverage +++ b/tests/coverage/mcdc/if.coverage @@ -1,6 +1,5 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/if.rs b/tests/coverage/mcdc/if.rs index a2abb2edf115..c4675f5d1672 100644 --- a/tests/coverage/mcdc/if.rs +++ b/tests/coverage/mcdc/if.rs @@ -1,6 +1,5 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/inlined_expressions.cov-map b/tests/coverage/mcdc/inlined_expressions.cov-map index 6a112b66e88b..7d78e572a3b0 100644 --- a/tests/coverage/mcdc/inlined_expressions.cov-map +++ b/tests/coverage/mcdc/inlined_expressions.cov-map @@ -1,12 +1,12 @@ Function name: inlined_expressions::inlined_instance -Raw bytes (50): 0x[01, 01, 02, 01, 05, 05, 09, 06, 01, 08, 01, 01, 06, 28, 03, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 06, 02, 00, 00, 00, 0a, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (50): 0x[01, 01, 02, 01, 05, 05, 09, 06, 01, 07, 01, 01, 06, 28, 03, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 06, 02, 00, 00, 00, 0a, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 6) +- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 6) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 5) to (start + 0, 6) true = c1 diff --git a/tests/coverage/mcdc/inlined_expressions.coverage b/tests/coverage/mcdc/inlined_expressions.coverage index 57c655a20547..cfe398995e4e 100644 --- a/tests/coverage/mcdc/inlined_expressions.coverage +++ b/tests/coverage/mcdc/inlined_expressions.coverage @@ -1,6 +1,5 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0 LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/inlined_expressions.rs b/tests/coverage/mcdc/inlined_expressions.rs index 651e2fe84387..15d4260f6e2c 100644 --- a/tests/coverage/mcdc/inlined_expressions.rs +++ b/tests/coverage/mcdc/inlined_expressions.rs @@ -1,6 +1,5 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0 //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/nested_if.cov-map b/tests/coverage/mcdc/nested_if.cov-map index a231ac7b4c98..83d0739aaf59 100644 --- a/tests/coverage/mcdc/nested_if.cov-map +++ b/tests/coverage/mcdc/nested_if.cov-map @@ -1,5 +1,5 @@ Function name: nested_if::doubly_nested_if_in_condition -Raw bytes (170): 0x[01, 01, 0f, 01, 05, 05, 11, 05, 09, 05, 37, 09, 0d, 05, 09, 05, 1f, 09, 15, 15, 19, 05, 2b, 09, 19, 09, 0d, 05, 37, 09, 0d, 01, 11, 14, 01, 0f, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 06, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 06, 02, 00, 10, 00, 36, 30, 09, 16, 01, 00, 02, 00, 10, 00, 11, 30, 0d, 32, 02, 00, 00, 00, 15, 00, 36, 16, 00, 18, 00, 19, 28, 03, 02, 00, 18, 00, 1e, 30, 15, 1a, 01, 02, 00, 00, 18, 00, 19, 15, 00, 1d, 00, 1e, 30, 19, 22, 02, 00, 00, 00, 1d, 00, 1e, 19, 00, 21, 00, 25, 26, 00, 2f, 00, 34, 37, 00, 39, 00, 3e, 32, 00, 48, 00, 4c, 11, 00, 4f, 02, 06, 3a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (170): 0x[01, 01, 0f, 01, 05, 05, 11, 05, 09, 05, 37, 09, 0d, 05, 09, 05, 1f, 09, 15, 15, 19, 05, 2b, 09, 19, 09, 0d, 05, 37, 09, 0d, 01, 11, 14, 01, 0e, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 06, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 06, 02, 00, 10, 00, 36, 30, 09, 16, 01, 00, 02, 00, 10, 00, 11, 30, 0d, 32, 02, 00, 00, 00, 15, 00, 36, 16, 00, 18, 00, 19, 28, 03, 02, 00, 18, 00, 1e, 30, 15, 1a, 01, 02, 00, 00, 18, 00, 19, 15, 00, 1d, 00, 1e, 30, 19, 22, 02, 00, 00, 00, 1d, 00, 1e, 19, 00, 21, 00, 25, 26, 00, 2f, 00, 34, 37, 00, 39, 00, 3e, 32, 00, 48, 00, 4c, 11, 00, 4f, 02, 06, 3a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 15 @@ -19,7 +19,7 @@ Number of expressions: 15 - expression 13 operands: lhs = Counter(2), rhs = Counter(3) - expression 14 operands: lhs = Counter(0), rhs = Counter(4) Number of file 0 mappings: 20 -- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -59,7 +59,7 @@ Number of file 0 mappings: 20 Highest counter ID seen: c6 Function name: nested_if::nested_if_in_condition -Raw bytes (118): 0x[01, 01, 0a, 01, 05, 05, 11, 05, 09, 05, 09, 05, 23, 09, 0d, 09, 0d, 05, 23, 09, 0d, 01, 11, 0e, 01, 07, 01, 01, 09, 28, 06, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 06, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0e, 01, 00, 02, 00, 10, 00, 11, 0e, 00, 15, 00, 16, 30, 0d, 1e, 02, 00, 00, 00, 15, 00, 16, 23, 00, 19, 00, 1d, 1e, 00, 27, 00, 2c, 11, 00, 2f, 02, 06, 26, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (118): 0x[01, 01, 0a, 01, 05, 05, 11, 05, 09, 05, 09, 05, 23, 09, 0d, 09, 0d, 05, 23, 09, 0d, 01, 11, 0e, 01, 06, 01, 01, 09, 28, 06, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 06, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0e, 01, 00, 02, 00, 10, 00, 11, 0e, 00, 15, 00, 16, 30, 0d, 1e, 02, 00, 00, 00, 15, 00, 16, 23, 00, 19, 00, 1d, 1e, 00, 27, 00, 2c, 11, 00, 2f, 02, 06, 26, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 10 @@ -74,7 +74,7 @@ Number of expressions: 10 - expression 8 operands: lhs = Counter(2), rhs = Counter(3) - expression 9 operands: lhs = Counter(0), rhs = Counter(4) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -103,7 +103,7 @@ Number of file 0 mappings: 14 Highest counter ID seen: c4 Function name: nested_if::nested_in_then_block_in_condition -Raw bytes (170): 0x[01, 01, 0f, 01, 05, 05, 19, 05, 09, 05, 09, 05, 37, 09, 0d, 09, 0d, 37, 11, 09, 0d, 11, 15, 37, 15, 09, 0d, 05, 37, 09, 0d, 01, 19, 14, 01, 22, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 19, 06, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0e, 01, 00, 02, 00, 10, 00, 11, 0e, 00, 15, 00, 16, 30, 0d, 32, 02, 00, 00, 00, 15, 00, 16, 37, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 11, 1e, 01, 02, 00, 00, 1c, 00, 1d, 11, 00, 21, 00, 22, 30, 15, 26, 02, 00, 00, 00, 21, 00, 22, 15, 00, 25, 00, 29, 2a, 00, 33, 00, 38, 32, 00, 44, 00, 49, 19, 00, 4c, 02, 06, 3a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (170): 0x[01, 01, 0f, 01, 05, 05, 19, 05, 09, 05, 09, 05, 37, 09, 0d, 09, 0d, 37, 11, 09, 0d, 11, 15, 37, 15, 09, 0d, 05, 37, 09, 0d, 01, 19, 14, 01, 21, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 19, 06, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0e, 01, 00, 02, 00, 10, 00, 11, 0e, 00, 15, 00, 16, 30, 0d, 32, 02, 00, 00, 00, 15, 00, 16, 37, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 11, 1e, 01, 02, 00, 00, 1c, 00, 1d, 11, 00, 21, 00, 22, 30, 15, 26, 02, 00, 00, 00, 21, 00, 22, 15, 00, 25, 00, 29, 2a, 00, 33, 00, 38, 32, 00, 44, 00, 49, 19, 00, 4c, 02, 06, 3a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 15 @@ -123,7 +123,7 @@ Number of expressions: 15 - expression 13 operands: lhs = Counter(2), rhs = Counter(3) - expression 14 operands: lhs = Counter(0), rhs = Counter(6) Number of file 0 mappings: 20 -- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -163,7 +163,7 @@ Number of file 0 mappings: 20 Highest counter ID seen: c6 Function name: nested_if::nested_single_condition_decision -Raw bytes (83): 0x[01, 01, 05, 01, 05, 05, 0d, 05, 09, 05, 09, 01, 0d, 0b, 01, 17, 01, 04, 09, 28, 03, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 06, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 09, 0e, 00, 10, 00, 11, 09, 00, 14, 00, 19, 0e, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (83): 0x[01, 01, 05, 01, 05, 05, 0d, 05, 09, 05, 09, 01, 0d, 0b, 01, 16, 01, 04, 09, 28, 03, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 06, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 09, 0e, 00, 10, 00, 11, 09, 00, 14, 00, 19, 0e, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -173,7 +173,7 @@ Number of expressions: 5 - expression 3 operands: lhs = Counter(1), rhs = Counter(2) - expression 4 operands: lhs = Counter(0), rhs = Counter(3) Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 23, 1) to (start + 4, 9) +- Code(Counter(0)) at (prev + 22, 1) to (start + 4, 9) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 diff --git a/tests/coverage/mcdc/nested_if.coverage b/tests/coverage/mcdc/nested_if.coverage index ca0cb54d5815..c3ac30d22bf8 100644 --- a/tests/coverage/mcdc/nested_if.coverage +++ b/tests/coverage/mcdc/nested_if.coverage @@ -1,6 +1,5 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/nested_if.rs b/tests/coverage/mcdc/nested_if.rs index 83f188ea47e3..db02aece33c9 100644 --- a/tests/coverage/mcdc/nested_if.rs +++ b/tests/coverage/mcdc/nested_if.rs @@ -1,6 +1,5 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map index 959d21901de8..48a103b2c7d7 100644 --- a/tests/coverage/mcdc/non_control_flow.cov-map +++ b/tests/coverage/mcdc/non_control_flow.cov-map @@ -1,5 +1,5 @@ Function name: non_control_flow::assign_3 -Raw bytes (79): 0x[01, 01, 04, 01, 05, 01, 0b, 05, 09, 09, 0d, 0a, 01, 16, 01, 00, 28, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 04, 03, 00, 0d, 00, 18, 30, 05, 02, 01, 00, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 30, 09, 06, 02, 03, 00, 00, 12, 00, 13, 09, 00, 17, 00, 18, 30, 0d, 0e, 03, 00, 00, 00, 17, 00, 18, 01, 01, 05, 01, 02] +Raw bytes (79): 0x[01, 01, 04, 01, 05, 01, 0b, 05, 09, 09, 0d, 0a, 01, 15, 01, 00, 28, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 04, 03, 00, 0d, 00, 18, 30, 05, 02, 01, 00, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 30, 09, 06, 02, 03, 00, 00, 12, 00, 13, 09, 00, 17, 00, 18, 30, 0d, 0e, 03, 00, 00, 00, 17, 00, 18, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -8,7 +8,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Counter(1), rhs = Counter(2) - expression 3 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40) +- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 40) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) @@ -28,7 +28,7 @@ Number of file 0 mappings: 10 Highest counter ID seen: c3 Function name: non_control_flow::assign_3_bis -Raw bytes (81): 0x[01, 01, 05, 01, 05, 05, 09, 01, 09, 01, 13, 09, 0d, 0a, 01, 1b, 01, 00, 2c, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 02, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 06, 03, 00, 02, 00, 12, 00, 13, 0a, 00, 17, 00, 18, 30, 0d, 0e, 02, 00, 00, 00, 17, 00, 18, 01, 01, 05, 01, 02] +Raw bytes (81): 0x[01, 01, 05, 01, 05, 05, 09, 01, 09, 01, 13, 09, 0d, 0a, 01, 1a, 01, 00, 2c, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 02, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 06, 03, 00, 02, 00, 12, 00, 13, 0a, 00, 17, 00, 18, 30, 0d, 0e, 02, 00, 00, 00, 17, 00, 18, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -38,7 +38,7 @@ Number of expressions: 5 - expression 3 operands: lhs = Counter(0), rhs = Expression(4, Add) - expression 4 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 44) +- Code(Counter(0)) at (prev + 26, 1) to (start + 0, 44) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) @@ -58,14 +58,14 @@ Number of file 0 mappings: 10 Highest counter ID seen: c3 Function name: non_control_flow::assign_and -Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 0c, 01, 00, 21, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 02, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 06, 02, 00, 00, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 0b, 01, 00, 21, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 02, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 06, 02, 00, 00, 00, 12, 00, 13, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33) +- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 33) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) @@ -80,7 +80,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: non_control_flow::assign_or -Raw bytes (62): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 08, 01, 11, 01, 00, 20, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 02, 01, 00, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 30, 09, 06, 02, 00, 00, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (62): 0x[01, 01, 03, 01, 05, 01, 0b, 05, 09, 08, 01, 10, 01, 00, 20, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 02, 01, 00, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 30, 09, 06, 02, 00, 00, 00, 12, 00, 13, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -88,7 +88,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 32) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) @@ -104,23 +104,23 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: non_control_flow::foo -Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 2) Highest counter ID seen: c0 Function name: non_control_flow::func_call -Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 29, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 28, 03, 02, 00, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] +Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 28, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 28, 03, 02, 00, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 40, 1) to (start + 0, 32) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) - Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10) - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 9) to (start + 0, 15) @@ -135,7 +135,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: non_control_flow::right_comb_tree -Raw bytes (111): 0x[01, 01, 05, 01, 05, 05, 09, 09, 0d, 0d, 11, 11, 15, 0e, 01, 20, 01, 00, 41, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 02, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 09, 06, 02, 03, 00, 00, 13, 00, 14, 09, 00, 19, 00, 1a, 30, 0d, 0a, 03, 04, 00, 00, 19, 00, 1a, 0d, 00, 1f, 00, 20, 30, 11, 0e, 04, 05, 00, 00, 1f, 00, 20, 11, 00, 24, 00, 27, 30, 15, 12, 05, 00, 00, 00, 24, 00, 27, 01, 01, 05, 01, 02] +Raw bytes (111): 0x[01, 01, 05, 01, 05, 05, 09, 09, 0d, 0d, 11, 11, 15, 0e, 01, 1f, 01, 00, 41, 01, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 02, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 09, 06, 02, 03, 00, 00, 13, 00, 14, 09, 00, 19, 00, 1a, 30, 0d, 0a, 03, 04, 00, 00, 19, 00, 1a, 0d, 00, 1f, 00, 20, 30, 11, 0e, 04, 05, 00, 00, 1f, 00, 20, 11, 00, 24, 00, 27, 30, 15, 12, 05, 00, 00, 00, 24, 00, 27, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -145,7 +145,7 @@ Number of expressions: 5 - expression 3 operands: lhs = Counter(3), rhs = Counter(4) - expression 4 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65) +- Code(Counter(0)) at (prev + 31, 1) to (start + 0, 65) - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - MCDCDecision { bitmap_idx: 6, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42) diff --git a/tests/coverage/mcdc/non_control_flow.coverage b/tests/coverage/mcdc/non_control_flow.coverage index cead419fbdf9..419d40bb6f99 100644 --- a/tests/coverage/mcdc/non_control_flow.coverage +++ b/tests/coverage/mcdc/non_control_flow.coverage @@ -1,6 +1,5 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/non_control_flow.rs b/tests/coverage/mcdc/non_control_flow.rs index 6cfce6fae935..863bb8a5756d 100644 --- a/tests/coverage/mcdc/non_control_flow.rs +++ b/tests/coverage/mcdc/non_control_flow.rs @@ -1,6 +1,5 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/ui/abi/large-byval-align.rs b/tests/ui/abi/large-byval-align.rs index ddd579f264e6..c1de841178fc 100644 --- a/tests/ui/abi/large-byval-align.rs +++ b/tests/ui/abi/large-byval-align.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Copt-level=0 //@ only-x86_64 -//@ min-llvm-version: 19 //@ build-pass #[repr(align(536870912))] diff --git a/tests/ui/asm/aarch64/srcloc.old.stderr b/tests/ui/asm/aarch64/srcloc.old.stderr deleted file mode 100644 index 2a15e48f0256..000000000000 --- a/tests/ui/asm/aarch64/srcloc.old.stderr +++ /dev/null @@ -1,290 +0,0 @@ -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:15:15 - | -LL | asm!("invalid_instruction"); - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:19:13 - | -LL | invalid_instruction - | ^ - | -note: instantiated into assembly here - --> :2:13 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:24:13 - | -LL | invalid_instruction - | ^ - | -note: instantiated into assembly here - --> :2:13 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:30:13 - | -LL | invalid_instruction - | ^ - | -note: instantiated into assembly here - --> :3:13 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:37:13 - | -LL | invalid_instruction - | ^ - | -note: instantiated into assembly here - --> :3:13 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:42:14 - | -LL | asm!(concat!("invalid", "_", "instruction")); - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:46:14 - | -LL | "invalid_instruction", - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:52:14 - | -LL | "invalid_instruction", - | ^ - | -note: instantiated into assembly here - --> :2:1 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:59:14 - | -LL | "invalid_instruction", - | ^ - | -note: instantiated into assembly here - --> :3:1 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:66:13 - | -LL | concat!("invalid", "_", "instruction"), - | ^ - | -note: instantiated into assembly here - --> :2:1 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:73:13 - | -LL | concat!("invalid", "_", "instruction"), - | ^ - | -note: instantiated into assembly here - --> :2:1 - | -LL | invalid_instruction - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:80:14 - | -LL | "invalid_instruction1", - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | invalid_instruction1 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:81:14 - | -LL | "invalid_instruction2", - | ^ - | -note: instantiated into assembly here - --> :2:1 - | -LL | invalid_instruction2 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:87:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | invalid_instruction1 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:87:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :2:1 - | -LL | invalid_instruction2 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:96:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | invalid_instruction1 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:96:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :2:1 - | -LL | invalid_instruction2 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:100:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :3:1 - | -LL | invalid_instruction3 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:100:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :4:1 - | -LL | invalid_instruction4 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:111:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | invalid_instruction1 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:111:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :2:1 - | -LL | invalid_instruction2 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:115:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :4:1 - | -LL | invalid_instruction3 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:115:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :5:1 - | -LL | invalid_instruction4 - | ^ - -error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:128:14 - | -LL | "invalid_instruction" - | ^ - | -note: instantiated into assembly here - --> :4:1 - | -LL | invalid_instruction - | ^ - -error: aborting due to 24 previous errors - diff --git a/tests/ui/asm/aarch64/srcloc.rs b/tests/ui/asm/aarch64/srcloc.rs index 9b92dfef056d..c635fa6ba700 100644 --- a/tests/ui/asm/aarch64/srcloc.rs +++ b/tests/ui/asm/aarch64/srcloc.rs @@ -1,10 +1,7 @@ -//@ revisions: old new //@ only-aarch64 //@ build-fail //@ needs-asm-support //@ compile-flags: -Ccodegen-units=1 -//@[old] ignore-llvm-version: 19 - 99 -//@[new] min-llvm-version: 19 use std::arch::asm; diff --git a/tests/ui/asm/aarch64/srcloc.new.stderr b/tests/ui/asm/aarch64/srcloc.stderr similarity index 91% rename from tests/ui/asm/aarch64/srcloc.new.stderr rename to tests/ui/asm/aarch64/srcloc.stderr index b92a07e5fb13..b47f19bea614 100644 --- a/tests/ui/asm/aarch64/srcloc.new.stderr +++ b/tests/ui/asm/aarch64/srcloc.stderr @@ -1,5 +1,5 @@ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:15:15 + --> $DIR/srcloc.rs:12:15 | LL | asm!("invalid_instruction"); | ^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:19:13 + --> $DIR/srcloc.rs:16:13 | LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:24:13 + --> $DIR/srcloc.rs:21:13 | LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:30:13 + --> $DIR/srcloc.rs:27:13 | LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:37:13 + --> $DIR/srcloc.rs:34:13 | LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:42:14 + --> $DIR/srcloc.rs:39:14 | LL | asm!(concat!("invalid", "_", "instruction")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:46:14 + --> $DIR/srcloc.rs:43:14 | LL | "invalid_instruction", | ^^^^^^^^^^^^^^^^^^^ @@ -83,7 +83,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:52:14 + --> $DIR/srcloc.rs:49:14 | LL | "invalid_instruction", | ^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:59:14 + --> $DIR/srcloc.rs:56:14 | LL | "invalid_instruction", | ^^^^^^^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:66:13 + --> $DIR/srcloc.rs:63:13 | LL | concat!("invalid", "_", "instruction"), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:73:13 + --> $DIR/srcloc.rs:70:13 | LL | concat!("invalid", "_", "instruction"), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:80:14 + --> $DIR/srcloc.rs:77:14 | LL | "invalid_instruction1", | ^^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | invalid_instruction1 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:81:14 + --> $DIR/srcloc.rs:78:14 | LL | "invalid_instruction2", | ^^^^^^^^^^^^^^^^^^^^ @@ -155,7 +155,7 @@ LL | invalid_instruction2 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:87:13 + --> $DIR/srcloc.rs:84:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -170,7 +170,7 @@ LL | invalid_instruction1 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:87:13 + --> $DIR/srcloc.rs:84:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -185,7 +185,7 @@ LL | invalid_instruction2 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:96:13 + --> $DIR/srcloc.rs:93:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -200,7 +200,7 @@ LL | invalid_instruction1 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:96:13 + --> $DIR/srcloc.rs:93:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -215,7 +215,7 @@ LL | invalid_instruction2 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:100:13 + --> $DIR/srcloc.rs:97:13 | LL | / concat!( LL | | "invalid", "_", "instruction3", "\n", @@ -230,7 +230,7 @@ LL | invalid_instruction3 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:100:13 + --> $DIR/srcloc.rs:97:13 | LL | / concat!( LL | | "invalid", "_", "instruction3", "\n", @@ -245,7 +245,7 @@ LL | invalid_instruction4 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:111:13 + --> $DIR/srcloc.rs:108:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -260,7 +260,7 @@ LL | invalid_instruction1 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:111:13 + --> $DIR/srcloc.rs:108:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -275,7 +275,7 @@ LL | invalid_instruction2 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:115:13 + --> $DIR/srcloc.rs:112:13 | LL | / concat!( LL | | "invalid", "_", "instruction3", "\n", @@ -290,7 +290,7 @@ LL | invalid_instruction3 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:115:13 + --> $DIR/srcloc.rs:112:13 | LL | / concat!( LL | | "invalid", "_", "instruction3", "\n", @@ -305,7 +305,7 @@ LL | invalid_instruction4 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:128:14 + --> $DIR/srcloc.rs:125:14 | LL | "invalid_instruction" | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/inline-syntax.arm.stderr b/tests/ui/asm/inline-syntax.arm.stderr index 4003a10f3745..5b4eb3cc1409 100644 --- a/tests/ui/asm/inline-syntax.arm.stderr +++ b/tests/ui/asm/inline-syntax.arm.stderr @@ -15,7 +15,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:26:15 + --> $DIR/inline-syntax.rs:21:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:30:15 + --> $DIR/inline-syntax.rs:24:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | .intel_syntax aaa noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:34:15 + --> $DIR/inline-syntax.rs:27:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | .att_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:30:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | .att_syntax bbb noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:42:15 + --> $DIR/inline-syntax.rs:33:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,7 +75,7 @@ LL | .intel_syntax noprefix; nop | ^ error: unknown directive - --> $DIR/inline-syntax.rs:49:13 + --> $DIR/inline-syntax.rs:39:13 | LL | .intel_syntax noprefix | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/inline-syntax.arm_llvm_18.stderr b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr deleted file mode 100644 index a03861c78a3e..000000000000 --- a/tests/ui/asm/inline-syntax.arm_llvm_18.stderr +++ /dev/null @@ -1,90 +0,0 @@ -error: unknown directive - | -note: instantiated into assembly here - --> :1:1 - | -LL | .intel_syntax noprefix - | ^ - -error: unknown directive - | -note: instantiated into assembly here - --> :1:1 - | -LL | .intel_syntax noprefix - | ^ - -error: unknown directive - --> $DIR/inline-syntax.rs:26:15 - | -LL | asm!(".intel_syntax noprefix", "nop"); - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | .intel_syntax noprefix - | ^ - -error: unknown directive - --> $DIR/inline-syntax.rs:30:15 - | -LL | asm!(".intel_syntax aaa noprefix", "nop"); - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | .intel_syntax aaa noprefix - | ^ - -error: unknown directive - --> $DIR/inline-syntax.rs:34:15 - | -LL | asm!(".att_syntax noprefix", "nop"); - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | .att_syntax noprefix - | ^ - -error: unknown directive - --> $DIR/inline-syntax.rs:38:15 - | -LL | asm!(".att_syntax bbb noprefix", "nop"); - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | .att_syntax bbb noprefix - | ^ - -error: unknown directive - --> $DIR/inline-syntax.rs:42:15 - | -LL | asm!(".intel_syntax noprefix; nop"); - | ^ - | -note: instantiated into assembly here - --> :1:2 - | -LL | .intel_syntax noprefix; nop - | ^ - -error: unknown directive - --> $DIR/inline-syntax.rs:49:13 - | -LL | .intel_syntax noprefix - | ^ - | -note: instantiated into assembly here - --> :2:13 - | -LL | .intel_syntax noprefix - | ^ - -error: aborting due to 8 previous errors - diff --git a/tests/ui/asm/inline-syntax.rs b/tests/ui/asm/inline-syntax.rs index 78f30d50d8c0..5f2f4e357f9c 100644 --- a/tests/ui/asm/inline-syntax.rs +++ b/tests/ui/asm/inline-syntax.rs @@ -1,17 +1,12 @@ //@ add-core-stubs -//@ revisions: x86_64 arm_llvm_18 arm +//@ revisions: x86_64 arm //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu //@[x86_64] check-pass //@[x86_64] needs-llvm-components: x86 -//@[arm_llvm_18] compile-flags: --target armv7-unknown-linux-gnueabihf -//@[arm_llvm_18] build-fail -//@[arm_llvm_18] needs-llvm-components: arm -//@[arm_llvm_18] ignore-llvm-version: 19 - 99 // LLVM 19+ has full support for 64-bit cookies. //@[arm] compile-flags: --target armv7-unknown-linux-gnueabihf //@[arm] build-fail //@[arm] needs-llvm-components: arm -//@[arm] min-llvm-version: 19 //@ needs-asm-support #![feature(no_core)] @@ -26,23 +21,18 @@ pub fn main() { asm!(".intel_syntax noprefix", "nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` //[arm]~^^ ERROR unknown directive - //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".intel_syntax aaa noprefix", "nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` //[arm]~^^ ERROR unknown directive - //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".att_syntax noprefix", "nop"); //[x86_64]~^ WARN avoid using `.att_syntax` //[arm]~^^ ERROR unknown directive - //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".att_syntax bbb noprefix", "nop"); //[x86_64]~^ WARN avoid using `.att_syntax` //[arm]~^^ ERROR unknown directive - //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".intel_syntax noprefix; nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` //[arm]~^^ ERROR unknown directive - //[arm_llvm_18]~^^^ ERROR unknown directive asm!( r" @@ -51,7 +41,6 @@ pub fn main() { ); //[x86_64]~^^^ WARN avoid using `.intel_syntax` //[arm]~^^^^ ERROR unknown directive - //[arm_llvm_18]~^^^^^ ERROR unknown directive } } @@ -59,7 +48,5 @@ global_asm!(".intel_syntax noprefix", "nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` // Global assembly errors don't have line numbers, so no error on ARM. -//[arm_llvm_18]~? ERROR unknown directive -//[arm_llvm_18]~? ERROR unknown directive //[arm]~? ERROR unknown directive //[arm]~? ERROR unknown directive diff --git a/tests/ui/asm/inline-syntax.x86_64.stderr b/tests/ui/asm/inline-syntax.x86_64.stderr index 369f7b66ae45..2d8091c20441 100644 --- a/tests/ui/asm/inline-syntax.x86_64.stderr +++ b/tests/ui/asm/inline-syntax.x86_64.stderr @@ -1,5 +1,5 @@ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:58:14 + --> $DIR/inline-syntax.rs:47:14 | LL | global_asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | global_asm!(".intel_syntax noprefix", "nop"); = note: `#[warn(bad_asm_style)]` on by default warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:26:15 + --> $DIR/inline-syntax.rs:21:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:30:15 + --> $DIR/inline-syntax.rs:24:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:34:15 + --> $DIR/inline-syntax.rs:27:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:30:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:42:15 + --> $DIR/inline-syntax.rs:33:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:49:13 + --> $DIR/inline-syntax.rs:39:13 | LL | .intel_syntax noprefix | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr index 07c1bf211839..5d527cd70b81 100644 --- a/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr +++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr @@ -1,5 +1,5 @@ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:54:11 + --> $DIR/riscv32e-registers.rs:42:11 | LL | asm!("li x16, 0"); | ^^^^^^^^^ @@ -11,7 +11,7 @@ LL | li x16, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:57:11 + --> $DIR/riscv32e-registers.rs:45:11 | LL | asm!("li x17, 0"); | ^^^^^^^^^ @@ -23,7 +23,7 @@ LL | li x17, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:60:11 + --> $DIR/riscv32e-registers.rs:48:11 | LL | asm!("li x18, 0"); | ^^^^^^^^^ @@ -35,7 +35,7 @@ LL | li x18, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:63:11 + --> $DIR/riscv32e-registers.rs:51:11 | LL | asm!("li x19, 0"); | ^^^^^^^^^ @@ -47,7 +47,7 @@ LL | li x19, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:66:11 + --> $DIR/riscv32e-registers.rs:54:11 | LL | asm!("li x20, 0"); | ^^^^^^^^^ @@ -59,7 +59,7 @@ LL | li x20, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:69:11 + --> $DIR/riscv32e-registers.rs:57:11 | LL | asm!("li x21, 0"); | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | li x21, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:72:11 + --> $DIR/riscv32e-registers.rs:60:11 | LL | asm!("li x22, 0"); | ^^^^^^^^^ @@ -83,7 +83,7 @@ LL | li x22, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:75:11 + --> $DIR/riscv32e-registers.rs:63:11 | LL | asm!("li x23, 0"); | ^^^^^^^^^ @@ -95,7 +95,7 @@ LL | li x23, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:78:11 + --> $DIR/riscv32e-registers.rs:66:11 | LL | asm!("li x24, 0"); | ^^^^^^^^^ @@ -107,7 +107,7 @@ LL | li x24, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:81:11 + --> $DIR/riscv32e-registers.rs:69:11 | LL | asm!("li x25, 0"); | ^^^^^^^^^ @@ -119,7 +119,7 @@ LL | li x25, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:84:11 + --> $DIR/riscv32e-registers.rs:72:11 | LL | asm!("li x26, 0"); | ^^^^^^^^^ @@ -131,7 +131,7 @@ LL | li x26, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:87:11 + --> $DIR/riscv32e-registers.rs:75:11 | LL | asm!("li x27, 0"); | ^^^^^^^^^ @@ -143,7 +143,7 @@ LL | li x27, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:90:11 + --> $DIR/riscv32e-registers.rs:78:11 | LL | asm!("li x28, 0"); | ^^^^^^^^^ @@ -155,7 +155,7 @@ LL | li x28, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:93:11 + --> $DIR/riscv32e-registers.rs:81:11 | LL | asm!("li x29, 0"); | ^^^^^^^^^ @@ -167,7 +167,7 @@ LL | li x29, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:96:11 + --> $DIR/riscv32e-registers.rs:84:11 | LL | asm!("li x30, 0"); | ^^^^^^^^^ @@ -179,7 +179,7 @@ LL | li x30, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:99:11 + --> $DIR/riscv32e-registers.rs:87:11 | LL | asm!("li x31, 0"); | ^^^^^^^^^ diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32e_llvm_18.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32e_llvm_18.stderr deleted file mode 100644 index 59009b8c3525..000000000000 --- a/tests/ui/asm/riscv/riscv32e-registers.riscv32e_llvm_18.stderr +++ /dev/null @@ -1,194 +0,0 @@ -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:54:11 - | -LL | asm!("li x16, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x16, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:57:11 - | -LL | asm!("li x17, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x17, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:60:11 - | -LL | asm!("li x18, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x18, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:63:11 - | -LL | asm!("li x19, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x19, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:66:11 - | -LL | asm!("li x20, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x20, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:69:11 - | -LL | asm!("li x21, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x21, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:72:11 - | -LL | asm!("li x22, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x22, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:75:11 - | -LL | asm!("li x23, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x23, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:78:11 - | -LL | asm!("li x24, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x24, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:81:11 - | -LL | asm!("li x25, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x25, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:84:11 - | -LL | asm!("li x26, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x26, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:87:11 - | -LL | asm!("li x27, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x27, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:90:11 - | -LL | asm!("li x28, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x28, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:93:11 - | -LL | asm!("li x29, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x29, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:96:11 - | -LL | asm!("li x30, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x30, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:99:11 - | -LL | asm!("li x31, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x31, 0 - | ^ - -error: aborting due to 16 previous errors - diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr index 07c1bf211839..5d527cd70b81 100644 --- a/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr +++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr @@ -1,5 +1,5 @@ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:54:11 + --> $DIR/riscv32e-registers.rs:42:11 | LL | asm!("li x16, 0"); | ^^^^^^^^^ @@ -11,7 +11,7 @@ LL | li x16, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:57:11 + --> $DIR/riscv32e-registers.rs:45:11 | LL | asm!("li x17, 0"); | ^^^^^^^^^ @@ -23,7 +23,7 @@ LL | li x17, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:60:11 + --> $DIR/riscv32e-registers.rs:48:11 | LL | asm!("li x18, 0"); | ^^^^^^^^^ @@ -35,7 +35,7 @@ LL | li x18, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:63:11 + --> $DIR/riscv32e-registers.rs:51:11 | LL | asm!("li x19, 0"); | ^^^^^^^^^ @@ -47,7 +47,7 @@ LL | li x19, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:66:11 + --> $DIR/riscv32e-registers.rs:54:11 | LL | asm!("li x20, 0"); | ^^^^^^^^^ @@ -59,7 +59,7 @@ LL | li x20, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:69:11 + --> $DIR/riscv32e-registers.rs:57:11 | LL | asm!("li x21, 0"); | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | li x21, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:72:11 + --> $DIR/riscv32e-registers.rs:60:11 | LL | asm!("li x22, 0"); | ^^^^^^^^^ @@ -83,7 +83,7 @@ LL | li x22, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:75:11 + --> $DIR/riscv32e-registers.rs:63:11 | LL | asm!("li x23, 0"); | ^^^^^^^^^ @@ -95,7 +95,7 @@ LL | li x23, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:78:11 + --> $DIR/riscv32e-registers.rs:66:11 | LL | asm!("li x24, 0"); | ^^^^^^^^^ @@ -107,7 +107,7 @@ LL | li x24, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:81:11 + --> $DIR/riscv32e-registers.rs:69:11 | LL | asm!("li x25, 0"); | ^^^^^^^^^ @@ -119,7 +119,7 @@ LL | li x25, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:84:11 + --> $DIR/riscv32e-registers.rs:72:11 | LL | asm!("li x26, 0"); | ^^^^^^^^^ @@ -131,7 +131,7 @@ LL | li x26, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:87:11 + --> $DIR/riscv32e-registers.rs:75:11 | LL | asm!("li x27, 0"); | ^^^^^^^^^ @@ -143,7 +143,7 @@ LL | li x27, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:90:11 + --> $DIR/riscv32e-registers.rs:78:11 | LL | asm!("li x28, 0"); | ^^^^^^^^^ @@ -155,7 +155,7 @@ LL | li x28, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:93:11 + --> $DIR/riscv32e-registers.rs:81:11 | LL | asm!("li x29, 0"); | ^^^^^^^^^ @@ -167,7 +167,7 @@ LL | li x29, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:96:11 + --> $DIR/riscv32e-registers.rs:84:11 | LL | asm!("li x30, 0"); | ^^^^^^^^^ @@ -179,7 +179,7 @@ LL | li x30, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:99:11 + --> $DIR/riscv32e-registers.rs:87:11 | LL | asm!("li x31, 0"); | ^^^^^^^^^ diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32em_llvm_18.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32em_llvm_18.stderr deleted file mode 100644 index 59009b8c3525..000000000000 --- a/tests/ui/asm/riscv/riscv32e-registers.riscv32em_llvm_18.stderr +++ /dev/null @@ -1,194 +0,0 @@ -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:54:11 - | -LL | asm!("li x16, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x16, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:57:11 - | -LL | asm!("li x17, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x17, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:60:11 - | -LL | asm!("li x18, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x18, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:63:11 - | -LL | asm!("li x19, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x19, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:66:11 - | -LL | asm!("li x20, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x20, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:69:11 - | -LL | asm!("li x21, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x21, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:72:11 - | -LL | asm!("li x22, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x22, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:75:11 - | -LL | asm!("li x23, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x23, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:78:11 - | -LL | asm!("li x24, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x24, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:81:11 - | -LL | asm!("li x25, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x25, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:84:11 - | -LL | asm!("li x26, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x26, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:87:11 - | -LL | asm!("li x27, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x27, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:90:11 - | -LL | asm!("li x28, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x28, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:93:11 - | -LL | asm!("li x29, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x29, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:96:11 - | -LL | asm!("li x30, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x30, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:99:11 - | -LL | asm!("li x31, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x31, 0 - | ^ - -error: aborting due to 16 previous errors - diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr index 07c1bf211839..5d527cd70b81 100644 --- a/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr +++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr @@ -1,5 +1,5 @@ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:54:11 + --> $DIR/riscv32e-registers.rs:42:11 | LL | asm!("li x16, 0"); | ^^^^^^^^^ @@ -11,7 +11,7 @@ LL | li x16, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:57:11 + --> $DIR/riscv32e-registers.rs:45:11 | LL | asm!("li x17, 0"); | ^^^^^^^^^ @@ -23,7 +23,7 @@ LL | li x17, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:60:11 + --> $DIR/riscv32e-registers.rs:48:11 | LL | asm!("li x18, 0"); | ^^^^^^^^^ @@ -35,7 +35,7 @@ LL | li x18, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:63:11 + --> $DIR/riscv32e-registers.rs:51:11 | LL | asm!("li x19, 0"); | ^^^^^^^^^ @@ -47,7 +47,7 @@ LL | li x19, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:66:11 + --> $DIR/riscv32e-registers.rs:54:11 | LL | asm!("li x20, 0"); | ^^^^^^^^^ @@ -59,7 +59,7 @@ LL | li x20, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:69:11 + --> $DIR/riscv32e-registers.rs:57:11 | LL | asm!("li x21, 0"); | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | li x21, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:72:11 + --> $DIR/riscv32e-registers.rs:60:11 | LL | asm!("li x22, 0"); | ^^^^^^^^^ @@ -83,7 +83,7 @@ LL | li x22, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:75:11 + --> $DIR/riscv32e-registers.rs:63:11 | LL | asm!("li x23, 0"); | ^^^^^^^^^ @@ -95,7 +95,7 @@ LL | li x23, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:78:11 + --> $DIR/riscv32e-registers.rs:66:11 | LL | asm!("li x24, 0"); | ^^^^^^^^^ @@ -107,7 +107,7 @@ LL | li x24, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:81:11 + --> $DIR/riscv32e-registers.rs:69:11 | LL | asm!("li x25, 0"); | ^^^^^^^^^ @@ -119,7 +119,7 @@ LL | li x25, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:84:11 + --> $DIR/riscv32e-registers.rs:72:11 | LL | asm!("li x26, 0"); | ^^^^^^^^^ @@ -131,7 +131,7 @@ LL | li x26, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:87:11 + --> $DIR/riscv32e-registers.rs:75:11 | LL | asm!("li x27, 0"); | ^^^^^^^^^ @@ -143,7 +143,7 @@ LL | li x27, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:90:11 + --> $DIR/riscv32e-registers.rs:78:11 | LL | asm!("li x28, 0"); | ^^^^^^^^^ @@ -155,7 +155,7 @@ LL | li x28, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:93:11 + --> $DIR/riscv32e-registers.rs:81:11 | LL | asm!("li x29, 0"); | ^^^^^^^^^ @@ -167,7 +167,7 @@ LL | li x29, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:96:11 + --> $DIR/riscv32e-registers.rs:84:11 | LL | asm!("li x30, 0"); | ^^^^^^^^^ @@ -179,7 +179,7 @@ LL | li x30, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:99:11 + --> $DIR/riscv32e-registers.rs:87:11 | LL | asm!("li x31, 0"); | ^^^^^^^^^ diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32emc_llvm_18.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32emc_llvm_18.stderr deleted file mode 100644 index 59009b8c3525..000000000000 --- a/tests/ui/asm/riscv/riscv32e-registers.riscv32emc_llvm_18.stderr +++ /dev/null @@ -1,194 +0,0 @@ -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:54:11 - | -LL | asm!("li x16, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x16, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:57:11 - | -LL | asm!("li x17, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x17, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:60:11 - | -LL | asm!("li x18, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x18, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:63:11 - | -LL | asm!("li x19, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x19, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:66:11 - | -LL | asm!("li x20, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x20, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:69:11 - | -LL | asm!("li x21, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x21, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:72:11 - | -LL | asm!("li x22, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x22, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:75:11 - | -LL | asm!("li x23, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x23, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:78:11 - | -LL | asm!("li x24, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x24, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:81:11 - | -LL | asm!("li x25, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x25, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:84:11 - | -LL | asm!("li x26, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x26, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:87:11 - | -LL | asm!("li x27, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x27, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:90:11 - | -LL | asm!("li x28, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x28, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:93:11 - | -LL | asm!("li x29, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x29, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:96:11 - | -LL | asm!("li x30, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x30, 0 - | ^ - -error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:99:11 - | -LL | asm!("li x31, 0"); - | ^ - | -note: instantiated into assembly here - --> :1:5 - | -LL | li x31, 0 - | ^ - -error: aborting due to 16 previous errors - diff --git a/tests/ui/asm/riscv/riscv32e-registers.rs b/tests/ui/asm/riscv/riscv32e-registers.rs index 99cbdf5ead3f..96bfe2af0644 100644 --- a/tests/ui/asm/riscv/riscv32e-registers.rs +++ b/tests/ui/asm/riscv/riscv32e-registers.rs @@ -2,27 +2,15 @@ // //@ add-core-stubs //@ build-fail -//@ revisions: riscv32e riscv32em riscv32emc riscv32e_llvm_18 riscv32em_llvm_18 riscv32emc_llvm_18 +//@ revisions: riscv32e riscv32em riscv32emc // //@ compile-flags: --crate-type=rlib //@ [riscv32e] needs-llvm-components: riscv //@ [riscv32e] compile-flags: --target=riscv32e-unknown-none-elf -//@ [riscv32e] min-llvm-version: 19 //@ [riscv32em] needs-llvm-components: riscv //@ [riscv32em] compile-flags: --target=riscv32em-unknown-none-elf -//@ [riscv32em] min-llvm-version: 19 //@ [riscv32emc] needs-llvm-components: riscv //@ [riscv32emc] compile-flags: --target=riscv32emc-unknown-none-elf -//@ [riscv32emc] min-llvm-version: 19 -//@ [riscv32e_llvm_18] needs-llvm-components: riscv -//@ [riscv32e_llvm_18] compile-flags: --target=riscv32e-unknown-none-elf -//@ [riscv32e_llvm_18] ignore-llvm-version: 19 - 99 -//@ [riscv32em_llvm_18] needs-llvm-components: riscv -//@ [riscv32em_llvm_18] compile-flags: --target=riscv32em-unknown-none-elf -//@ [riscv32em_llvm_18] ignore-llvm-version: 19 - 99 -//@ [riscv32emc_llvm_18] needs-llvm-components: riscv -//@ [riscv32emc_llvm_18] compile-flags: --target=riscv32emc-unknown-none-elf -//@ [riscv32emc_llvm_18] ignore-llvm-version: 19 - 99 // Unlike bad-reg.rs, this tests if the assembler can reject invalid registers // usage in assembly code. diff --git a/tests/ui/asm/x86_64/srcloc.old.stderr b/tests/ui/asm/x86_64/srcloc.old.stderr deleted file mode 100644 index edb9ee46812f..000000000000 --- a/tests/ui/asm/x86_64/srcloc.old.stderr +++ /dev/null @@ -1,302 +0,0 @@ -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:14:15 - | -LL | asm!("invalid_instruction"); - | ^ - | -note: instantiated into assembly here - --> :2:2 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:18:13 - | -LL | invalid_instruction - | ^ - | -note: instantiated into assembly here - --> :3:13 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:23:13 - | -LL | invalid_instruction - | ^ - | -note: instantiated into assembly here - --> :3:13 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:29:13 - | -LL | invalid_instruction - | ^ - | -note: instantiated into assembly here - --> :4:13 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:36:13 - | -LL | invalid_instruction - | ^ - | -note: instantiated into assembly here - --> :4:13 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:41:14 - | -LL | asm!(concat!("invalid", "_", "instruction")); - | ^ - | -note: instantiated into assembly here - --> :2:2 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -warning: scale factor without index register is ignored - --> $DIR/srcloc.rs:44:15 - | -LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax)); - | ^ - | -note: instantiated into assembly here - --> :1:23 - | -LL | movaps %xmm3, (%esi, 2) - | ^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:48:14 - | -LL | "invalid_instruction", - | ^ - | -note: instantiated into assembly here - --> :2:2 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:54:14 - | -LL | "invalid_instruction", - | ^ - | -note: instantiated into assembly here - --> :3:1 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:61:14 - | -LL | "invalid_instruction", - | ^ - | -note: instantiated into assembly here - --> :4:1 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:68:13 - | -LL | concat!("invalid", "_", "instruction"), - | ^ - | -note: instantiated into assembly here - --> :3:1 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:75:13 - | -LL | concat!("invalid", "_", "instruction"), - | ^ - | -note: instantiated into assembly here - --> :3:1 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:82:14 - | -LL | "invalid_instruction1", - | ^ - | -note: instantiated into assembly here - --> :2:2 - | -LL | invalid_instruction1 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:83:14 - | -LL | "invalid_instruction2", - | ^ - | -note: instantiated into assembly here - --> :3:1 - | -LL | invalid_instruction2 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:89:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :2:2 - | -LL | invalid_instruction1 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:89:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :3:1 - | -LL | invalid_instruction2 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:98:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :2:2 - | -LL | invalid_instruction1 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:98:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :3:1 - | -LL | invalid_instruction2 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction3' - --> $DIR/srcloc.rs:102:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :4:1 - | -LL | invalid_instruction3 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction4' - --> $DIR/srcloc.rs:102:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :5:1 - | -LL | invalid_instruction4 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:113:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :2:2 - | -LL | invalid_instruction1 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:113:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :3:1 - | -LL | invalid_instruction2 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction3' - --> $DIR/srcloc.rs:117:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :5:1 - | -LL | invalid_instruction3 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction4' - --> $DIR/srcloc.rs:117:13 - | -LL | concat!( - | ^ - | -note: instantiated into assembly here - --> :6:1 - | -LL | invalid_instruction4 - | ^^^^^^^^^^^^^^^^^^^^ - -error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:130:14 - | -LL | "invalid_instruction" - | ^ - | -note: instantiated into assembly here - --> :5:1 - | -LL | invalid_instruction - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 24 previous errors; 1 warning emitted - diff --git a/tests/ui/asm/x86_64/srcloc.rs b/tests/ui/asm/x86_64/srcloc.rs index 40fc66cbc929..2938bafe5e70 100644 --- a/tests/ui/asm/x86_64/srcloc.rs +++ b/tests/ui/asm/x86_64/srcloc.rs @@ -1,9 +1,6 @@ -//@ revisions: old new //@ only-x86_64 //@ build-fail //@ compile-flags: -Ccodegen-units=1 -//@[old] ignore-llvm-version: 19 - 99 -//@[new] min-llvm-version: 19 use std::arch::asm; diff --git a/tests/ui/asm/x86_64/srcloc.new.stderr b/tests/ui/asm/x86_64/srcloc.stderr similarity index 92% rename from tests/ui/asm/x86_64/srcloc.new.stderr rename to tests/ui/asm/x86_64/srcloc.stderr index 7211f1ab69dc..bb4e855163d7 100644 --- a/tests/ui/asm/x86_64/srcloc.new.stderr +++ b/tests/ui/asm/x86_64/srcloc.stderr @@ -1,5 +1,5 @@ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:14:15 + --> $DIR/srcloc.rs:11:15 | LL | asm!("invalid_instruction"); | ^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:18:13 + --> $DIR/srcloc.rs:15:13 | LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:23:13 + --> $DIR/srcloc.rs:20:13 | LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:29:13 + --> $DIR/srcloc.rs:26:13 | LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:36:13 + --> $DIR/srcloc.rs:33:13 | LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:41:14 + --> $DIR/srcloc.rs:38:14 | LL | asm!(concat!("invalid", "_", "instruction")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ warning: scale factor without index register is ignored - --> $DIR/srcloc.rs:44:15 + --> $DIR/srcloc.rs:41:15 | LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax)); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -83,7 +83,7 @@ LL | movaps %xmm3, (%esi, 2) | ^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:48:14 + --> $DIR/srcloc.rs:45:14 | LL | "invalid_instruction", | ^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:54:14 + --> $DIR/srcloc.rs:51:14 | LL | "invalid_instruction", | ^^^^^^^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:61:14 + --> $DIR/srcloc.rs:58:14 | LL | "invalid_instruction", | ^^^^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:68:13 + --> $DIR/srcloc.rs:65:13 | LL | concat!("invalid", "_", "instruction"), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:75:13 + --> $DIR/srcloc.rs:72:13 | LL | concat!("invalid", "_", "instruction"), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:82:14 + --> $DIR/srcloc.rs:79:14 | LL | "invalid_instruction1", | ^^^^^^^^^^^^^^^^^^^^ @@ -155,7 +155,7 @@ LL | invalid_instruction1 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:83:14 + --> $DIR/srcloc.rs:80:14 | LL | "invalid_instruction2", | ^^^^^^^^^^^^^^^^^^^^ @@ -167,7 +167,7 @@ LL | invalid_instruction2 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:89:13 + --> $DIR/srcloc.rs:86:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -182,7 +182,7 @@ LL | invalid_instruction1 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:89:13 + --> $DIR/srcloc.rs:86:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -197,7 +197,7 @@ LL | invalid_instruction2 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:98:13 + --> $DIR/srcloc.rs:95:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -212,7 +212,7 @@ LL | invalid_instruction1 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:98:13 + --> $DIR/srcloc.rs:95:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -227,7 +227,7 @@ LL | invalid_instruction2 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction3' - --> $DIR/srcloc.rs:102:13 + --> $DIR/srcloc.rs:99:13 | LL | / concat!( LL | | "invalid", "_", "instruction3", "\n", @@ -242,7 +242,7 @@ LL | invalid_instruction3 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction4' - --> $DIR/srcloc.rs:102:13 + --> $DIR/srcloc.rs:99:13 | LL | / concat!( LL | | "invalid", "_", "instruction3", "\n", @@ -257,7 +257,7 @@ LL | invalid_instruction4 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:113:13 + --> $DIR/srcloc.rs:110:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -272,7 +272,7 @@ LL | invalid_instruction1 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:113:13 + --> $DIR/srcloc.rs:110:13 | LL | / concat!( LL | | "invalid", "_", "instruction1", "\n", @@ -287,7 +287,7 @@ LL | invalid_instruction2 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction3' - --> $DIR/srcloc.rs:117:13 + --> $DIR/srcloc.rs:114:13 | LL | / concat!( LL | | "invalid", "_", "instruction3", "\n", @@ -302,7 +302,7 @@ LL | invalid_instruction3 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction4' - --> $DIR/srcloc.rs:117:13 + --> $DIR/srcloc.rs:114:13 | LL | / concat!( LL | | "invalid", "_", "instruction3", "\n", @@ -317,7 +317,7 @@ LL | invalid_instruction4 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:130:14 + --> $DIR/srcloc.rs:127:14 | LL | "invalid_instruction" | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.rs b/tests/ui/instrument-coverage/mcdc-condition-limit.rs index 118ae482fc6c..74707ba2e670 100644 --- a/tests/ui/instrument-coverage/mcdc-condition-limit.rs +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.rs @@ -1,5 +1,4 @@ //@ edition: 2021 -//@ min-llvm-version: 19 //@ revisions: good //@ check-pass //@ compile-flags: -Cinstrument-coverage -Zcoverage-options=mcdc -Zno-profiler-runtime From 3af666ea915aa0a125f5d473e30b20600ca90f08 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sat, 29 Mar 2025 15:23:58 -0700 Subject: [PATCH 173/176] tidy: Fix paths to coretests and alloctests Following `#135937` and `#136642`, tests for core and alloc are in coretests and alloctests. Fix tidy to lint for the new paths. Also, update comments referring to the old locations. Some context for changes which don't match that pattern: * library/std/src/thread/local/dynamic_tests.rs and library/std/src/sync/mpsc/sync_tests.rs were moved under library/std/tests/ in 332fb7e6f1d (Move std::thread_local unit tests to integration tests, 2025-01-17) and b8ae372e483 (Move std::sync unit tests to integration tests, 2025-01-17), respectively, so are no longer special cases. * There never was a library/core/tests/fmt.rs file. That comment previously referred to src/test/ui/ifmt.rs, which was folded into library/alloc/tests/fmt.rs in 949c96660c3 (move format! interface tests, 2020-09-08). --- library/core/src/fmt/mod.rs | 4 +-- library/coretests/tests/str.rs | 2 +- src/tools/tidy/src/unit_tests.rs | 51 ++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 30fd2d7815f5..f1a9cec318fd 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -3016,6 +3016,6 @@ impl Debug for SyncUnsafeCell { } } -// If you expected tests to be here, look instead at the core/tests/fmt.rs file, +// If you expected tests to be here, look instead at coretests/tests/fmt/; // it's a lot easier than creating all of the rt::Piece structures here. -// There are also tests in the alloc crate, for those that need allocations. +// There are also tests in alloctests/tests/fmt.rs, for those that need allocations. diff --git a/library/coretests/tests/str.rs b/library/coretests/tests/str.rs index f5066343af20..5e23e910f0ae 100644 --- a/library/coretests/tests/str.rs +++ b/library/coretests/tests/str.rs @@ -1 +1 @@ -// All `str` tests live in library/alloc/tests/str.rs +// All `str` tests live in library/alloctests/tests/str.rs diff --git a/src/tools/tidy/src/unit_tests.rs b/src/tools/tidy/src/unit_tests.rs index 708e4ef80857..90ef36d5882d 100644 --- a/src/tools/tidy/src/unit_tests.rs +++ b/src/tools/tidy/src/unit_tests.rs @@ -1,11 +1,13 @@ -//! Tidy check to ensure `#[test]` and `#[bench]` are not used directly inside `core`. +//! Tidy check to ensure `#[test]` and `#[bench]` are not used directly inside +//! `core` or `alloc`. //! -//! `#![no_core]` libraries cannot be tested directly due to duplicating lang -//! items. All tests and benchmarks must be written externally in `core/{tests,benches}`. +//! `core` and `alloc` cannot be tested directly due to duplicating lang items. +//! All tests and benchmarks must be written externally in +//! `{coretests,alloctests}/{tests,benches}`. //! -//! Outside of core tests and benchmarks should be outlined into separate files -//! named `tests.rs` or `benches.rs`, or directories named `tests` or `benches` unconfigured -//! during normal build. +//! Outside of `core` and `alloc`, tests and benchmarks should be outlined into +//! separate files named `tests.rs` or `benches.rs`, or directories named +//! `tests` or `benches` unconfigured during normal build. use std::path::Path; @@ -14,40 +16,51 @@ use crate::walk::{filter_dirs, walk}; pub fn check(root_path: &Path, bad: &mut bool) { let core = root_path.join("core"); let core_copy = core.clone(); - let core_tests = core.join("tests"); - let core_benches = core.join("benches"); - let is_core = move |path: &Path| { - path.starts_with(&core) - && !(path.starts_with(&core_tests) || path.starts_with(&core_benches)) - }; + let is_core = move |path: &Path| path.starts_with(&core); + let alloc = root_path.join("alloc"); + let alloc_copy = alloc.clone(); + let is_alloc = move |path: &Path| path.starts_with(&alloc); let skip = move |path: &Path, is_dir| { let file_name = path.file_name().unwrap_or_default(); if is_dir { filter_dirs(path) || path.ends_with("src/doc") - || (file_name == "tests" || file_name == "benches") && !is_core(path) + || (file_name == "tests" || file_name == "benches") + && !is_core(path) + && !is_alloc(path) } else { let extension = path.extension().unwrap_or_default(); extension != "rs" - || (file_name == "tests.rs" || file_name == "benches.rs") && !is_core(path) - // UI tests with different names - || path.ends_with("src/thread/local/dynamic_tests.rs") - || path.ends_with("src/sync/mpsc/sync_tests.rs") + || (file_name == "tests.rs" || file_name == "benches.rs") + && !is_core(path) + && !is_alloc(path) + // Tests which use non-public internals and, as such, need to + // have the types in the same crate as the tests themselves. See + // the comment in alloctests/lib.rs. + || path.ends_with("library/alloc/src/collections/btree/borrow/tests.rs") + || path.ends_with("library/alloc/src/collections/btree/map/tests.rs") + || path.ends_with("library/alloc/src/collections/btree/node/tests.rs") + || path.ends_with("library/alloc/src/collections/btree/set/tests.rs") + || path.ends_with("library/alloc/src/collections/linked_list/tests.rs") + || path.ends_with("library/alloc/src/collections/vec_deque/tests.rs") + || path.ends_with("library/alloc/src/raw_vec/tests.rs") } }; walk(root_path, skip, &mut |entry, contents| { let path = entry.path(); let is_core = path.starts_with(&core_copy); + let is_alloc = path.starts_with(&alloc_copy); for (i, line) in contents.lines().enumerate() { let line = line.trim(); let is_test = || line.contains("#[test]") && !line.contains("`#[test]"); let is_bench = || line.contains("#[bench]") && !line.contains("`#[bench]"); if !line.starts_with("//") && (is_test() || is_bench()) { let explanation = if is_core { - "core unit tests and benchmarks must be placed into \ - `core/tests` or `core/benches`" + "`core` unit tests and benchmarks must be placed into `coretests`" + } else if is_alloc { + "`alloc` unit tests and benchmarks must be placed into `alloctests`" } else { "unit tests and benchmarks must be placed into \ separate files or directories named \ From d1eebd4b8c78bba38ff91d2f5ea24f2839b5029a Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 6 Apr 2025 00:23:40 +0000 Subject: [PATCH 174/176] cargo update compiler & tools dependencies: Locking 11 packages to latest compatible versions Updating blake3 v1.8.0 -> v1.8.1 Updating ctrlc v3.4.5 -> v3.4.6 Updating env_logger v0.11.7 -> v0.11.8 Updating errno v0.3.10 -> v0.3.11 Updating flate2 v1.1.0 -> v1.1.1 Updating indexmap v2.8.0 -> v2.9.0 Updating miniz_oxide v0.8.5 -> v0.8.7 Updating openssl-sys v0.9.106 -> v0.9.107 Updating redox_syscall v0.5.10 -> v0.5.11 Updating smallvec v1.14.0 -> v1.15.0 Updating tokio v1.44.1 -> v1.44.2 note: pass `--verbose` to see 40 unchanged dependencies behind latest library dependencies: Locking 1 package to latest compatible version Updating miniz_oxide v0.8.5 -> v0.8.7 note: pass `--verbose` to see 4 unchanged dependencies behind latest rustbook dependencies: Locking 30 packages to latest compatible versions Updating cc v1.2.17 -> v1.2.18 Updating clap v4.5.32 -> v4.5.35 Updating clap_builder v4.5.32 -> v4.5.35 Updating darling v0.20.10 -> v0.20.11 Updating darling_core v0.20.10 -> v0.20.11 Updating darling_macro v0.20.10 -> v0.20.11 Updating env_logger v0.11.7 -> v0.11.8 Updating errno v0.3.10 -> v0.3.11 Updating flate2 v1.1.0 -> v1.1.1 Updating iana-time-zone v0.1.61 -> v0.1.63 Updating icu_locid_transform_data v1.5.0 -> v1.5.1 Updating icu_normalizer_data v1.5.0 -> v1.5.1 Updating icu_properties_data v1.5.0 -> v1.5.1 Updating indexmap v2.8.0 -> v2.9.0 Updating log v0.4.26 -> v0.4.27 Updating miniz_oxide v0.8.5 -> v0.8.7 Updating once_cell v1.21.1 -> v1.21.3 Updating pest v2.7.15 -> v2.8.0 Updating pest_derive v2.7.15 -> v2.8.0 Updating pest_generator v2.7.15 -> v2.8.0 Updating pest_meta v2.7.15 -> v2.8.0 Updating redox_syscall v0.5.10 -> v0.5.11 Updating rustix v1.0.3 -> v1.0.5 Updating smallvec v1.14.0 -> v1.15.0 Updating string_cache v0.8.8 -> v0.8.9 Updating windows-core v0.52.0 -> v0.61.0 Adding windows-implement v0.60.0 Adding windows-interface v0.59.1 Adding windows-result v0.3.2 Adding windows-strings v0.4.0 --- Cargo.lock | 46 +++++------ library/Cargo.lock | 4 +- src/tools/rustbook/Cargo.lock | 151 ++++++++++++++++++++++------------ 3 files changed, 123 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99bd1bff0204..6f4fe01f0fee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -239,9 +239,9 @@ checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "blake3" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34a796731680be7931955498a16a10b2270c7762963d5d570fdbfe02dcbf314f" +checksum = "389a099b34312839e16420d499a9cad9650541715937ffbdd40d36f49e77eeb3" dependencies = [ "arrayref", "arrayvec", @@ -800,9 +800,9 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.5" +version = "3.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" +checksum = "697b5419f348fd5ae2478e8018cb016c00a5881c7f46c717de98ffd135a5651c" dependencies = [ "nix", "windows-sys 0.59.0", @@ -1079,9 +1079,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", @@ -1098,9 +1098,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys 0.59.0", @@ -1163,12 +1163,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", - "miniz_oxide 0.8.5", + "miniz_oxide 0.8.7", ] [[package]] @@ -1773,9 +1773,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown", @@ -2252,9 +2252,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" dependencies = [ "adler2", ] @@ -2506,9 +2506,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", @@ -2970,9 +2970,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags", ] @@ -4918,9 +4918,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "socket2" @@ -5368,9 +5368,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", diff --git a/library/Cargo.lock b/library/Cargo.lock index 23d9d926eba3..c9ce9a0fb85a 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -176,9 +176,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" dependencies = [ "adler2", "compiler_builtins", diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 08011e1d427d..09bbbd61de50 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -156,9 +156,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "cc" -version = "1.2.17" +version = "1.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" +checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" dependencies = [ "shlex", ] @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.32" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" dependencies = [ "clap_builder", "clap_derive", @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.32" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" dependencies = [ "anstream", "anstyle", @@ -275,9 +275,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -285,9 +285,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", @@ -299,9 +299,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", @@ -413,9 +413,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", @@ -432,9 +432,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys", @@ -455,9 +455,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", "miniz_oxide", @@ -584,14 +584,15 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -646,9 +647,9 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" [[package]] name = "icu_normalizer" @@ -670,9 +671,9 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" [[package]] name = "icu_properties" @@ -691,9 +692,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" [[package]] name = "icu_provider" @@ -752,9 +753,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown", @@ -861,9 +862,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "mac" @@ -980,9 +981,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" dependencies = [ "adler2", ] @@ -1028,9 +1029,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "onig" @@ -1103,9 +1104,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" dependencies = [ "memchr", "thiserror 2.0.12", @@ -1114,9 +1115,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" +checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5" dependencies = [ "pest", "pest_generator", @@ -1124,9 +1125,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" +checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841" dependencies = [ "pest", "pest_meta", @@ -1137,9 +1138,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" +checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" dependencies = [ "once_cell", "pest", @@ -1316,9 +1317,9 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags 2.9.0", ] @@ -1366,9 +1367,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags 2.9.0", "errno", @@ -1476,9 +1477,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "stable_deref_trait" @@ -1488,9 +1489,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "string_cache" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938d512196766101d333398efde81bc1f37b00cb42c2f8350e5df639f040bbbe" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", "parking_lot", @@ -1879,11 +1880,37 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" dependencies = [ - "windows-targets", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1892,6 +1919,24 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.59.0" From f6afb35c6170ad3cadc6e6d7d41dc4dc3bd46556 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 6 Apr 2025 12:33:22 +1000 Subject: [PATCH 175/176] Prevent a test from seeing forbidden numbers in the rustc version The final CHECK-NOT directive in this test was able to see past the end of the enclosing function, and find the substring 753 or 754 in the git hash in the rustc version number, causing false failures in CI. Adding an explicit check for `ret` prevents the CHECK-NOT directive from seeing past the end of the function. --- tests/codegen/issues/issue-122600-ptr-discriminant-update.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs index fbea4ee8979f..74bc824dbfef 100644 --- a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs +++ b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs @@ -37,6 +37,8 @@ pub unsafe fn update(s: *mut State) { // CHECK-NOT: store // CHECK-NOT: memcpy // CHECK-NOT: 75{{3|4}} + + // CHECK: ret let State::A(v) = s.read() else { std::hint::unreachable_unchecked() }; s.write(State::B(v)); } From 3034e571a4f37b2983207ef5766b1eba23b8da6b Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 6 Apr 2025 00:04:41 -0400 Subject: [PATCH 176/176] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index a6c604d1b8a2..0e93c5bf6a1d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit a6c604d1b8a2f2a8ff1f3ba6092f9fda42f4b7e9 +Subproject commit 0e93c5bf6a1d5ee7bc2af63d1afb16cd28793601