Skip to content

Commit 61392fe

Browse files
committed
Coerce pattern types to their base type
1 parent dbae3b9 commit 61392fe

File tree

24 files changed

+100
-153
lines changed

24 files changed

+100
-153
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,6 +2176,21 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21762176
}
21772177
}
21782178
}
2179+
CastKind::StripPat => {
2180+
let ty_from = op.ty(body, tcx);
2181+
match ty_from.kind() {
2182+
ty::Pat(base, _) if base == ty => (),
2183+
_ => {
2184+
span_mirbug!(
2185+
self,
2186+
rvalue,
2187+
"Invalid StripPat cast {:?} -> {:?}",
2188+
ty_from,
2189+
ty
2190+
)
2191+
}
2192+
}
2193+
}
21792194
CastKind::Transmute => {
21802195
span_mirbug!(
21812196
self,

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ fn codegen_stmt<'tcx>(
793793
let operand = codegen_operand(fx, operand);
794794
crate::unsize::coerce_dyn_star(fx, operand, lval);
795795
}
796-
Rvalue::Cast(CastKind::Transmute, ref operand, _to_ty) => {
796+
Rvalue::Cast(CastKind::Transmute | CastKind::StripPat, ref operand, _to_ty) => {
797797
let operand = codegen_operand(fx, operand);
798798
lval.write_cvalue_transmute(fx, operand);
799799
}

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
599599
bug!("Unsupported cast of {operand:?} to {cast:?}");
600600
})
601601
}
602-
mir::CastKind::Transmute => {
602+
mir::CastKind::StripPat | mir::CastKind::Transmute => {
603603
self.codegen_transmute_operand(bx, operand, cast).unwrap_or_else(|| {
604604
bug!("Unsupported transmute-as-operand of {operand:?} to {cast:?}");
605605
})

compiler/rustc_const_eval/src/interpret/cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
141141
}
142142
}
143143

144-
CastKind::Transmute => {
144+
CastKind::StripPat | CastKind::Transmute => {
145145
assert!(src.layout.is_sized());
146146
assert!(dest.layout.is_sized());
147147
assert_eq!(cast_ty, dest.layout.ty); // we otherwise ignore `cast_ty` enirely...

compiler/rustc_hir_typeck/src/cast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
838838
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
839839

840840
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
841+
(Pat, _) => Err(CastError::IllegalCast),
842+
(_, Pat) => Err(CastError::IllegalCast),
841843
}
842844
}
843845

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use rustc_middle::ty::adjustment::{
5757
};
5858
use rustc_middle::ty::error::TypeError;
5959
use rustc_middle::ty::visit::TypeVisitableExt;
60-
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
60+
use rustc_middle::ty::{self, GenericArgsRef, Pattern, Ty, TyCtxt};
6161
use rustc_session::parse::feature_err;
6262
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span, sym};
6363
use rustc_trait_selection::infer::InferCtxtExt as _;
@@ -259,6 +259,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
259259
// It cannot convert closures that require unsafe.
260260
self.coerce_closure_to_fn(a, closure_def_id_a, args_a, b)
261261
}
262+
ty::Pat(base, pat) => self.coerce_from_pat_ty(base, pat, b),
262263
_ => {
263264
// Otherwise, just use unification rules.
264265
self.unify_and(a, b, identity)
@@ -1017,6 +1018,24 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
10171018
}
10181019
}
10191020

1021+
fn coerce_from_pat_ty(
1022+
&self,
1023+
base: Ty<'tcx>,
1024+
pat: Pattern<'tcx>,
1025+
b: Ty<'tcx>,
1026+
) -> CoerceResult<'tcx> {
1027+
match *b.kind() {
1028+
// FIXME(pattern_types): allow coercion to less restrictive patterns
1029+
ty::Pat(b_base, b_pat) if b_pat == pat => self.unify_and(base, b_base, identity),
1030+
// Coercing to anything but a pattern type only works by dismissing the pattern
1031+
_ => {
1032+
let mut coerce = self.unify_and(base, b, identity)?;
1033+
coerce.value.0.insert(0, Adjustment { kind: Adjust::StripPattern, target: base });
1034+
Ok(coerce)
1035+
}
1036+
}
1037+
}
1038+
10201039
fn coerce_raw_ptr(
10211040
&self,
10221041
a: Ty<'tcx>,

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
762762
for adjustment in adjustments {
763763
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
764764
match adjustment.kind {
765-
adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) => {
765+
adjustment::Adjust::StripPattern
766+
| adjustment::Adjust::NeverToAny
767+
| adjustment::Adjust::Pointer(_) => {
766768
// Creating a closure/fn-pointer or unsizing consumes
767769
// the input and stores it into the resulting rvalue.
768770
self.consume_or_copy(&place_with_id, place_with_id.hir_id);
@@ -1325,6 +1327,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13251327
adjustment::Adjust::NeverToAny
13261328
| adjustment::Adjust::Pointer(_)
13271329
| adjustment::Adjust::Borrow(_)
1330+
| adjustment::Adjust::StripPattern
13281331
| adjustment::Adjust::ReborrowPin(..) => {
13291332
// Result is an rvalue.
13301333
Ok(self.cat_rvalue(expr.hir_id, target))

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
281281
// FIXME(const_trait_impl): We could enforce these; they correspond to
282282
// `&mut T: DerefMut` tho, so it's kinda moot.
283283
}
284-
Adjust::Borrow(_) => {
284+
Adjust::StripPattern | Adjust::Borrow(_) => {
285285
// No effects to enforce here.
286286
}
287287
}
@@ -321,11 +321,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
321321
}
322322

323323
(
324-
&mut [
324+
[
325325
Adjustment { kind: Adjust::Deref(_), .. },
326326
Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. },
327327
],
328-
&[
328+
[
329329
Adjustment { kind: Adjust::Deref(_), .. },
330330
.., // Any following adjustments are allowed.
331331
],
@@ -334,6 +334,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
334334
*entry.get_mut() = adj;
335335
}
336336

337+
(
338+
[Adjustment { kind: Adjust::StripPattern, .. }],
339+
[Adjustment { kind: Adjust::Borrow(_), .. }, ..],
340+
) => {
341+
entry.get_mut().extend(adj);
342+
}
343+
337344
_ => {
338345
// FIXME: currently we never try to compose autoderefs
339346
// and ReifyFnPointer/UnsafeFnPointer, but we could.

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ impl<'tcx> Rvalue<'tcx> {
662662
| CastKind::PtrToPtr
663663
| CastKind::PointerCoercion(_, _)
664664
| CastKind::PointerWithExposedProvenance
665+
| CastKind::StripPat
665666
| CastKind::Transmute,
666667
_,
667668
_,

compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,9 @@ pub enum CastKind {
14401440
///
14411441
/// Allowed only in [`MirPhase::Runtime`]; Earlier it's a [`TerminatorKind::Call`].
14421442
Transmute,
1443+
/// Removing the pattern of a pattern type and yielding the base type is entirely
1444+
/// safe and requires no additional checks.
1445+
StripPat,
14431446
}
14441447

14451448
/// Represents how a [`CastKind::PointerCoercion`] was constructed.

0 commit comments

Comments
 (0)