Commit cdddb85

Browse files
authored
Rollup merge of #150660 - Zalathar:pass-nodes, r=davidtwco
THIR pattern building: Pass HIR nodes instead of loose types/spans This should make it easier to keep track of where the types/spans came from. There should be no change to compiler output. --- In the future I would also like to make more of these lowering methods return `Box<thir::Pat>` instead of `thir::PatKind`, so that it becomes feasible to add more fields to `thir::Pat` (e.g. for #150498 (comment)). That will be easier if those methods have easy access to the corresponding HIR pattern node, from which they can obtain a type and span.
2 parents 18910b7 + de37724 commit cdddb85

1 file changed

Lines changed: 62 additions & 29 deletions

File tree

  • compiler/rustc_mir_build/src/thir/pattern

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

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod check_match;
44
mod const_to_pat;
55
mod migration;
66

7+
use std::assert_matches::assert_matches;
78
use std::cmp::Ordering;
89
use std::sync::Arc;
910

@@ -21,7 +22,7 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2122
use rustc_middle::ty::layout::IntegerExt;
2223
use rustc_middle::ty::{self,CanonicalUserTypeAnnotation,Ty,TyCtxt};
2324
use rustc_middle::{bug, span_bug};
24-
use rustc_span::{ErrorGuaranteed,Span};
25+
use rustc_span::ErrorGuaranteed;
2526
use tracing::{debug, instrument};
2627

2728
pub(crate)useself::check_match::check_match;
@@ -129,15 +130,20 @@ impl<'tcx> PatCtxt<'tcx> {
129130

130131
fnlower_pattern_range_endpoint(
131132
&mutself,
133+
pat:&'tcx hir::Pat<'tcx>,// Range pattern containing the endpoint
132134
expr:Option<&'tcx hir::PatExpr<'tcx>>,
133135
// Out-parameter collecting extra data to be reapplied by the caller
134136
ascriptions:&mutVec<Ascription<'tcx>>,
135137
) -> Result<Option<PatRangeBoundary<'tcx>>,ErrorGuaranteed>{
138+
assert_matches!(pat.kind, hir::PatKind::Range(..));
139+
140+
// For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
141+
// Return None in that case; the caller will use NegInfinity or PosInfinity instead.
136142
letSome(expr) = expr else{returnOk(None)};
137143

138144
// Lower the endpoint into a temporary `PatKind` that will then be
139145
// deconstructed to obtain the constant value and other data.
140-
letmut kind:PatKind<'tcx> = self.lower_pat_expr(expr,None);
146+
letmut kind:PatKind<'tcx> = self.lower_pat_expr(pat, expr);
141147

142148
// Unpeel any ascription or inline-const wrapper nodes.
143149
loop{
@@ -214,20 +220,23 @@ impl<'tcx> PatCtxt<'tcx> {
214220

215221
fnlower_pattern_range(
216222
&mutself,
223+
pat:&'tcx hir::Pat<'tcx>,
217224
lo_expr:Option<&'tcx hir::PatExpr<'tcx>>,
218225
hi_expr:Option<&'tcx hir::PatExpr<'tcx>>,
219226
end:RangeEnd,
220-
ty:Ty<'tcx>,
221-
span:Span,
222227
) -> Result<PatKind<'tcx>,ErrorGuaranteed>{
228+
let ty = self.typeck_results.node_type(pat.hir_id);
229+
let span = pat.span;
230+
223231
if lo_expr.is_none() && hi_expr.is_none(){
224232
let msg = "found twice-open range pattern (`..`) outside of error recovery";
225233
self.tcx.dcx().span_bug(span, msg);
226234
}
227235

228236
// Collect extra data while lowering the endpoints, to be reapplied later.
229237
letmut ascriptions = vec![];
230-
letmut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr,&mut ascriptions);
238+
letmut lower_endpoint =
239+
|expr| self.lower_pattern_range_endpoint(pat, expr,&mut ascriptions);
231240

232241
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
233242
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -299,12 +308,10 @@ impl<'tcx> PatCtxt<'tcx> {
299308

300309
hir::PatKind::Never => PatKind::Never,
301310

302-
hir::PatKind::Expr(value) => self.lower_pat_expr(value,Some(ty)),
311+
hir::PatKind::Expr(value) => self.lower_pat_expr(pat, value),
303312

304-
hir::PatKind::Range(ref lo_expr,ref hi_expr, end) => {
305-
let(lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
306-
self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
307-
.unwrap_or_else(PatKind::Error)
313+
hir::PatKind::Range(lo_expr, hi_expr, end) => {
314+
self.lower_pattern_range(pat, lo_expr, hi_expr, end).unwrap_or_else(PatKind::Error)
308315
}
309316

310317
hir::PatKind::Deref(subpattern) => {
@@ -327,7 +334,7 @@ impl<'tcx> PatCtxt<'tcx> {
327334
},
328335

329336
hir::PatKind::Slice(prefix, slice, suffix) => {
330-
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
337+
self.slice_or_array_pattern(pat, prefix, slice, suffix)
331338
}
332339

333340
hir::PatKind::Tuple(pats, ddpos) => {
@@ -389,7 +396,7 @@ impl<'tcx> PatCtxt<'tcx> {
389396
};
390397
let variant_def = adt_def.variant_of_res(res);
391398
let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
392-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
399+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
393400
}
394401

395402
hir::PatKind::Struct(ref qpath, fields, _) => {
@@ -406,7 +413,7 @@ impl<'tcx> PatCtxt<'tcx> {
406413
})
407414
.collect();
408415

409-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
416+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
410417
}
411418

412419
hir::PatKind::Or(pats) => PatKind::Or{pats:self.lower_patterns(pats)},
@@ -445,12 +452,13 @@ impl<'tcx> PatCtxt<'tcx> {
445452

446453
fnslice_or_array_pattern(
447454
&mutself,
448-
span:Span,
449-
ty:Ty<'tcx>,
455+
pat:&'tcx hir::Pat<'tcx>,
450456
prefix:&'tcx[hir::Pat<'tcx>],
451457
slice:Option<&'tcx hir::Pat<'tcx>>,
452458
suffix:&'tcx[hir::Pat<'tcx>],
453459
) -> PatKind<'tcx>{
460+
let ty = self.typeck_results.node_type(pat.hir_id);
461+
454462
let prefix = self.lower_patterns(prefix);
455463
let slice = self.lower_opt_pattern(slice);
456464
let suffix = self.lower_patterns(suffix);
@@ -465,18 +473,32 @@ impl<'tcx> PatCtxt<'tcx> {
465473
assert!(len >= prefix.len()asu64 + suffix.len()asu64);
466474
PatKind::Array{ prefix, slice, suffix }
467475
}
468-
_ => span_bug!(span,"bad slice pattern type {:?}", ty),
476+
_ => span_bug!(pat.span,"bad slice pattern type {ty:?}"),
469477
}
470478
}
471479

472480
fnlower_variant_or_leaf(
473481
&mutself,
482+
pat:&'tcx hir::Pat<'tcx>,
483+
expr:Option<&'tcx hir::PatExpr<'tcx>>,
474484
res:Res,
475-
hir_id: hir::HirId,
476-
span:Span,
477-
ty:Ty<'tcx>,
478485
subpatterns:Vec<FieldPat<'tcx>>,
479486
) -> PatKind<'tcx>{
487+
// Check whether the caller should have provided an `expr` for this pattern kind.
488+
assert_matches!(
489+
(pat.kind, expr),
490+
(hir::PatKind::Expr(..) | hir::PatKind::Range(..),Some(_))
491+
| (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..),None)
492+
);
493+
494+
// Use the id/span of the `hir::PatExpr`, if provided.
495+
// Otherwise, use the id/span of the `hir::Pat`.
496+
let(hir_id, span) = match expr {
497+
Some(expr) => (expr.hir_id, expr.span),
498+
None => (pat.hir_id, pat.span),
499+
};
500+
let ty = self.typeck_results.node_type(hir_id);
501+
480502
let res = match res {
481503
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
482504
let variant_id = self.tcx.parent(variant_ctor_id);
@@ -563,7 +585,16 @@ impl<'tcx> PatCtxt<'tcx> {
563585
/// it to `const_to_pat`. Any other path (like enum variants without fields)
564586
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
565587
#[instrument(skip(self), level = "debug")]
566-
fnlower_path(&mutself,qpath:&hir::QPath<'_>,id: hir::HirId,span:Span) -> Box<Pat<'tcx>>{
588+
fnlower_path(
589+
&mutself,
590+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
591+
expr:&'tcx hir::PatExpr<'tcx>,
592+
qpath:&hir::QPath<'_>,
593+
) -> Box<Pat<'tcx>>{
594+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
595+
596+
let id = expr.hir_id;
597+
let span = expr.span;
567598
let ty = self.typeck_results.node_type(id);
568599
let res = self.typeck_results.qpath_res(qpath, id);
569600

@@ -575,7 +606,7 @@ impl<'tcx> PatCtxt<'tcx> {
575606
_ => {
576607
// The path isn't the name of a constant, so it must actually
577608
// be a unit struct or unit variant (e.g. `Option::None`).
578-
let kind = self.lower_variant_or_leaf(res, id, span, ty,vec![]);
609+
let kind = self.lower_variant_or_leaf(pat,Some(expr), res,vec![]);
579610
returnBox::new(Pat{ span, ty, kind });
580611
}
581612
};
@@ -615,24 +646,26 @@ impl<'tcx> PatCtxt<'tcx> {
615646
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
616647
fnlower_pat_expr(
617648
&mutself,
649+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
618650
expr:&'tcx hir::PatExpr<'tcx>,
619-
pat_ty:Option<Ty<'tcx>>,
620651
) -> PatKind<'tcx>{
652+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
621653
match&expr.kind{
622-
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
654+
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath).kind,
623655
hir::PatExprKind::Lit{ lit, negated } => {
624656
// We handle byte string literal patterns by using the pattern's type instead of the
625657
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
626658
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
627659
// pattern's type means we'll properly translate it to a slice reference pattern. This works
628660
// because slices and arrays have the same valtree representation.
629-
let ct_ty = match pat_ty {
630-
Some(pat_ty) => pat_ty,
631-
None => self.typeck_results.node_type(expr.hir_id),
632-
};
633-
let lit_input = LitToConstInput{lit: lit.node,ty: ct_ty,neg:*negated };
661+
//
662+
// Under `feature(deref_patterns)`, this adjustment can also convert string literal
663+
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
664+
665+
let pat_ty = self.typeck_results.node_type(pat.hir_id);
666+
let lit_input = LitToConstInput{lit: lit.node,ty: pat_ty,neg:*negated };
634667
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
635-
self.const_to_pat(constant,ct_ty, expr.hir_id, lit.span).kind
668+
self.const_to_pat(constant,pat_ty, expr.hir_id, lit.span).kind
636669
}
637670
}
638671
}

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Commit cdddb85

Browse files
authored
Rollup merge of #150660 - Zalathar:pass-nodes, r=davidtwco
THIR pattern building: Pass HIR nodes instead of loose types/spans This should make it easier to keep track of where the types/spans came from. There should be no change to compiler output. --- In the future I would also like to make more of these lowering methods return `Box<thir::Pat>` instead of `thir::PatKind`, so that it becomes feasible to add more fields to `thir::Pat` (e.g. for #150498 (comment)). That will be easier if those methods have easy access to the corresponding HIR pattern node, from which they can obtain a type and span.
2 parents 18910b7 + de37724 commit cdddb85

1 file changed

Lines changed: 62 additions & 29 deletions

File tree

  • compiler/rustc_mir_build/src/thir/pattern

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

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod check_match;
44
mod const_to_pat;
55
mod migration;
66

7+
use std::assert_matches::assert_matches;
78
use std::cmp::Ordering;
89
use std::sync::Arc;
910

@@ -21,7 +22,7 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2122
use rustc_middle::ty::layout::IntegerExt;
2223
use rustc_middle::ty::{self,CanonicalUserTypeAnnotation,Ty,TyCtxt};
2324
use rustc_middle::{bug, span_bug};
24-
use rustc_span::{ErrorGuaranteed,Span};
25+
use rustc_span::ErrorGuaranteed;
2526
use tracing::{debug, instrument};
2627

2728
pub(crate)useself::check_match::check_match;
@@ -129,15 +130,20 @@ impl<'tcx> PatCtxt<'tcx> {
129130

130131
fnlower_pattern_range_endpoint(
131132
&mutself,
133+
pat:&'tcx hir::Pat<'tcx>,// Range pattern containing the endpoint
132134
expr:Option<&'tcx hir::PatExpr<'tcx>>,
133135
// Out-parameter collecting extra data to be reapplied by the caller
134136
ascriptions:&mutVec<Ascription<'tcx>>,
135137
) -> Result<Option<PatRangeBoundary<'tcx>>,ErrorGuaranteed>{
138+
assert_matches!(pat.kind, hir::PatKind::Range(..));
139+
140+
// For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
141+
// Return None in that case; the caller will use NegInfinity or PosInfinity instead.
136142
letSome(expr) = expr else{returnOk(None)};
137143

138144
// Lower the endpoint into a temporary `PatKind` that will then be
139145
// deconstructed to obtain the constant value and other data.
140-
letmut kind:PatKind<'tcx> = self.lower_pat_expr(expr,None);
146+
letmut kind:PatKind<'tcx> = self.lower_pat_expr(pat, expr);
141147

142148
// Unpeel any ascription or inline-const wrapper nodes.
143149
loop{
@@ -214,20 +220,23 @@ impl<'tcx> PatCtxt<'tcx> {
214220

215221
fnlower_pattern_range(
216222
&mutself,
223+
pat:&'tcx hir::Pat<'tcx>,
217224
lo_expr:Option<&'tcx hir::PatExpr<'tcx>>,
218225
hi_expr:Option<&'tcx hir::PatExpr<'tcx>>,
219226
end:RangeEnd,
220-
ty:Ty<'tcx>,
221-
span:Span,
222227
) -> Result<PatKind<'tcx>,ErrorGuaranteed>{
228+
let ty = self.typeck_results.node_type(pat.hir_id);
229+
let span = pat.span;
230+
223231
if lo_expr.is_none() && hi_expr.is_none(){
224232
let msg = "found twice-open range pattern (`..`) outside of error recovery";
225233
self.tcx.dcx().span_bug(span, msg);
226234
}
227235

228236
// Collect extra data while lowering the endpoints, to be reapplied later.
229237
letmut ascriptions = vec![];
230-
letmut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr,&mut ascriptions);
238+
letmut lower_endpoint =
239+
|expr| self.lower_pattern_range_endpoint(pat, expr,&mut ascriptions);
231240

232241
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
233242
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -299,12 +308,10 @@ impl<'tcx> PatCtxt<'tcx> {
299308

300309
hir::PatKind::Never => PatKind::Never,
301310

302-
hir::PatKind::Expr(value) => self.lower_pat_expr(value,Some(ty)),
311+
hir::PatKind::Expr(value) => self.lower_pat_expr(pat, value),
303312

304-
hir::PatKind::Range(ref lo_expr,ref hi_expr, end) => {
305-
let(lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
306-
self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
307-
.unwrap_or_else(PatKind::Error)
313+
hir::PatKind::Range(lo_expr, hi_expr, end) => {
314+
self.lower_pattern_range(pat, lo_expr, hi_expr, end).unwrap_or_else(PatKind::Error)
308315
}
309316

310317
hir::PatKind::Deref(subpattern) => {
@@ -327,7 +334,7 @@ impl<'tcx> PatCtxt<'tcx> {
327334
},
328335

329336
hir::PatKind::Slice(prefix, slice, suffix) => {
330-
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
337+
self.slice_or_array_pattern(pat, prefix, slice, suffix)
331338
}
332339

333340
hir::PatKind::Tuple(pats, ddpos) => {
@@ -389,7 +396,7 @@ impl<'tcx> PatCtxt<'tcx> {
389396
};
390397
let variant_def = adt_def.variant_of_res(res);
391398
let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
392-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
399+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
393400
}
394401

395402
hir::PatKind::Struct(ref qpath, fields, _) => {
@@ -406,7 +413,7 @@ impl<'tcx> PatCtxt<'tcx> {
406413
})
407414
.collect();
408415

409-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
416+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
410417
}
411418

412419
hir::PatKind::Or(pats) => PatKind::Or{pats:self.lower_patterns(pats)},
@@ -445,12 +452,13 @@ impl<'tcx> PatCtxt<'tcx> {
445452

446453
fnslice_or_array_pattern(
447454
&mutself,
448-
span:Span,
449-
ty:Ty<'tcx>,
455+
pat:&'tcx hir::Pat<'tcx>,
450456
prefix:&'tcx[hir::Pat<'tcx>],
451457
slice:Option<&'tcx hir::Pat<'tcx>>,
452458
suffix:&'tcx[hir::Pat<'tcx>],
453459
) -> PatKind<'tcx>{
460+
let ty = self.typeck_results.node_type(pat.hir_id);
461+
454462
let prefix = self.lower_patterns(prefix);
455463
let slice = self.lower_opt_pattern(slice);
456464
let suffix = self.lower_patterns(suffix);
@@ -465,18 +473,32 @@ impl<'tcx> PatCtxt<'tcx> {
465473
assert!(len >= prefix.len()asu64 + suffix.len()asu64);
466474
PatKind::Array{ prefix, slice, suffix }
467475
}
468-
_ => span_bug!(span,"bad slice pattern type {:?}", ty),
476+
_ => span_bug!(pat.span,"bad slice pattern type {ty:?}"),
469477
}
470478
}
471479

472480
fnlower_variant_or_leaf(
473481
&mutself,
482+
pat:&'tcx hir::Pat<'tcx>,
483+
expr:Option<&'tcx hir::PatExpr<'tcx>>,
474484
res:Res,
475-
hir_id: hir::HirId,
476-
span:Span,
477-
ty:Ty<'tcx>,
478485
subpatterns:Vec<FieldPat<'tcx>>,
479486
) -> PatKind<'tcx>{
487+
// Check whether the caller should have provided an `expr` for this pattern kind.
488+
assert_matches!(
489+
(pat.kind, expr),
490+
(hir::PatKind::Expr(..) | hir::PatKind::Range(..),Some(_))
491+
| (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..),None)
492+
);
493+
494+
// Use the id/span of the `hir::PatExpr`, if provided.
495+
// Otherwise, use the id/span of the `hir::Pat`.
496+
let(hir_id, span) = match expr {
497+
Some(expr) => (expr.hir_id, expr.span),
498+
None => (pat.hir_id, pat.span),
499+
};
500+
let ty = self.typeck_results.node_type(hir_id);
501+
480502
let res = match res {
481503
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
482504
let variant_id = self.tcx.parent(variant_ctor_id);
@@ -563,7 +585,16 @@ impl<'tcx> PatCtxt<'tcx> {
563585
/// it to `const_to_pat`. Any other path (like enum variants without fields)
564586
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
565587
#[instrument(skip(self), level = "debug")]
566-
fnlower_path(&mutself,qpath:&hir::QPath<'_>,id: hir::HirId,span:Span) -> Box<Pat<'tcx>>{
588+
fnlower_path(
589+
&mutself,
590+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
591+
expr:&'tcx hir::PatExpr<'tcx>,
592+
qpath:&hir::QPath<'_>,
593+
) -> Box<Pat<'tcx>>{
594+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
595+
596+
let id = expr.hir_id;
597+
let span = expr.span;
567598
let ty = self.typeck_results.node_type(id);
568599
let res = self.typeck_results.qpath_res(qpath, id);
569600

@@ -575,7 +606,7 @@ impl<'tcx> PatCtxt<'tcx> {
575606
_ => {
576607
// The path isn't the name of a constant, so it must actually
577608
// be a unit struct or unit variant (e.g. `Option::None`).
578-
let kind = self.lower_variant_or_leaf(res, id, span, ty,vec![]);
609+
let kind = self.lower_variant_or_leaf(pat,Some(expr), res,vec![]);
579610
returnBox::new(Pat{ span, ty, kind });
580611
}
581612
};
@@ -615,24 +646,26 @@ impl<'tcx> PatCtxt<'tcx> {
615646
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
616647
fnlower_pat_expr(
617648
&mutself,
649+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
618650
expr:&'tcx hir::PatExpr<'tcx>,
619-
pat_ty:Option<Ty<'tcx>>,
620651
) -> PatKind<'tcx>{
652+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
621653
match&expr.kind{
622-
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
654+
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath).kind,
623655
hir::PatExprKind::Lit{ lit, negated } => {
624656
// We handle byte string literal patterns by using the pattern's type instead of the
625657
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
626658
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
627659
// pattern's type means we'll properly translate it to a slice reference pattern. This works
628660
// because slices and arrays have the same valtree representation.
629-
let ct_ty = match pat_ty {
630-
Some(pat_ty) => pat_ty,
631-
None => self.typeck_results.node_type(expr.hir_id),
632-
};
633-
let lit_input = LitToConstInput{lit: lit.node,ty: ct_ty,neg:*negated };
661+
//
662+
// Under `feature(deref_patterns)`, this adjustment can also convert string literal
663+
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
664+
665+
let pat_ty = self.typeck_results.node_type(pat.hir_id);
666+
let lit_input = LitToConstInput{lit: lit.node,ty: pat_ty,neg:*negated };
634667
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
635-
self.const_to_pat(constant,ct_ty, expr.hir_id, lit.span).kind
668+
self.const_to_pat(constant,pat_ty, expr.hir_id, lit.span).kind
636669
}
637670
}
638671
}

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit cdddb85

Browse files
authored
Rollup merge of #150660 - Zalathar:pass-nodes, r=davidtwco
THIR pattern building: Pass HIR nodes instead of loose types/spans This should make it easier to keep track of where the types/spans came from. There should be no change to compiler output. --- In the future I would also like to make more of these lowering methods return `Box<thir::Pat>` instead of `thir::PatKind`, so that it becomes feasible to add more fields to `thir::Pat` (e.g. for #150498 (comment)). That will be easier if those methods have easy access to the corresponding HIR pattern node, from which they can obtain a type and span.
2 parents 18910b7 + de37724 commit cdddb85

1 file changed

Lines changed: 62 additions & 29 deletions

File tree

  • compiler/rustc_mir_build/src/thir/pattern

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

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod check_match;
44
mod const_to_pat;
55
mod migration;
66

7+
use std::assert_matches::assert_matches;
78
use std::cmp::Ordering;
89
use std::sync::Arc;
910

@@ -21,7 +22,7 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2122
use rustc_middle::ty::layout::IntegerExt;
2223
use rustc_middle::ty::{self,CanonicalUserTypeAnnotation,Ty,TyCtxt};
2324
use rustc_middle::{bug, span_bug};
24-
use rustc_span::{ErrorGuaranteed,Span};
25+
use rustc_span::ErrorGuaranteed;
2526
use tracing::{debug, instrument};
2627

2728
pub(crate)useself::check_match::check_match;
@@ -129,15 +130,20 @@ impl<'tcx> PatCtxt<'tcx> {
129130

130131
fnlower_pattern_range_endpoint(
131132
&mutself,
133+
pat:&'tcx hir::Pat<'tcx>,// Range pattern containing the endpoint
132134
expr:Option<&'tcx hir::PatExpr<'tcx>>,
133135
// Out-parameter collecting extra data to be reapplied by the caller
134136
ascriptions:&mutVec<Ascription<'tcx>>,
135137
) -> Result<Option<PatRangeBoundary<'tcx>>,ErrorGuaranteed>{
138+
assert_matches!(pat.kind, hir::PatKind::Range(..));
139+
140+
// For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
141+
// Return None in that case; the caller will use NegInfinity or PosInfinity instead.
136142
letSome(expr) = expr else{returnOk(None)};
137143

138144
// Lower the endpoint into a temporary `PatKind` that will then be
139145
// deconstructed to obtain the constant value and other data.
140-
letmut kind:PatKind<'tcx> = self.lower_pat_expr(expr,None);
146+
letmut kind:PatKind<'tcx> = self.lower_pat_expr(pat, expr);
141147

142148
// Unpeel any ascription or inline-const wrapper nodes.
143149
loop{
@@ -214,20 +220,23 @@ impl<'tcx> PatCtxt<'tcx> {
214220

215221
fnlower_pattern_range(
216222
&mutself,
223+
pat:&'tcx hir::Pat<'tcx>,
217224
lo_expr:Option<&'tcx hir::PatExpr<'tcx>>,
218225
hi_expr:Option<&'tcx hir::PatExpr<'tcx>>,
219226
end:RangeEnd,
220-
ty:Ty<'tcx>,
221-
span:Span,
222227
) -> Result<PatKind<'tcx>,ErrorGuaranteed>{
228+
let ty = self.typeck_results.node_type(pat.hir_id);
229+
let span = pat.span;
230+
223231
if lo_expr.is_none() && hi_expr.is_none(){
224232
let msg = "found twice-open range pattern (`..`) outside of error recovery";
225233
self.tcx.dcx().span_bug(span, msg);
226234
}
227235

228236
// Collect extra data while lowering the endpoints, to be reapplied later.
229237
letmut ascriptions = vec![];
230-
letmut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr,&mut ascriptions);
238+
letmut lower_endpoint =
239+
|expr| self.lower_pattern_range_endpoint(pat, expr,&mut ascriptions);
231240

232241
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
233242
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -299,12 +308,10 @@ impl<'tcx> PatCtxt<'tcx> {
299308

300309
hir::PatKind::Never => PatKind::Never,
301310

302-
hir::PatKind::Expr(value) => self.lower_pat_expr(value,Some(ty)),
311+
hir::PatKind::Expr(value) => self.lower_pat_expr(pat, value),
303312

304-
hir::PatKind::Range(ref lo_expr,ref hi_expr, end) => {
305-
let(lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
306-
self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
307-
.unwrap_or_else(PatKind::Error)
313+
hir::PatKind::Range(lo_expr, hi_expr, end) => {
314+
self.lower_pattern_range(pat, lo_expr, hi_expr, end).unwrap_or_else(PatKind::Error)
308315
}
309316

310317
hir::PatKind::Deref(subpattern) => {
@@ -327,7 +334,7 @@ impl<'tcx> PatCtxt<'tcx> {
327334
},
328335

329336
hir::PatKind::Slice(prefix, slice, suffix) => {
330-
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
337+
self.slice_or_array_pattern(pat, prefix, slice, suffix)
331338
}
332339

333340
hir::PatKind::Tuple(pats, ddpos) => {
@@ -389,7 +396,7 @@ impl<'tcx> PatCtxt<'tcx> {
389396
};
390397
let variant_def = adt_def.variant_of_res(res);
391398
let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
392-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
399+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
393400
}
394401

395402
hir::PatKind::Struct(ref qpath, fields, _) => {
@@ -406,7 +413,7 @@ impl<'tcx> PatCtxt<'tcx> {
406413
})
407414
.collect();
408415

409-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
416+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
410417
}
411418

412419
hir::PatKind::Or(pats) => PatKind::Or{pats:self.lower_patterns(pats)},
@@ -445,12 +452,13 @@ impl<'tcx> PatCtxt<'tcx> {
445452

446453
fnslice_or_array_pattern(
447454
&mutself,
448-
span:Span,
449-
ty:Ty<'tcx>,
455+
pat:&'tcx hir::Pat<'tcx>,
450456
prefix:&'tcx[hir::Pat<'tcx>],
451457
slice:Option<&'tcx hir::Pat<'tcx>>,
452458
suffix:&'tcx[hir::Pat<'tcx>],
453459
) -> PatKind<'tcx>{
460+
let ty = self.typeck_results.node_type(pat.hir_id);
461+
454462
let prefix = self.lower_patterns(prefix);
455463
let slice = self.lower_opt_pattern(slice);
456464
let suffix = self.lower_patterns(suffix);
@@ -465,18 +473,32 @@ impl<'tcx> PatCtxt<'tcx> {
465473
assert!(len >= prefix.len()asu64 + suffix.len()asu64);
466474
PatKind::Array{ prefix, slice, suffix }
467475
}
468-
_ => span_bug!(span,"bad slice pattern type {:?}", ty),
476+
_ => span_bug!(pat.span,"bad slice pattern type {ty:?}"),
469477
}
470478
}
471479

472480
fnlower_variant_or_leaf(
473481
&mutself,
482+
pat:&'tcx hir::Pat<'tcx>,
483+
expr:Option<&'tcx hir::PatExpr<'tcx>>,
474484
res:Res,
475-
hir_id: hir::HirId,
476-
span:Span,
477-
ty:Ty<'tcx>,
478485
subpatterns:Vec<FieldPat<'tcx>>,
479486
) -> PatKind<'tcx>{
487+
// Check whether the caller should have provided an `expr` for this pattern kind.
488+
assert_matches!(
489+
(pat.kind, expr),
490+
(hir::PatKind::Expr(..) | hir::PatKind::Range(..),Some(_))
491+
| (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..),None)
492+
);
493+
494+
// Use the id/span of the `hir::PatExpr`, if provided.
495+
// Otherwise, use the id/span of the `hir::Pat`.
496+
let(hir_id, span) = match expr {
497+
Some(expr) => (expr.hir_id, expr.span),
498+
None => (pat.hir_id, pat.span),
499+
};
500+
let ty = self.typeck_results.node_type(hir_id);
501+
480502
let res = match res {
481503
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
482504
let variant_id = self.tcx.parent(variant_ctor_id);
@@ -563,7 +585,16 @@ impl<'tcx> PatCtxt<'tcx> {
563585
/// it to `const_to_pat`. Any other path (like enum variants without fields)
564586
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
565587
#[instrument(skip(self), level = "debug")]
566-
fnlower_path(&mutself,qpath:&hir::QPath<'_>,id: hir::HirId,span:Span) -> Box<Pat<'tcx>>{
588+
fnlower_path(
589+
&mutself,
590+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
591+
expr:&'tcx hir::PatExpr<'tcx>,
592+
qpath:&hir::QPath<'_>,
593+
) -> Box<Pat<'tcx>>{
594+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
595+
596+
let id = expr.hir_id;
597+
let span = expr.span;
567598
let ty = self.typeck_results.node_type(id);
568599
let res = self.typeck_results.qpath_res(qpath, id);
569600

@@ -575,7 +606,7 @@ impl<'tcx> PatCtxt<'tcx> {
575606
_ => {
576607
// The path isn't the name of a constant, so it must actually
577608
// be a unit struct or unit variant (e.g. `Option::None`).
578-
let kind = self.lower_variant_or_leaf(res, id, span, ty,vec![]);
609+
let kind = self.lower_variant_or_leaf(pat,Some(expr), res,vec![]);
579610
returnBox::new(Pat{ span, ty, kind });
580611
}
581612
};
@@ -615,24 +646,26 @@ impl<'tcx> PatCtxt<'tcx> {
615646
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
616647
fnlower_pat_expr(
617648
&mutself,
649+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
618650
expr:&'tcx hir::PatExpr<'tcx>,
619-
pat_ty:Option<Ty<'tcx>>,
620651
) -> PatKind<'tcx>{
652+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
621653
match&expr.kind{
622-
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
654+
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath).kind,
623655
hir::PatExprKind::Lit{ lit, negated } => {
624656
// We handle byte string literal patterns by using the pattern's type instead of the
625657
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
626658
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
627659
// pattern's type means we'll properly translate it to a slice reference pattern. This works
628660
// because slices and arrays have the same valtree representation.
629-
let ct_ty = match pat_ty {
630-
Some(pat_ty) => pat_ty,
631-
None => self.typeck_results.node_type(expr.hir_id),
632-
};
633-
let lit_input = LitToConstInput{lit: lit.node,ty: ct_ty,neg:*negated };
661+
//
662+
// Under `feature(deref_patterns)`, this adjustment can also convert string literal
663+
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
664+
665+
let pat_ty = self.typeck_results.node_type(pat.hir_id);
666+
let lit_input = LitToConstInput{lit: lit.node,ty: pat_ty,neg:*negated };
634667
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
635-
self.const_to_pat(constant,ct_ty, expr.hir_id, lit.span).kind
668+
self.const_to_pat(constant,pat_ty, expr.hir_id, lit.span).kind
636669
}
637670
}
638671
}

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit cdddb85

Browse files
authored
Rollup merge of #150660 - Zalathar:pass-nodes, r=davidtwco
THIR pattern building: Pass HIR nodes instead of loose types/spans This should make it easier to keep track of where the types/spans came from. There should be no change to compiler output. --- In the future I would also like to make more of these lowering methods return `Box<thir::Pat>` instead of `thir::PatKind`, so that it becomes feasible to add more fields to `thir::Pat` (e.g. for #150498 (comment)). That will be easier if those methods have easy access to the corresponding HIR pattern node, from which they can obtain a type and span.
2 parents 18910b7 + de37724 commit cdddb85

1 file changed

Lines changed: 62 additions & 29 deletions

File tree

  • compiler/rustc_mir_build/src/thir/pattern

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

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod check_match;
44
mod const_to_pat;
55
mod migration;
66

7+
use std::assert_matches::assert_matches;
78
use std::cmp::Ordering;
89
use std::sync::Arc;
910

@@ -21,7 +22,7 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2122
use rustc_middle::ty::layout::IntegerExt;
2223
use rustc_middle::ty::{self,CanonicalUserTypeAnnotation,Ty,TyCtxt};
2324
use rustc_middle::{bug, span_bug};
24-
use rustc_span::{ErrorGuaranteed,Span};
25+
use rustc_span::ErrorGuaranteed;
2526
use tracing::{debug, instrument};
2627

2728
pub(crate)useself::check_match::check_match;
@@ -129,15 +130,20 @@ impl<'tcx> PatCtxt<'tcx> {
129130

130131
fnlower_pattern_range_endpoint(
131132
&mutself,
133+
pat:&'tcx hir::Pat<'tcx>,// Range pattern containing the endpoint
132134
expr:Option<&'tcx hir::PatExpr<'tcx>>,
133135
// Out-parameter collecting extra data to be reapplied by the caller
134136
ascriptions:&mutVec<Ascription<'tcx>>,
135137
) -> Result<Option<PatRangeBoundary<'tcx>>,ErrorGuaranteed>{
138+
assert_matches!(pat.kind, hir::PatKind::Range(..));
139+
140+
// For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
141+
// Return None in that case; the caller will use NegInfinity or PosInfinity instead.
136142
letSome(expr) = expr else{returnOk(None)};
137143

138144
// Lower the endpoint into a temporary `PatKind` that will then be
139145
// deconstructed to obtain the constant value and other data.
140-
letmut kind:PatKind<'tcx> = self.lower_pat_expr(expr,None);
146+
letmut kind:PatKind<'tcx> = self.lower_pat_expr(pat, expr);
141147

142148
// Unpeel any ascription or inline-const wrapper nodes.
143149
loop{
@@ -214,20 +220,23 @@ impl<'tcx> PatCtxt<'tcx> {
214220

215221
fnlower_pattern_range(
216222
&mutself,
223+
pat:&'tcx hir::Pat<'tcx>,
217224
lo_expr:Option<&'tcx hir::PatExpr<'tcx>>,
218225
hi_expr:Option<&'tcx hir::PatExpr<'tcx>>,
219226
end:RangeEnd,
220-
ty:Ty<'tcx>,
221-
span:Span,
222227
) -> Result<PatKind<'tcx>,ErrorGuaranteed>{
228+
let ty = self.typeck_results.node_type(pat.hir_id);
229+
let span = pat.span;
230+
223231
if lo_expr.is_none() && hi_expr.is_none(){
224232
let msg = "found twice-open range pattern (`..`) outside of error recovery";
225233
self.tcx.dcx().span_bug(span, msg);
226234
}
227235

228236
// Collect extra data while lowering the endpoints, to be reapplied later.
229237
letmut ascriptions = vec![];
230-
letmut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr,&mut ascriptions);
238+
letmut lower_endpoint =
239+
|expr| self.lower_pattern_range_endpoint(pat, expr,&mut ascriptions);
231240

232241
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
233242
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -299,12 +308,10 @@ impl<'tcx> PatCtxt<'tcx> {
299308

300309
hir::PatKind::Never => PatKind::Never,
301310

302-
hir::PatKind::Expr(value) => self.lower_pat_expr(value,Some(ty)),
311+
hir::PatKind::Expr(value) => self.lower_pat_expr(pat, value),
303312

304-
hir::PatKind::Range(ref lo_expr,ref hi_expr, end) => {
305-
let(lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
306-
self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
307-
.unwrap_or_else(PatKind::Error)
313+
hir::PatKind::Range(lo_expr, hi_expr, end) => {
314+
self.lower_pattern_range(pat, lo_expr, hi_expr, end).unwrap_or_else(PatKind::Error)
308315
}
309316

310317
hir::PatKind::Deref(subpattern) => {
@@ -327,7 +334,7 @@ impl<'tcx> PatCtxt<'tcx> {
327334
},
328335

329336
hir::PatKind::Slice(prefix, slice, suffix) => {
330-
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
337+
self.slice_or_array_pattern(pat, prefix, slice, suffix)
331338
}
332339

333340
hir::PatKind::Tuple(pats, ddpos) => {
@@ -389,7 +396,7 @@ impl<'tcx> PatCtxt<'tcx> {
389396
};
390397
let variant_def = adt_def.variant_of_res(res);
391398
let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
392-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
399+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
393400
}
394401

395402
hir::PatKind::Struct(ref qpath, fields, _) => {
@@ -406,7 +413,7 @@ impl<'tcx> PatCtxt<'tcx> {
406413
})
407414
.collect();
408415

409-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
416+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
410417
}
411418

412419
hir::PatKind::Or(pats) => PatKind::Or{pats:self.lower_patterns(pats)},
@@ -445,12 +452,13 @@ impl<'tcx> PatCtxt<'tcx> {
445452

446453
fnslice_or_array_pattern(
447454
&mutself,
448-
span:Span,
449-
ty:Ty<'tcx>,
455+
pat:&'tcx hir::Pat<'tcx>,
450456
prefix:&'tcx[hir::Pat<'tcx>],
451457
slice:Option<&'tcx hir::Pat<'tcx>>,
452458
suffix:&'tcx[hir::Pat<'tcx>],
453459
) -> PatKind<'tcx>{
460+
let ty = self.typeck_results.node_type(pat.hir_id);
461+
454462
let prefix = self.lower_patterns(prefix);
455463
let slice = self.lower_opt_pattern(slice);
456464
let suffix = self.lower_patterns(suffix);
@@ -465,18 +473,32 @@ impl<'tcx> PatCtxt<'tcx> {
465473
assert!(len >= prefix.len()asu64 + suffix.len()asu64);
466474
PatKind::Array{ prefix, slice, suffix }
467475
}
468-
_ => span_bug!(span,"bad slice pattern type {:?}", ty),
476+
_ => span_bug!(pat.span,"bad slice pattern type {ty:?}"),
469477
}
470478
}
471479

472480
fnlower_variant_or_leaf(
473481
&mutself,
482+
pat:&'tcx hir::Pat<'tcx>,
483+
expr:Option<&'tcx hir::PatExpr<'tcx>>,
474484
res:Res,
475-
hir_id: hir::HirId,
476-
span:Span,
477-
ty:Ty<'tcx>,
478485
subpatterns:Vec<FieldPat<'tcx>>,
479486
) -> PatKind<'tcx>{
487+
// Check whether the caller should have provided an `expr` for this pattern kind.
488+
assert_matches!(
489+
(pat.kind, expr),
490+
(hir::PatKind::Expr(..) | hir::PatKind::Range(..),Some(_))
491+
| (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..),None)
492+
);
493+
494+
// Use the id/span of the `hir::PatExpr`, if provided.
495+
// Otherwise, use the id/span of the `hir::Pat`.
496+
let(hir_id, span) = match expr {
497+
Some(expr) => (expr.hir_id, expr.span),
498+
None => (pat.hir_id, pat.span),
499+
};
500+
let ty = self.typeck_results.node_type(hir_id);
501+
480502
let res = match res {
481503
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
482504
let variant_id = self.tcx.parent(variant_ctor_id);
@@ -563,7 +585,16 @@ impl<'tcx> PatCtxt<'tcx> {
563585
/// it to `const_to_pat`. Any other path (like enum variants without fields)
564586
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
565587
#[instrument(skip(self), level = "debug")]
566-
fnlower_path(&mutself,qpath:&hir::QPath<'_>,id: hir::HirId,span:Span) -> Box<Pat<'tcx>>{
588+
fnlower_path(
589+
&mutself,
590+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
591+
expr:&'tcx hir::PatExpr<'tcx>,
592+
qpath:&hir::QPath<'_>,
593+
) -> Box<Pat<'tcx>>{
594+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
595+
596+
let id = expr.hir_id;
597+
let span = expr.span;
567598
let ty = self.typeck_results.node_type(id);
568599
let res = self.typeck_results.qpath_res(qpath, id);
569600

@@ -575,7 +606,7 @@ impl<'tcx> PatCtxt<'tcx> {
575606
_ => {
576607
// The path isn't the name of a constant, so it must actually
577608
// be a unit struct or unit variant (e.g. `Option::None`).
578-
let kind = self.lower_variant_or_leaf(res, id, span, ty,vec![]);
609+
let kind = self.lower_variant_or_leaf(pat,Some(expr), res,vec![]);
579610
returnBox::new(Pat{ span, ty, kind });
580611
}
581612
};
@@ -615,24 +646,26 @@ impl<'tcx> PatCtxt<'tcx> {
615646
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
616647
fnlower_pat_expr(
617648
&mutself,
649+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
618650
expr:&'tcx hir::PatExpr<'tcx>,
619-
pat_ty:Option<Ty<'tcx>>,
620651
) -> PatKind<'tcx>{
652+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
621653
match&expr.kind{
622-
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
654+
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath).kind,
623655
hir::PatExprKind::Lit{ lit, negated } => {
624656
// We handle byte string literal patterns by using the pattern's type instead of the
625657
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
626658
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
627659
// pattern's type means we'll properly translate it to a slice reference pattern. This works
628660
// because slices and arrays have the same valtree representation.
629-
let ct_ty = match pat_ty {
630-
Some(pat_ty) => pat_ty,
631-
None => self.typeck_results.node_type(expr.hir_id),
632-
};
633-
let lit_input = LitToConstInput{lit: lit.node,ty: ct_ty,neg:*negated };
661+
//
662+
// Under `feature(deref_patterns)`, this adjustment can also convert string literal
663+
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
664+
665+
let pat_ty = self.typeck_results.node_type(pat.hir_id);
666+
let lit_input = LitToConstInput{lit: lit.node,ty: pat_ty,neg:*negated };
634667
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
635-
self.const_to_pat(constant,ct_ty, expr.hir_id, lit.span).kind
668+
self.const_to_pat(constant,pat_ty, expr.hir_id, lit.span).kind
636669
}
637670
}
638671
}

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Commit cdddb85

Browse files
authored
Rollup merge of #150660 - Zalathar:pass-nodes, r=davidtwco
THIR pattern building: Pass HIR nodes instead of loose types/spans This should make it easier to keep track of where the types/spans came from. There should be no change to compiler output. --- In the future I would also like to make more of these lowering methods return `Box<thir::Pat>` instead of `thir::PatKind`, so that it becomes feasible to add more fields to `thir::Pat` (e.g. for #150498 (comment)). That will be easier if those methods have easy access to the corresponding HIR pattern node, from which they can obtain a type and span.
2 parents 18910b7 + de37724 commit cdddb85

1 file changed

Lines changed: 62 additions & 29 deletions

File tree

  • compiler/rustc_mir_build/src/thir/pattern

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

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod check_match;
44
mod const_to_pat;
55
mod migration;
66

7+
use std::assert_matches::assert_matches;
78
use std::cmp::Ordering;
89
use std::sync::Arc;
910

@@ -21,7 +22,7 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2122
use rustc_middle::ty::layout::IntegerExt;
2223
use rustc_middle::ty::{self,CanonicalUserTypeAnnotation,Ty,TyCtxt};
2324
use rustc_middle::{bug, span_bug};
24-
use rustc_span::{ErrorGuaranteed,Span};
25+
use rustc_span::ErrorGuaranteed;
2526
use tracing::{debug, instrument};
2627

2728
pub(crate)useself::check_match::check_match;
@@ -129,15 +130,20 @@ impl<'tcx> PatCtxt<'tcx> {
129130

130131
fnlower_pattern_range_endpoint(
131132
&mutself,
133+
pat:&'tcx hir::Pat<'tcx>,// Range pattern containing the endpoint
132134
expr:Option<&'tcx hir::PatExpr<'tcx>>,
133135
// Out-parameter collecting extra data to be reapplied by the caller
134136
ascriptions:&mutVec<Ascription<'tcx>>,
135137
) -> Result<Option<PatRangeBoundary<'tcx>>,ErrorGuaranteed>{
138+
assert_matches!(pat.kind, hir::PatKind::Range(..));
139+
140+
// For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
141+
// Return None in that case; the caller will use NegInfinity or PosInfinity instead.
136142
letSome(expr) = expr else{returnOk(None)};
137143

138144
// Lower the endpoint into a temporary `PatKind` that will then be
139145
// deconstructed to obtain the constant value and other data.
140-
letmut kind:PatKind<'tcx> = self.lower_pat_expr(expr,None);
146+
letmut kind:PatKind<'tcx> = self.lower_pat_expr(pat, expr);
141147

142148
// Unpeel any ascription or inline-const wrapper nodes.
143149
loop{
@@ -214,20 +220,23 @@ impl<'tcx> PatCtxt<'tcx> {
214220

215221
fnlower_pattern_range(
216222
&mutself,
223+
pat:&'tcx hir::Pat<'tcx>,
217224
lo_expr:Option<&'tcx hir::PatExpr<'tcx>>,
218225
hi_expr:Option<&'tcx hir::PatExpr<'tcx>>,
219226
end:RangeEnd,
220-
ty:Ty<'tcx>,
221-
span:Span,
222227
) -> Result<PatKind<'tcx>,ErrorGuaranteed>{
228+
let ty = self.typeck_results.node_type(pat.hir_id);
229+
let span = pat.span;
230+
223231
if lo_expr.is_none() && hi_expr.is_none(){
224232
let msg = "found twice-open range pattern (`..`) outside of error recovery";
225233
self.tcx.dcx().span_bug(span, msg);
226234
}
227235

228236
// Collect extra data while lowering the endpoints, to be reapplied later.
229237
letmut ascriptions = vec![];
230-
letmut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr,&mut ascriptions);
238+
letmut lower_endpoint =
239+
|expr| self.lower_pattern_range_endpoint(pat, expr,&mut ascriptions);
231240

232241
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
233242
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -299,12 +308,10 @@ impl<'tcx> PatCtxt<'tcx> {
299308

300309
hir::PatKind::Never => PatKind::Never,
301310

302-
hir::PatKind::Expr(value) => self.lower_pat_expr(value,Some(ty)),
311+
hir::PatKind::Expr(value) => self.lower_pat_expr(pat, value),
303312

304-
hir::PatKind::Range(ref lo_expr,ref hi_expr, end) => {
305-
let(lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
306-
self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
307-
.unwrap_or_else(PatKind::Error)
313+
hir::PatKind::Range(lo_expr, hi_expr, end) => {
314+
self.lower_pattern_range(pat, lo_expr, hi_expr, end).unwrap_or_else(PatKind::Error)
308315
}
309316

310317
hir::PatKind::Deref(subpattern) => {
@@ -327,7 +334,7 @@ impl<'tcx> PatCtxt<'tcx> {
327334
},
328335

329336
hir::PatKind::Slice(prefix, slice, suffix) => {
330-
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
337+
self.slice_or_array_pattern(pat, prefix, slice, suffix)
331338
}
332339

333340
hir::PatKind::Tuple(pats, ddpos) => {
@@ -389,7 +396,7 @@ impl<'tcx> PatCtxt<'tcx> {
389396
};
390397
let variant_def = adt_def.variant_of_res(res);
391398
let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
392-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
399+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
393400
}
394401

395402
hir::PatKind::Struct(ref qpath, fields, _) => {
@@ -406,7 +413,7 @@ impl<'tcx> PatCtxt<'tcx> {
406413
})
407414
.collect();
408415

409-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
416+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
410417
}
411418

412419
hir::PatKind::Or(pats) => PatKind::Or{pats:self.lower_patterns(pats)},
@@ -445,12 +452,13 @@ impl<'tcx> PatCtxt<'tcx> {
445452

446453
fnslice_or_array_pattern(
447454
&mutself,
448-
span:Span,
449-
ty:Ty<'tcx>,
455+
pat:&'tcx hir::Pat<'tcx>,
450456
prefix:&'tcx[hir::Pat<'tcx>],
451457
slice:Option<&'tcx hir::Pat<'tcx>>,
452458
suffix:&'tcx[hir::Pat<'tcx>],
453459
) -> PatKind<'tcx>{
460+
let ty = self.typeck_results.node_type(pat.hir_id);
461+
454462
let prefix = self.lower_patterns(prefix);
455463
let slice = self.lower_opt_pattern(slice);
456464
let suffix = self.lower_patterns(suffix);
@@ -465,18 +473,32 @@ impl<'tcx> PatCtxt<'tcx> {
465473
assert!(len >= prefix.len()asu64 + suffix.len()asu64);
466474
PatKind::Array{ prefix, slice, suffix }
467475
}
468-
_ => span_bug!(span,"bad slice pattern type {:?}", ty),
476+
_ => span_bug!(pat.span,"bad slice pattern type {ty:?}"),
469477
}
470478
}
471479

472480
fnlower_variant_or_leaf(
473481
&mutself,
482+
pat:&'tcx hir::Pat<'tcx>,
483+
expr:Option<&'tcx hir::PatExpr<'tcx>>,
474484
res:Res,
475-
hir_id: hir::HirId,
476-
span:Span,
477-
ty:Ty<'tcx>,
478485
subpatterns:Vec<FieldPat<'tcx>>,
479486
) -> PatKind<'tcx>{
487+
// Check whether the caller should have provided an `expr` for this pattern kind.
488+
assert_matches!(
489+
(pat.kind, expr),
490+
(hir::PatKind::Expr(..) | hir::PatKind::Range(..),Some(_))
491+
| (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..),None)
492+
);
493+
494+
// Use the id/span of the `hir::PatExpr`, if provided.
495+
// Otherwise, use the id/span of the `hir::Pat`.
496+
let(hir_id, span) = match expr {
497+
Some(expr) => (expr.hir_id, expr.span),
498+
None => (pat.hir_id, pat.span),
499+
};
500+
let ty = self.typeck_results.node_type(hir_id);
501+
480502
let res = match res {
481503
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
482504
let variant_id = self.tcx.parent(variant_ctor_id);
@@ -563,7 +585,16 @@ impl<'tcx> PatCtxt<'tcx> {
563585
/// it to `const_to_pat`. Any other path (like enum variants without fields)
564586
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
565587
#[instrument(skip(self), level = "debug")]
566-
fnlower_path(&mutself,qpath:&hir::QPath<'_>,id: hir::HirId,span:Span) -> Box<Pat<'tcx>>{
588+
fnlower_path(
589+
&mutself,
590+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
591+
expr:&'tcx hir::PatExpr<'tcx>,
592+
qpath:&hir::QPath<'_>,
593+
) -> Box<Pat<'tcx>>{
594+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
595+
596+
let id = expr.hir_id;
597+
let span = expr.span;
567598
let ty = self.typeck_results.node_type(id);
568599
let res = self.typeck_results.qpath_res(qpath, id);
569600

@@ -575,7 +606,7 @@ impl<'tcx> PatCtxt<'tcx> {
575606
_ => {
576607
// The path isn't the name of a constant, so it must actually
577608
// be a unit struct or unit variant (e.g. `Option::None`).
578-
let kind = self.lower_variant_or_leaf(res, id, span, ty,vec![]);
609+
let kind = self.lower_variant_or_leaf(pat,Some(expr), res,vec![]);
579610
returnBox::new(Pat{ span, ty, kind });
580611
}
581612
};
@@ -615,24 +646,26 @@ impl<'tcx> PatCtxt<'tcx> {
615646
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
616647
fnlower_pat_expr(
617648
&mutself,
649+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
618650
expr:&'tcx hir::PatExpr<'tcx>,
619-
pat_ty:Option<Ty<'tcx>>,
620651
) -> PatKind<'tcx>{
652+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
621653
match&expr.kind{
622-
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
654+
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath).kind,
623655
hir::PatExprKind::Lit{ lit, negated } => {
624656
// We handle byte string literal patterns by using the pattern's type instead of the
625657
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
626658
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
627659
// pattern's type means we'll properly translate it to a slice reference pattern. This works
628660
// because slices and arrays have the same valtree representation.
629-
let ct_ty = match pat_ty {
630-
Some(pat_ty) => pat_ty,
631-
None => self.typeck_results.node_type(expr.hir_id),
632-
};
633-
let lit_input = LitToConstInput{lit: lit.node,ty: ct_ty,neg:*negated };
661+
//
662+
// Under `feature(deref_patterns)`, this adjustment can also convert string literal
663+
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
664+
665+
let pat_ty = self.typeck_results.node_type(pat.hir_id);
666+
let lit_input = LitToConstInput{lit: lit.node,ty: pat_ty,neg:*negated };
634667
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
635-
self.const_to_pat(constant,ct_ty, expr.hir_id, lit.span).kind
668+
self.const_to_pat(constant,pat_ty, expr.hir_id, lit.span).kind
636669
}
637670
}
638671
}

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit cdddb85

Browse files
authored
Rollup merge of #150660 - Zalathar:pass-nodes, r=davidtwco
THIR pattern building: Pass HIR nodes instead of loose types/spans This should make it easier to keep track of where the types/spans came from. There should be no change to compiler output. --- In the future I would also like to make more of these lowering methods return `Box<thir::Pat>` instead of `thir::PatKind`, so that it becomes feasible to add more fields to `thir::Pat` (e.g. for #150498 (comment)). That will be easier if those methods have easy access to the corresponding HIR pattern node, from which they can obtain a type and span.
2 parents 18910b7 + de37724 commit cdddb85

1 file changed

Lines changed: 62 additions & 29 deletions

File tree

  • compiler/rustc_mir_build/src/thir/pattern

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

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod check_match;
44
mod const_to_pat;
55
mod migration;
66

7+
use std::assert_matches::assert_matches;
78
use std::cmp::Ordering;
89
use std::sync::Arc;
910

@@ -21,7 +22,7 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2122
use rustc_middle::ty::layout::IntegerExt;
2223
use rustc_middle::ty::{self,CanonicalUserTypeAnnotation,Ty,TyCtxt};
2324
use rustc_middle::{bug, span_bug};
24-
use rustc_span::{ErrorGuaranteed,Span};
25+
use rustc_span::ErrorGuaranteed;
2526
use tracing::{debug, instrument};
2627

2728
pub(crate)useself::check_match::check_match;
@@ -129,15 +130,20 @@ impl<'tcx> PatCtxt<'tcx> {
129130

130131
fnlower_pattern_range_endpoint(
131132
&mutself,
133+
pat:&'tcx hir::Pat<'tcx>,// Range pattern containing the endpoint
132134
expr:Option<&'tcx hir::PatExpr<'tcx>>,
133135
// Out-parameter collecting extra data to be reapplied by the caller
134136
ascriptions:&mutVec<Ascription<'tcx>>,
135137
) -> Result<Option<PatRangeBoundary<'tcx>>,ErrorGuaranteed>{
138+
assert_matches!(pat.kind, hir::PatKind::Range(..));
139+
140+
// For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
141+
// Return None in that case; the caller will use NegInfinity or PosInfinity instead.
136142
letSome(expr) = expr else{returnOk(None)};
137143

138144
// Lower the endpoint into a temporary `PatKind` that will then be
139145
// deconstructed to obtain the constant value and other data.
140-
letmut kind:PatKind<'tcx> = self.lower_pat_expr(expr,None);
146+
letmut kind:PatKind<'tcx> = self.lower_pat_expr(pat, expr);
141147

142148
// Unpeel any ascription or inline-const wrapper nodes.
143149
loop{
@@ -214,20 +220,23 @@ impl<'tcx> PatCtxt<'tcx> {
214220

215221
fnlower_pattern_range(
216222
&mutself,
223+
pat:&'tcx hir::Pat<'tcx>,
217224
lo_expr:Option<&'tcx hir::PatExpr<'tcx>>,
218225
hi_expr:Option<&'tcx hir::PatExpr<'tcx>>,
219226
end:RangeEnd,
220-
ty:Ty<'tcx>,
221-
span:Span,
222227
) -> Result<PatKind<'tcx>,ErrorGuaranteed>{
228+
let ty = self.typeck_results.node_type(pat.hir_id);
229+
let span = pat.span;
230+
223231
if lo_expr.is_none() && hi_expr.is_none(){
224232
let msg = "found twice-open range pattern (`..`) outside of error recovery";
225233
self.tcx.dcx().span_bug(span, msg);
226234
}
227235

228236
// Collect extra data while lowering the endpoints, to be reapplied later.
229237
letmut ascriptions = vec![];
230-
letmut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr,&mut ascriptions);
238+
letmut lower_endpoint =
239+
|expr| self.lower_pattern_range_endpoint(pat, expr,&mut ascriptions);
231240

232241
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
233242
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -299,12 +308,10 @@ impl<'tcx> PatCtxt<'tcx> {
299308

300309
hir::PatKind::Never => PatKind::Never,
301310

302-
hir::PatKind::Expr(value) => self.lower_pat_expr(value,Some(ty)),
311+
hir::PatKind::Expr(value) => self.lower_pat_expr(pat, value),
303312

304-
hir::PatKind::Range(ref lo_expr,ref hi_expr, end) => {
305-
let(lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
306-
self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
307-
.unwrap_or_else(PatKind::Error)
313+
hir::PatKind::Range(lo_expr, hi_expr, end) => {
314+
self.lower_pattern_range(pat, lo_expr, hi_expr, end).unwrap_or_else(PatKind::Error)
308315
}
309316

310317
hir::PatKind::Deref(subpattern) => {
@@ -327,7 +334,7 @@ impl<'tcx> PatCtxt<'tcx> {
327334
},
328335

329336
hir::PatKind::Slice(prefix, slice, suffix) => {
330-
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
337+
self.slice_or_array_pattern(pat, prefix, slice, suffix)
331338
}
332339

333340
hir::PatKind::Tuple(pats, ddpos) => {
@@ -389,7 +396,7 @@ impl<'tcx> PatCtxt<'tcx> {
389396
};
390397
let variant_def = adt_def.variant_of_res(res);
391398
let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
392-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
399+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
393400
}
394401

395402
hir::PatKind::Struct(ref qpath, fields, _) => {
@@ -406,7 +413,7 @@ impl<'tcx> PatCtxt<'tcx> {
406413
})
407414
.collect();
408415

409-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
416+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
410417
}
411418

412419
hir::PatKind::Or(pats) => PatKind::Or{pats:self.lower_patterns(pats)},
@@ -445,12 +452,13 @@ impl<'tcx> PatCtxt<'tcx> {
445452

446453
fnslice_or_array_pattern(
447454
&mutself,
448-
span:Span,
449-
ty:Ty<'tcx>,
455+
pat:&'tcx hir::Pat<'tcx>,
450456
prefix:&'tcx[hir::Pat<'tcx>],
451457
slice:Option<&'tcx hir::Pat<'tcx>>,
452458
suffix:&'tcx[hir::Pat<'tcx>],
453459
) -> PatKind<'tcx>{
460+
let ty = self.typeck_results.node_type(pat.hir_id);
461+
454462
let prefix = self.lower_patterns(prefix);
455463
let slice = self.lower_opt_pattern(slice);
456464
let suffix = self.lower_patterns(suffix);
@@ -465,18 +473,32 @@ impl<'tcx> PatCtxt<'tcx> {
465473
assert!(len >= prefix.len()asu64 + suffix.len()asu64);
466474
PatKind::Array{ prefix, slice, suffix }
467475
}
468-
_ => span_bug!(span,"bad slice pattern type {:?}", ty),
476+
_ => span_bug!(pat.span,"bad slice pattern type {ty:?}"),
469477
}
470478
}
471479

472480
fnlower_variant_or_leaf(
473481
&mutself,
482+
pat:&'tcx hir::Pat<'tcx>,
483+
expr:Option<&'tcx hir::PatExpr<'tcx>>,
474484
res:Res,
475-
hir_id: hir::HirId,
476-
span:Span,
477-
ty:Ty<'tcx>,
478485
subpatterns:Vec<FieldPat<'tcx>>,
479486
) -> PatKind<'tcx>{
487+
// Check whether the caller should have provided an `expr` for this pattern kind.
488+
assert_matches!(
489+
(pat.kind, expr),
490+
(hir::PatKind::Expr(..) | hir::PatKind::Range(..),Some(_))
491+
| (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..),None)
492+
);
493+
494+
// Use the id/span of the `hir::PatExpr`, if provided.
495+
// Otherwise, use the id/span of the `hir::Pat`.
496+
let(hir_id, span) = match expr {
497+
Some(expr) => (expr.hir_id, expr.span),
498+
None => (pat.hir_id, pat.span),
499+
};
500+
let ty = self.typeck_results.node_type(hir_id);
501+
480502
let res = match res {
481503
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
482504
let variant_id = self.tcx.parent(variant_ctor_id);
@@ -563,7 +585,16 @@ impl<'tcx> PatCtxt<'tcx> {
563585
/// it to `const_to_pat`. Any other path (like enum variants without fields)
564586
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
565587
#[instrument(skip(self), level = "debug")]
566-
fnlower_path(&mutself,qpath:&hir::QPath<'_>,id: hir::HirId,span:Span) -> Box<Pat<'tcx>>{
588+
fnlower_path(
589+
&mutself,
590+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
591+
expr:&'tcx hir::PatExpr<'tcx>,
592+
qpath:&hir::QPath<'_>,
593+
) -> Box<Pat<'tcx>>{
594+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
595+
596+
let id = expr.hir_id;
597+
let span = expr.span;
567598
let ty = self.typeck_results.node_type(id);
568599
let res = self.typeck_results.qpath_res(qpath, id);
569600

@@ -575,7 +606,7 @@ impl<'tcx> PatCtxt<'tcx> {
575606
_ => {
576607
// The path isn't the name of a constant, so it must actually
577608
// be a unit struct or unit variant (e.g. `Option::None`).
578-
let kind = self.lower_variant_or_leaf(res, id, span, ty,vec![]);
609+
let kind = self.lower_variant_or_leaf(pat,Some(expr), res,vec![]);
579610
returnBox::new(Pat{ span, ty, kind });
580611
}
581612
};
@@ -615,24 +646,26 @@ impl<'tcx> PatCtxt<'tcx> {
615646
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
616647
fnlower_pat_expr(
617648
&mutself,
649+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
618650
expr:&'tcx hir::PatExpr<'tcx>,
619-
pat_ty:Option<Ty<'tcx>>,
620651
) -> PatKind<'tcx>{
652+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
621653
match&expr.kind{
622-
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
654+
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath).kind,
623655
hir::PatExprKind::Lit{ lit, negated } => {
624656
// We handle byte string literal patterns by using the pattern's type instead of the
625657
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
626658
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
627659
// pattern's type means we'll properly translate it to a slice reference pattern. This works
628660
// because slices and arrays have the same valtree representation.
629-
let ct_ty = match pat_ty {
630-
Some(pat_ty) => pat_ty,
631-
None => self.typeck_results.node_type(expr.hir_id),
632-
};
633-
let lit_input = LitToConstInput{lit: lit.node,ty: ct_ty,neg:*negated };
661+
//
662+
// Under `feature(deref_patterns)`, this adjustment can also convert string literal
663+
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
664+
665+
let pat_ty = self.typeck_results.node_type(pat.hir_id);
666+
let lit_input = LitToConstInput{lit: lit.node,ty: pat_ty,neg:*negated };
634667
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
635-
self.const_to_pat(constant,ct_ty, expr.hir_id, lit.span).kind
668+
self.const_to_pat(constant,pat_ty, expr.hir_id, lit.span).kind
636669
}
637670
}
638671
}

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit cdddb85

Browse files
authored
Rollup merge of #150660 - Zalathar:pass-nodes, r=davidtwco
THIR pattern building: Pass HIR nodes instead of loose types/spans This should make it easier to keep track of where the types/spans came from. There should be no change to compiler output. --- In the future I would also like to make more of these lowering methods return `Box<thir::Pat>` instead of `thir::PatKind`, so that it becomes feasible to add more fields to `thir::Pat` (e.g. for #150498 (comment)). That will be easier if those methods have easy access to the corresponding HIR pattern node, from which they can obtain a type and span.
2 parents 18910b7 + de37724 commit cdddb85

1 file changed

Lines changed: 62 additions & 29 deletions

File tree

  • compiler/rustc_mir_build/src/thir/pattern

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

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod check_match;
44
mod const_to_pat;
55
mod migration;
66

7+
use std::assert_matches::assert_matches;
78
use std::cmp::Ordering;
89
use std::sync::Arc;
910

@@ -21,7 +22,7 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2122
use rustc_middle::ty::layout::IntegerExt;
2223
use rustc_middle::ty::{self,CanonicalUserTypeAnnotation,Ty,TyCtxt};
2324
use rustc_middle::{bug, span_bug};
24-
use rustc_span::{ErrorGuaranteed,Span};
25+
use rustc_span::ErrorGuaranteed;
2526
use tracing::{debug, instrument};
2627

2728
pub(crate)useself::check_match::check_match;
@@ -129,15 +130,20 @@ impl<'tcx> PatCtxt<'tcx> {
129130

130131
fnlower_pattern_range_endpoint(
131132
&mutself,
133+
pat:&'tcx hir::Pat<'tcx>,// Range pattern containing the endpoint
132134
expr:Option<&'tcx hir::PatExpr<'tcx>>,
133135
// Out-parameter collecting extra data to be reapplied by the caller
134136
ascriptions:&mutVec<Ascription<'tcx>>,
135137
) -> Result<Option<PatRangeBoundary<'tcx>>,ErrorGuaranteed>{
138+
assert_matches!(pat.kind, hir::PatKind::Range(..));
139+
140+
// For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
141+
// Return None in that case; the caller will use NegInfinity or PosInfinity instead.
136142
letSome(expr) = expr else{returnOk(None)};
137143

138144
// Lower the endpoint into a temporary `PatKind` that will then be
139145
// deconstructed to obtain the constant value and other data.
140-
letmut kind:PatKind<'tcx> = self.lower_pat_expr(expr,None);
146+
letmut kind:PatKind<'tcx> = self.lower_pat_expr(pat, expr);
141147

142148
// Unpeel any ascription or inline-const wrapper nodes.
143149
loop{
@@ -214,20 +220,23 @@ impl<'tcx> PatCtxt<'tcx> {
214220

215221
fnlower_pattern_range(
216222
&mutself,
223+
pat:&'tcx hir::Pat<'tcx>,
217224
lo_expr:Option<&'tcx hir::PatExpr<'tcx>>,
218225
hi_expr:Option<&'tcx hir::PatExpr<'tcx>>,
219226
end:RangeEnd,
220-
ty:Ty<'tcx>,
221-
span:Span,
222227
) -> Result<PatKind<'tcx>,ErrorGuaranteed>{
228+
let ty = self.typeck_results.node_type(pat.hir_id);
229+
let span = pat.span;
230+
223231
if lo_expr.is_none() && hi_expr.is_none(){
224232
let msg = "found twice-open range pattern (`..`) outside of error recovery";
225233
self.tcx.dcx().span_bug(span, msg);
226234
}
227235

228236
// Collect extra data while lowering the endpoints, to be reapplied later.
229237
letmut ascriptions = vec![];
230-
letmut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr,&mut ascriptions);
238+
letmut lower_endpoint =
239+
|expr| self.lower_pattern_range_endpoint(pat, expr,&mut ascriptions);
231240

232241
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
233242
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -299,12 +308,10 @@ impl<'tcx> PatCtxt<'tcx> {
299308

300309
hir::PatKind::Never => PatKind::Never,
301310

302-
hir::PatKind::Expr(value) => self.lower_pat_expr(value,Some(ty)),
311+
hir::PatKind::Expr(value) => self.lower_pat_expr(pat, value),
303312

304-
hir::PatKind::Range(ref lo_expr,ref hi_expr, end) => {
305-
let(lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
306-
self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
307-
.unwrap_or_else(PatKind::Error)
313+
hir::PatKind::Range(lo_expr, hi_expr, end) => {
314+
self.lower_pattern_range(pat, lo_expr, hi_expr, end).unwrap_or_else(PatKind::Error)
308315
}
309316

310317
hir::PatKind::Deref(subpattern) => {
@@ -327,7 +334,7 @@ impl<'tcx> PatCtxt<'tcx> {
327334
},
328335

329336
hir::PatKind::Slice(prefix, slice, suffix) => {
330-
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
337+
self.slice_or_array_pattern(pat, prefix, slice, suffix)
331338
}
332339

333340
hir::PatKind::Tuple(pats, ddpos) => {
@@ -389,7 +396,7 @@ impl<'tcx> PatCtxt<'tcx> {
389396
};
390397
let variant_def = adt_def.variant_of_res(res);
391398
let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
392-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
399+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
393400
}
394401

395402
hir::PatKind::Struct(ref qpath, fields, _) => {
@@ -406,7 +413,7 @@ impl<'tcx> PatCtxt<'tcx> {
406413
})
407414
.collect();
408415

409-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
416+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
410417
}
411418

412419
hir::PatKind::Or(pats) => PatKind::Or{pats:self.lower_patterns(pats)},
@@ -445,12 +452,13 @@ impl<'tcx> PatCtxt<'tcx> {
445452

446453
fnslice_or_array_pattern(
447454
&mutself,
448-
span:Span,
449-
ty:Ty<'tcx>,
455+
pat:&'tcx hir::Pat<'tcx>,
450456
prefix:&'tcx[hir::Pat<'tcx>],
451457
slice:Option<&'tcx hir::Pat<'tcx>>,
452458
suffix:&'tcx[hir::Pat<'tcx>],
453459
) -> PatKind<'tcx>{
460+
let ty = self.typeck_results.node_type(pat.hir_id);
461+
454462
let prefix = self.lower_patterns(prefix);
455463
let slice = self.lower_opt_pattern(slice);
456464
let suffix = self.lower_patterns(suffix);
@@ -465,18 +473,32 @@ impl<'tcx> PatCtxt<'tcx> {
465473
assert!(len >= prefix.len()asu64 + suffix.len()asu64);
466474
PatKind::Array{ prefix, slice, suffix }
467475
}
468-
_ => span_bug!(span,"bad slice pattern type {:?}", ty),
476+
_ => span_bug!(pat.span,"bad slice pattern type {ty:?}"),
469477
}
470478
}
471479

472480
fnlower_variant_or_leaf(
473481
&mutself,
482+
pat:&'tcx hir::Pat<'tcx>,
483+
expr:Option<&'tcx hir::PatExpr<'tcx>>,
474484
res:Res,
475-
hir_id: hir::HirId,
476-
span:Span,
477-
ty:Ty<'tcx>,
478485
subpatterns:Vec<FieldPat<'tcx>>,
479486
) -> PatKind<'tcx>{
487+
// Check whether the caller should have provided an `expr` for this pattern kind.
488+
assert_matches!(
489+
(pat.kind, expr),
490+
(hir::PatKind::Expr(..) | hir::PatKind::Range(..),Some(_))
491+
| (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..),None)
492+
);
493+
494+
// Use the id/span of the `hir::PatExpr`, if provided.
495+
// Otherwise, use the id/span of the `hir::Pat`.
496+
let(hir_id, span) = match expr {
497+
Some(expr) => (expr.hir_id, expr.span),
498+
None => (pat.hir_id, pat.span),
499+
};
500+
let ty = self.typeck_results.node_type(hir_id);
501+
480502
let res = match res {
481503
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
482504
let variant_id = self.tcx.parent(variant_ctor_id);
@@ -563,7 +585,16 @@ impl<'tcx> PatCtxt<'tcx> {
563585
/// it to `const_to_pat`. Any other path (like enum variants without fields)
564586
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
565587
#[instrument(skip(self), level = "debug")]
566-
fnlower_path(&mutself,qpath:&hir::QPath<'_>,id: hir::HirId,span:Span) -> Box<Pat<'tcx>>{
588+
fnlower_path(
589+
&mutself,
590+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
591+
expr:&'tcx hir::PatExpr<'tcx>,
592+
qpath:&hir::QPath<'_>,
593+
) -> Box<Pat<'tcx>>{
594+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
595+
596+
let id = expr.hir_id;
597+
let span = expr.span;
567598
let ty = self.typeck_results.node_type(id);
568599
let res = self.typeck_results.qpath_res(qpath, id);
569600

@@ -575,7 +606,7 @@ impl<'tcx> PatCtxt<'tcx> {
575606
_ => {
576607
// The path isn't the name of a constant, so it must actually
577608
// be a unit struct or unit variant (e.g. `Option::None`).
578-
let kind = self.lower_variant_or_leaf(res, id, span, ty,vec![]);
609+
let kind = self.lower_variant_or_leaf(pat,Some(expr), res,vec![]);
579610
returnBox::new(Pat{ span, ty, kind });
580611
}
581612
};
@@ -615,24 +646,26 @@ impl<'tcx> PatCtxt<'tcx> {
615646
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
616647
fnlower_pat_expr(
617648
&mutself,
649+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
618650
expr:&'tcx hir::PatExpr<'tcx>,
619-
pat_ty:Option<Ty<'tcx>>,
620651
) -> PatKind<'tcx>{
652+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
621653
match&expr.kind{
622-
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
654+
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath).kind,
623655
hir::PatExprKind::Lit{ lit, negated } => {
624656
// We handle byte string literal patterns by using the pattern's type instead of the
625657
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
626658
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
627659
// pattern's type means we'll properly translate it to a slice reference pattern. This works
628660
// because slices and arrays have the same valtree representation.
629-
let ct_ty = match pat_ty {
630-
Some(pat_ty) => pat_ty,
631-
None => self.typeck_results.node_type(expr.hir_id),
632-
};
633-
let lit_input = LitToConstInput{lit: lit.node,ty: ct_ty,neg:*negated };
661+
//
662+
// Under `feature(deref_patterns)`, this adjustment can also convert string literal
663+
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
664+
665+
let pat_ty = self.typeck_results.node_type(pat.hir_id);
666+
let lit_input = LitToConstInput{lit: lit.node,ty: pat_ty,neg:*negated };
634667
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
635-
self.const_to_pat(constant,ct_ty, expr.hir_id, lit.span).kind
668+
self.const_to_pat(constant,pat_ty, expr.hir_id, lit.span).kind
636669
}
637670
}
638671
}

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Commit cdddb85

Browse files
authored
Rollup merge of #150660 - Zalathar:pass-nodes, r=davidtwco
THIR pattern building: Pass HIR nodes instead of loose types/spans This should make it easier to keep track of where the types/spans came from. There should be no change to compiler output. --- In the future I would also like to make more of these lowering methods return `Box<thir::Pat>` instead of `thir::PatKind`, so that it becomes feasible to add more fields to `thir::Pat` (e.g. for #150498 (comment)). That will be easier if those methods have easy access to the corresponding HIR pattern node, from which they can obtain a type and span.
2 parents 18910b7 + de37724 commit cdddb85

1 file changed

Lines changed: 62 additions & 29 deletions

File tree

  • compiler/rustc_mir_build/src/thir/pattern

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

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod check_match;
44
mod const_to_pat;
55
mod migration;
66

7+
use std::assert_matches::assert_matches;
78
use std::cmp::Ordering;
89
use std::sync::Arc;
910

@@ -21,7 +22,7 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2122
use rustc_middle::ty::layout::IntegerExt;
2223
use rustc_middle::ty::{self,CanonicalUserTypeAnnotation,Ty,TyCtxt};
2324
use rustc_middle::{bug, span_bug};
24-
use rustc_span::{ErrorGuaranteed,Span};
25+
use rustc_span::ErrorGuaranteed;
2526
use tracing::{debug, instrument};
2627

2728
pub(crate)useself::check_match::check_match;
@@ -129,15 +130,20 @@ impl<'tcx> PatCtxt<'tcx> {
129130

130131
fnlower_pattern_range_endpoint(
131132
&mutself,
133+
pat:&'tcx hir::Pat<'tcx>,// Range pattern containing the endpoint
132134
expr:Option<&'tcx hir::PatExpr<'tcx>>,
133135
// Out-parameter collecting extra data to be reapplied by the caller
134136
ascriptions:&mutVec<Ascription<'tcx>>,
135137
) -> Result<Option<PatRangeBoundary<'tcx>>,ErrorGuaranteed>{
138+
assert_matches!(pat.kind, hir::PatKind::Range(..));
139+
140+
// For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
141+
// Return None in that case; the caller will use NegInfinity or PosInfinity instead.
136142
letSome(expr) = expr else{returnOk(None)};
137143

138144
// Lower the endpoint into a temporary `PatKind` that will then be
139145
// deconstructed to obtain the constant value and other data.
140-
letmut kind:PatKind<'tcx> = self.lower_pat_expr(expr,None);
146+
letmut kind:PatKind<'tcx> = self.lower_pat_expr(pat, expr);
141147

142148
// Unpeel any ascription or inline-const wrapper nodes.
143149
loop{
@@ -214,20 +220,23 @@ impl<'tcx> PatCtxt<'tcx> {
214220

215221
fnlower_pattern_range(
216222
&mutself,
223+
pat:&'tcx hir::Pat<'tcx>,
217224
lo_expr:Option<&'tcx hir::PatExpr<'tcx>>,
218225
hi_expr:Option<&'tcx hir::PatExpr<'tcx>>,
219226
end:RangeEnd,
220-
ty:Ty<'tcx>,
221-
span:Span,
222227
) -> Result<PatKind<'tcx>,ErrorGuaranteed>{
228+
let ty = self.typeck_results.node_type(pat.hir_id);
229+
let span = pat.span;
230+
223231
if lo_expr.is_none() && hi_expr.is_none(){
224232
let msg = "found twice-open range pattern (`..`) outside of error recovery";
225233
self.tcx.dcx().span_bug(span, msg);
226234
}
227235

228236
// Collect extra data while lowering the endpoints, to be reapplied later.
229237
letmut ascriptions = vec![];
230-
letmut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr,&mut ascriptions);
238+
letmut lower_endpoint =
239+
|expr| self.lower_pattern_range_endpoint(pat, expr,&mut ascriptions);
231240

232241
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
233242
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -299,12 +308,10 @@ impl<'tcx> PatCtxt<'tcx> {
299308

300309
hir::PatKind::Never => PatKind::Never,
301310

302-
hir::PatKind::Expr(value) => self.lower_pat_expr(value,Some(ty)),
311+
hir::PatKind::Expr(value) => self.lower_pat_expr(pat, value),
303312

304-
hir::PatKind::Range(ref lo_expr,ref hi_expr, end) => {
305-
let(lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
306-
self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
307-
.unwrap_or_else(PatKind::Error)
313+
hir::PatKind::Range(lo_expr, hi_expr, end) => {
314+
self.lower_pattern_range(pat, lo_expr, hi_expr, end).unwrap_or_else(PatKind::Error)
308315
}
309316

310317
hir::PatKind::Deref(subpattern) => {
@@ -327,7 +334,7 @@ impl<'tcx> PatCtxt<'tcx> {
327334
},
328335

329336
hir::PatKind::Slice(prefix, slice, suffix) => {
330-
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
337+
self.slice_or_array_pattern(pat, prefix, slice, suffix)
331338
}
332339

333340
hir::PatKind::Tuple(pats, ddpos) => {
@@ -389,7 +396,7 @@ impl<'tcx> PatCtxt<'tcx> {
389396
};
390397
let variant_def = adt_def.variant_of_res(res);
391398
let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
392-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
399+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
393400
}
394401

395402
hir::PatKind::Struct(ref qpath, fields, _) => {
@@ -406,7 +413,7 @@ impl<'tcx> PatCtxt<'tcx> {
406413
})
407414
.collect();
408415

409-
self.lower_variant_or_leaf(res,pat.hir_id, pat.span, ty, subpatterns)
416+
self.lower_variant_or_leaf(pat,None, res, subpatterns)
410417
}
411418

412419
hir::PatKind::Or(pats) => PatKind::Or{pats:self.lower_patterns(pats)},
@@ -445,12 +452,13 @@ impl<'tcx> PatCtxt<'tcx> {
445452

446453
fnslice_or_array_pattern(
447454
&mutself,
448-
span:Span,
449-
ty:Ty<'tcx>,
455+
pat:&'tcx hir::Pat<'tcx>,
450456
prefix:&'tcx[hir::Pat<'tcx>],
451457
slice:Option<&'tcx hir::Pat<'tcx>>,
452458
suffix:&'tcx[hir::Pat<'tcx>],
453459
) -> PatKind<'tcx>{
460+
let ty = self.typeck_results.node_type(pat.hir_id);
461+
454462
let prefix = self.lower_patterns(prefix);
455463
let slice = self.lower_opt_pattern(slice);
456464
let suffix = self.lower_patterns(suffix);
@@ -465,18 +473,32 @@ impl<'tcx> PatCtxt<'tcx> {
465473
assert!(len >= prefix.len()asu64 + suffix.len()asu64);
466474
PatKind::Array{ prefix, slice, suffix }
467475
}
468-
_ => span_bug!(span,"bad slice pattern type {:?}", ty),
476+
_ => span_bug!(pat.span,"bad slice pattern type {ty:?}"),
469477
}
470478
}
471479

472480
fnlower_variant_or_leaf(
473481
&mutself,
482+
pat:&'tcx hir::Pat<'tcx>,
483+
expr:Option<&'tcx hir::PatExpr<'tcx>>,
474484
res:Res,
475-
hir_id: hir::HirId,
476-
span:Span,
477-
ty:Ty<'tcx>,
478485
subpatterns:Vec<FieldPat<'tcx>>,
479486
) -> PatKind<'tcx>{
487+
// Check whether the caller should have provided an `expr` for this pattern kind.
488+
assert_matches!(
489+
(pat.kind, expr),
490+
(hir::PatKind::Expr(..) | hir::PatKind::Range(..),Some(_))
491+
| (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..),None)
492+
);
493+
494+
// Use the id/span of the `hir::PatExpr`, if provided.
495+
// Otherwise, use the id/span of the `hir::Pat`.
496+
let(hir_id, span) = match expr {
497+
Some(expr) => (expr.hir_id, expr.span),
498+
None => (pat.hir_id, pat.span),
499+
};
500+
let ty = self.typeck_results.node_type(hir_id);
501+
480502
let res = match res {
481503
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
482504
let variant_id = self.tcx.parent(variant_ctor_id);
@@ -563,7 +585,16 @@ impl<'tcx> PatCtxt<'tcx> {
563585
/// it to `const_to_pat`. Any other path (like enum variants without fields)
564586
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
565587
#[instrument(skip(self), level = "debug")]
566-
fnlower_path(&mutself,qpath:&hir::QPath<'_>,id: hir::HirId,span:Span) -> Box<Pat<'tcx>>{
588+
fnlower_path(
589+
&mutself,
590+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
591+
expr:&'tcx hir::PatExpr<'tcx>,
592+
qpath:&hir::QPath<'_>,
593+
) -> Box<Pat<'tcx>>{
594+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
595+
596+
let id = expr.hir_id;
597+
let span = expr.span;
567598
let ty = self.typeck_results.node_type(id);
568599
let res = self.typeck_results.qpath_res(qpath, id);
569600

@@ -575,7 +606,7 @@ impl<'tcx> PatCtxt<'tcx> {
575606
_ => {
576607
// The path isn't the name of a constant, so it must actually
577608
// be a unit struct or unit variant (e.g. `Option::None`).
578-
let kind = self.lower_variant_or_leaf(res, id, span, ty,vec![]);
609+
let kind = self.lower_variant_or_leaf(pat,Some(expr), res,vec![]);
579610
returnBox::new(Pat{ span, ty, kind });
580611
}
581612
};
@@ -615,24 +646,26 @@ impl<'tcx> PatCtxt<'tcx> {
615646
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
616647
fnlower_pat_expr(
617648
&mutself,
649+
pat:&'tcx hir::Pat<'tcx>,// Pattern that directly contains `expr`
618650
expr:&'tcx hir::PatExpr<'tcx>,
619-
pat_ty:Option<Ty<'tcx>>,
620651
) -> PatKind<'tcx>{
652+
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
621653
match&expr.kind{
622-
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
654+
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath).kind,
623655
hir::PatExprKind::Lit{ lit, negated } => {
624656
// We handle byte string literal patterns by using the pattern's type instead of the
625657
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
626658
// the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
627659
// pattern's type means we'll properly translate it to a slice reference pattern. This works
628660
// because slices and arrays have the same valtree representation.
629-
let ct_ty = match pat_ty {
630-
Some(pat_ty) => pat_ty,
631-
None => self.typeck_results.node_type(expr.hir_id),
632-
};
633-
let lit_input = LitToConstInput{lit: lit.node,ty: ct_ty,neg:*negated };
661+
//
662+
// Under `feature(deref_patterns)`, this adjustment can also convert string literal
663+
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
664+
665+
let pat_ty = self.typeck_results.node_type(pat.hir_id);
666+
let lit_input = LitToConstInput{lit: lit.node,ty: pat_ty,neg:*negated };
634667
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
635-
self.const_to_pat(constant,ct_ty, expr.hir_id, lit.span).kind
668+
self.const_to_pat(constant,pat_ty, expr.hir_id, lit.span).kind
636669
}
637670
}
638671
}

0 commit comments

Comments
 (0)