Skip to content

Commit 832c927

Browse files
committed
Actually create ranged types
1 parent 6a9b008 commit 832c927

File tree

91 files changed

+941
-392
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+941
-392
lines changed

compiler/rustc_borrowck/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2103,6 +2103,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21032103
ProjectionElem::Deref => {
21042104
let base_ty = place_base.ty(self.body(), self.infcx.tcx).ty;
21052105

2106+
let base_ty = match *base_ty.kind() {
2107+
ty::Pat(inner, _) => inner,
2108+
_ => base_ty,
2109+
};
2110+
21062111
// Check the kind of deref to decide
21072112
match base_ty.kind() {
21082113
ty::Ref(_, _, mutbl) => {

compiler/rustc_borrowck/src/type_check/mod.rs

+69-3
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
433433
}
434434
}
435435

436+
#[instrument(level = "trace", skip(self))]
436437
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
437438
self.super_rvalue(rvalue, location);
438439
let rval_ty = rvalue.ty(self.body(), self.tcx());
@@ -517,14 +518,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
517518

518519
/// Checks that the types internal to the `place` match up with
519520
/// what would be expected.
521+
#[instrument(level = "trace", skip(self), ret)]
520522
fn sanitize_place(
521523
&mut self,
522524
place: &Place<'tcx>,
523525
location: Location,
524526
context: PlaceContext,
525527
) -> PlaceTy<'tcx> {
526-
debug!("sanitize_place: {:?}", place);
527-
528528
let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
529529

530530
for elem in place.projection.iter() {
@@ -630,14 +630,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
630630
}
631631
}
632632

633+
#[instrument(level = "trace", skip(self), ret)]
633634
fn sanitize_projection(
634635
&mut self,
635636
base: PlaceTy<'tcx>,
636637
pi: PlaceElem<'tcx>,
637638
place: &Place<'tcx>,
638639
location: Location,
639640
) -> PlaceTy<'tcx> {
640-
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
641641
let tcx = self.tcx();
642642
let base_ty = base.ty;
643643
match pi {
@@ -1310,6 +1310,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
13101310
self.check_operand(discr, term_location);
13111311

13121312
let switch_ty = discr.ty(body, tcx);
1313+
let switch_ty = switch_ty.strip_pattern().unwrap_or(switch_ty);
13131314
if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
13141315
span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
13151316
}
@@ -2107,6 +2108,66 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21072108
}
21082109
}
21092110
}
2111+
CastKind::Patternize => {
2112+
let ty_from = op.ty(body, tcx);
2113+
let cast_ty_to = CastTy::from_ty(*ty);
2114+
match cast_ty_to {
2115+
Some(CastTy::Pat(to)) => {
2116+
if let Err(terr) = self.eq_types(
2117+
ty_from,
2118+
to,
2119+
location.to_locations(),
2120+
ConstraintCategory::Cast,
2121+
) {
2122+
span_mirbug!(
2123+
self,
2124+
rvalue,
2125+
"relating {:?} with {:?} yields {:?}",
2126+
ty_from,
2127+
to,
2128+
terr
2129+
)
2130+
}
2131+
}
2132+
_ => {
2133+
span_mirbug!(
2134+
self,
2135+
rvalue,
2136+
"Invalid Patternize cast {ty_from} -> {ty}",
2137+
)
2138+
}
2139+
}
2140+
}
2141+
CastKind::StripPattern => {
2142+
let ty_from = op.ty(body, tcx);
2143+
let cast_ty_from = CastTy::from_ty(ty_from);
2144+
match cast_ty_from {
2145+
Some(CastTy::Pat(from)) => {
2146+
if let Err(terr) = self.eq_types(
2147+
*ty,
2148+
from,
2149+
location.to_locations(),
2150+
ConstraintCategory::Cast,
2151+
) {
2152+
span_mirbug!(
2153+
self,
2154+
rvalue,
2155+
"relating {:?} with {:?} yields {:?}",
2156+
ty,
2157+
from,
2158+
terr
2159+
)
2160+
}
2161+
}
2162+
_ => {
2163+
span_mirbug!(
2164+
self,
2165+
rvalue,
2166+
"Invalid StripPattern cast {ty_from} -> {ty}",
2167+
)
2168+
}
2169+
}
2170+
}
21102171
CastKind::IntToFloat => {
21112172
let ty_from = op.ty(body, tcx);
21122173
let cast_ty_from = CastTy::from_ty(ty_from);
@@ -2427,6 +2488,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
24272488
ProjectionElem::Deref => {
24282489
let base_ty = Place::ty_from(borrowed_place.local, proj_base, body, tcx).ty;
24292490

2491+
let base_ty = match *base_ty.kind() {
2492+
ty::Pat(inner, _) => inner,
2493+
_ => base_ty,
2494+
};
2495+
24302496
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
24312497
match base_ty.kind() {
24322498
ty::Ref(ref_region, _, mutbl) => {

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+1
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
462462
ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
463463
// Type parameters from polymorphized functions.
464464
ty::Param(_) => build_param_type_di_node(cx, t),
465+
ty::Pat(inner, _) => return type_di_node(cx, inner),
465466
_ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t),
466467
};
467468

compiler/rustc_codegen_ssa/src/base.rs

+3
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
256256
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
257257
(bx.bitcast(lldata, lldata_ty), bx.bitcast(llextra, llextra_ty))
258258
}
259+
(&ty::Pat(a, a_pat), &ty::Pat(b, b_pat)) if a_pat == b_pat => {
260+
unsize_ptr(bx, src, a, b, old_info)
261+
}
259262
_ => bug!("unsize_ptr: called on bad types"),
260263
}
261264
}

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
219219
_ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty),
220220
}
221221
}
222-
mir::CastKind::Pointer(PointerCast::UnsafeFnPointer) => {
222+
mir::CastKind::Patternize
223+
| mir::CastKind::StripPattern
224+
| mir::CastKind::Pointer(PointerCast::UnsafeFnPointer) => {
223225
// This is a no-op at the LLVM level.
224226
operand.val
225227
}

compiler/rustc_const_eval/src/interpret/cast.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
2525
use rustc_middle::mir::CastKind::*;
2626
// FIXME: In which cases should we trigger UB when the source is uninit?
2727
match cast_kind {
28+
Patternize | StripPattern => {
29+
self.copy_op(src, dest, true)?;
30+
}
31+
2832
Pointer(PointerCast::Unsize) => {
2933
let cast_ty = self.layout_of(cast_ty)?;
3034
self.unsize_into(src, cast_ty, dest)?;
@@ -368,10 +372,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
368372
dest: &PlaceTy<'tcx, M::Provenance>,
369373
) -> InterpResult<'tcx> {
370374
trace!("Unsizing {:?} of type {} into {:?}", *src, src.layout.ty, cast_ty.ty);
371-
match (&src.layout.ty.kind(), &cast_ty.ty.kind()) {
375+
let (src_ty, target_ty) = match (src.layout.ty.kind(), cast_ty.ty.kind()) {
376+
(&ty::Pat(a, pat_a), &ty::Pat(b, pat_b)) if pat_a == pat_b => (a, b),
377+
_ => (src.layout.ty, cast_ty.ty),
378+
};
379+
match (src_ty.kind(), target_ty.kind()) {
372380
(&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(TypeAndMut { ty: c, .. }))
373381
| (&ty::RawPtr(TypeAndMut { ty: s, .. }), &ty::RawPtr(TypeAndMut { ty: c, .. })) => {
374-
self.unsize_into_ptr(src, dest, *s, *c)
382+
self.unsize_into_ptr(src, dest, s, c)
375383
}
376384
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
377385
assert_eq!(def_a, def_b);

compiler/rustc_const_eval/src/interpret/validity.rs

+25-6
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,27 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
491491
) -> InterpResult<'tcx, bool> {
492492
// Go over all the primitive types
493493
let ty = value.layout.ty;
494-
match ty.kind() {
494+
match *ty.kind() {
495+
ty::Pat(inner, _) => {
496+
let mut value = value.clone();
497+
value.layout.ty = inner;
498+
// First visit the inner type to report more targetted errors
499+
// if the value is already not valid at the inner type.
500+
self.visit_value(&value)?;
501+
// Then check the extra pattern restrictions.
502+
let scalar = self.read_immediate(&value, "initialized scalar value")?;
503+
match (*scalar, value.layout.abi) {
504+
(Immediate::Scalar(scalar), Abi::Scalar(s))
505+
| (Immediate::ScalarPair(scalar, _), Abi::ScalarPair(s, _)) => {
506+
self.visit_scalar(scalar, s)?
507+
}
508+
other => span_bug!(
509+
self.ecx.cur_span(),
510+
"invalid abi {other:?} for pattern type {ty:?}"
511+
),
512+
}
513+
Ok(true)
514+
}
495515
ty::Bool => {
496516
let value = self.read_scalar(value, "a boolean")?;
497517
try_validation!(
@@ -545,11 +565,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
545565
}
546566
ty::Ref(_, ty, mutbl) => {
547567
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
548-
&& *mutbl == Mutability::Mut
568+
&& mutbl == Mutability::Mut
549569
{
550570
// A mutable reference inside a const? That does not seem right (except if it is
551571
// a ZST).
552-
let layout = self.ecx.layout_of(*ty)?;
572+
let layout = self.ecx.layout_of(ty)?;
553573
if !layout.is_zst() {
554574
throw_validation_failure!(self.path, { "mutable reference in a `const`" });
555575
}
@@ -584,7 +604,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
584604
// Nothing to check.
585605
Ok(true)
586606
}
587-
ty::Pat(..) => unimplemented!(),
588607
// The above should be all the primitive types. The rest is compound, we
589608
// check them by visiting their fields/variants.
590609
ty::Adt(..)
@@ -779,7 +798,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
779798
Abi::Scalar(scalar_layout) => {
780799
if !scalar_layout.is_uninit_valid() {
781800
// There is something to check here.
782-
let scalar = self.read_scalar(op, "initiailized scalar value")?;
801+
let scalar = self.read_scalar(op, "initialized scalar value")?;
783802
self.visit_scalar(scalar, scalar_layout)?;
784803
}
785804
}
@@ -789,7 +808,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
789808
// the other must be init.
790809
if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
791810
let (a, b) =
792-
self.read_immediate(op, "initiailized scalar value")?.to_scalar_pair();
811+
self.read_immediate(op, "initialized scalar value")?.to_scalar_pair();
793812
self.visit_scalar(a, a_layout)?;
794813
self.visit_scalar(b, b_layout)?;
795814
}

compiler/rustc_const_eval/src/interpret/visitor.rs

+52-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ pub trait Value<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized {
4949
ecx: &InterpCx<'mir, 'tcx, M>,
5050
field: usize,
5151
) -> InterpResult<'tcx, Self>;
52+
53+
/// Strip a layer of pattern types to get at the inner type
54+
fn strip_pat_ty(self) -> Self;
5255
}
5356

5457
/// A thing that we can project into given *mutable* access to `ecx`, and that has a layout.
@@ -88,6 +91,9 @@ pub trait ValueMut<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized {
8891
ecx: &mut InterpCx<'mir, 'tcx, M>,
8992
field: usize,
9093
) -> InterpResult<'tcx, Self>;
94+
95+
/// Strip a layer of pattern types to get at the inner type
96+
fn strip_pat_ty(self) -> Self;
9197
}
9298

9399
// We cannot have a general impl which shows that Value implies ValueMut. (When we do, it says we
@@ -131,6 +137,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for OpTy<'tc
131137
) -> InterpResult<'tcx, Self> {
132138
ecx.operand_field(self, field)
133139
}
140+
141+
#[inline(always)]
142+
fn strip_pat_ty(mut self) -> Self {
143+
let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else {
144+
bug!("NonNull must contain a pattern type, but had {}", self.layout.ty)
145+
};
146+
self.layout.ty = raw_ptr_ty;
147+
self
148+
}
134149
}
135150

136151
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M>
@@ -179,6 +194,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M>
179194
) -> InterpResult<'tcx, Self> {
180195
ecx.operand_field(self, field)
181196
}
197+
198+
#[inline(always)]
199+
fn strip_pat_ty(mut self) -> Self {
200+
let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else {
201+
bug!("NonNull must contain a pattern type, but had {}", self.layout.ty)
202+
};
203+
self.layout.ty = raw_ptr_ty;
204+
self
205+
}
182206
}
183207

184208
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M>
@@ -220,6 +244,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M>
220244
) -> InterpResult<'tcx, Self> {
221245
ecx.mplace_field(self, field)
222246
}
247+
248+
#[inline(always)]
249+
fn strip_pat_ty(mut self) -> Self {
250+
let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else {
251+
bug!("NonNull must contain a pattern type, but had {}", self.layout.ty)
252+
};
253+
self.layout.ty = raw_ptr_ty;
254+
self
255+
}
223256
}
224257

225258
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M>
@@ -269,6 +302,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M>
269302
) -> InterpResult<'tcx, Self> {
270303
ecx.mplace_field(self, field)
271304
}
305+
306+
#[inline(always)]
307+
fn strip_pat_ty(mut self) -> Self {
308+
let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else {
309+
bug!("NonNull must contain a pattern type, but had {}", self.layout.ty)
310+
};
311+
self.layout.ty = raw_ptr_ty;
312+
self
313+
}
272314
}
273315

274316
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M>
@@ -320,6 +362,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M>
320362
) -> InterpResult<'tcx, Self> {
321363
ecx.place_field(self, field)
322364
}
365+
366+
#[inline(always)]
367+
fn strip_pat_ty(mut self) -> Self {
368+
let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else {
369+
bug!("NonNull must contain a pattern type, but had {}", self.layout.ty)
370+
};
371+
self.layout.ty = raw_ptr_ty;
372+
self
373+
}
323374
}
324375

325376
macro_rules! make_value_visitor {
@@ -466,7 +517,7 @@ macro_rules! make_value_visitor {
466517
);
467518
// ... that contains a `NonNull`... (gladly, only a single field here)
468519
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
469-
let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?; // the actual raw ptr
520+
let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?.strip_pat_ty(); // the actual raw ptr
470521
// ... whose only field finally is a raw ptr we can dereference.
471522
self.visit_box(&raw_ptr)?;
472523

0 commit comments

Comments
 (0)