File tree Expand file tree Collapse file tree 4 files changed +38
-0
lines changed
compiler/src/dotty/tools/dotc Expand file tree Collapse file tree 4 files changed +38
-0
lines changed Original file line number Diff line number Diff line change @@ -369,6 +369,7 @@ object NameKinds {
369369 val FieldName : SuffixNameKind = new SuffixNameKind (FIELD , " $$local" ) {
370370 override def mkString (underlying : TermName , info : ThisInfo ) = underlying.toString
371371 }
372+ val ExplicitFieldName : SuffixNameKind = new SuffixNameKind (EXPLICITFIELD , " $field" )
372373 val ExtMethName : SuffixNameKind = new SuffixNameKind (EXTMETH , " $extension" )
373374 val ParamAccessorName : SuffixNameKind = new SuffixNameKind (PARAMACC , " $accessor" )
374375 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 {
3737 final val AVOIDLOWER = 36
3838 final val AVOIDBOTH = 37
3939
40+ inline val EXPLICITFIELD = 38 // An explicitly named field, introduce to avoid a clash
41+ // with a regular field of the underlying name
42+
4043 def nameTagToString (tag : Int ): String = tag match {
4144 case UTF8 => " UTF8"
4245 case QUALIFIED => " QUALIFIED"
Original file line number Diff line number Diff line change @@ -9,7 +9,9 @@ import dotty.tools.dotc.core.StdNames._
99import ast ._
1010import Trees ._
1111import Flags ._
12+ import Names .Name
1213import NameOps ._
14+ import NameKinds .{FieldName , ExplicitFieldName }
1315import SymUtils ._
1416import Symbols ._
1517import Decorators ._
@@ -249,7 +251,28 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase =
249251 splitStats(stats1)
250252 case Nil =>
251253 }
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+
252274 splitStats(tree.body)
275+ checkNoFieldClashes()
253276
254277 // The initializers for the retained accessors */
255278 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