Skip to content

Commit d040505

Browse files
committed
doc: explain why expected_ty participates in the LUB of CoerceMany
1 parent 9d0fe04 commit d040505

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,7 @@ pub fn can_coerce<'tcx>(
13811381
/// - WARNING: I don't believe this final type is guaranteed to be
13821382
/// related to your initial `expected_ty` in any particular way,
13831383
/// although it will typically be a subtype, so you should check it.
1384+
/// Check the note below for more details.
13841385
/// - Invoking `complete()` may cause us to go and adjust the "adjustments" on
13851386
/// previously coerced expressions.
13861387
///
@@ -1394,6 +1395,28 @@ pub fn can_coerce<'tcx>(
13941395
/// }
13951396
/// let final_ty = coerce.complete(fcx);
13961397
/// ```
1398+
///
1399+
/// NOTE: Why does the `expected_ty` participate in the LUB?
1400+
/// When coercing, each branch should use the following expectations for type inference:
1401+
/// - The branch can be coerced to the expected type of the match/if/whatever.
1402+
/// - The branch can be coercion lub'd with the types of the previous branches.
1403+
/// Ideally we'd have some sort of `Expectation::ParticipatsInCoerceLub(ongoing_lub_ty, final_ty)`,
1404+
/// but adding and using this feels very challenging.
1405+
/// What we instead do is to use the expected type of the match/if/whatever as
1406+
/// the initial coercion lub. This allows us to use the lub of "expected type of match" with
1407+
/// "types from previous branches" as the coercion target, which can contains both expectations.
1408+
///
1409+
/// Two concerns with this approach:
1410+
/// - We may have incompatible `final_ty` if that lub is different from the expected
1411+
/// type of the match. However, in this case coercing the final type of the
1412+
/// `CoerceMany` to its expected type would have error'd anyways, so we don't care.
1413+
/// - We may constrain the `expected_ty` too early. For some branches with
1414+
/// type `a` and `b`, we end up with `(a lub expected_ty) lub b` instead of
1415+
/// `(a lub b) lub expected_ty`. They should be the same type. However,
1416+
/// `a lub expected_ty` may constrain inference variables in `expected_ty`.
1417+
/// In this case the difference does matter and we get actually incorrect results.
1418+
/// FIXME: Ideally we'd compute the final type without unnecessarily constraining
1419+
/// the expected type of the match when computing the types of its branches.
13971420
pub(crate) struct CoerceMany<'tcx, 'exprs, E: AsCoercionSite> {
13981421
expected_ty: Ty<'tcx>,
13991422
final_ty: Option<Ty<'tcx>>,

0 commit comments

Comments
 (0)