Skip to content

Commit

Permalink
Fix #8861: Replace type variables by wildcards in closure results
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
odersky committed May 6, 2020
1 parent c4c1f65 commit 5ec4773
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 3 deletions.
9 changes: 8 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1496,7 +1496,14 @@ class Namer { typer: Typer =>
case TypedSplice(tpt: TypeTree) if !isFullyDefined(tpt.tpe, ForceDegree.none) =>
mdef match {
case mdef: DefDef if mdef.name == nme.ANON_FUN =>
val rhsType = typedAheadExpr(mdef.rhs, tpt.tpe).tpe
// Need to constrain the type varianbes in the handed-down expected
// result type with the actual result type of the closure body.
// Two steps:
// 1. Type closure body with the wildcard approximation of the expected result type.
// wildApprox is needed since otherwise type variables in the expected result type
// might get polluted constraints referring to local parameters. See run/i8861.scala.
// 2. Constrain the expected result type from below with the actual result type.
val rhsType = typedAheadExpr(mdef.rhs, wildApprox(tpt.tpe)).tpe
val hygienicType = avoid(rhsType, paramss.flatten)
if (!hygienicType.isValueType || !(hygienicType <:< tpt.tpe))
ctx.error(i"return type ${tpt.tpe} of lambda cannot be made hygienic;\n" +
Expand Down
4 changes: 2 additions & 2 deletions tests/neg/i6565.scala → tests/pos/i6565.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ lazy val ok: Lifted[String] = { // ok despite map returning a union
point("a").map(_ => if true then "foo" else error) // ok
}

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

0 comments on commit 5ec4773

Please sign in to comment.