Skip to content

Commit

Permalink
Merge pull request #10715 from som-snytt/backport/19386-record
Browse files Browse the repository at this point in the history
Record accessor is nilary not nullary [ci: last-only]
  • Loading branch information
SethTisue committed Mar 16, 2024
2 parents 6b1b9d7 + bda67fd commit c2333de
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 11 deletions.
17 changes: 6 additions & 11 deletions src/compiler/scala/tools/nsc/javac/JavaParsers.scala
Expand Up @@ -871,17 +871,12 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
val interfaces = interfacesOpt()
val (statics, body) = typeBody(RECORD)

// Generate accessors, if not already manually specified
var generateAccessors = header
.view
.map { case ValDef(mods, name, tpt, _) => (name, (tpt, mods.annotations)) }
.toMap
for (DefDef(_, name, List(), List(params), _, _) <- body if generateAccessors.contains(name) && params.isEmpty)
generateAccessors -= name

val accessors = generateAccessors
.map { case (name, (tpt, annots)) =>
DefDef(Modifiers(Flags.JAVA) withAnnotations annots, name, List(), List(), tpt.duplicate, blankExpr)
// Generate accessors, if not already explicitly specified. Record bodies tend to be trivial.
val existing = body.iterator.collect { case DefDef(_, name, Nil, ListOfNil, _, _) => name }.toSet
val accessors = header.iterator
.collect {
case ValDef(mods, name, tpt, _) if !existing(name) =>
DefDef(Modifiers(Flags.JAVA).withAnnotations(mods.annotations), name, tparams = Nil, vparamss = ListOfNil, tpt.duplicate, blankExpr)
}
.toList

Expand Down
16 changes: 16 additions & 0 deletions test/files/pos/t11908/C.scala
@@ -1,13 +1,18 @@
// javaVersion: 16+
object C {

def useR0: Unit = {
val r0 = new R0
}

def useR1 = {
// constructor signature
val r1 = new R1(123, "hello")

// accessors signature
val i: Int = r1.i
val s: String = r1.s
val j: Int = r1.i()

// method
val s2: String = r1.someMethod()
Expand Down Expand Up @@ -46,10 +51,21 @@ object C {
val l: Long = r3.l
val s: String = r3.s

locally {
val i: Int = r3.i()
val l: Long = r3.l()
val s: String = r3.s()
}

// method
val l2: Long = r3.l(43L, 44L)

// supertype
val isRecord: java.lang.Record = r3
}

def useR4: Unit = {
val r4 = new R4(42)
val n: Int = r4.t
}
}
4 changes: 4 additions & 0 deletions test/files/pos/t11908/R1.java
Expand Up @@ -5,3 +5,7 @@ public String someMethod() {
return s + "!";
}
}

record R0() {}

record R4<T>(T t) {}
71 changes: 71 additions & 0 deletions test/files/pos/t11908b/C_2.scala
@@ -0,0 +1,71 @@
// javaVersion: 16+
object C {

def useR0: Unit = {
val r0 = new R0
}

def useR1 = {
// constructor signature
val r1 = new R1(123, "hello")

// accessors signature
val i: Int = r1.i
val s: String = r1.s
val j: Int = r1.i()

// method
val s2: String = r1.someMethod()

// supertype
val isRecord: java.lang.Record = r1

()
}

def useR2 = {
// constructor signature
val r2 = new R2.R(123, "hello")

// accessors signature
val i: Int = r2.i
val s: String = r2.s

// method
val i2: Int = r2.getInt

// supertype
val isIntLike: IntLike = r2
val isRecord: java.lang.Record = r2

()
}

def useR3 = {
// constructor signature
val r3 = new R3(123, 42L, "hi")
new R3("hi", 123)

// accessors signature
val i: Int = r3.i
val l: Long = r3.l
val s: String = r3.s

locally {
val i: Int = r3.i()
val l: Long = r3.l()
val s: String = r3.s()
}

// method
val l2: Long = r3.l(43L, 44L)

// supertype
val isRecord: java.lang.Record = r3
}

def useR4: Unit = {
val r4 = new R4(42)
val n: Int = r4.t
}
}
4 changes: 4 additions & 0 deletions test/files/pos/t11908b/IntLike.scala
@@ -0,0 +1,4 @@
// javaVersion: 16+
trait IntLike {
def getInt: Int
}
11 changes: 11 additions & 0 deletions test/files/pos/t11908b/R1.java
@@ -0,0 +1,11 @@
// javaVersion: 16+
record R1(int i, String s) {

public String someMethod() {
return s + "!";
}
}

record R0() {}

record R4<T>(T t) {}
14 changes: 14 additions & 0 deletions test/files/pos/t11908b/R2.java
@@ -0,0 +1,14 @@
// javaVersion: 16+
public class R2 {
final record R(int i, String s) implements IntLike {
public int getInt() {
return i;
}

// Canonical constructor
public R(int i, java.lang.String s) {
this.i = i;
this.s = s.intern();
}
}
}
23 changes: 23 additions & 0 deletions test/files/pos/t11908b/R3.java
@@ -0,0 +1,23 @@
// javaVersion: 16+
public record R3(int i, long l, String s) {

// User-specified accessor
public int i() {
return i + 1; // evil >:)
}

// Not an accessor - too many parameters
public long l(long a1, long a2) {
return a1 + a2;
}

// Secondary constructor
public R3(String s, int i) {
this(i, 42L, s);
}

// Compact constructor
public R3 {
s = s.intern();
}
}

0 comments on commit c2333de

Please sign in to comment.