8000 Eta-expanded tycon's type params need own owner · adriaanm/scala@7c0e42b · GitHub
[go: up one dir, main page]

Skip to content

Commit 7c0e42b

Browse files
retronymadriaanm
authored andcommitted
Eta-expanded tycon's type params need own owner
Since scala#6069, it is possible to have type variables compared to the eta expansion of a class type, which is `[CLASSTPARAM] => Class[CLASSTPARAM]`. After separate compilation, the owner of this type constructor param is adjusted to the root class (see the comments and special cases in Pickler.localizedOwner), which makes it show up to certain subsequent as-seen-from maps as a type parameter of an enclosing class. SBT's ExtractAPI phase runs into this problem. Eta expansion of the tycon type ref uses an owner (NoSymbol) that will not become a class after pickling. Fixes scala/bug#10762
1 parent e64564b commit 7c0e42b

File tree

4 files changed

+44
-18
lines changed

4 files changed

+44
-18
lines changed

src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,16 @@ abstract class Pickler extends SubComponent {
9696
private def isRootSym(sym: Symbol) =
9797
sym.name.toTermName == rootName && sym.owner == rootOwner
9898

99-
/** Returns usually symbol's owner, but picks classfile root instead
100-
* for existentially bound variables that have a non-local owner.
101-
* Question: Should this be done for refinement class symbols as well?
102-
*
103-
* Note: tree pickling also finds its way here; e.g. in scala/bug#7501 the pickling
104-
* of trees in annotation arguments considers the parameter symbol of a method
105-
* called in such a tree as "local". The condition `sym.isValueParameter` was
106-
* added to fix that bug, but there may be a better way.
107-
*/
99+
/** Usually `sym.owner`, except when `sym` is pickle-local, while `sym.owner` is not.
100+
*
101+
* In the latter case, the alternative owner is the pickle root,
102+
* or a non-class owner of root (so that term-owned parameters remain term-owned).
103+
*
104+
* Note: tree pickling also finds its way here; e.g. in scala/bug#7501 the pickling
105+
* of trees in annotation arguments considers the parameter symbol of a method
106+
* called in such a tree as "local". The condition `sym.isValueParameter` was
107+
* added to fix that bug, but there may be a better way.
108+
*/
108109
private def localizedOwner(sym: Symbol) =
109110
if (isLocalToPickle(sym) && !isRootSym(sym) && !isLocalToPickle(sym.owner))
110111
// don't use a class as the localized owner for type parameters that are not owned by a class: those are not instantiated by asSeenFrom

src/reflect/scala/reflect/internal/Types.scala

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2330,7 +2330,24 @@ trait Types
23302330
// must initialise symbol, see test/files/pos/ticket0137.scala
23312331
val tpars = initializedTypeParams
23322332
if (tpars.isEmpty) this
2333-
else typeFunAnon(tpars, copyTypeRef(this, pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
2333+
else {
2334+
val tparsAtNonClass =
2335+
// if we're eta-expanding a reference to a class, it can remain the owner of the type params
2336+
// TODO: why does cloning tpars break stuff?
2337+
if (sym.isClass) tpars
2338+
else {
2339+
// NOTE: during pickling, localizedOwner will change the owner to a non-class owner of the pickle root;
2340+
// (the pickle root is the current top-level class).
2341+
// The difference in owner between source-compiled vs class-loaded should not trigger recompilation (or breakage in ASF).
2342+
// We can't just re-use the owner of the type params (the class or type constructor that defines the type params),
2343+
// because if the owner is a type that's under consideration for relativizing, ASF thinks it needs to act on them.
2344+
// We want something enclosing that's not a class, but usually `sym.enclosingSuchThat(_.isTerm)` is NoSymbol anyway
2345+
// when using `sym` (the current owner for `tpars`), pos/t10762 will fail
2346+
val nonClassRoot = sym.enclosingSuchThat(_.isTerm)
2347+
cloneSymbolsAtOwner(tpars, nonClassRoot)
2348+
}
2349+
PolyType(tparsAtNonClass, copyTypeRef(this, pre, sym, tparsAtNonClass map (_.typeConstructor)))
2350+
}
23342351
}
23352352

23362353
// only need to rebind type aliases, as typeRef already handles abstract types
@@ -3932,14 +3949,6 @@ trait Types
39323949
@deprecated("use genPolyType(...) instead", "2.10.0") // Used in reflection API
39333950
def polyType(params: List[Symbol], tpe: Type): Type = GenPolyType(params, tpe)
39343951

3935-
/** A creator for anonymous type functions, where the symbol for the type function still needs to be created.
3936-
*
3937-
* TODO:
3938-
* type params of anonymous type functions, which currently can only arise from normalising type aliases, are owned by the type alias of which they are the eta-expansion
3939-
* higher-order subtyping expects eta-expansion of type constructors that arise from a class; here, the type params are owned by that class, but is that the right thing to do?
3940-
*/
3941-
def typeFunAnon(tps: List[Symbol], body: Type): Type = typeFun(tps, body)
3942-
39433952
/** A creator for a type functions, assuming the type parameters tps already have the right owner. */
39443953
def typeFun(tps: List[Symbol], body: Type): Type = PolyType(tps, body)
39453954

test/files/pos/t10762/t10762_1.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import language.higherKinds
2+
3+
trait Tycon[A]
4+
trait MatcherFactory1X[TC1[_]]
5+
trait Matcher[T]{
6+
class X {
7+
def be = {
8+
def inferTycon[TC1[_]](other: MatcherFactory1X[TC1]): MatcherFactory1X[TC1] = ???
9+
inferTycon(??? : MatcherFactory1X[Tycon])
10+
}
11+
}
12+
}

test/files/pos/t10762/t10762_2.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
object Test {
2+
val m: Matcher[_] = ???
3+
val tpinfer = (new m.X).be
4+
}

0 commit comments

Comments
 (0)
0