Skip to content

Commit d9a9952

Browse files
committed
Fix typing of new
Assume ``` class C[X] type A[X] = C[X] ``` The previous rule for `new A` overwrote the type of `A` with `C`, in order to satisfy the condition that the type of `new` should be a class type. Overwriting types like that in Typer is wrong, since it is not preserved by pickling. We tried to patch up things in RefinedPrinter, but this is not enough, as test case `alias-new.scala` shows. This test caused the type in a `new` to be unpickled as a <notype>. The fix is to treat eta-reduction in new types in a purely functional way, applied in both Typer and TypeAssigner. The problem was encountered when systematically testing creation methods, but it has nothing to do with them.
1 parent 3f06117 commit d9a9952

File tree

4 files changed

+22
-13
lines changed

4 files changed

+22
-13
lines changed

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
331331
if (tree.hasType && tree.symbol == defn.QuotedExpr_splice) keywordStr("${") ~ toTextLocal(qual) ~ keywordStr("}")
332332
else if (tree.hasType && tree.symbol == defn.QuotedType_splice) typeText("${") ~ toTextLocal(qual) ~ typeText("}")
333333
else if (qual.isType) toTextLocal(qual) ~ "#" ~ typeText(toText(name))
334-
else toTextLocal(qual) ~ ("." ~ nameIdText(tree) provided name != nme.CONSTRUCTOR)
334+
else toTextLocal(qual) ~ ("." ~ nameIdText(tree) provided name != nme.CONSTRUCTOR || ctx.settings.YprintDebug.value)
335335
case tree: This =>
336336
optDotPrefix(tree) ~ keywordStr("this") ~ idText(tree)
337337
case Super(qual: This, mix) =>
@@ -356,11 +356,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
356356
keywordStr("new ") ~ {
357357
tpt match {
358358
case tpt: Template => toTextTemplate(tpt, ofNew = true)
359-
case _ =>
360-
if (tpt.hasType)
361-
toTextLocal(tpt.typeOpt.underlyingClassRef(refinementOK = false))
362-
else
363-
toTextLocal(tpt)
359+
case _ => toTextLocal(tpt)
364360
}
365361
}
366362
case Typed(expr, tpt) =>

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,16 @@ trait TypeAssigner {
301301
ConstFold(tree.withType(tp))
302302
}
303303

304+
/** Normalize type T appearing in a new T by following eta expansions to
305+
* avoid higher-kinded types.
306+
*/
307+
def typeOfNew(tpt: Tree)(implicit ctx: Context): Type = tpt.tpe.dealias match {
308+
case TypeApplications.EtaExpansion(tycon) => tycon
309+
case t => tpt.tpe
310+
}
311+
304312
def assignType(tree: untpd.New, tpt: Tree)(implicit ctx: Context): New =
305-
tree.withType(tpt.tpe)
313+
tree.withType(typeOfNew(tpt))
306314

307315
def assignType(tree: untpd.Literal)(implicit ctx: Context): Literal =
308316
tree.withType {

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -533,11 +533,8 @@ class Typer extends Namer
533533
case _ =>
534534
var tpt1 = typedType(tree.tpt)
535535
tpt1 = tpt1.withType(ensureAccessible(tpt1.tpe, superAccess = false, tpt1.sourcePos))
536-
tpt1.tpe.dealias match {
537-
case TypeApplications.EtaExpansion(tycon) => tpt1 = tpt1.withType(tycon)
538-
case _ =>
539-
}
540-
if (checkClassType(tpt1.tpe, tpt1.sourcePos, traitReq = false, stablePrefixReq = true) eq defn.ObjectType)
536+
537+
if (checkClassType(typeOfNew(tpt1), tpt1.sourcePos, traitReq = false, stablePrefixReq = true) eq defn.ObjectType)
541538
tpt1 = TypeTree(defn.ObjectType).withSpan(tpt1.span)
542539

543540
tpt1 match {
@@ -548,7 +545,6 @@ class Typer extends Namer
548545
}
549546

550547
assignType(cpy.New(tree)(tpt1), tpt1)
551-
// todo in a later phase: checkInstantiatable(cls, tpt1.pos)
552548
}
553549
}
554550

tests/pos/alias-new.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object O {
2+
class B[T]
3+
}
4+
object O2 {
5+
type B[T] = O.B[T]
6+
}
7+
object Test {
8+
val x: O2.B[String] = new O2.B()
9+
}

0 commit comments

Comments
 (0)