Skip to content

Commit 74f4201

Browse files
authored
Unrolled build for rust-lang#138821
Rollup merge of rust-lang#138821 - dianne:cleanup-non-scalar-compare, r=oli-obk match lowering cleanup: remove unused unsizing logic from `non_scalar_compare` Since array and slice constants are now translated to array and slice patterns, `non_scalar_compare` is only used for string comparisons. This specializes it to strings, renames it, and removes the unused array-unsizing logic. This also updates the doc comments for `thir::PatKind::Constant` and `TestKind::Eq`, which referred to them being used for slice references. r? ````@oli-obk````
2 parents 4510e86 + 83145a6 commit 74f4201

File tree

3 files changed

+24
-94
lines changed

3 files changed

+24
-94
lines changed

compiler/rustc_middle/src/thir.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -800,9 +800,9 @@ pub enum PatKind<'tcx> {
800800
},
801801

802802
/// One of the following:
803-
/// * `&str`/`&[u8]` (represented as a valtree), which will be handled as a string/slice pattern
804-
/// and thus exhaustiveness checking will detect if you use the same string/slice twice in
805-
/// different patterns.
803+
/// * `&str` (represented as a valtree), which will be handled as a string pattern and thus
804+
/// exhaustiveness checking will detect if you use the same string twice in different
805+
/// patterns.
806806
/// * integer, bool, char or float (represented as a valtree), which will be handled by
807807
/// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
808808
/// much simpler.

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1326,8 +1326,8 @@ enum TestKind<'tcx> {
13261326
Eq {
13271327
value: Const<'tcx>,
13281328
// Integer types are handled by `SwitchInt`, and constants with ADT
1329-
// types are converted back into patterns, so this can only be `&str`,
1330-
// `&[T]`, `f32` or `f64`.
1329+
// types and `&[T]` types are converted back into patterns, so this can
1330+
// only be `&str`, `f32` or `f64`.
13311331
ty: Ty<'tcx>,
13321332
},
13331333

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

+19-89
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use std::sync::Arc;
1111
use rustc_data_structures::fx::FxIndexMap;
1212
use rustc_hir::{LangItem, RangeEnd};
1313
use rustc_middle::mir::*;
14-
use rustc_middle::ty::adjustment::PointerCoercion;
1514
use rustc_middle::ty::util::IntTypeExt;
1615
use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt};
1716
use rustc_middle::{bug, span_bug};
@@ -178,21 +177,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
178177
_ => {}
179178
}
180179

180+
assert_eq!(expect_ty, ty);
181181
if !ty.is_scalar() {
182182
// Use `PartialEq::eq` instead of `BinOp::Eq`
183183
// (the binop can only handle primitives)
184-
self.non_scalar_compare(
184+
// Make sure that we do *not* call any user-defined code here.
185+
// The only type that can end up here is string literals, which have their
186+
// comparison defined in `core`.
187+
// (Interestingly this means that exhaustiveness analysis relies, for soundness,
188+
// on the `PartialEq` impl for `str` to b correct!)
189+
match *ty.kind() {
190+
ty::Ref(_, deref_ty, _) if deref_ty == self.tcx.types.str_ => {}
191+
_ => {
192+
span_bug!(source_info.span, "invalid type for non-scalar compare: {ty}")
193+
}
194+
};
195+
self.string_compare(
185196
block,
186197
success_block,
187198
fail_block,
188199
source_info,
189200
expect,
190-
expect_ty,
191201
Operand::Copy(place),
192-
ty,
193202
);
194203
} else {
195-
assert_eq!(expect_ty, ty);
196204
self.compare(
197205
block,
198206
success_block,
@@ -370,97 +378,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
370378
);
371379
}
372380

373-
/// Compare two values using `<T as std::compare::PartialEq>::eq`.
374-
/// If the values are already references, just call it directly, otherwise
375-
/// take a reference to the values first and then call it.
376-
fn non_scalar_compare(
381+
/// Compare two values of type `&str` using `<str as std::cmp::PartialEq>::eq`.
382+
fn string_compare(
377383
&mut self,
378384
block: BasicBlock,
379385
success_block: BasicBlock,
380386
fail_block: BasicBlock,
381387
source_info: SourceInfo,
382-
mut expect: Operand<'tcx>,
383-
expect_ty: Ty<'tcx>,
384-
mut val: Operand<'tcx>,
385-
mut ty: Ty<'tcx>,
388+
expect: Operand<'tcx>,
389+
val: Operand<'tcx>,
386390
) {
387-
// If we're using `b"..."` as a pattern, we need to insert an
388-
// unsizing coercion, as the byte string has the type `&[u8; N]`.
389-
//
390-
// We want to do this even when the scrutinee is a reference to an
391-
// array, so we can call `<[u8]>::eq` rather than having to find an
392-
// `<[u8; N]>::eq`.
393-
let unsize = |ty: Ty<'tcx>| match ty.kind() {
394-
ty::Ref(region, rty, _) => match rty.kind() {
395-
ty::Array(inner_ty, n) => Some((region, inner_ty, n)),
396-
_ => None,
397-
},
398-
_ => None,
399-
};
400-
let opt_ref_ty = unsize(ty);
401-
let opt_ref_test_ty = unsize(expect_ty);
402-
match (opt_ref_ty, opt_ref_test_ty) {
403-
// nothing to do, neither is an array
404-
(None, None) => {}
405-
(Some((region, elem_ty, _)), _) | (None, Some((region, elem_ty, _))) => {
406-
let tcx = self.tcx;
407-
// make both a slice
408-
ty = Ty::new_imm_ref(tcx, *region, Ty::new_slice(tcx, *elem_ty));
409-
if opt_ref_ty.is_some() {
410-
let temp = self.temp(ty, source_info.span);
411-
self.cfg.push_assign(
412-
block,
413-
source_info,
414-
temp,
415-
Rvalue::Cast(
416-
CastKind::PointerCoercion(
417-
PointerCoercion::Unsize,
418-
CoercionSource::Implicit,
419-
),
420-
val,
421-
ty,
422-
),
423-
);
424-
val = Operand::Copy(temp);
425-
}
426-
if opt_ref_test_ty.is_some() {
427-
let slice = self.temp(ty, source_info.span);
428-
self.cfg.push_assign(
429-
block,
430-
source_info,
431-
slice,
432-
Rvalue::Cast(
433-
CastKind::PointerCoercion(
434-
PointerCoercion::Unsize,
435-
CoercionSource::Implicit,
436-
),
437-
expect,
438-
ty,
439-
),
440-
);
441-
expect = Operand::Move(slice);
442-
}
443-
}
444-
}
445-
446-
// Figure out the type on which we are calling `PartialEq`. This involves an extra wrapping
447-
// reference: we can only compare two `&T`, and then compare_ty will be `T`.
448-
// Make sure that we do *not* call any user-defined code here.
449-
// The only types that can end up here are string and byte literals,
450-
// which have their comparison defined in `core`.
451-
// (Interestingly this means that exhaustiveness analysis relies, for soundness,
452-
// on the `PartialEq` impls for `str` and `[u8]` to b correct!)
453-
let compare_ty = match *ty.kind() {
454-
ty::Ref(_, deref_ty, _)
455-
if deref_ty == self.tcx.types.str_ || deref_ty != self.tcx.types.u8 =>
456-
{
457-
deref_ty
458-
}
459-
_ => span_bug!(source_info.span, "invalid type for non-scalar compare: {}", ty),
460-
};
461-
391+
let str_ty = self.tcx.types.str_;
462392
let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span));
463-
let method = trait_method(self.tcx, eq_def_id, sym::eq, [compare_ty, compare_ty]);
393+
let method = trait_method(self.tcx, eq_def_id, sym::eq, [str_ty, str_ty]);
464394

465395
let bool_ty = self.tcx.types.bool;
466396
let eq_result = self.temp(bool_ty, source_info.span);

0 commit comments

Comments
 (0)