Skip to content

Commit

Permalink
Always generate Record constructor, unlink later if a matching one ex…
Browse files Browse the repository at this point in the history
…ists
  • Loading branch information
lrytz committed Jun 28, 2021
1 parent 9c8db16 commit a7450e1
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 26 deletions.
34 changes: 11 additions & 23 deletions src/compiler/scala/tools/nsc/javac/JavaParsers.scala
Expand Up @@ -837,46 +837,34 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
val (statics, body) = typeBody(RECORD)

// Records generate a canonical constructor and accessors, unless they are manually specified
var generateCanonicalCtor = true
var generateAccessors = header
.view
.map { case ValDef(mods, name, tpt, _) => (name, (tpt, mods.annotations)) }
.toMap
for (DefDef(_, name, List(), List(params), _, _) <- body) {
if (name == nme.CONSTRUCTOR && params.size == header.size) {
val ctorParamsAreCanonical = params.lazyZip(header).forall {
case (ValDef(_, _, tpt1, _), ValDef(_, _, tpt2, _)) => tpt1 equalsStructure tpt2
case _ => false
}
if (ctorParamsAreCanonical) generateCanonicalCtor = false
} else if (generateAccessors.contains(name) && params.isEmpty) {
generateAccessors -= name
}
}
for (DefDef(_, name, List(), List(params), _, _) <- body if generateAccessors.contains(name) && params.isEmpty)
generateAccessors -= name

// Generate canonical constructor and accessors, if not already manually specified
val accessors = generateAccessors
.map { case (name, (tpt, annots)) =>
DefDef(Modifiers(Flags.JAVA) withAnnotations annots, name, List(), List(), tpt.duplicate, blankExpr)
}
.toList
val canonicalCtor = Option.when(generateCanonicalCtor) {
DefDef(
mods,
nme.CONSTRUCTOR,
List(),
List(header.map(_.duplicate)),
TypeTree(),
blankExpr
)
}
val canonicalCtor = DefDef(
mods | Flags.SYNTHETIC,
nme.CONSTRUCTOR,
List(),
List(header.map(_.duplicate)),
TypeTree(),
blankExpr
)

addCompanionObject(statics, atPos(pos) {
ClassDef(
mods | Flags.FINAL,
name,
tparams,
makeTemplate(superclass :: interfaces, canonicalCtor.toList ++ accessors ++ body)
makeTemplate(superclass :: interfaces, canonicalCtor :: accessors ::: body)
)
})
}
Expand Down
8 changes: 7 additions & 1 deletion src/compiler/scala/tools/nsc/typechecker/Namers.scala
Expand Up @@ -1487,7 +1487,13 @@ trait Namers extends MethodSynthesis {
}

val methSig = deskolemizedPolySig(vparamSymssOrEmptyParamsFromOverride, resTp)
pluginsTypeSig(methSig, typer, ddef, resTpGiven)
val unlink = methOwner.superClass == JavaRecordClass && meth.isConstructor && meth.isSynthetic &&
methOwner.info.decl(meth.name).alternatives.exists(c => c != meth && c.tpe.matches(methSig))
if (unlink) {
methOwner.info.decls.unlink(meth)
ErrorType
} else
pluginsTypeSig(methSig, typer, ddef, resTpGiven)
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/reflect/scala/reflect/internal/Definitions.scala
Expand Up @@ -411,6 +411,7 @@ trait Definitions extends api.StandardDefinitions {
lazy val JavaEnumClass = requiredClass[java.lang.Enum[_]]
lazy val JavaUtilMap = requiredClass[java.util.Map[_, _]]
lazy val JavaUtilHashMap = requiredClass[java.util.HashMap[_, _]]
lazy val JavaRecordClass = getClassIfDefined("java.lang.Record")

lazy val ByNameParamClass = specialPolyClass(tpnme.BYNAME_PARAM_CLASS_NAME, COVARIANT)(_ => AnyTpe)
lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.tpe))
Expand Down
4 changes: 2 additions & 2 deletions test/files/pos/t11908/R2.java
Expand Up @@ -6,9 +6,9 @@ public int getInt() {
}

// Canonical constructor
public R(int i, String s) {
public R(int i, java.lang.String s) {
this.i = i;
this.s = s.intern();
}
}
}
}

0 comments on commit a7450e1

Please sign in to comment.