File tree 4 files changed +38
-0
lines changed
compiler/src/dotty/tools/dotc
4 files changed +38
-0
lines changed Original file line number Diff line number Diff line change @@ -369,6 +369,7 @@ object NameKinds {
369
369
val FieldName : SuffixNameKind = new SuffixNameKind (FIELD , " $$local" ) {
370
370
override def mkString (underlying : TermName , info : ThisInfo ) = underlying.toString
371
371
}
372
+ val ExplicitFieldName : SuffixNameKind = new SuffixNameKind (EXPLICITFIELD , " $field" )
372
373
val ExtMethName : SuffixNameKind = new SuffixNameKind (EXTMETH , " $extension" )
373
374
val ParamAccessorName : SuffixNameKind = new SuffixNameKind (PARAMACC , " $accessor" )
374
375
val ModuleClassName : SuffixNameKind = new SuffixNameKind (OBJECTCLASS , " $" , optInfoString = " ModuleClass" )
Original file line number Diff line number Diff line change @@ -37,6 +37,9 @@ object NameTags extends TastyFormat.NameTags {
37
37
final val AVOIDLOWER = 36
38
38
final val AVOIDBOTH = 37
39
39
40
+ inline val EXPLICITFIELD = 38 // An explicitly named field, introduce to avoid a clash
41
+ // with a regular field of the underlying name
42
+
40
43
def nameTagToString (tag : Int ): String = tag match {
41
44
case UTF8 => " UTF8"
42
45
case QUALIFIED => " QUALIFIED"
Original file line number Diff line number Diff line change @@ -9,7 +9,9 @@ import dotty.tools.dotc.core.StdNames._
9
9
import ast ._
10
10
import Trees ._
11
11
import Flags ._
12
+ import Names .Name
12
13
import NameOps ._
14
+ import NameKinds .{FieldName , ExplicitFieldName }
13
15
import SymUtils ._
14
16
import Symbols ._
15
17
import Decorators ._
@@ -249,7 +251,28 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase =
249
251
splitStats(stats1)
250
252
case Nil =>
251
253
}
254
+
255
+ /** Check that we do not have both a private field with name `x` and a private field
256
+ * with name `FieldName(x)`. These will map to the same JVM name and therefore cause
257
+ * a duplicate field error. If that case arises (as in i13862.scala), use an explicit
258
+ * name `x$field` instead of `FieldName(x).
259
+ */
260
+ def checkNoFieldClashes () =
261
+ val fieldNames = mutable.HashSet [Name ]()
262
+ for case field : ValDef <- clsStats do
263
+ field.symbol.name match
264
+ case FieldName (_) =>
265
+ case name => fieldNames += name
266
+ for case field : ValDef <- clsStats do
267
+ field.symbol.name match
268
+ case fldName @ FieldName (name) if fieldNames.contains(name) =>
269
+ val newName = ExplicitFieldName (name)
270
+ report.log(i " avoid field/field conflict by renaming $fldName to $newName" )
271
+ field.symbol.copySymDenotation(name = newName).installAfter(thisPhase)
272
+ case _ =>
273
+
252
274
splitStats(tree.body)
275
+ checkNoFieldClashes()
253
276
254
277
// The initializers for the retained accessors */
255
278
val copyParams = accessors flatMap { acc =>
Original file line number Diff line number Diff line change
1
+ trait Foo (val num : Int ) // a trait with a parameter stored in a val
2
+
3
+ class Bar (num : Int ) extends Foo (num): // an extending class with a parameter of the same name
4
+ def bar = this .num // implicitly creates another num in Bar
5
+
6
+ @ main def Test = Bar (123 )
7
+
8
+ class Bar2 (n : Int ) extends Foo (n): // an extending class with a parameter of the same name
9
+ private val num = n
10
+ def bar = this .num // implicitly creates another num in Bar
11
+
You can’t perform that action at this time.
0 commit comments