Skip to content

Commit 28c13d2

Browse files
Resolve more
1 parent 0ac93cd commit 28c13d2

33 files changed

+278
-210
lines changed

compiler/rustc_hir_typeck/src/_match.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8686
let arm_ty = self.check_expr_with_expectation(arm.body, expected);
8787
all_arms_diverge &= self.diverges.get();
8888
let tail_defines_return_position_impl_trait =
89-
self.return_position_impl_trait_from_match_expectation(orig_expected);
89+
self.return_position_impl_trait_from_match_expectation(orig_expected, expr.span);
9090

9191
let (arm_block_id, arm_span) = if let hir::ExprKind::Block(blk, _) = arm.body.kind {
9292
(Some(blk.hir_id), self.find_block_span(blk))
@@ -586,8 +586,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
586586
pub(crate) fn return_position_impl_trait_from_match_expectation(
587587
&self,
588588
expectation: Expectation<'tcx>,
589+
span: Span,
589590
) -> Option<LocalDefId> {
590-
let expected_ty = expectation.to_option(self)?;
591+
let expected_ty = expectation.structurally_resolve(self, span)?;
591592
let (def_id, args) = match *expected_ty.kind() {
592593
// FIXME: Could also check that the RPIT is not defined
593594
ty::Alias(ty::Opaque, alias_ty) => (alias_ty.def_id.as_local()?, alias_ty.args),

compiler/rustc_hir_typeck/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
573573
// We didn't record the in scope traits during late resolution
574574
// so we need to probe AllTraits unfortunately
575575
ProbeScope::AllTraits,
576-
expected.only_has_type(self),
576+
expected.structurally_resolve_hard_expectation(self, call_expr.span),
577577
) else {
578578
return;
579579
};

compiler/rustc_hir_typeck/src/closure.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5757
// It's always helpful for inference if we know the kind of
5858
// closure sooner rather than later, so first examine the expected
5959
// type, and see if can glean a closure kind from there.
60-
let (expected_sig, expected_kind) = match expected.to_option(self) {
61-
Some(ty) => self.deduce_closure_signature(
62-
self.try_structurally_resolve_type(expr_span, ty),
63-
closure.kind,
64-
),
60+
let (expected_sig, expected_kind) = match expected.structurally_resolve(self, expr_span) {
61+
Some(ty) => self.deduce_closure_signature(ty, closure.kind),
6562
None => (None, None),
6663
};
6764

compiler/rustc_hir_typeck/src/expectation.rs

+14-22
Original file line numberDiff line numberDiff line change
@@ -81,39 +81,31 @@ impl<'a, 'tcx> Expectation<'tcx> {
8181
}
8282
}
8383

84-
/// Resolves `expected` by a single level if it is a variable. If
85-
/// there is no expected type or resolution is not possible (e.g.,
86-
/// no constraints yet present), just returns `self`.
87-
fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
84+
pub(super) fn structurally_resolve(
85+
self,
86+
fcx: &FnCtxt<'a, 'tcx>,
87+
span: Span,
88+
) -> Option<Ty<'tcx>> {
8889
match self {
89-
NoExpectation => NoExpectation,
90-
ExpectCastableToType(t) => ExpectCastableToType(fcx.resolve_vars_if_possible(t)),
91-
ExpectHasType(t) => ExpectHasType(fcx.resolve_vars_if_possible(t)),
92-
ExpectRvalueLikeUnsized(t) => ExpectRvalueLikeUnsized(fcx.resolve_vars_if_possible(t)),
93-
}
94-
}
95-
96-
pub(super) fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
97-
match self.resolve(fcx) {
9890
NoExpectation => None,
99-
ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => Some(ty),
91+
ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => {
92+
Some(fcx.try_structurally_resolve_type(span, ty))
93+
}
10094
}
10195
}
10296

10397
/// It sometimes happens that we want to turn an expectation into
10498
/// a **hard constraint** (i.e., something that must be satisfied
10599
/// for the program to type-check). `only_has_type` will return
106100
/// such a constraint, if it exists.
107-
pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
101+
pub(super) fn structurally_resolve_hard_expectation(
102+
self,
103+
fcx: &FnCtxt<'a, 'tcx>,
104+
span: Span,
105+
) -> Option<Ty<'tcx>> {
108106
match self {
109-
ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)),
107+
ExpectHasType(ty) => Some(fcx.try_structurally_resolve_type(span, ty)),
110108
NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None,
111109
}
112110
}
113-
114-
/// Like `only_has_type`, but instead of returning `None` if no
115-
/// hard constraint exists, creates a fresh type variable.
116-
pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> {
117-
self.only_has_type(fcx).unwrap_or_else(|| fcx.next_ty_var(span))
118-
}
119111
}

compiler/rustc_hir_typeck/src/expr.rs

+45-37
Original file line numberDiff line numberDiff line change
@@ -624,21 +624,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
624624
expected: Expectation<'tcx>,
625625
expr: &'tcx hir::Expr<'tcx>,
626626
) -> Ty<'tcx> {
627-
let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
628-
match ty.kind() {
629-
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
630-
if oprnd.is_syntactic_place_expr() {
631-
// Places may legitimately have unsized types.
632-
// For example, dereferences of a wide pointer and
633-
// the last field of a struct can be unsized.
634-
ExpectHasType(*ty)
635-
} else {
636-
Expectation::rvalue_hint(self, *ty)
627+
let hint = expected.structurally_resolve_hard_expectation(self, expr.span).map_or(
628+
NoExpectation,
629+
|ty| {
630+
match ty.kind() {
631+
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
632+
if oprnd.is_syntactic_place_expr() {
633+
// Places may legitimately have unsized types.
634+
// For example, dereferences of a wide pointer and
635+
// the last field of a struct can be unsized.
636+
ExpectHasType(*ty)
637+
} else {
638+
Expectation::rvalue_hint(self, *ty)
639+
}
637640
}
641+
_ => NoExpectation,
638642
}
639-
_ => NoExpectation,
640-
}
641-
});
643+
},
644+
);
642645
let ty =
643646
self.check_expr_with_expectation_and_needs(oprnd, hint, Needs::maybe_mut_place(mutbl));
644647

@@ -1301,7 +1304,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13011304
// `expected` if it represents a *hard* constraint
13021305
// (`only_has_type`); otherwise, we just go with a
13031306
// fresh type variable.
1304-
let coerce_to_ty = expected.coercion_target_type(self, sp);
1307+
let coerce_to_ty = expected
1308+
.structurally_resolve_hard_expectation(self, sp)
1309+
.unwrap_or_else(|| self.next_ty_var(sp));
13051310
let mut coerce: DynamicCoerceMany<'_> = CoerceMany::new(coerce_to_ty);
13061311

13071312
coerce.coerce(self, &self.misc(sp), then_expr, then_ty);
@@ -1311,7 +1316,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13111316
let else_diverges = self.diverges.get();
13121317

13131318
let tail_defines_return_position_impl_trait =
1314-
self.return_position_impl_trait_from_match_expectation(orig_expected);
1319+
self.return_position_impl_trait_from_match_expectation(orig_expected, sp);
13151320
let if_cause = self.if_cause(
13161321
sp,
13171322
cond_expr.span,
@@ -1351,8 +1356,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13511356
rhs: &'tcx hir::Expr<'tcx>,
13521357
span: Span,
13531358
) -> Ty<'tcx> {
1354-
let expected_ty = expected.coercion_target_type(self, expr.span);
1355-
if expected_ty == self.tcx.types.bool {
1359+
let expected_ty = expected.structurally_resolve_hard_expectation(self, expr.span);
1360+
if expected_ty == Some(self.tcx.types.bool) {
13561361
let guar = self.expr_assign_expected_bool_error(expr, lhs, rhs, span);
13571362
return Ty::new_error(self.tcx, guar);
13581363
}
@@ -1518,7 +1523,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15181523
let coerce = match source {
15191524
// you can only use break with a value from a normal `loop { }`
15201525
hir::LoopSource::Loop => {
1521-
let coerce_to = expected.coercion_target_type(self, body.span);
1526+
let coerce_to = expected
1527+
.structurally_resolve_hard_expectation(self, body.span)
1528+
.unwrap_or_else(|| self.next_ty_var(body.span));
15221529
Some(CoerceMany::new(coerce_to))
15231530
}
15241531

@@ -1635,7 +1642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16351642
) -> Ty<'tcx> {
16361643
let element_ty = if !args.is_empty() {
16371644
let coerce_to = expected
1638-
.to_option(self)
1645+
.structurally_resolve(self, expr.span)
16391646
.and_then(|uty| match *uty.kind() {
16401647
ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
16411648
_ => None,
@@ -1820,13 +1827,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18201827
expected: Expectation<'tcx>,
18211828
expr: &'tcx hir::Expr<'tcx>,
18221829
) -> Ty<'tcx> {
1823-
let flds = expected.only_has_type(self).and_then(|ty| {
1824-
let ty = self.try_structurally_resolve_type(expr.span, ty);
1825-
match ty.kind() {
1830+
let flds =
1831+
expected.structurally_resolve_hard_expectation(self, expr.span).and_then(|ty| match ty
1832+
.kind()
1833+
{
18261834
ty::Tuple(flds) => Some(&flds[..]),
18271835
_ => None,
1828-
}
1829-
});
1836+
});
18301837

18311838
let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds {
18321839
Some(fs) if i < fs.len() => {
@@ -1900,17 +1907,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19001907
let tcx = self.tcx;
19011908

19021909
let adt_ty = self.try_structurally_resolve_type(span, adt_ty);
1903-
let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {
1904-
self.fudge_inference_if_ok(|| {
1905-
let ocx = ObligationCtxt::new(self);
1906-
ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?;
1907-
if !ocx.select_where_possible().is_empty() {
1908-
return Err(TypeError::Mismatch);
1909-
}
1910-
Ok(self.resolve_vars_if_possible(adt_ty))
1911-
})
1912-
.ok()
1913-
});
1910+
let adt_ty_hint =
1911+
expected.structurally_resolve_hard_expectation(self, expr.span).and_then(|expected| {
1912+
self.fudge_inference_if_ok(|| {
1913+
let ocx = ObligationCtxt::new(self);
1914+
ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?;
1915+
if !ocx.select_where_possible().is_empty() {
1916+
return Err(TypeError::Mismatch);
1917+
}
1918+
Ok(self.resolve_vars_if_possible(adt_ty))
1919+
})
1920+
.ok()
1921+
});
19141922
if let Some(adt_ty_hint) = adt_ty_hint {
19151923
// re-link the variables that the fudging above can create.
19161924
self.demand_eqtype(span, adt_ty_hint, adt_ty);
@@ -2678,7 +2686,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26782686
base_ty,
26792687
field,
26802688
did,
2681-
expected.only_has_type(self),
2689+
expected.structurally_resolve_hard_expectation(self, expr.span),
26822690
);
26832691
return Ty::new_error(self.tcx(), guar);
26842692
}
@@ -2689,7 +2697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26892697
field,
26902698
base_ty,
26912699
expr.hir_id,
2692-
expected.only_has_type(self),
2700+
expected.structurally_resolve_hard_expectation(self, expr.span),
26932701
) {
26942702
self.ban_take_value_of_method(expr, base_ty, field)
26952703
} else if !base_ty.is_primitive_ty() {

0 commit comments

Comments
 (0)