Skip to content

Commit 3024069

Browse files
Apply nits
1 parent 4cf661c commit 3024069

File tree

2 files changed

+105
-49
lines changed

2 files changed

+105
-49
lines changed

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+101-49
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ use ty::BorrowKind::ImmBorrow;
3030

3131
use crate::fn_ctxt::FnCtxt;
3232

33-
type McResult<T> = Result<T, ErrorGuaranteed>;
34-
3533
/// This trait defines the callbacks you can expect to receive when
3634
/// employing the ExprUseVisitor.
3735
pub trait Delegate<'tcx> {
@@ -219,6 +217,8 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
219217
/// This is the code that actually walks the tree.
220218
pub struct ExprUseVisitor<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> {
221219
cx: Cx,
220+
/// We use a `RefCell` here so that delegates can mutate themselves, but we can
221+
/// still have calls to our own helper functions.
222222
delegate: RefCell<D>,
223223
upvars: Option<&'tcx FxIndexMap<HirId, hir::Upvar>>,
224224
}
@@ -517,14 +517,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
517517
discr: &Expr<'_>,
518518
discr_place: PlaceWithHirId<'tcx>,
519519
pats: impl Iterator<Item = &'t hir::Pat<'t>>,
520-
) -> McResult<()> {
520+
) -> Result<(), ErrorGuaranteed> {
521521
// Matching should not always be considered a use of the place, hence
522522
// discr does not necessarily need to be borrowed.
523523
// We only want to borrow discr if the pattern contain something other
524524
// than wildcards.
525525
let mut needs_to_be_read = false;
526526
for pat in pats {
527-
self.cat_pattern(discr_place.clone(), pat, |place, pat| {
527+
self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
528528
match &pat.kind {
529529
PatKind::Binding(.., opt_sub_pat) => {
530530
// If the opt_sub_pat is None, then the binding does not count as
@@ -836,7 +836,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
836836
debug!("walk_pat(discr_place={:?}, pat={:?}, has_guard={:?})", discr_place, pat, has_guard);
837837

838838
let tcx = self.cx.tcx();
839-
return_if_err!(self.cat_pattern(discr_place.clone(), pat, |place, pat| {
839+
return_if_err!(self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
840840
if let PatKind::Binding(_, canonical_id, ..) = pat.kind {
841841
debug!("walk_pat: binding place={:?} pat={:?}", place, pat);
842842
if let Some(bm) =
@@ -1021,8 +1021,61 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10211021
}
10221022
}
10231023
}
1024+
}
10241025

1025-
fn resolve_type_vars_or_error(&self, id: HirId, ty: Option<Ty<'tcx>>) -> McResult<Ty<'tcx>> {
1026+
/// The job of the categorization methods is to analyze an expression to
1027+
/// determine what kind of memory is used in evaluating it (for example,
1028+
/// where dereferences occur and what kind of pointer is dereferenced;
1029+
/// whether the memory is mutable, etc.).
1030+
///
1031+
/// Categorization effectively transforms all of our expressions into
1032+
/// expressions of the following forms (the actual enum has many more
1033+
/// possibilities, naturally, but they are all variants of these base
1034+
/// forms):
1035+
/// ```ignore (not-rust)
1036+
/// E = rvalue // some computed rvalue
1037+
/// | x // address of a local variable or argument
1038+
/// | *E // deref of a ptr
1039+
/// | E.comp // access to an interior component
1040+
/// ```
1041+
/// Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
1042+
/// address where the result is to be found. If Expr is a place, then this
1043+
/// is the address of the place. If `Expr` is an rvalue, this is the address of
1044+
/// some temporary spot in memory where the result is stored.
1045+
///
1046+
/// Now, `cat_expr()` classifies the expression `Expr` and the address `A = ToAddr(Expr)`
1047+
/// as follows:
1048+
///
1049+
/// - `cat`: what kind of expression was this? This is a subset of the
1050+
/// full expression forms which only includes those that we care about
1051+
/// for the purpose of the analysis.
1052+
/// - `mutbl`: mutability of the address `A`.
1053+
/// - `ty`: the type of data found at the address `A`.
1054+
///
1055+
/// The resulting categorization tree differs somewhat from the expressions
1056+
/// themselves. For example, auto-derefs are explicit. Also, an index `a[b]` is
1057+
/// decomposed into two operations: a dereference to reach the array data and
1058+
/// then an index to jump forward to the relevant item.
1059+
///
1060+
/// ## By-reference upvars
1061+
///
1062+
/// One part of the codegen which may be non-obvious is that we translate
1063+
/// closure upvars into the dereference of a borrowed pointer; this more closely
1064+
/// resembles the runtime codegen. So, for example, if we had:
1065+
///
1066+
/// let mut x = 3;
1067+
/// let y = 5;
1068+
/// let inc = || x += y;
1069+
///
1070+
/// Then when we categorize `x` (*within* the closure) we would yield a
1071+
/// result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference
1072+
/// tied to `x`. The type of `x'` will be a borrowed pointer.
1073+
impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> {
1074+
fn resolve_type_vars_or_error(
1075+
&self,
1076+
id: HirId,
1077+
ty: Option<Ty<'tcx>>,
1078+
) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10261079
match ty {
10271080
Some(ty) => {
10281081
let ty = self.cx.resolve_vars_if_possible(ty);
@@ -1053,15 +1106,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10531106
}
10541107
}
10551108

1056-
fn node_ty(&self, hir_id: HirId) -> McResult<Ty<'tcx>> {
1109+
fn node_ty(&self, hir_id: HirId) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10571110
self.resolve_type_vars_or_error(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
10581111
}
10591112

1060-
fn expr_ty(&self, expr: &hir::Expr<'_>) -> McResult<Ty<'tcx>> {
1113+
fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10611114
self.resolve_type_vars_or_error(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
10621115
}
10631116

1064-
fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> McResult<Ty<'tcx>> {
1117+
fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10651118
self.resolve_type_vars_or_error(
10661119
expr.hir_id,
10671120
self.cx.typeck_results().expr_ty_adjusted_opt(expr),
@@ -1078,7 +1131,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10781131
/// implicit deref patterns attached (e.g., it is really
10791132
/// `&Some(x)`). In that case, we return the "outermost" type
10801133
/// (e.g., `&Option<T>`).
1081-
fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
1134+
fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10821135
// Check for implicit `&` types wrapping the pattern; note
10831136
// that these are never attached to binding patterns, so
10841137
// actually this is somewhat "disjoint" from the code below
@@ -1093,8 +1146,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10931146
self.pat_ty_unadjusted(pat)
10941147
}
10951148

1096-
/// Like `pat_ty`, but ignores implicit `&` patterns.
1097-
fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
1149+
/// Like `TypeckResults::pat_ty`, but ignores implicit `&` patterns.
1150+
fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10981151
let base_ty = self.node_ty(pat.hir_id)?;
10991152
trace!(?base_ty);
11001153

@@ -1136,7 +1189,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11361189
}
11371190
}
11381191

1139-
fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
1192+
fn cat_expr(&self, expr: &hir::Expr<'_>) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
11401193
self.cat_expr_(expr, self.cx.typeck_results().expr_adjustments(expr))
11411194
}
11421195

@@ -1146,7 +1199,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11461199
&self,
11471200
expr: &hir::Expr<'_>,
11481201
adjustments: &[adjustment::Adjustment<'tcx>],
1149-
) -> McResult<PlaceWithHirId<'tcx>> {
1202+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
11501203
match adjustments.split_last() {
11511204
None => self.cat_expr_unadjusted(expr),
11521205
Some((adjustment, previous)) => {
@@ -1160,7 +1213,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11601213
expr: &hir::Expr<'_>,
11611214
previous: PlaceWithHirId<'tcx>,
11621215
adjustment: &adjustment::Adjustment<'tcx>,
1163-
) -> McResult<PlaceWithHirId<'tcx>> {
1216+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
11641217
self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment)
11651218
}
11661219

@@ -1169,9 +1222,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11691222
expr: &hir::Expr<'_>,
11701223
previous: F,
11711224
adjustment: &adjustment::Adjustment<'tcx>,
1172-
) -> McResult<PlaceWithHirId<'tcx>>
1225+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed>
11731226
where
1174-
F: FnOnce() -> McResult<PlaceWithHirId<'tcx>>,
1227+
F: FnOnce() -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed>,
11751228
{
11761229
let target = self.cx.resolve_vars_if_possible(adjustment.target);
11771230
match adjustment.kind {
@@ -1196,7 +1249,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11961249
}
11971250
}
11981251

1199-
fn cat_expr_unadjusted(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
1252+
fn cat_expr_unadjusted(
1253+
&self,
1254+
expr: &hir::Expr<'_>,
1255+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
12001256
let expr_ty = self.expr_ty(expr)?;
12011257
match expr.kind {
12021258
hir::ExprKind::Unary(hir::UnOp::Deref, e_base) => {
@@ -1287,7 +1343,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
12871343
span: Span,
12881344
expr_ty: Ty<'tcx>,
12891345
res: Res,
1290-
) -> McResult<PlaceWithHirId<'tcx>> {
1346+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
12911347
match res {
12921348
Res::Def(
12931349
DefKind::Ctor(..)
@@ -1321,7 +1377,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13211377
/// Note: the actual upvar access contains invisible derefs of closure
13221378
/// environment and upvar reference as appropriate. Only regionck cares
13231379
/// about these dereferences, so we let it compute them as needed.
1324-
fn cat_upvar(&self, hir_id: HirId, var_id: HirId) -> McResult<PlaceWithHirId<'tcx>> {
1380+
fn cat_upvar(
1381+
&self,
1382+
hir_id: HirId,
1383+
var_id: HirId,
1384+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
13251385
let closure_expr_def_id = self.cx.body_owner_def_id();
13261386

13271387
let upvar_id = ty::UpvarId {
@@ -1370,7 +1430,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13701430
&self,
13711431
expr: &hir::Expr<'_>,
13721432
base: &hir::Expr<'_>,
1373-
) -> McResult<PlaceWithHirId<'tcx>> {
1433+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
13741434
// Reconstruct the output assuming it's a reference with the
13751435
// same region and mutability as the receiver. This holds for
13761436
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
@@ -1392,7 +1452,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13921452
&self,
13931453
node: HirId,
13941454
base_place: PlaceWithHirId<'tcx>,
1395-
) -> McResult<PlaceWithHirId<'tcx>> {
1455+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
13961456
let base_curr_ty = base_place.place.ty();
13971457
let deref_ty = match self
13981458
.cx
@@ -1417,26 +1477,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14171477
Ok(PlaceWithHirId::new(node, base_place.place.base_ty, base_place.place.base, projections))
14181478
}
14191479

1420-
fn cat_pattern<F>(
1421-
&self,
1422-
place: PlaceWithHirId<'tcx>,
1423-
pat: &hir::Pat<'_>,
1424-
mut op: F,
1425-
) -> McResult<()>
1426-
where
1427-
F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
1428-
{
1429-
self.cat_pattern_(place, pat, &mut op)
1430-
}
1431-
14321480
/// Returns the variant index for an ADT used within a Struct or TupleStruct pattern
14331481
/// Here `pat_hir_id` is the HirId of the pattern itself.
14341482
fn variant_index_for_adt(
14351483
&self,
14361484
qpath: &hir::QPath<'_>,
14371485
pat_hir_id: HirId,
14381486
span: Span,
1439-
) -> McResult<VariantIdx> {
1487+
) -> Result<VariantIdx, ErrorGuaranteed> {
14401488
let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
14411489
let ty = self.cx.typeck_results().node_type(pat_hir_id);
14421490
let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
@@ -1471,7 +1519,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14711519
pat_hir_id: HirId,
14721520
variant_index: VariantIdx,
14731521
span: Span,
1474-
) -> McResult<usize> {
1522+
) -> Result<usize, ErrorGuaranteed> {
14751523
let ty = self.cx.typeck_results().node_type(pat_hir_id);
14761524
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14771525
ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
@@ -1486,7 +1534,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14861534

14871535
/// Returns the total number of fields in a tuple used within a Tuple pattern.
14881536
/// Here `pat_hir_id` is the HirId of the pattern itself.
1489-
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
1537+
fn total_fields_in_tuple(
1538+
&self,
1539+
pat_hir_id: HirId,
1540+
span: Span,
1541+
) -> Result<usize, ErrorGuaranteed> {
14901542
let ty = self.cx.typeck_results().node_type(pat_hir_id);
14911543
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14921544
ty::Tuple(args) => Ok(args.len()),
@@ -1504,12 +1556,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15041556
/// In general, the way that this works is that we walk down the pattern,
15051557
/// constructing a `PlaceWithHirId` that represents the path that will be taken
15061558
/// to reach the value being matched.
1507-
fn cat_pattern_<F>(
1559+
fn cat_pattern<F>(
15081560
&self,
15091561
mut place_with_id: PlaceWithHirId<'tcx>,
15101562
pat: &hir::Pat<'_>,
15111563
op: &mut F,
1512-
) -> McResult<()>
1564+
) -> Result<(), ErrorGuaranteed>
15131565
where
15141566
F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
15151567
{
@@ -1580,7 +1632,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15801632
subpat_ty,
15811633
projection_kind,
15821634
);
1583-
self.cat_pattern_(sub_place, subpat, op)?;
1635+
self.cat_pattern(sub_place, subpat, op)?;
15841636
}
15851637
}
15861638

@@ -1600,7 +1652,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16001652
subpat_ty,
16011653
projection_kind,
16021654
);
1603-
self.cat_pattern_(sub_place, subpat, op)?;
1655+
self.cat_pattern(sub_place, subpat, op)?;
16041656
}
16051657
}
16061658

@@ -1625,26 +1677,26 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16251677
field_ty,
16261678
ProjectionKind::Field(field_index, variant_index),
16271679
);
1628-
self.cat_pattern_(field_place, fp.pat, op)?;
1680+
self.cat_pattern(field_place, fp.pat, op)?;
16291681
}
16301682
}
16311683

16321684
PatKind::Or(pats) => {
16331685
for pat in pats {
1634-
self.cat_pattern_(place_with_id.clone(), pat, op)?;
1686+
self.cat_pattern(place_with_id.clone(), pat, op)?;
16351687
}
16361688
}
16371689

16381690
PatKind::Binding(.., Some(subpat)) => {
1639-
self.cat_pattern_(place_with_id, subpat, op)?;
1691+
self.cat_pattern(place_with_id, subpat, op)?;
16401692
}
16411693

16421694
PatKind::Box(subpat) | PatKind::Ref(subpat, _) => {
16431695
// box p1, &p1, &mut p1. we can ignore the mutability of
16441696
// PatKind::Ref since that information is already contained
16451697
// in the type.
16461698
let subplace = self.cat_deref(pat.hir_id, place_with_id)?;
1647-
self.cat_pattern_(subplace, subpat, op)?;
1699+
self.cat_pattern(subplace, subpat, op)?;
16481700
}
16491701
PatKind::Deref(subpat) => {
16501702
let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpat);
@@ -1654,7 +1706,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16541706
let ty = Ty::new_ref(self.cx.tcx(), re_erased, ty, mutability);
16551707
// A deref pattern generates a temporary.
16561708
let place = self.cat_rvalue(pat.hir_id, ty);
1657-
self.cat_pattern_(place, subpat, op)?;
1709+
self.cat_pattern(place, subpat, op)?;
16581710
}
16591711

16601712
PatKind::Slice(before, ref slice, after) => {
@@ -1673,7 +1725,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16731725
ProjectionKind::Index,
16741726
);
16751727
for before_pat in before {
1676-
self.cat_pattern_(elt_place.clone(), before_pat, op)?;
1728+
self.cat_pattern(elt_place.clone(), before_pat, op)?;
16771729
}
16781730
if let Some(slice_pat) = *slice {
16791731
let slice_pat_ty = self.pat_ty_adjusted(slice_pat)?;
@@ -1683,10 +1735,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16831735
slice_pat_ty,
16841736
ProjectionKind::Subslice,
16851737
);
1686-
self.cat_pattern_(slice_place, slice_pat, op)?;
1738+
self.cat_pattern(slice_place, slice_pat, op)?;
16871739
}
16881740
for after_pat in after {
1689-
self.cat_pattern_(elt_place.clone(), after_pat, op)?;
1741+
self.cat_pattern(elt_place.clone(), after_pat, op)?;
16901742
}
16911743
}
16921744

tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
//@ compile-flags: -Znext-solver
22
//@ check-pass
33

4+
// Fixes a regression in icu_provider_adaptors where we weren't normalizing the
5+
// return type of a function type before performing a `Ty::builtin_deref` call,
6+
// leading to an ICE.
7+
48
struct Struct {
59
field: i32,
610
}

0 commit comments

Comments
 (0)