Skip to content

Fix #13197: Deskolemize lifted named arguments #13590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,17 @@ object Types {
/** Like `dealiasKeepAnnots`, but keeps only refining annotations */
final def dealiasKeepRefiningAnnots(using Context): Type = dealias1(keepIfRefining)

/** Approximate this type with a type that does not contain skolem types. */
final def deskolemized(using Context): Type =
val deskolemizer = new ApproximatingTypeMap {
def apply(tp: Type) = /*trace(i"deskolemize($tp) at $variance", show = true)*/
tp match {
case tp: SkolemType => range(defn.NothingType, atVariance(1)(apply(tp.info)))
case _ => mapOver(tp)
}
}
deskolemizer(this)

/** The result of normalization using `tryNormalize`, or the type itself if
* tryNormlize yields NoType
*/
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ abstract class Lifter {
else {
val name = UniqueName.fresh(prefix)
// don't instantiate here, as the type params could be further constrained, see tests/pos/pickleinf.scala
var liftedType = expr.tpe.widen
var liftedType = expr.tpe.widen.deskolemized
if (liftedFlags.is(Method)) liftedType = ExprType(liftedType)
val lifted = newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = spanCoord(expr.span))
defs += liftedDef(lifted, expr)
Expand Down
11 changes: 1 addition & 10 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1704,16 +1704,7 @@ class Namer { typer: Typer =>
// it would be erased to BoxedUnit.
def dealiasIfUnit(tp: Type) = if (tp.isRef(defn.UnitClass)) defn.UnitType else tp

// Approximate a type `tp` with a type that does not contain skolem types.
val deskolemize = new ApproximatingTypeMap {
def apply(tp: Type) = /*trace(i"deskolemize($tp) at $variance", show = true)*/
tp match {
case tp: SkolemType => range(defn.NothingType, atVariance(1)(apply(tp.info)))
case _ => mapOver(tp)
}
}

def cookedRhsType = deskolemize(dealiasIfUnit(rhsType))
def cookedRhsType = dealiasIfUnit(rhsType).deskolemized
def lhsType = fullyDefinedType(cookedRhsType, "right-hand side", mdef.span)
//if (sym.name.toString == "y") println(i"rhs = $rhsType, cooked = $cookedRhsType")
if (inherited.exists)
Expand Down
7 changes: 7 additions & 0 deletions tests/explicit-nulls/pos/i13197.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
trait Bar:
def b: String | Null

class Foo(a: String = "", b: String)

object Foo:
def foo(bar: Bar) = Foo(b = bar.b.nn)
12 changes: 12 additions & 0 deletions tests/pos/i13197.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// this test is similar to explicit-nulls/pos/i13197.scala, but without explicit nulls

extension [T](x: T | String) inline def forceString: x.type & String =
x.asInstanceOf

trait Bar:
def b: String | Int

class Foo(a: String = "", b: String)

object Foo:
def foo(bar: Bar) = Foo(b = bar.b.forceString)