Skip to content

Commit 9af26d0

Browse files
Try structurally resolve
1 parent c320536 commit 9af26d0

File tree

1 file changed

+60
-27
lines changed

1 file changed

+60
-27
lines changed

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+60-27
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ pub trait TypeInformationCtxt<'tcx> {
134134

135135
fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T;
136136

137+
fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
138+
137139
fn tainted_by_errors(&self) -> Option<ErrorGuaranteed>;
138140

139141
fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool;
@@ -156,6 +158,10 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
156158
self.infcx.resolve_vars_if_possible(t)
157159
}
158160

161+
fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
162+
(**self).try_structurally_resolve_type(sp, ty)
163+
}
164+
159165
fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
160166
self.infcx.tainted_by_errors()
161167
}
@@ -182,6 +188,11 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
182188
self.0.maybe_typeck_results().expect("expected typeck results")
183189
}
184190

191+
fn try_structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
192+
// FIXME: Maybe need to normalize here.
193+
ty
194+
}
195+
185196
fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
186197
t
187198
}
@@ -543,7 +554,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
543554
_ => {
544555
// Otherwise, this is a struct/enum variant, and so it's
545556
// only a read if we need to read the discriminant.
546-
needs_to_be_read |= is_multivariant_adt(place.place.ty());
557+
needs_to_be_read |=
558+
self.is_multivariant_adt(place.place.ty(), pat.span);
547559
}
548560
}
549561
}
@@ -555,7 +567,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
555567
// perform some reads).
556568

557569
let place_ty = place.place.ty();
558-
needs_to_be_read |= is_multivariant_adt(place_ty);
570+
needs_to_be_read |= self.is_multivariant_adt(place_ty, pat.span);
559571
}
560572
PatKind::Lit(_) | PatKind::Range(..) => {
561573
// If the PatKind is a Lit or a Range then we want
@@ -676,7 +688,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
676688

677689
// Select just those fields of the `with`
678690
// expression that will actually be used
679-
match with_place.place.ty().kind() {
691+
match self.cx.try_structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() {
680692
ty::Adt(adt, args) if adt.is_struct() => {
681693
// Consume those fields of the with expression that are needed.
682694
for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() {
@@ -1100,7 +1112,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11001112
// a bind-by-ref means that the base_ty will be the type of the ident itself,
11011113
// but what we want here is the type of the underlying value being borrowed.
11021114
// So peel off one-level, turning the &T into T.
1103-
match base_ty.builtin_deref(false) {
1115+
match self
1116+
.cx
1117+
.try_structurally_resolve_type(pat.span, base_ty)
1118+
.builtin_deref(false)
1119+
{
11041120
Some(t) => Ok(t.ty),
11051121
None => {
11061122
debug!("By-ref binding of non-derefable type");
@@ -1334,7 +1350,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13341350
// Opaque types can't have field projections, but we can instead convert
13351351
// the current place in-place (heh) to the hidden type, and then apply all
13361352
// follow up projections on that.
1337-
if node_ty != place_ty && matches!(place_ty.kind(), ty::Alias(ty::Opaque, ..)) {
1353+
if node_ty != place_ty
1354+
&& self
1355+
.cx
1356+
.try_structurally_resolve_type(
1357+
self.cx.tcx().hir().span(base_place.hir_id),
1358+
place_ty,
1359+
)
1360+
.is_impl_trait()
1361+
{
13381362
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
13391363
}
13401364
projections.push(Projection { kind, ty });
@@ -1352,7 +1376,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13521376
let place_ty = self.expr_ty(expr)?;
13531377
let base_ty = self.expr_ty_adjusted(base)?;
13541378

1355-
let ty::Ref(region, _, mutbl) = *base_ty.kind() else {
1379+
let ty::Ref(region, _, mutbl) =
1380+
*self.cx.try_structurally_resolve_type(base.span, base_ty).kind()
1381+
else {
13561382
span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
13571383
};
13581384
let ref_ty = Ty::new_ref(self.cx.tcx(), region, place_ty, mutbl);
@@ -1367,7 +1393,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13671393
base_place: PlaceWithHirId<'tcx>,
13681394
) -> McResult<PlaceWithHirId<'tcx>> {
13691395
let base_curr_ty = base_place.place.ty();
1370-
let deref_ty = match base_curr_ty.builtin_deref(true) {
1396+
let deref_ty = match self
1397+
.cx
1398+
.try_structurally_resolve_type(
1399+
self.cx.tcx().hir().span(base_place.hir_id),
1400+
base_curr_ty,
1401+
)
1402+
.builtin_deref(true)
1403+
{
13711404
Some(mt) => mt.ty,
13721405
None => {
13731406
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
@@ -1405,7 +1438,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14051438
) -> McResult<VariantIdx> {
14061439
let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
14071440
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1408-
let ty::Adt(adt_def, _) = ty.kind() else {
1441+
let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
14091442
return Err(self
14101443
.cx
14111444
.tcx()
@@ -1439,7 +1472,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14391472
span: Span,
14401473
) -> McResult<usize> {
14411474
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1442-
match ty.kind() {
1475+
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14431476
ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
14441477
_ => {
14451478
self.cx
@@ -1454,7 +1487,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14541487
/// Here `pat_hir_id` is the HirId of the pattern itself.
14551488
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
14561489
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1457-
match ty.kind() {
1490+
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14581491
ty::Tuple(args) => Ok(args.len()),
14591492
_ => Err(self
14601493
.cx
@@ -1669,23 +1702,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16691702

16701703
Ok(())
16711704
}
1672-
}
16731705

1674-
fn is_multivariant_adt(ty: Ty<'_>) -> bool {
1675-
if let ty::Adt(def, _) = ty.kind() {
1676-
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
1677-
// to assume that more cases will be added to the variant in the future. This mean
1678-
// that we should handle non-exhaustive SingleVariant the same way we would handle
1679-
// a MultiVariant.
1680-
// If the variant is not local it must be defined in another crate.
1681-
let is_non_exhaustive = match def.adt_kind() {
1682-
AdtKind::Struct | AdtKind::Union => {
1683-
def.non_enum_variant().is_field_list_non_exhaustive()
1684-
}
1685-
AdtKind::Enum => def.is_variant_list_non_exhaustive(),
1686-
};
1687-
def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive)
1688-
} else {
1689-
false
1706+
fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
1707+
if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() {
1708+
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
1709+
// to assume that more cases will be added to the variant in the future. This mean
1710+
// that we should handle non-exhaustive SingleVariant the same way we would handle
1711+
// a MultiVariant.
1712+
// If the variant is not local it must be defined in another crate.
1713+
let is_non_exhaustive = match def.adt_kind() {
1714+
AdtKind::Struct | AdtKind::Union => {
1715+
def.non_enum_variant().is_field_list_non_exhaustive()
1716+
}
1717+
AdtKind::Enum => def.is_variant_list_non_exhaustive(),
1718+
};
1719+
def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive)
1720+
} else {
1721+
false
1722+
}
16901723
}
16911724
}

0 commit comments

Comments
 (0)