Skip to content

Commit 79699cf

Browse files
authored
Merge pull request #171 from scala/backport-lts-3.3-22104
Backport "Do not return java outline dummy constructor in `primaryConstructor`" to 3.3 LTS
2 parents e76d3fe + 137aec3 commit 79699cf

File tree

9 files changed

+62
-1
lines changed

9 files changed

+62
-1
lines changed

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2740,7 +2740,26 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
27402740
self.typeRef.info.decls.toList
27412741

27422742
def paramSymss: List[List[Symbol]] = self.denot.paramSymss
2743-
def primaryConstructor: Symbol = self.denot.primaryConstructor
2743+
def primaryConstructor: Symbol =
2744+
val initialPrimary = self.denot.primaryConstructor
2745+
// Java outline parser creates a dummyConstructor. We want to avoid returning it here,
2746+
// instead returning the first non-dummy one, which is what happens when a java classfile
2747+
// is read from classpath instead of using the java outline parser.
2748+
// We check if the constructor is dummy if it has the same parameters as defined in JavaParsers.scala,
2749+
// incliding the private[this] flags and parameter shape with scala.Unit argument.
2750+
val isJavaDummyConstructor =
2751+
val paramSymss = initialPrimary.paramSymss
2752+
initialPrimary.flags.is(Flags.JavaDefined | Flags.Local | Flags.Method | Flags.Private | Flags.PrivateLocal)
2753+
&& {
2754+
paramSymss match
2755+
case List(List(typeTree)) if self.typeRef.memberType(typeTree).typeSymbol == defn.UnitClass => true
2756+
case _ => false
2757+
}
2758+
if isJavaDummyConstructor then
2759+
declarations.filter(sym => sym != initialPrimary && sym.isConstructor).headOption.getOrElse(Symbol.noSymbol)
2760+
else
2761+
initialPrimary
2762+
27442763
def allOverriddenSymbols: Iterator[Symbol] = self.denot.allOverriddenSymbols
27452764
def overridingSymbol(ofclazz: Symbol): Symbol =
27462765
if ofclazz.isClass then self.denot.overridingSymbol(ofclazz.asClass)

tests/run-macros/i20052.check

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
method <init> (Flags.JavaDefined | Flags.Method) List(List((x$0,scala.Int)))
2+
method <init> (Flags.JavaDefined | Flags.Method) List(List())
3+
method <init> (Flags.JavaDefined | Flags.Method | Flags.Private) List(List())
4+
method <init> (Flags.JavaDefined | Flags.Method | Flags.Private) List(List())
5+
method <init> (Flags.JavaDefined | Flags.Method) List(List((A,_ >: scala.Nothing <: <special-ops>.<FromJavaObject>)), List((x$0,A)))
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class JavaClass {
2+
public JavaClass(int a) {}
3+
public JavaClass(float a) {}
4+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public class JavaClassEmpty {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public class JavaClassParam<A> {
2+
public JavaClassParam(A a) {}
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class JavaClassPrivate {
2+
private JavaClassPrivate() {}
3+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class JavaClassStartsWithPrivate {
2+
private JavaClassStartsWithPrivate() {}
3+
public JavaClassStartsWithPrivate(int a) {}
4+
}

tests/run-macros/i20052/Macro.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import scala.quoted.*
2+
3+
object Macro {
4+
inline def logPrimaryConstructor[A]: String = ${ logPrimaryConstructorImpl[A] }
5+
6+
def logPrimaryConstructorImpl[A](using Type[A], Quotes): Expr[String] = {
7+
import quotes.reflect.*
8+
9+
val primaryConstructor = TypeRepr.of[A].typeSymbol.primaryConstructor
10+
val flags = primaryConstructor.flags.show
11+
val paramSymss = primaryConstructor.paramSymss
12+
val clauses = paramSymss.map(_.map(param => (param.name, TypeRepr.of[A].memberType(param).show)))
13+
val str = s"${primaryConstructor} (${primaryConstructor.flags.show}) ${clauses}"
14+
Expr(str)
15+
}
16+
}

tests/run-macros/i20052/Test_2.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@main def Test() =
2+
println(Macro.logPrimaryConstructor[JavaClass])
3+
println(Macro.logPrimaryConstructor[JavaClassEmpty])
4+
println(Macro.logPrimaryConstructor[JavaClassPrivate])
5+
println(Macro.logPrimaryConstructor[JavaClassStartsWithPrivate])
6+
println(Macro.logPrimaryConstructor[JavaClassParam[Int]])

0 commit comments

Comments
 (0)