Skip to content

Commit fb298e8

Browse files
Apply nits
1 parent 5ab6dca commit fb298e8

File tree

2 files changed

+105
-49
lines changed

2 files changed

+105
-49
lines changed

Diff for: 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);
@@ -1051,15 +1104,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10511104
}
10521105
}
10531106

1054-
fn node_ty(&self, hir_id: HirId) -> McResult<Ty<'tcx>> {
1107+
fn node_ty(&self, hir_id: HirId) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10551108
self.resolve_type_vars_or_error(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
10561109
}
10571110

1058-
fn expr_ty(&self, expr: &hir::Expr<'_>) -> McResult<Ty<'tcx>> {
1111+
fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10591112
self.resolve_type_vars_or_error(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
10601113
}
10611114

1062-
fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> McResult<Ty<'tcx>> {
1115+
fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10631116
self.resolve_type_vars_or_error(
10641117
expr.hir_id,
10651118
self.cx.typeck_results().expr_ty_adjusted_opt(expr),
@@ -1076,7 +1129,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10761129
/// implicit deref patterns attached (e.g., it is really
10771130
/// `&Some(x)`). In that case, we return the "outermost" type
10781131
/// (e.g., `&Option<T>`).
1079-
fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
1132+
fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10801133
// Check for implicit `&` types wrapping the pattern; note
10811134
// that these are never attached to binding patterns, so
10821135
// actually this is somewhat "disjoint" from the code below
@@ -1091,8 +1144,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10911144
self.pat_ty_unadjusted(pat)
10921145
}
10931146

1094-
/// Like `pat_ty`, but ignores implicit `&` patterns.
1095-
fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
1147+
/// Like `TypeckResults::pat_ty`, but ignores implicit `&` patterns.
1148+
fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, ErrorGuaranteed> {
10961149
let base_ty = self.node_ty(pat.hir_id)?;
10971150
trace!(?base_ty);
10981151

@@ -1134,7 +1187,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11341187
}
11351188
}
11361189

1137-
fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
1190+
fn cat_expr(&self, expr: &hir::Expr<'_>) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
11381191
self.cat_expr_(expr, self.cx.typeck_results().expr_adjustments(expr))
11391192
}
11401193

@@ -1144,7 +1197,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11441197
&self,
11451198
expr: &hir::Expr<'_>,
11461199
adjustments: &[adjustment::Adjustment<'tcx>],
1147-
) -> McResult<PlaceWithHirId<'tcx>> {
1200+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
11481201
match adjustments.split_last() {
11491202
None => self.cat_expr_unadjusted(expr),
11501203
Some((adjustment, previous)) => {
@@ -1158,7 +1211,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11581211
expr: &hir::Expr<'_>,
11591212
previous: PlaceWithHirId<'tcx>,
11601213
adjustment: &adjustment::Adjustment<'tcx>,
1161-
) -> McResult<PlaceWithHirId<'tcx>> {
1214+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
11621215
self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment)
11631216
}
11641217

@@ -1167,9 +1220,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11671220
expr: &hir::Expr<'_>,
11681221
previous: F,
11691222
adjustment: &adjustment::Adjustment<'tcx>,
1170-
) -> McResult<PlaceWithHirId<'tcx>>
1223+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed>
11711224
where
1172-
F: FnOnce() -> McResult<PlaceWithHirId<'tcx>>,
1225+
F: FnOnce() -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed>,
11731226
{
11741227
let target = self.cx.resolve_vars_if_possible(adjustment.target);
11751228
match adjustment.kind {
@@ -1194,7 +1247,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11941247
}
11951248
}
11961249

1197-
fn cat_expr_unadjusted(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
1250+
fn cat_expr_unadjusted(
1251+
&self,
1252+
expr: &hir::Expr<'_>,
1253+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
11981254
let expr_ty = self.expr_ty(expr)?;
11991255
match expr.kind {
12001256
hir::ExprKind::Unary(hir::UnOp::Deref, e_base) => {
@@ -1285,7 +1341,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
12851341
span: Span,
12861342
expr_ty: Ty<'tcx>,
12871343
res: Res,
1288-
) -> McResult<PlaceWithHirId<'tcx>> {
1344+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
12891345
match res {
12901346
Res::Def(
12911347
DefKind::Ctor(..)
@@ -1319,7 +1375,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13191375
/// Note: the actual upvar access contains invisible derefs of closure
13201376
/// environment and upvar reference as appropriate. Only regionck cares
13211377
/// about these dereferences, so we let it compute them as needed.
1322-
fn cat_upvar(&self, hir_id: HirId, var_id: HirId) -> McResult<PlaceWithHirId<'tcx>> {
1378+
fn cat_upvar(
1379+
&self,
1380+
hir_id: HirId,
1381+
var_id: HirId,
1382+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
13231383
let closure_expr_def_id = self.cx.body_owner_def_id();
13241384

13251385
let upvar_id = ty::UpvarId {
@@ -1368,7 +1428,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13681428
&self,
13691429
expr: &hir::Expr<'_>,
13701430
base: &hir::Expr<'_>,
1371-
) -> McResult<PlaceWithHirId<'tcx>> {
1431+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
13721432
// Reconstruct the output assuming it's a reference with the
13731433
// same region and mutability as the receiver. This holds for
13741434
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
@@ -1390,7 +1450,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13901450
&self,
13911451
node: HirId,
13921452
base_place: PlaceWithHirId<'tcx>,
1393-
) -> McResult<PlaceWithHirId<'tcx>> {
1453+
) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
13941454
let base_curr_ty = base_place.place.ty();
13951455
let deref_ty = match self
13961456
.cx
@@ -1415,26 +1475,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14151475
Ok(PlaceWithHirId::new(node, base_place.place.base_ty, base_place.place.base, projections))
14161476
}
14171477

1418-
fn cat_pattern<F>(
1419-
&self,
1420-
place: PlaceWithHirId<'tcx>,
1421-
pat: &hir::Pat<'_>,
1422-
mut op: F,
1423-
) -> McResult<()>
1424-
where
1425-
F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
1426-
{
1427-
self.cat_pattern_(place, pat, &mut op)
1428-
}
1429-
14301478
/// Returns the variant index for an ADT used within a Struct or TupleStruct pattern
14311479
/// Here `pat_hir_id` is the HirId of the pattern itself.
14321480
fn variant_index_for_adt(
14331481
&self,
14341482
qpath: &hir::QPath<'_>,
14351483
pat_hir_id: HirId,
14361484
span: Span,
1437-
) -> McResult<VariantIdx> {
1485+
) -> Result<VariantIdx, ErrorGuaranteed> {
14381486
let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
14391487
let ty = self.cx.typeck_results().node_type(pat_hir_id);
14401488
let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
@@ -1469,7 +1517,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14691517
pat_hir_id: HirId,
14701518
variant_index: VariantIdx,
14711519
span: Span,
1472-
) -> McResult<usize> {
1520+
) -> Result<usize, ErrorGuaranteed> {
14731521
let ty = self.cx.typeck_results().node_type(pat_hir_id);
14741522
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14751523
ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
@@ -1484,7 +1532,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14841532

14851533
/// Returns the total number of fields in a tuple used within a Tuple pattern.
14861534
/// Here `pat_hir_id` is the HirId of the pattern itself.
1487-
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
1535+
fn total_fields_in_tuple(
1536+
&self,
1537+
pat_hir_id: HirId,
1538+
span: Span,
1539+
) -> Result<usize, ErrorGuaranteed> {
14881540
let ty = self.cx.typeck_results().node_type(pat_hir_id);
14891541
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14901542
ty::Tuple(args) => Ok(args.len()),
@@ -1502,12 +1554,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15021554
/// In general, the way that this works is that we walk down the pattern,
15031555
/// constructing a `PlaceWithHirId` that represents the path that will be taken
15041556
/// to reach the value being matched.
1505-
fn cat_pattern_<F>(
1557+
fn cat_pattern<F>(
15061558
&self,
15071559
mut place_with_id: PlaceWithHirId<'tcx>,
15081560
pat: &hir::Pat<'_>,
15091561
op: &mut F,
1510-
) -> McResult<()>
1562+
) -> Result<(), ErrorGuaranteed>
15111563
where
15121564
F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
15131565
{
@@ -1578,7 +1630,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15781630
subpat_ty,
15791631
projection_kind,
15801632
);
1581-
self.cat_pattern_(sub_place, subpat, op)?;
1633+
self.cat_pattern(sub_place, subpat, op)?;
15821634
}
15831635
}
15841636

@@ -1598,7 +1650,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15981650
subpat_ty,
15991651
projection_kind,
16001652
);
1601-
self.cat_pattern_(sub_place, subpat, op)?;
1653+
self.cat_pattern(sub_place, subpat, op)?;
16021654
}
16031655
}
16041656

@@ -1623,26 +1675,26 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16231675
field_ty,
16241676
ProjectionKind::Field(field_index, variant_index),
16251677
);
1626-
self.cat_pattern_(field_place, fp.pat, op)?;
1678+
self.cat_pattern(field_place, fp.pat, op)?;
16271679
}
16281680
}
16291681

16301682
PatKind::Or(pats) => {
16311683
for pat in pats {
1632-
self.cat_pattern_(place_with_id.clone(), pat, op)?;
1684+
self.cat_pattern(place_with_id.clone(), pat, op)?;
16331685
}
16341686
}
16351687

16361688
PatKind::Binding(.., Some(subpat)) => {
1637-
self.cat_pattern_(place_with_id, subpat, op)?;
1689+
self.cat_pattern(place_with_id, subpat, op)?;
16381690
}
16391691

16401692
PatKind::Box(subpat) | PatKind::Ref(subpat, _) => {
16411693
// box p1, &p1, &mut p1. we can ignore the mutability of
16421694
// PatKind::Ref since that information is already contained
16431695
// in the type.
16441696
let subplace = self.cat_deref(pat.hir_id, place_with_id)?;
1645-
self.cat_pattern_(subplace, subpat, op)?;
1697+
self.cat_pattern(subplace, subpat, op)?;
16461698
}
16471699
PatKind::Deref(subpat) => {
16481700
let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpat);
@@ -1652,7 +1704,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16521704
let ty = Ty::new_ref(self.cx.tcx(), re_erased, ty, mutability);
16531705
// A deref pattern generates a temporary.
16541706
let place = self.cat_rvalue(pat.hir_id, ty);
1655-
self.cat_pattern_(place, subpat, op)?;
1707+
self.cat_pattern(place, subpat, op)?;
16561708
}
16571709

16581710
PatKind::Slice(before, ref slice, after) => {
@@ -1671,7 +1723,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16711723
ProjectionKind::Index,
16721724
);
16731725
for before_pat in before {
1674-
self.cat_pattern_(elt_place.clone(), before_pat, op)?;
1726+
self.cat_pattern(elt_place.clone(), before_pat, op)?;
16751727
}
16761728
if let Some(slice_pat) = *slice {
16771729
let slice_pat_ty = self.pat_ty_adjusted(slice_pat)?;
@@ -1681,10 +1733,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16811733
slice_pat_ty,
16821734
ProjectionKind::Subslice,
16831735
);
1684-
self.cat_pattern_(slice_place, slice_pat, op)?;
1736+
self.cat_pattern(slice_place, slice_pat, op)?;
16851737
}
16861738
for after_pat in after {
1687-
self.cat_pattern_(elt_place.clone(), after_pat, op)?;
1739+
self.cat_pattern(elt_place.clone(), after_pat, op)?;
16881740
}
16891741
}
16901742

Diff for: 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)