Skip to content

Commit 5ab6dca

Browse files
Try structurally resolve
1 parent 55cf09d commit 5ab6dca

File tree

2 files changed

+77
-29
lines changed

2 files changed

+77
-29
lines changed

Diff for: compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+62-29
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
if let Some(guar) = self.infcx.tainted_by_errors() { Err(guar) } else { Ok(()) }
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() {
@@ -1099,8 +1111,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10991111
// a bind-by-ref means that the base_ty will be the type of the ident itself,
11001112
// but what we want here is the type of the underlying value being borrowed.
11011113
// So peel off one-level, turning the &T into T.
1102-
match base_ty.builtin_deref(false) {
1103-
Some(t) => Ok(t.ty),
1114+
match self
1115+
.cx
1116+
.try_structurally_resolve_type(pat.span, base_ty)
1117+
.builtin_deref(false)
1118+
{
1119+
Some(ty) => Ok(ty),
11041120
None => {
11051121
debug!("By-ref binding of non-derefable type");
11061122
Err(self
@@ -1333,7 +1349,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13331349
// Opaque types can't have field projections, but we can instead convert
13341350
// the current place in-place (heh) to the hidden type, and then apply all
13351351
// follow up projections on that.
1336-
if node_ty != place_ty && matches!(place_ty.kind(), ty::Alias(ty::Opaque, ..)) {
1352+
if node_ty != place_ty
1353+
&& self
1354+
.cx
1355+
.try_structurally_resolve_type(
1356+
self.cx.tcx().hir().span(base_place.hir_id),
1357+
place_ty,
1358+
)
1359+
.is_impl_trait()
1360+
{
13371361
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
13381362
}
13391363
projections.push(Projection { kind, ty });
@@ -1351,7 +1375,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13511375
let place_ty = self.expr_ty(expr)?;
13521376
let base_ty = self.expr_ty_adjusted(base)?;
13531377

1354-
let ty::Ref(region, _, mutbl) = *base_ty.kind() else {
1378+
let ty::Ref(region, _, mutbl) =
1379+
*self.cx.try_structurally_resolve_type(base.span, base_ty).kind()
1380+
else {
13551381
span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
13561382
};
13571383
let ref_ty = Ty::new_ref(self.cx.tcx(), region, place_ty, mutbl);
@@ -1366,8 +1392,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13661392
base_place: PlaceWithHirId<'tcx>,
13671393
) -> McResult<PlaceWithHirId<'tcx>> {
13681394
let base_curr_ty = base_place.place.ty();
1369-
let deref_ty = match base_curr_ty.builtin_deref(true) {
1370-
Some(mt) => mt.ty,
1395+
let deref_ty = match self
1396+
.cx
1397+
.try_structurally_resolve_type(
1398+
self.cx.tcx().hir().span(base_place.hir_id),
1399+
base_curr_ty,
1400+
)
1401+
.builtin_deref(true)
1402+
{
1403+
Some(ty) => ty,
13711404
None => {
13721405
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
13731406
return Err(self.cx.tcx().dcx().span_delayed_bug(
@@ -1404,7 +1437,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14041437
) -> McResult<VariantIdx> {
14051438
let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
14061439
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1407-
let ty::Adt(adt_def, _) = ty.kind() else {
1440+
let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
14081441
return Err(self
14091442
.cx
14101443
.tcx()
@@ -1438,7 +1471,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14381471
span: Span,
14391472
) -> McResult<usize> {
14401473
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1441-
match ty.kind() {
1474+
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14421475
ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
14431476
_ => {
14441477
self.cx
@@ -1453,7 +1486,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14531486
/// Here `pat_hir_id` is the HirId of the pattern itself.
14541487
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
14551488
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1456-
match ty.kind() {
1489+
match self.cx.try_structurally_resolve_type(span, ty).kind() {
14571490
ty::Tuple(args) => Ok(args.len()),
14581491
_ => Err(self
14591492
.cx
@@ -1668,23 +1701,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16681701

16691702
Ok(())
16701703
}
1671-
}
16721704

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