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

Skip to content

Commit 802a173

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 2465fce commit 802a173

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
@@ -2337,7 +2337,24 @@ trait Types
23372337
// must initialise symbol, see test/files/pos/ticket0137.scala
23382338
val tpars = initializedTypeParams
23392339
if (tpars.isEmpty) this
2340-
else typeFunAnon(tpars, copyTypeRef(this, pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
2340+
else {
2341+
val tparsAtNonClass =
2342+
// if we're eta-expanding a reference to a class, it can remain the owner of the type params
2343+
// TODO: why does cloning tpars break stuff?
2344+
if (sym.isClass) tpars
2345+
else {
2346+
// NOTE: during pickling, localizedOwner will change the owner to a non-class owner of the pickle root;
2347+
// (the pickle root is the current top-level class).
2348+
// The difference in owner between source-compiled vs class-loaded should not trigger recompilation (or breakage in ASF).
2349+
// We can't just re-use the owner of the type params (the class or type constructor that defines the type params),
2350+
// because if the owner is a type that's under consideration for relativizing, ASF thinks it needs to act on them.
2351+
// We want something enclosing that's not a class, but usually `sym.enclosingSuchThat(_.isTerm)` is NoSymbol anyway
2352+
// when using `sym` (the current owner for `tpars`), pos/t10762 will fail
2353+
val nonClassRoot = sym.enclosingSuchThat(_.isTerm)
2354+
cloneSymbolsAtOwner(tpars, nonClassRoot)
2355+
}
2356+
PolyType(tparsAtNonClass, copyTypeRef(this, pre, sym, tparsAtNonClass map (_.typeConstructor)))
2357+
}
23412358
}
23422359

23432360
// only need to rebind type aliases, as typeRef already handles abstract types
@@ -3939,14 +3956,6 @@ trait Types
39393956
@deprecated("use genPolyType(...) instead", "2.10.0") // Used in reflection API
39403957
def polyType(params: List[Symbol], tpe: Type): Type = GenPolyType(params, tpe)
39413958

3942-
/** A creator for anonymous type functions, where the symbol for the type function still needs to be created.
3943-
*
3944-
* TODO:
3945-
* 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
3946-
* 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?
3947-
*/
3948-
def typeFunAnon(tps: List[Symbol], body: Type): Type = typeFun(tps, body)
3949-
39503959
/** A creator for a type functions, assuming the type parameters tps already have the right owner. */
39513960
def typeFun(tps: List[Symbol], body: Type): Type = PolyType(tps, body)
39523961

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