Skip to content

Commit 8b060ab

Browse files
Try structurally resolve
1 parent 2af6c1a commit 8b060ab

File tree

2 files changed

+75
-27
lines changed

2 files changed

+75
-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() {
@@ -1101,7 +1113,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11011113
// a bind-by-ref means that the base_ty will be the type of the ident itself,
11021114
// but what we want here is the type of the underlying value being borrowed.
11031115
// So peel off one-level, turning the &T into T.
1104-
match base_ty.builtin_deref(false) {
1116+
match self
1117+
.cx
1118+
.try_structurally_resolve_type(pat.span, base_ty)
1119+
.builtin_deref(false)
1120+
{
11051121
Some(t) => Ok(t.ty),
11061122
None => {
11071123
debug!("By-ref binding of non-derefable type");
@@ -1335,7 +1351,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13351351
// Opaque types can't have field projections, but we can instead convert
13361352
// the current place in-place (heh) to the hidden type, and then apply all
13371353
// follow up projections on that.
1338-
if node_ty != place_ty && matches!(place_ty.kind(), ty::Alias(ty::Opaque, ..)) {
1354+
if node_ty != place_ty
1355+
&& self
1356+
.cx
1357+
.try_structurally_resolve_type(
1358+
self.cx.tcx().hir().span(base_place.hir_id),
1359+
place_ty,
1360+
)
1361+
.is_impl_trait()
1362+
{
13391363
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
13401364
}
13411365
projections.push(Projection { kind, ty });
@@ -1353,7 +1377,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13531377
let place_ty = self.expr_ty(expr)?;
13541378
let base_ty = self.expr_ty_adjusted(base)?;
13551379

1356-
let ty::Ref(region, _, mutbl) = *base_ty.kind() else {
1380+
let ty::Ref(region, _, mutbl) =
1381+
*self.cx.try_structurally_resolve_type(base.span, base_ty).kind()
1382+
else {
13571383
span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
13581384
};
13591385
let ref_ty = Ty::new_ref(self.cx.tcx(), region, place_ty, mutbl);
@@ -1368,7 +1394,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13681394
base_place: PlaceWithHirId<'tcx>,
13691395
) -> McResult<PlaceWithHirId<'tcx>> {
13701396
let base_curr_ty = base_place.place.ty();
1371-
let deref_ty = match base_curr_ty.builtin_deref(true) {
1397+
let deref_ty = match self
1398+
.cx
1399+
.try_structurally_resolve_type(
1400+
self.cx.tcx().hir().span(base_place.hir_id),
1401+
base_curr_ty,
1402+
)
1403+
.builtin_deref(true)
1404+
{
13721405
Some(mt) => mt.ty,
13731406
None => {
13741407
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
@@ -1406,7 +1439,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14061439
) -> McResult<VariantIdx> {
14071440
let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
14081441
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1409-
let ty::Adt(adt_def, _) = ty.kind() else {
1442+
let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
14101443
return Err(self
14111444
.cx
14121445
.tcx()
@@ -1440,7 +1473,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14401473
span: Span,
14411474
) -> McResult<usize> {
14421475
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1443-
match ty.kind() {
1476+
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14441477
ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
14451478
_ => {
14461479
self.cx
@@ -1455,7 +1488,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14551488
/// Here `pat_hir_id` is the HirId of the pattern itself.
14561489
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
14571490
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1458-
match ty.kind() {
1491+
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14591492
ty::Tuple(args) => Ok(args.len()),
14601493
_ => Err(self
14611494
.cx
@@ -1670,23 +1703,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16701703

16711704
Ok(())
16721705
}
1673-
}
16741706

1675-
fn is_multivariant_adt(ty: Ty<'_>) -> bool {
1676-
if let ty::Adt(def, _) = ty.kind() {
1677-
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
1678-
// to assume that more cases will be added to the variant in the future. This mean
1679-
// that we should handle non-exhaustive SingleVariant the same way we would handle
1680-
// a MultiVariant.
1681-
// If the variant is not local it must be defined in another crate.
1682-
let is_non_exhaustive = match def.adt_kind() {
1683-
AdtKind::Struct | AdtKind::Union => {
1684-
def.non_enum_variant().is_field_list_non_exhaustive()
1685-
}
1686-
AdtKind::Enum => def.is_variant_list_non_exhaustive(),
1687-
};
1688-
def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive)
1689-
} else {
1690-
false
1707+
fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
1708+
if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() {
1709+
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
1710+
// to assume that more cases will be added to the variant in the future. This mean
1711+
// that we should handle non-exhaustive SingleVariant the same way we would handle
1712+
// a MultiVariant.
1713+
// If the variant is not local it must be defined in another crate.
1714+
let is_non_exhaustive = match def.adt_kind() {
1715+
AdtKind::Struct | AdtKind::Union => {
1716+
def.non_enum_variant().is_field_list_non_exhaustive()
1717+
}
1718+
AdtKind::Enum => def.is_variant_list_non_exhaustive(),
1719+
};
1720+
def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive)
1721+
} else {
1722+
false
1723+
}
16911724
}
16921725
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ compile-flags: -Znext-solver
2+
//@ check-pass
3+
4+
struct Struct {
5+
field: i32,
6+
}
7+
8+
fn hello(f: impl Fn() -> &'static Box<[i32]>, f2: impl Fn() -> &'static Struct) {
9+
let cl = || {
10+
let x = &f()[0];
11+
let y = &f2().field;
12+
};
13+
}
14+
15+
fn main() {}

0 commit comments

Comments
 (0)