Skip to content

Commit 2e19304

Browse files
Check New tree for ill-formed module instantiations (#17553)
Fixes #17545
2 parents acb3dba + 61190e6 commit 2e19304

File tree

9 files changed

+70
-0
lines changed

9 files changed

+70
-0
lines changed

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,18 @@ object TreeChecker {
495495
assert(tree.qual.typeOpt.isInstanceOf[ThisType], i"expect prefix of Super to be This, actual = ${tree.qual}")
496496
super.typedSuper(tree, pt)
497497

498+
override def typedNew(tree: untpd.New, pt: Type)(using Context): Tree =
499+
val tree1 = super.typedNew(tree, pt).asInstanceOf[tpd.New]
500+
val sym = tree1.tpe.typeSymbol
501+
if postTyperPhase <= ctx.phase then // postTyper checks that `New` nodes can be instantiated
502+
assert(!tree1.tpe.isInstanceOf[TermRef], s"New should not have a TermRef type: ${tree1.tpe}")
503+
assert(
504+
!sym.is(Module)
505+
|| ctx.erasedTypes // TODO add check for module initialization after erasure (LazyVals transformation)
506+
|| ctx.owner == sym.companionModule,
507+
i"new of $sym module should only exist in ${sym.companionModule} but was in ${ctx.owner}")
508+
tree1
509+
498510
override def typedApply(tree: untpd.Apply, pt: Type)(using Context): Tree = tree match
499511
case Apply(Select(qual, nme.CONSTRUCTOR), _)
500512
if !ctx.phase.erasedTypes
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted.*
2+
3+
object InvokeConstructor {
4+
inline def apply[A] = ${ constructorMacro[A] }
5+
6+
def constructorMacro[A: Type](using Quotes) = {
7+
import quotes.reflect.*
8+
val tpe = TypeRepr.of[A]
9+
New(Inferred(tpe)).select(tpe.typeSymbol.primaryConstructor).appliedToArgs(Nil).asExprOf[A]
10+
}
11+
}

tests/neg-macros/i17545a/Test_2.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
case object WhateverA
2+
3+
def testA =
4+
val whateverA: WhateverA.type = InvokeConstructor[WhateverA.type] // error
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted.*
2+
3+
object InvokeConstructor {
4+
inline def apply[A] = ${ constructorMacro[A] }
5+
6+
def constructorMacro[A: Type](using Quotes) = {
7+
import quotes.reflect.*
8+
val tpe = TypeRepr.of[A]
9+
New(Inferred(tpe)).select(tpe.typeSymbol.primaryConstructor).appliedToArgs(Nil).asExprOf[A]
10+
}
11+
}

tests/neg-macros/i17545b/Test_2.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def testB =
2+
case object WhateverB
3+
val whateverB: WhateverB.type = InvokeConstructor[WhateverB.type] // error
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted.*
2+
3+
object InvokeConstructor {
4+
inline def apply[A] = ${ constructorMacro[A] }
5+
6+
def constructorMacro[A: Type](using Quotes) = {
7+
import quotes.reflect.*
8+
val tpe = TypeRepr.of[A].termSymbol.moduleClass.typeRef
9+
New(Inferred(tpe)).select(tpe.typeSymbol.primaryConstructor).appliedToArgs(Nil).asExprOf[A]
10+
}
11+
}

tests/neg-macros/i17545c/Test_2.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
case object WhateverA
2+
3+
def testA =
4+
val whateverA: WhateverA.type = InvokeConstructor[WhateverA.type] // error
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted.*
2+
3+
object InvokeConstructor {
4+
inline def apply[A] = ${ constructorMacro[A] }
5+
6+
def constructorMacro[A: Type](using Quotes) = {
7+
import quotes.reflect.*
8+
val tpe = TypeRepr.of[A].termSymbol.moduleClass.typeRef
9+
New(Inferred(tpe)).select(tpe.typeSymbol.primaryConstructor).appliedToArgs(Nil).asExprOf[A]
10+
}
11+
}

tests/neg-macros/i17545d/Test_2.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def testB =
2+
case object WhateverB
3+
val whateverB: WhateverB.type = InvokeConstructor[WhateverB.type] // error

0 commit comments

Comments
 (0)