diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index c8162fcca948..d3c0eeab73d9 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -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 */ diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index 74891fccd985..c04b5f1d2d85 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 1eb6c47bce4a..8fba8b59ba8f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -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) diff --git a/tests/explicit-nulls/pos/i13197.scala b/tests/explicit-nulls/pos/i13197.scala new file mode 100644 index 000000000000..85835f9850c5 --- /dev/null +++ b/tests/explicit-nulls/pos/i13197.scala @@ -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) \ No newline at end of file diff --git a/tests/pos/i13197.scala b/tests/pos/i13197.scala new file mode 100644 index 000000000000..cf8b2bb3ef0d --- /dev/null +++ b/tests/pos/i13197.scala @@ -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) \ No newline at end of file