Skip to content

Commit efd6aec

Browse files
Be a bit more relaxed about not yet constrained infer vars in closure upvar analysis
1 parent 243c5a3 commit efd6aec

File tree

4 files changed

+48
-37
lines changed

4 files changed

+48
-37
lines changed

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+15-26
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ pub trait TypeInformationCtxt<'tcx> {
158158

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

161-
fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
161+
fn structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
162162

163163
fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error;
164164

@@ -191,8 +191,8 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
191191
self.infcx.resolve_vars_if_possible(t)
192192
}
193193

194-
fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
195-
(**self).try_structurally_resolve_type(sp, ty)
194+
fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
195+
(**self).structurally_resolve_type(sp, ty)
196196
}
197197

198198
fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error {
@@ -236,7 +236,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
236236
self.0.maybe_typeck_results().expect("expected typeck results")
237237
}
238238

239-
fn try_structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
239+
fn structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
240240
// FIXME: Maybe need to normalize here.
241241
ty
242242
}
@@ -776,7 +776,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
776776

777777
// Select just those fields of the `with`
778778
// expression that will actually be used
779-
match self.cx.try_structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() {
779+
match self.cx.structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() {
780780
ty::Adt(adt, args) if adt.is_struct() => {
781781
// Consume those fields of the with expression that are needed.
782782
for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() {
@@ -1185,12 +1185,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11851185
Some(ty) => {
11861186
let ty = self.cx.resolve_vars_if_possible(ty);
11871187
self.cx.error_reported_in_ty(ty)?;
1188-
if ty.is_ty_var() {
1189-
debug!("resolve_type_vars_or_bug: infer var from {:?}", ty);
1190-
Err(self.cx.report_bug(self.cx.tcx().hir_span(id), "encountered type variable"))
1191-
} else {
1192-
Ok(ty)
1193-
}
1188+
Ok(ty)
11941189
}
11951190
None => {
11961191
// FIXME: We shouldn't be relying on the infcx being tainted.
@@ -1264,10 +1259,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
12641259
// a bind-by-ref means that the base_ty will be the type of the ident itself,
12651260
// but what we want here is the type of the underlying value being borrowed.
12661261
// So peel off one-level, turning the &T into T.
1267-
match self
1268-
.cx
1269-
.try_structurally_resolve_type(pat.span, base_ty)
1270-
.builtin_deref(false)
1262+
match self.cx.structurally_resolve_type(pat.span, base_ty).builtin_deref(false)
12711263
{
12721264
Some(ty) => Ok(ty),
12731265
None => {
@@ -1513,10 +1505,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15131505
if node_ty != place_ty
15141506
&& self
15151507
.cx
1516-
.try_structurally_resolve_type(
1517-
self.cx.tcx().hir_span(base_place.hir_id),
1518-
place_ty,
1519-
)
1508+
.structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), place_ty)
15201509
.is_impl_trait()
15211510
{
15221511
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
@@ -1538,7 +1527,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15381527
let base_ty = self.expr_ty_adjusted(base)?;
15391528

15401529
let ty::Ref(region, _, mutbl) =
1541-
*self.cx.try_structurally_resolve_type(base.span, base_ty).kind()
1530+
*self.cx.structurally_resolve_type(base.span, base_ty).kind()
15421531
else {
15431532
span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
15441533
};
@@ -1556,7 +1545,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15561545
let base_curr_ty = base_place.place.ty();
15571546
let deref_ty = match self
15581547
.cx
1559-
.try_structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty)
1548+
.structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty)
15601549
.builtin_deref(true)
15611550
{
15621551
Some(ty) => ty,
@@ -1584,7 +1573,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15841573
) -> Result<VariantIdx, Cx::Error> {
15851574
let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
15861575
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1587-
let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
1576+
let ty::Adt(adt_def, _) = self.cx.structurally_resolve_type(span, ty).kind() else {
15881577
return Err(self
15891578
.cx
15901579
.report_bug(span, "struct or tuple struct pattern not applied to an ADT"));
@@ -1616,7 +1605,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16161605
span: Span,
16171606
) -> Result<usize, Cx::Error> {
16181607
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1619-
match self.cx.try_structurally_resolve_type(span, ty).kind() {
1608+
match self.cx.structurally_resolve_type(span, ty).kind() {
16201609
ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
16211610
_ => {
16221611
self.cx
@@ -1631,7 +1620,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16311620
/// Here `pat_hir_id` is the HirId of the pattern itself.
16321621
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> Result<usize, Cx::Error> {
16331622
let ty = self.cx.typeck_results().node_type(pat_hir_id);
1634-
match self.cx.try_structurally_resolve_type(span, ty).kind() {
1623+
match self.cx.structurally_resolve_type(span, ty).kind() {
16351624
ty::Tuple(args) => Ok(args.len()),
16361625
_ => Err(self.cx.report_bug(span, "tuple pattern not applied to a tuple")),
16371626
}
@@ -1820,7 +1809,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
18201809
PatKind::Slice(before, ref slice, after) => {
18211810
let Some(element_ty) = self
18221811
.cx
1823-
.try_structurally_resolve_type(pat.span, place_with_id.place.ty())
1812+
.structurally_resolve_type(pat.span, place_with_id.place.ty())
18241813
.builtin_index()
18251814
else {
18261815
debug!("explicit index of non-indexable type {:?}", place_with_id);
@@ -1890,7 +1879,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
18901879
}
18911880

18921881
fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
1893-
if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() {
1882+
if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() {
18941883
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
18951884
// to assume that more cases will be added to the variant in the future. This mean
18961885
// that we should handle non-exhaustive SingleVariant the same way we would handle

tests/crashes/131758.rs

-11
This file was deleted.

tests/ui/closures/opaque-upvar.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] compile-flags: -Znext-solver
5+
6+
// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/197>.
7+
// This is only an issue in the new solver, but I'm testing it in both solvers for now.
8+
// This has to do with the fact that the recursive `walk_dir` is a revealing use, which has not
9+
// yet been constrained from the defining use by the time that closure signature inference is
10+
// performed. We don't really care, though, since anywhere we structurally match on a type in
11+
// upvar analysis, we already call `structurally_resolve_type` right before `.kind()`.
12+
13+
fn walk_dir(cb: &()) -> impl Sized {
14+
|| {
15+
let fut = walk_dir(cb);
16+
};
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(unboxed_closures)]
2+
3+
// Regression test for #131758. We only know the type of `x` after closure upvar
4+
// inference is done, even if we don't need to structurally resolve the type of `x`.
5+
6+
trait Foo {}
7+
8+
impl<T: Fn<(i32,)>> Foo for T {}
9+
10+
fn baz<T: Foo>(_: T) {}
11+
12+
fn main() {
13+
baz(|x| ());
14+
}

0 commit comments

Comments
 (0)