Skip to content

Commit 5ec4773

Browse files
committed
Fix #8861: Replace type variables by wildcards in closure results
When passing down an expected result type for typing a closure body, replace any type variables by wildcards. This is needed to avoid such type variables getting constraints that are polluted with local parameters.
1 parent c4c1f65 commit 5ec4773

File tree

4 files changed

+10
-3
lines changed

4 files changed

+10
-3
lines changed

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1496,7 +1496,14 @@ class Namer { typer: Typer =>
14961496
case TypedSplice(tpt: TypeTree) if !isFullyDefined(tpt.tpe, ForceDegree.none) =>
14971497
mdef match {
14981498
case mdef: DefDef if mdef.name == nme.ANON_FUN =>
1499-
val rhsType = typedAheadExpr(mdef.rhs, tpt.tpe).tpe
1499+
// Need to constrain the type varianbes in the handed-down expected
1500+
// result type with the actual result type of the closure body.
1501+
// Two steps:
1502+
// 1. Type closure body with the wildcard approximation of the expected result type.
1503+
// wildApprox is needed since otherwise type variables in the expected result type
1504+
// might get polluted constraints referring to local parameters. See run/i8861.scala.
1505+
// 2. Constrain the expected result type from below with the actual result type.
1506+
val rhsType = typedAheadExpr(mdef.rhs, wildApprox(tpt.tpe)).tpe
15001507
val hygienicType = avoid(rhsType, paramss.flatten)
15011508
if (!hygienicType.isValueType || !(hygienicType <:< tpt.tpe))
15021509
ctx.error(i"return type ${tpt.tpe} of lambda cannot be made hygienic;\n" +

tests/neg/i6565.scala renamed to tests/pos/i6565.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ lazy val ok: Lifted[String] = { // ok despite map returning a union
1212
point("a").map(_ => if true then "foo" else error) // ok
1313
}
1414

15-
lazy val bad: Lifted[String] = { // found Lifted[Object]
16-
point("a").flatMap(_ => point("b").map(_ => if true then "foo" else error)) // error
15+
lazy val nowAlsoOK: Lifted[String] = {
16+
point("a").flatMap(_ => point("b").map(_ => if true then "foo" else error)) // now also OK
1717
}

0 commit comments

Comments
 (0)