Skip to content

Commit 0a05677

Browse files
committed
lower_pat_expr: use the pattern's type instead of the literal's
This allows us to remove the field `treat_byte_string_as_slice` from `TypeckResults`, since the pattern's type contains everything necessary to get the correct lowering for byte string literal patterns. This leaves the implementation of `string_deref_patterns` broken, to be fixed in the next commit.
1 parent 65899c0 commit 0a05677

File tree

5 files changed

+15
-47
lines changed

5 files changed

+15
-47
lines changed

compiler/rustc_hir_typeck/src/pat.rs

-4
Original file line numberDiff line numberDiff line change
@@ -632,10 +632,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
632632
{
633633
let tcx = self.tcx;
634634
trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
635-
self.typeck_results
636-
.borrow_mut()
637-
.treat_byte_string_as_slice
638-
.insert(lt.hir_id.local_id);
639635
pat_ty =
640636
Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8));
641637
}

compiler/rustc_hir_typeck/src/writeback.rs

-3
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8181
debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
8282
wbcx.typeck_results.used_trait_imports = used_trait_imports;
8383

84-
wbcx.typeck_results.treat_byte_string_as_slice =
85-
mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice);
86-
8784
debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);
8885

8986
self.tcx.arena.alloc(wbcx.typeck_results)

compiler/rustc_middle/src/ty/typeck_results.rs

-7
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,6 @@ pub struct TypeckResults<'tcx> {
197197
/// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
198198
pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
199199

200-
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
201-
/// as `&[u8]`, depending on the pattern in which they are used.
202-
/// This hashset records all instances where we behave
203-
/// like this to allow `const_to_pat` to reliably handle this situation.
204-
pub treat_byte_string_as_slice: ItemLocalSet,
205-
206200
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
207201
/// on closure size.
208202
pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
@@ -237,7 +231,6 @@ impl<'tcx> TypeckResults<'tcx> {
237231
closure_fake_reads: Default::default(),
238232
rvalue_scopes: Default::default(),
239233
coroutine_stalled_predicates: Default::default(),
240-
treat_byte_string_as_slice: Default::default(),
241234
closure_size_eval: Default::default(),
242235
offset_of_data: Default::default(),
243236
}

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+2-29
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,13 @@ struct ConstToPat<'tcx> {
5858
span: Span,
5959
id: hir::HirId,
6060

61-
treat_byte_string_as_slice: bool,
62-
6361
c: ty::Const<'tcx>,
6462
}
6563

6664
impl<'tcx> ConstToPat<'tcx> {
6765
fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
6866
trace!(?pat_ctxt.typeck_results.hir_owner);
69-
ConstToPat {
70-
tcx: pat_ctxt.tcx,
71-
typing_env: pat_ctxt.typing_env,
72-
span,
73-
id,
74-
treat_byte_string_as_slice: pat_ctxt
75-
.typeck_results
76-
.treat_byte_string_as_slice
77-
.contains(&id.local_id),
78-
c,
79-
}
67+
ConstToPat { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, id, c }
8068
}
8169

8270
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
@@ -108,8 +96,6 @@ impl<'tcx> ConstToPat<'tcx> {
10896
uv: ty::UnevaluatedConst<'tcx>,
10997
ty: Ty<'tcx>,
11098
) -> Box<Pat<'tcx>> {
111-
trace!(self.treat_byte_string_as_slice);
112-
11399
// It's not *technically* correct to be revealing opaque types here as borrowcheck has
114100
// not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even
115101
// during typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
@@ -307,21 +293,8 @@ impl<'tcx> ConstToPat<'tcx> {
307293
ty,
308294
);
309295
} else {
310-
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
311-
// matching against references, you can only use byte string literals.
312-
// The typechecker has a special case for byte string literals, by treating them
313-
// as slices. This means we turn `&[T; N]` constants into slice patterns, which
314-
// has no negative effects on pattern matching, even if we're actually matching on
315-
// arrays.
316-
let pointee_ty = match *pointee_ty.kind() {
317-
ty::Array(elem_ty, _) if self.treat_byte_string_as_slice => {
318-
Ty::new_slice(tcx, elem_ty)
319-
}
320-
_ => *pointee_ty,
321-
};
322296
// References have the same valtree representation as their pointee.
323-
let subpattern = self.valtree_to_pat(cv, pointee_ty);
324-
PatKind::Deref { subpattern }
297+
PatKind::Deref { subpattern: self.valtree_to_pat(cv, *pointee_ty) }
325298
}
326299
}
327300
},

compiler/rustc_mir_build/src/thir/pattern/mod.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
130130

131131
// Lower the endpoint into a temporary `PatKind` that will then be
132132
// deconstructed to obtain the constant value and other data.
133-
let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr);
133+
let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr, None);
134134

135135
// Unpeel any ascription or inline-const wrapper nodes.
136136
loop {
@@ -294,7 +294,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
294294

295295
hir::PatKind::Never => PatKind::Never,
296296

297-
hir::PatKind::Expr(value) => self.lower_pat_expr(value),
297+
hir::PatKind::Expr(value) => self.lower_pat_expr(value, Some(ty)),
298298

299299
hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
300300
let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
@@ -630,7 +630,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
630630
/// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`)
631631
/// - Inline const blocks (e.g. `const { 1 + 1 }`)
632632
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
633-
fn lower_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> {
633+
fn lower_pat_expr(
634+
&mut self,
635+
expr: &'tcx hir::PatExpr<'tcx>,
636+
pat_ty: Option<Ty<'tcx>>,
637+
) -> PatKind<'tcx> {
634638
let (lit, neg) = match &expr.kind {
635639
hir::PatExprKind::Path(qpath) => {
636640
return self.lower_path(qpath, expr.hir_id, expr.span).kind;
@@ -641,7 +645,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
641645
hir::PatExprKind::Lit { lit, negated } => (lit, *negated),
642646
};
643647

644-
let ct_ty = self.typeck_results.node_type(expr.hir_id);
648+
// We handle byte string literal patterns by using the pattern's type instead of the
649+
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
650+
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
651+
// pattern's type means we'll properly translate it to a slice reference pattern. This works
652+
// because slices and arrays have the same valtree representation.
653+
let ct_ty = pat_ty.unwrap_or_else(|| self.typeck_results.node_type(expr.hir_id));
645654
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
646655
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
647656
self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind

0 commit comments

Comments
 (0)