diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index e50fb9d8b09c..fcb20ea920e9 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -495,6 +495,18 @@ object TreeChecker { assert(tree.qual.typeOpt.isInstanceOf[ThisType], i"expect prefix of Super to be This, actual = ${tree.qual}") super.typedSuper(tree, pt) + override def typedNew(tree: untpd.New, pt: Type)(using Context): Tree = + val tree1 = super.typedNew(tree, pt).asInstanceOf[tpd.New] + val sym = tree1.tpe.typeSymbol + if postTyperPhase <= ctx.phase then // postTyper checks that `New` nodes can be instantiated + assert(!tree1.tpe.isInstanceOf[TermRef], s"New should not have a TermRef type: ${tree1.tpe}") + assert( + !sym.is(Module) + || ctx.erasedTypes // TODO add check for module initialization after erasure (LazyVals transformation) + || ctx.owner == sym.companionModule, + i"new of $sym module should only exist in ${sym.companionModule} but was in ${ctx.owner}") + tree1 + override def typedApply(tree: untpd.Apply, pt: Type)(using Context): Tree = tree match case Apply(Select(qual, nme.CONSTRUCTOR), _) if !ctx.phase.erasedTypes diff --git a/tests/neg-macros/i17545a/Macro_1.scala b/tests/neg-macros/i17545a/Macro_1.scala new file mode 100644 index 000000000000..29127f7aa97e --- /dev/null +++ b/tests/neg-macros/i17545a/Macro_1.scala @@ -0,0 +1,11 @@ +import scala.quoted.* + +object InvokeConstructor { + inline def apply[A] = ${ constructorMacro[A] } + + def constructorMacro[A: Type](using Quotes) = { + import quotes.reflect.* + val tpe = TypeRepr.of[A] + New(Inferred(tpe)).select(tpe.typeSymbol.primaryConstructor).appliedToArgs(Nil).asExprOf[A] + } +} diff --git a/tests/neg-macros/i17545a/Test_2.scala b/tests/neg-macros/i17545a/Test_2.scala new file mode 100644 index 000000000000..82d4ab4dcfdd --- /dev/null +++ b/tests/neg-macros/i17545a/Test_2.scala @@ -0,0 +1,4 @@ +case object WhateverA + +def testA = + val whateverA: WhateverA.type = InvokeConstructor[WhateverA.type] // error diff --git a/tests/neg-macros/i17545b/Macro_1.scala b/tests/neg-macros/i17545b/Macro_1.scala new file mode 100644 index 000000000000..29127f7aa97e --- /dev/null +++ b/tests/neg-macros/i17545b/Macro_1.scala @@ -0,0 +1,11 @@ +import scala.quoted.* + +object InvokeConstructor { + inline def apply[A] = ${ constructorMacro[A] } + + def constructorMacro[A: Type](using Quotes) = { + import quotes.reflect.* + val tpe = TypeRepr.of[A] + New(Inferred(tpe)).select(tpe.typeSymbol.primaryConstructor).appliedToArgs(Nil).asExprOf[A] + } +} diff --git a/tests/neg-macros/i17545b/Test_2.scala b/tests/neg-macros/i17545b/Test_2.scala new file mode 100644 index 000000000000..6cad2cf16e5c --- /dev/null +++ b/tests/neg-macros/i17545b/Test_2.scala @@ -0,0 +1,3 @@ +def testB = + case object WhateverB + val whateverB: WhateverB.type = InvokeConstructor[WhateverB.type] // error diff --git a/tests/neg-macros/i17545c/Macro_1.scala b/tests/neg-macros/i17545c/Macro_1.scala new file mode 100644 index 000000000000..17e297497524 --- /dev/null +++ b/tests/neg-macros/i17545c/Macro_1.scala @@ -0,0 +1,11 @@ +import scala.quoted.* + +object InvokeConstructor { + inline def apply[A] = ${ constructorMacro[A] } + + def constructorMacro[A: Type](using Quotes) = { + import quotes.reflect.* + val tpe = TypeRepr.of[A].termSymbol.moduleClass.typeRef + New(Inferred(tpe)).select(tpe.typeSymbol.primaryConstructor).appliedToArgs(Nil).asExprOf[A] + } +} diff --git a/tests/neg-macros/i17545c/Test_2.scala b/tests/neg-macros/i17545c/Test_2.scala new file mode 100644 index 000000000000..82d4ab4dcfdd --- /dev/null +++ b/tests/neg-macros/i17545c/Test_2.scala @@ -0,0 +1,4 @@ +case object WhateverA + +def testA = + val whateverA: WhateverA.type = InvokeConstructor[WhateverA.type] // error diff --git a/tests/neg-macros/i17545d/Macro_1.scala b/tests/neg-macros/i17545d/Macro_1.scala new file mode 100644 index 000000000000..17e297497524 --- /dev/null +++ b/tests/neg-macros/i17545d/Macro_1.scala @@ -0,0 +1,11 @@ +import scala.quoted.* + +object InvokeConstructor { + inline def apply[A] = ${ constructorMacro[A] } + + def constructorMacro[A: Type](using Quotes) = { + import quotes.reflect.* + val tpe = TypeRepr.of[A].termSymbol.moduleClass.typeRef + New(Inferred(tpe)).select(tpe.typeSymbol.primaryConstructor).appliedToArgs(Nil).asExprOf[A] + } +} diff --git a/tests/neg-macros/i17545d/Test_2.scala b/tests/neg-macros/i17545d/Test_2.scala new file mode 100644 index 000000000000..6cad2cf16e5c --- /dev/null +++ b/tests/neg-macros/i17545d/Test_2.scala @@ -0,0 +1,3 @@ +def testB = + case object WhateverB + val whateverB: WhateverB.type = InvokeConstructor[WhateverB.type] // error