Skip to content

Commit 04f3e6d

Browse files
committed
actually fixed it
1 parent 867afcd commit 04f3e6d

File tree

5 files changed

+106
-33
lines changed

5 files changed

+106
-33
lines changed

compiler/rustc_hir/src/lang_items.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,8 @@ language_item_table! {
419419
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
420420

421421
// FIXME(xacrimon): Used for lowering of match/if let statements. will made obsolete by const PartialEq.
422-
PatternConstEq, sym::PatternConstEq, pattern_const_eq, Target::Trait, GenericRequirement::None;
422+
PatternConstEq, sym::PatternConstEq, pattern_const_eq, Target::Trait, GenericRequirement::None;
423+
AggregateRawPtr, sym::aggregate_raw_ptr, aggregate_raw_ptr, Target::Fn, GenericRequirement::None;
423424
}
424425

425426
pub enum GenericRequirement {

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

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5858
if self.should_optimize_subslice(prefix) {
5959
let elem_ty = prefix[0].ty;
6060
let prefix_valtree = self.simplify_const_pattern_slice_into_valtree(prefix);
61-
let prefix_len = prefix.len() as u64;
62-
63-
//let suffix_len = suffix.len() as u64;
64-
let midsection_offset = if opt_slice.is_some() {1} else {0};
65-
66-
// TODO: handle suffix offset
67-
68-
let src_path_subslice = place.clone_project(PlaceElem::Subslice {
69-
from: 0 as u64,
70-
to: if exact_size { prefix_len } else { min_length - prefix_len + midsection_offset }, // TODO: Is this correct?
71-
from_end: !exact_size,
72-
});
73-
7461
let match_pair = self.valtree_to_match_pair(
7562
src_path,
7663
prefix.len() as u64,
7764
prefix_valtree,
78-
src_path_subslice,
65+
place.clone(),
7966
elem_ty,
8067
);
8168

@@ -166,15 +153,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
166153
Ty::new_array(tcx, elem_ty, subslice_len),
167154
);
168155

169-
let pat_ty = match src_path.ty.kind() {
170-
ty::Slice(_) => Ty::new_slice(tcx, elem_ty),
171-
ty::Array(_, _) => Ty::new_array(tcx, elem_ty, subslice_len),
172-
_ => unreachable!(),
173-
};
174-
156+
// note: this is fine since we set range = Some in TestCase::Constant
157+
// which notifies any eventual comparison code that it should subslice `place`
158+
let pat_ty = Ty::new_slice(tcx, elem_ty);
175159
let ty_const = ty::Const::new(tcx, ty::ConstKind::Value(const_ty, valtree));
176160
let value = Const::Ty(const_ty, ty_const);
177-
let test_case = TestCase::Constant { value };
161+
let test_case = TestCase::Constant { value, range: Some(0..subslice_len) };
178162
let pattern = tcx.arena.alloc(Pat {
179163
ty: pat_ty,
180164
span: src_path.span,
@@ -236,7 +220,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
236220
}
237221
}
238222

239-
PatKind::Constant { value } => TestCase::Constant { value },
223+
PatKind::Constant { value } => TestCase::Constant { value, range: None },
240224

241225
PatKind::AscribeUserType {
242226
ascription: thir::Ascription { ref annotation, variance },

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
//! This also includes code for pattern bindings in `let` statements and
66
//! function parameters.
77
8+
use std::ops::Range;
9+
810
use rustc_abi::VariantIdx;
911
use rustc_data_structures::fx::FxIndexMap;
1012
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -1237,7 +1239,7 @@ struct Ascription<'tcx> {
12371239
enum TestCase<'pat, 'tcx> {
12381240
Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> },
12391241
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
1240-
Constant { value: mir::Const<'tcx> },
1242+
Constant { value: mir::Const<'tcx>, range: Option<Range<u64>> },
12411243
Range(&'pat PatRange<'tcx>),
12421244
Slice { len: usize, variable_length: bool },
12431245
Deref { temp: Place<'tcx>, mutability: Mutability },
@@ -1313,6 +1315,7 @@ enum TestKind<'tcx> {
13131315
/// `ty`,
13141316
Eq {
13151317
value: Const<'tcx>,
1318+
range: Option<Range<u64>>,
13161319
// Integer types are handled by `SwitchInt`, and constants with ADT
13171320
// types are converted back into patterns, so this can only be `&str`,
13181321
// `&[T]`, `f32` or `f64`.

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

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym};
2020
use rustc_trait_selection::infer::InferCtxtExt;
2121
use tracing::{debug, instrument};
2222

23-
use crate::builder::Builder;
2423
use crate::builder::matches::{Candidate, MatchPairTree, Test, TestBranch, TestCase, TestKind};
24+
use crate::builder::{Builder, PlaceBuilder};
2525

2626
impl<'a, 'tcx> Builder<'a, 'tcx> {
2727
/// Identifies what test is needed to decide if `match_pair` is applicable.
@@ -36,7 +36,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3636

3737
TestCase::Constant { .. } if match_pair.pattern.ty.is_bool() => TestKind::If,
3838
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => TestKind::SwitchInt,
39-
TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty },
39+
TestCase::Constant { value, ref range } => {
40+
TestKind::Eq { value, ty: match_pair.pattern.ty, range: range.clone() }
41+
}
4042

4143
TestCase::Range(range) => {
4244
assert_eq!(range.ty, match_pair.pattern.ty);
@@ -142,7 +144,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
142144
self.cfg.terminate(block, self.source_info(match_start_span), terminator);
143145
}
144146

145-
TestKind::Eq { value, ty } => {
147+
TestKind::Eq { value, ref range, ty } => {
146148
let tcx = self.tcx;
147149
let success_block = target_block(TestBranch::Success);
148150
let fail_block = target_block(TestBranch::Failure);
@@ -179,15 +181,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
179181
ref_str_ty,
180182
);
181183
} else if !ty.is_scalar() {
184+
let new_place;
185+
let cmp_block;
186+
if let Some(range) = range {
187+
assert_eq!(range.start, 0);
188+
let elem_ty = ty.sequence_element_type(tcx);
189+
cmp_block = self.cfg.start_new_block();
190+
let subslice_ptr = self.subslice(
191+
block,
192+
cmp_block,
193+
place,
194+
place_ty.ty,
195+
test.span,
196+
elem_ty,
197+
range.end,
198+
);
199+
200+
new_place = PlaceBuilder::from(subslice_ptr).deref().to_place(self);
201+
} else {
202+
cmp_block = block;
203+
new_place = place;
204+
}
205+
182206
// Use `PartialEq::eq` instead of `BinOp::Eq`
183207
// (the binop can only handle primitives)
184208
self.non_scalar_compare(
185-
block,
209+
cmp_block,
186210
success_block,
187211
fail_block,
188212
source_info,
189213
value,
190-
place,
214+
new_place,
191215
ty,
192216
);
193217
} else {
@@ -290,6 +314,66 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
290314
}
291315
}
292316

317+
fn subslice(
318+
&mut self,
319+
block: BasicBlock,
320+
target_block: BasicBlock,
321+
input: Place<'tcx>,
322+
input_ty: Ty<'tcx>,
323+
span: Span,
324+
elem_ty: Ty<'tcx>,
325+
new_len: u64,
326+
) -> Place<'tcx> {
327+
let tcx = self.tcx;
328+
let source_info = self.source_info(span);
329+
330+
let temp_source_ptr = self.temp(Ty::new_ptr(tcx, input_ty, Mutability::Not), span);
331+
self.cfg.push_assign(
332+
block,
333+
source_info,
334+
temp_source_ptr,
335+
Rvalue::RawPtr(Mutability::Not, input),
336+
);
337+
338+
let elem_ptr_ty = Ty::new_ptr(tcx, elem_ty, Mutability::Not);
339+
let slice_ptr_ty = Ty::new_ptr(tcx, Ty::new_slice(tcx, elem_ty), Mutability::Not);
340+
341+
let temp_elem_ptr = self.temp(elem_ptr_ty, span);
342+
self.cfg.push_assign(
343+
block,
344+
source_info,
345+
temp_elem_ptr,
346+
Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(temp_source_ptr), elem_ptr_ty),
347+
);
348+
349+
let temp_len = self.push_usize(block, source_info, new_len);
350+
351+
let aggregate_raw_ptr = Operand::function_handle(
352+
tcx,
353+
tcx.require_lang_item(LangItem::AggregateRawPtr, Some(span)),
354+
[slice_ptr_ty.into(), elem_ptr_ty.into(), tcx.types.usize.into()],
355+
span,
356+
);
357+
358+
let subslice_ptr = self.temp(slice_ptr_ty, span);
359+
360+
self.cfg.terminate(block, source_info, TerminatorKind::Call {
361+
func: aggregate_raw_ptr,
362+
args: [Spanned { node: Operand::Move(temp_elem_ptr), span }, Spanned {
363+
node: Operand::Move(temp_len),
364+
span,
365+
}]
366+
.into(),
367+
destination: subslice_ptr,
368+
target: Some(target_block),
369+
unwind: UnwindAction::Continue,
370+
call_source: CallSource::Misc,
371+
fn_span: source_info.span,
372+
});
373+
374+
subslice_ptr
375+
}
376+
293377
/// Perform `let temp = <ty as Deref>::deref(&place)`.
294378
/// or `let temp = <ty as DerefMut>::deref_mut(&mut place)`.
295379
pub(super) fn call_deref(
@@ -582,7 +666,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
582666
//
583667
// FIXME(#29623) we could use PatKind::Range to rule
584668
// things out here, in some cases.
585-
(TestKind::SwitchInt, &TestCase::Constant { value })
669+
(TestKind::SwitchInt, &TestCase::Constant { value, .. })
586670
if is_switch_ty(match_pair.pattern.ty) =>
587671
{
588672
// An important invariant of candidate sorting is that a candidate
@@ -636,7 +720,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
636720
})
637721
}
638722

639-
(TestKind::If, TestCase::Constant { value }) => {
723+
(TestKind::If, TestCase::Constant { value, .. }) => {
640724
fully_matched = true;
641725
let value = value.try_eval_bool(self.tcx, self.typing_env()).unwrap_or_else(|| {
642726
span_bug!(test.span, "expected boolean value but got {value:?}")
@@ -725,7 +809,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
725809
}
726810
}
727811
}
728-
(TestKind::Range(range), &TestCase::Constant { value }) => {
812+
(TestKind::Range(range), &TestCase::Constant { value, .. }) => {
729813
fully_matched = false;
730814
if !range.contains(value, self.tcx, self.typing_env())? {
731815
// `value` is not contained in the testing range,
@@ -736,7 +820,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
736820
}
737821
}
738822

739-
(TestKind::Eq { value: test_val, .. }, TestCase::Constant { value: case_val }) => {
823+
(TestKind::Eq { value: test_val, .. }, TestCase::Constant { value: case_val, .. }) => {
740824
if test_val == case_val {
741825
fully_matched = true;
742826
Some(TestBranch::Success)

library/core/src/intrinsics/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4202,6 +4202,7 @@ pub const fn type_id<T: ?Sized + 'static>() -> u128 {
42024202
/// This is used to implement functions like `slice::from_raw_parts_mut` and
42034203
/// `ptr::from_raw_parts` in a way compatible with the compiler being able to
42044204
/// change the possible layouts of pointers.
4205+
#[cfg_attr(not(bootstrap), lang = "aggregate_raw_ptr")]
42054206
#[rustc_nounwind]
42064207
#[unstable(feature = "core_intrinsics", issue = "none")]
42074208
#[rustc_intrinsic_const_stable_indirect]

0 commit comments

Comments
 (0)