diff options
author | Paul Phillips <paulp@improving.org> | 2013-01-30 16:25:53 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-01-30 16:25:53 -0800 |
commit | d24f341f081aef296d174ea54d0579976eeaae98 (patch) | |
tree | c708611aeb7bed6d2b7e05ee408a028a88b50150 | |
parent | 7d80e0846964053b81b4e4b5db7b9356e3bcc601 (diff) | |
parent | 9afae59f0e46bed0acf40d043d3ee2a0e0ef432f (diff) | |
download | scala-d24f341f081aef296d174ea54d0579976eeaae98.tar.gz scala-d24f341f081aef296d174ea54d0579976eeaae98.tar.bz2 scala-d24f341f081aef296d174ea54d0579976eeaae98.zip |
Merge pull request #1997 from retronym/ticket/7035
SI-7035 Centralize case field accessor sorting.
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala | 20 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala | 9 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Symbols.scala | 23 | ||||
-rw-r--r-- | test/files/pos/t7035.scala | 15 |
4 files changed, 38 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 1f5b8c74c5..b0745b4c09 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -746,26 +746,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // reference the (i-1)th case accessor if it exists, otherwise the (i-1)th tuple component override protected def tupleSel(binder: Symbol)(i: Int): Tree = { import CODE._ - // caseFieldAccessors is messed up after typers (reversed, names mangled for non-public fields) - // TODO: figure out why... val accessors = binder.caseFieldAccessors - // luckily, the constrParamAccessors are still sorted properly, so sort the field-accessors using them - // (need to undo name-mangling, including the sneaky trailing whitespace) - val constrParamAccessors = binder.constrParamAccessors - - def indexInCPA(acc: Symbol) = - constrParamAccessors indexWhere { orig => - // patmatDebug("compare: "+ (orig, acc, orig.name, acc.name, (acc.name == orig.name), (acc.name startsWith (orig.name append "$")))) - val origName = orig.name.toString.trim - val accName = acc.name.toString.trim - (accName == origName) || (accName startsWith (origName + "$")) - } - - // patmatDebug("caseFieldAccessors: "+ (accessors, binder.caseFieldAccessors map indexInCPA)) - // patmatDebug("constrParamAccessors: "+ constrParamAccessors) - - val accessorsSorted = accessors sortBy indexInCPA - if (accessorsSorted isDefinedAt (i-1)) REF(binder) DOT accessorsSorted(i-1) + if (accessors isDefinedAt (i-1)) REF(binder) DOT accessors(i-1) else codegen.tupleSel(binder)(i) // this won't type check for case classes, as they do not inherit ProductN } diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index a907ab6c66..39f6f764e7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -78,14 +78,7 @@ trait SyntheticMethods extends ast.TreeDSL { else templ } - val originalAccessors = clazz.caseFieldAccessors - // private ones will have been renamed -- make sure they are entered - // in the original order. - def accessors = clazz.caseFieldAccessors sortBy { acc => - originalAccessors indexWhere { orig => - (acc.name == orig.name) || (acc.name startsWith (orig.name append "$")) - } - } + def accessors = clazz.caseFieldAccessors val arity = accessors.size // If this is ProductN[T1, T2, ...], accessorLub is the lub of T1, T2, ..., . // !!! Hidden behind -Xexperimental due to bummer type inference bugs. diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index c274a9e3af..c1b868f3cb 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -1730,8 +1730,27 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** For a case class, the symbols of the accessor methods, one for each * argument in the first parameter list of the primary constructor. * The empty list for all other classes. - */ - final def caseFieldAccessors: List[Symbol] = + * + * This list will be sorted to correspond to the declaration order + * in the constructor parameter + */ + final def caseFieldAccessors: List[Symbol] = { + // We can't rely on the ordering of the case field accessors within decls -- + // handling of non-public parameters seems to change the order (see SI-7035.) + // + // Luckily, the constrParamAccessors are still sorted properly, so sort the field-accessors using them + // (need to undo name-mangling, including the sneaky trailing whitespace) + // + // The slightly more principled approach of using the paramss of the + // primary constructor leads to cycles in, for example, pos/t5084.scala. + val primaryNames = constrParamAccessors.map(acc => nme.dropLocalSuffix(acc.name)) + caseFieldAccessorsUnsorted.sortBy { acc => + primaryNames indexWhere { orig => + (acc.name == orig) || (acc.name startsWith (orig append "$")) + } + } + } + private final def caseFieldAccessorsUnsorted: List[Symbol] = (info.decls filter (_.isCaseAccessorMethod)).toList final def constrParamAccessors: List[Symbol] = diff --git a/test/files/pos/t7035.scala b/test/files/pos/t7035.scala new file mode 100644 index 0000000000..f45bd0a878 --- /dev/null +++ b/test/files/pos/t7035.scala @@ -0,0 +1,15 @@ +case class Y(final var x: Int, final private var y: String, final val z1: Boolean, final private val z2: Any) { + + import Test.{y => someY} + List(someY.x: Int, someY.y: String, someY.z1: Boolean, someY.z2: Any) + someY.y = "" +} + +object Test { + val y = Y(0, "", true, new {}) + val unapp: Option[(Int, String, Boolean, Any)] = // was (Int, Boolean, String, Any) !! + Y.unapply(y) + + val Y(a, b, c, d) = y + List(a: Int, b: String, c: Boolean, d: Any) +} |