Skip to content

Commit c4aa646

Browse files
committed
Auto merge of #150334 - jhpratt:rollup-met2i6d, r=jhpratt
Rollup of 3 pull requests Successful merges: - #150016 (stabilize `lazy_get`) - #150139 (Correct terminology in Clone) - #150238 (mir_build: Classify `TestableCase::Constant` into multiple sub-kinds) r? `@ghost` `@rustbot` modify labels: rollup
2 parents efa32de + f9e3c61 commit c4aa646

16 files changed

Lines changed: 141 additions & 102 deletions

compiler/rustc_mir_build/src/builder/matches/buckets.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ use rustc_middle::span_bug;
66
use tracing::debug;
77

88
use crate::builder::Builder;
9-
use crate::builder::matches::test::is_switch_ty;
10-
use crate::builder::matches::{Candidate, Test, TestBranch, TestKind, TestableCase};
9+
use crate::builder::matches::{Candidate, PatConstKind, Test, TestBranch, TestKind, TestableCase};
1110

1211
/// Output of [`Builder::partition_candidates_into_buckets`].
1312
pub(crate) struct PartitionedCandidates<'tcx, 'b, 'c> {
@@ -157,11 +156,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
157156
//
158157
// FIXME(#29623) we could use PatKind::Range to rule
159158
// things out here, in some cases.
160-
//
161-
// FIXME(Zalathar): Is the `is_switch_ty` test unnecessary?
162-
(TestKind::SwitchInt, &TestableCase::Constant { value })
163-
if is_switch_ty(match_pair.pattern_ty) =>
164-
{
159+
(
160+
TestKind::SwitchInt,
161+
&TestableCase::Constant { value, kind: PatConstKind::IntOrChar },
162+
) => {
165163
// An important invariant of candidate bucketing is that a candidate
166164
// must not match in multiple branches. For `SwitchInt` tests, adding
167165
// a new value might invalidate that property for range patterns that
@@ -206,7 +204,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
206204
})
207205
}
208206

209-
(TestKind::If, TestableCase::Constant { value }) => {
207+
(TestKind::If, TestableCase::Constant { value, kind: PatConstKind::Bool }) => {
210208
fully_matched = true;
211209
let value = value.try_to_bool().unwrap_or_else(|| {
212210
span_bug!(test.span, "expected boolean value but got {value:?}")
@@ -291,7 +289,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
291289
if !test.overlaps(pat, self.tcx)? { Some(TestBranch::Failure) } else { None }
292290
}
293291
}
294-
(TestKind::Range(range), &TestableCase::Constant { value }) => {
292+
(
293+
TestKind::Range(range),
294+
&TestableCase::Constant {
295+
value,
296+
kind: PatConstKind::Bool | PatConstKind::IntOrChar | PatConstKind::Float,
297+
},
298+
) => {
295299
fully_matched = false;
296300
if !range.contains(value, self.tcx)? {
297301
// `value` is not contained in the testing range,
@@ -302,7 +306,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
302306
}
303307
}
304308

305-
(TestKind::Eq { value: test_val, .. }, TestableCase::Constant { value: case_val }) => {
309+
(
310+
TestKind::Eq { value: test_val, .. },
311+
TestableCase::Constant {
312+
value: case_val,
313+
kind: PatConstKind::Float | PatConstKind::Other,
314+
},
315+
) => {
306316
if test_val == case_val {
307317
fully_matched = true;
308318
Some(TestBranch::Success)

compiler/rustc_mir_build/src/builder/matches/match_pair.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt};
77

88
use crate::builder::Builder;
99
use crate::builder::expr::as_place::{PlaceBase, PlaceBuilder};
10-
use crate::builder::matches::{FlatPat, MatchPairTree, PatternExtraData, TestableCase};
10+
use crate::builder::matches::{
11+
FlatPat, MatchPairTree, PatConstKind, PatternExtraData, TestableCase,
12+
};
1113

1214
impl<'a, 'tcx> Builder<'a, 'tcx> {
1315
/// Builds and pushes [`MatchPairTree`] subtrees, one for each pattern in
@@ -156,7 +158,29 @@ impl<'tcx> MatchPairTree<'tcx> {
156158
}
157159
}
158160

159-
PatKind::Constant { value } => Some(TestableCase::Constant { value }),
161+
PatKind::Constant { value } => {
162+
// CAUTION: The type of the pattern node (`pattern.ty`) is
163+
// _often_ the same as the type of the const value (`value.ty`),
164+
// but there are some cases where those types differ
165+
// (e.g. when `deref!(..)` patterns interact with `String`).
166+
167+
// Classify the constant-pattern into further kinds, to
168+
// reduce the number of ad-hoc type tests needed later on.
169+
let pat_ty = pattern.ty;
170+
let const_kind = if pat_ty.is_bool() {
171+
PatConstKind::Bool
172+
} else if pat_ty.is_integral() || pat_ty.is_char() {
173+
PatConstKind::IntOrChar
174+
} else if pat_ty.is_floating_point() {
175+
PatConstKind::Float
176+
} else {
177+
// FIXME(Zalathar): This still covers several different
178+
// categories (e.g. raw pointer, string, pattern-type)
179+
// which could be split out into their own kinds.
180+
PatConstKind::Other
181+
};
182+
Some(TestableCase::Constant { value, kind: const_kind })
183+
}
160184

161185
PatKind::AscribeUserType {
162186
ascription: Ascription { ref annotation, variance },

compiler/rustc_mir_build/src/builder/matches/mod.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1262,7 +1262,7 @@ struct Ascription<'tcx> {
12621262
#[derive(Debug, Clone)]
12631263
enum TestableCase<'tcx> {
12641264
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
1265-
Constant { value: ty::Value<'tcx> },
1265+
Constant { value: ty::Value<'tcx>, kind: PatConstKind },
12661266
Range(Arc<PatRange<'tcx>>),
12671267
Slice { len: u64, variable_length: bool },
12681268
Deref { temp: Place<'tcx>, mutability: Mutability },
@@ -1276,6 +1276,28 @@ impl<'tcx> TestableCase<'tcx> {
12761276
}
12771277
}
12781278

1279+
/// Sub-classification of [`TestableCase::Constant`], which helps to avoid
1280+
/// some redundant ad-hoc checks when preparing and lowering tests.
1281+
#[derive(Debug, Clone)]
1282+
enum PatConstKind {
1283+
/// The primitive `bool` type, which is like an integer but simpler,
1284+
/// having only two values.
1285+
Bool,
1286+
/// Primitive unsigned/signed integer types, plus `char`.
1287+
/// These types interact nicely with `SwitchInt`.
1288+
IntOrChar,
1289+
/// Floating-point primitives, e.g. `f32`, `f64`.
1290+
/// These types don't support `SwitchInt` and require an equality test,
1291+
/// but can also interact with range pattern tests.
1292+
Float,
1293+
/// Any other constant-pattern is usually tested via some kind of equality
1294+
/// check. Types that might be encountered here include:
1295+
/// - `&str`
1296+
/// - raw pointers derived from integer values
1297+
/// - pattern types, e.g. `pattern_type!(u32 is 1..)`
1298+
Other,
1299+
}
1300+
12791301
/// Node in a tree of "match pairs", where each pair consists of a place to be
12801302
/// tested, and a test to perform on that place.
12811303
///

compiler/rustc_mir_build/src/builder/matches/test.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym};
1919
use tracing::{debug, instrument};
2020

2121
use crate::builder::Builder;
22-
use crate::builder::matches::{MatchPairTree, Test, TestBranch, TestKind, TestableCase};
22+
use crate::builder::matches::{
23+
MatchPairTree, PatConstKind, Test, TestBranch, TestKind, TestableCase,
24+
};
2325

2426
impl<'a, 'tcx> Builder<'a, 'tcx> {
2527
/// Identifies what test is needed to decide if `match_pair` is applicable.
@@ -32,11 +34,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3234
let kind = match match_pair.testable_case {
3335
TestableCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def },
3436

35-
TestableCase::Constant { .. } if match_pair.pattern_ty.is_bool() => TestKind::If,
36-
TestableCase::Constant { .. } if is_switch_ty(match_pair.pattern_ty) => {
37+
TestableCase::Constant { value: _, kind: PatConstKind::Bool } => TestKind::If,
38+
TestableCase::Constant { value: _, kind: PatConstKind::IntOrChar } => {
3739
TestKind::SwitchInt
3840
}
39-
TestableCase::Constant { value } => {
41+
TestableCase::Constant { value, kind: PatConstKind::Float } => {
42+
TestKind::Eq { value, cast_ty: match_pair.pattern_ty }
43+
}
44+
TestableCase::Constant { value, kind: PatConstKind::Other } => {
4045
TestKind::Eq { value, cast_ty: match_pair.pattern_ty }
4146
}
4247

@@ -491,11 +496,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
491496
}
492497
}
493498

494-
/// Returns true if this type be used with [`TestKind::SwitchInt`].
495-
pub(crate) fn is_switch_ty(ty: Ty<'_>) -> bool {
496-
ty.is_integral() || ty.is_char()
497-
}
498-
499499
fn trait_method<'tcx>(
500500
tcx: TyCtxt<'tcx>,
501501
trait_def_id: DefId,

library/core/src/cell/lazy.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
165165
/// # Examples
166166
///
167167
/// ```
168-
/// #![feature(lazy_get)]
169168
/// use std::cell::LazyCell;
170169
///
171170
/// let mut lazy = LazyCell::new(|| 92);
@@ -176,7 +175,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
176175
/// assert_eq!(*lazy, 44);
177176
/// ```
178177
#[inline]
179-
#[unstable(feature = "lazy_get", issue = "129333")]
178+
#[stable(feature = "lazy_get", since = "CURRENT_RUSTC_VERSION")]
180179
pub fn force_mut(this: &mut LazyCell<T, F>) -> &mut T {
181180
#[cold]
182181
/// # Safety
@@ -264,8 +263,6 @@ impl<T, F> LazyCell<T, F> {
264263
/// # Examples
265264
///
266265
/// ```
267-
/// #![feature(lazy_get)]
268-
///
269266
/// use std::cell::LazyCell;
270267
///
271268
/// let mut lazy = LazyCell::new(|| 92);
@@ -276,7 +273,7 @@ impl<T, F> LazyCell<T, F> {
276273
/// assert_eq!(*lazy, 44);
277274
/// ```
278275
#[inline]
279-
#[unstable(feature = "lazy_get", issue = "129333")]
276+
#[stable(feature = "lazy_get", since = "CURRENT_RUSTC_VERSION")]
280277
pub fn get_mut(this: &mut LazyCell<T, F>) -> Option<&mut T> {
281278
let state = this.state.get_mut();
282279
match state {
@@ -291,8 +288,6 @@ impl<T, F> LazyCell<T, F> {
291288
/// # Examples
292289
///
293290
/// ```
294-
/// #![feature(lazy_get)]
295-
///
296291
/// use std::cell::LazyCell;
297292
///
298293
/// let lazy = LazyCell::new(|| 92);
@@ -302,7 +297,7 @@ impl<T, F> LazyCell<T, F> {
302297
/// assert_eq!(LazyCell::get(&lazy), Some(&92));
303298
/// ```
304299
#[inline]
305-
#[unstable(feature = "lazy_get", issue = "129333")]
300+
#[stable(feature = "lazy_get", since = "CURRENT_RUSTC_VERSION")]
306301
pub fn get(this: &LazyCell<T, F>) -> Option<&T> {
307302
// SAFETY:
308303
// This is sound for the same reason as in `force`: once the state is

library/core/src/clone.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ mod uninit;
5252
/// original.
5353
///
5454
/// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while
55-
/// `Clone` is always explicit and may or may not be expensive. In order to enforce
56-
/// these characteristics, Rust does not allow you to reimplement [`Copy`], but you
57-
/// may reimplement `Clone` and run arbitrary code.
55+
/// `Clone` is always explicit and may or may not be expensive. [`Copy`] has no methods, so you
56+
/// cannot change its behavior, but when implementing `Clone`, the `clone` method you provide
57+
/// may run arbitrary code.
5858
///
59-
/// Since `Clone` is more general than [`Copy`], you can automatically make anything
60-
/// [`Copy`] be `Clone` as well.
59+
/// Since `Clone` is a supertrait of [`Copy`], any type that implements `Copy` must also implement
60+
/// `Clone`.
6161
///
6262
/// ## Derivable
6363
///

library/core/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@
113113
#![feature(internal_impls_macro)]
114114
#![feature(ip)]
115115
#![feature(is_ascii_octdigit)]
116-
#![feature(lazy_get)]
117116
#![feature(link_cfg)]
118117
#![feature(offset_of_enum)]
119118
#![feature(panic_internals)]

library/coretests/tests/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
#![feature(iterator_try_collect)]
8080
#![feature(iterator_try_reduce)]
8181
#![feature(layout_for_ptr)]
82-
#![feature(lazy_get)]
8382
#![feature(maybe_uninit_fill)]
8483
#![feature(maybe_uninit_uninit_array_transpose)]
8584
#![feature(min_specialization)]

library/std/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,6 @@
344344
#![feature(hint_must_use)]
345345
#![feature(int_from_ascii)]
346346
#![feature(ip)]
347-
#![feature(lazy_get)]
348347
#![feature(maybe_uninit_array_assume_init)]
349348
#![feature(panic_can_unwind)]
350349
#![feature(panic_internals)]

library/std/src/sync/lazy_lock.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
172172
/// # Examples
173173
///
174174
/// ```
175-
/// #![feature(lazy_get)]
176175
/// use std::sync::LazyLock;
177176
///
178177
/// let mut lazy = LazyLock::new(|| 92);
@@ -183,7 +182,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
183182
/// assert_eq!(*lazy, 44);
184183
/// ```
185184
#[inline]
186-
#[unstable(feature = "lazy_get", issue = "129333")]
185+
#[stable(feature = "lazy_get", since = "CURRENT_RUSTC_VERSION")]
187186
pub fn force_mut(this: &mut LazyLock<T, F>) -> &mut T {
188187
#[cold]
189188
/// # Safety
@@ -279,8 +278,6 @@ impl<T, F> LazyLock<T, F> {
279278
/// # Examples
280279
///
281280
/// ```
282-
/// #![feature(lazy_get)]
283-
///
284281
/// use std::sync::LazyLock;
285282
///
286283
/// let mut lazy = LazyLock::new(|| 92);
@@ -291,7 +288,7 @@ impl<T, F> LazyLock<T, F> {
291288
/// assert_eq!(*lazy, 44);
292289
/// ```
293290
#[inline]
294-
#[unstable(feature = "lazy_get", issue = "129333")]
291+
#[stable(feature = "lazy_get", since = "CURRENT_RUSTC_VERSION")]
295292
pub fn get_mut(this: &mut LazyLock<T, F>) -> Option<&mut T> {
296293
// `state()` does not perform an atomic load, so prefer it over `is_complete()`.
297294
let state = this.once.state();
@@ -309,8 +306,6 @@ impl<T, F> LazyLock<T, F> {
309306
/// # Examples
310307
///
311308
/// ```
312-
/// #![feature(lazy_get)]
313-
///
314309
/// use std::sync::LazyLock;
315310
///
316311
/// let lazy = LazyLock::new(|| 92);
@@ -320,7 +315,7 @@ impl<T, F> LazyLock<T, F> {
320315
/// assert_eq!(LazyLock::get(&lazy), Some(&92));
321316
/// ```
322317
#[inline]
323-
#[unstable(feature = "lazy_get", issue = "129333")]
318+
#[stable(feature = "lazy_get", since = "CURRENT_RUSTC_VERSION")]
324319
#[rustc_should_not_be_called_on_const_items]
325320
pub fn get(this: &LazyLock<T, F>) -> Option<&T> {
326321
if this.once.is_completed() {

0 commit comments

Comments
 (0)