summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2014-02-14 13:21:34 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2014-02-14 13:21:34 -0800
commitd227a89363886635969f4a7725303c6b65b0914b (patch)
tree433096b16268bf327f0a5678f5e29aff914407d6 /src
parent35eb20283e7da0af28aaa0ae0d1051e21cc6c25d (diff)
parent5984461227c70dd48d9c87c6e5afe0cf8c58f8f1 (diff)
downloadscala-d227a89363886635969f4a7725303c6b65b0914b.tar.gz
scala-d227a89363886635969f4a7725303c6b65b0914b.tar.bz2
scala-d227a89363886635969f4a7725303c6b65b0914b.zip
Merge pull request #3525 from adriaanm/t8177b
SI-8177 specializeSym must use memberInfo on high side
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenSymbols.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala56
2 files changed, 39 insertions, 19 deletions
diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
index 3a97089d51..2965db17c6 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
@@ -93,7 +93,7 @@ trait GenSymbols {
// todo. make sure that free methods and free local defs work correctly
if (sym.isExistential) reifySymDef(sym)
else if (sym.isTerm) reifyFreeTerm(Ident(sym))
- else reifyFreeType(Ident(sym))
+ else reifyFreeType(Ident(sym)) // TODO: reify refinement classes
}
}
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 6010d4eb12..b2e36a2732 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -1143,7 +1143,7 @@ trait Types
/** A class for this-types of the form <sym>.this.type
*/
abstract case class ThisType(sym: Symbol) extends SingletonType with ThisTypeApi {
- if (!sym.isClass) {
+ if (!sym.isClass && !sym.isFreeType) {
// SI-6640 allow StubSymbols to reveal what's missing from the classpath before we trip the assertion.
sym.failIfStub()
abort(s"ThisType($sym) for sym which is not a class")
@@ -4100,24 +4100,44 @@ trait Types
)
}
- /** Does member `sym1` of `tp1` have a stronger type
- * than member `sym2` of `tp2`?
+ /** Does member `symLo` of `tpLo` have a stronger type
+ * than member `symHi` of `tpHi`?
*/
- protected[internal] def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol, depth: Depth): Boolean = {
- require((sym1 ne NoSymbol) && (sym2 ne NoSymbol), ((tp1, sym1, tp2, sym2, depth)))
- val info1 = tp1.memberInfo(sym1)
- val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1)
- //System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG
- ( sym2.isTerm && isSubType(info1, info2, depth) && (!sym2.isStable || sym1.isStable) && (!sym1.hasVolatileType || sym2.hasVolatileType)
- || sym2.isAbstractType && {
- val memberTp1 = tp1.memberType(sym1)
- // println("kinds conform? "+(memberTp1, tp1, sym2, kindsConform(List(sym2), List(memberTp1), tp2, sym2.owner)))
- info2.bounds.containsType(memberTp1) &&
- kindsConform(List(sym2), List(memberTp1), tp1, sym1.owner)
- }
- || sym2.isAliasType && tp2.memberType(sym2).substThis(tp2.typeSymbol, tp1) =:= tp1.memberType(sym1) //@MAT ok
- )
- }
+ protected[internal] def specializesSym(preLo: Type, symLo: Symbol, preHi: Type, symHi: Symbol, depth: Depth): Boolean =
+ (symHi.isAliasType || symHi.isTerm || symHi.isAbstractType) && {
+ // only now that we know symHi is a viable candidate ^^^^^^^, do the expensive checks: ----V
+ require((symLo ne NoSymbol) && (symHi ne NoSymbol), ((preLo, symLo, preHi, symHi, depth)))
+
+ val tpHi = preHi.memberInfo(symHi).substThis(preHi.typeSymbol, preLo)
+
+ // Should we use memberType or memberInfo?
+ // memberType transforms (using `asSeenFrom`) `sym.tpe`,
+ // whereas memberInfo performs the same transform on `sym.info`.
+ // For term symbols, this ends up being the same thing (`sym.tpe == sym.info`).
+ // For type symbols, however, the `.info` of an abstract type member
+ // is defined by its bounds, whereas its `.tpe` is a `TypeRef` to that type symbol,
+ // so that `sym.tpe <:< sym.info`, but not the other way around.
+ //
+ // Thus, for the strongest (correct) result,
+ // we should use `memberType` on the low side.
+ //
+ // On the high side, we should use the result appropriate
+ // for the right side of the `<:<` above (`memberInfo`).
+ val tpLo = preLo.memberType(symLo)
+
+ debuglog(s"specializesSymHi: $preHi . $symHi : $tpHi")
+ debuglog(s"specializesSymLo: $preLo . $symLo : $tpLo")
+
+ if (symHi.isTerm)
+ (isSubType(tpLo, tpHi, depth) &&
+ (!symHi.isStable || symLo.isStable) && // sub-member must remain stable
+ (!symLo.hasVolatileType || symHi.hasVolatileType)) // sub-member must not introduce volatility
+ else if (symHi.isAbstractType)
+ ((tpHi.bounds containsType tpLo) &&
+ kindsConform(symHi :: Nil, tpLo :: Nil, preLo, symLo.owner))
+ else // we know `symHi.isAliasType` (see above)
+ tpLo =:= tpHi
+ }
/** A function implementing `tp1` matches `tp2`. */
final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {