Skip to content

Commit 83449e1

Browse files
committed
Merge pull request #86 from dotty-staging/fixes
Fixes for various txxxx tickets
2 parents 398431a + 9b17c6c commit 83449e1

File tree

140 files changed

+316
-143
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

140 files changed

+316
-143
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
*.class
22
*.log
3+
*~
34

45
# sbt specific
56
dist/*

src/dotty/tools/dotc/Compiler.scala

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import core._
55
import Contexts._
66
import Periods._
77
import Symbols._
8+
import Scopes._
89
import typer.{FrontEnd, Typer, Mode, ImportInfo}
910
import reporting.ConsoleReporter
1011
import dotty.tools.dotc.core.Phases.Phase
@@ -28,16 +29,28 @@ class Compiler {
2829
runId += 1; runId
2930
}
3031

32+
/** Produces the following contexts, from outermost to innermost
33+
*
34+
* bootStrap: A context with next available runId and a scope consisting of
35+
* the RootPackage _root_
36+
* start A context with RootClass as owner and the necessary initializations
37+
* for type checking.
38+
* imports For each element of RootImports, an import context
39+
*/
3140
def rootContext(implicit ctx: Context): Context = {
3241
ctx.definitions.init(ctx)
3342
ctx.usePhases(phases)
34-
val start = ctx.fresh
43+
val rootScope = new MutableScope
44+
val bootstrap = ctx.fresh
3545
.withPeriod(Period(nextRunId, FirstPhaseId))
46+
.withScope(rootScope)
47+
rootScope.enter(ctx.definitions.RootPackage)(bootstrap)
48+
val start = bootstrap.fresh
3649
.withOwner(defn.RootClass)
3750
.withTyper(new Typer)
3851
.withNewMode(Mode.ImplicitsEnabled)
3952
.withTyperState(new MutableTyperState(ctx.typerState, new ConsoleReporter()(ctx), isCommittable = true))
40-
ctx.definitions.init(start)
53+
ctx.definitions.init(start) // set context of definitions to start
4154
def addImport(ctx: Context, sym: Symbol) =
4255
ctx.fresh.withImportInfo(ImportInfo.rootImport(sym)(ctx))
4356
(start.withRunInfo(new RunInfo(start)) /: defn.RootImports)(addImport)

src/dotty/tools/dotc/config/Printers.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ object Printers {
2222
val unapp: Printer = noPrinter
2323
val completions = noPrinter
2424
val gadts = noPrinter
25+
val hk = noPrinter
2526
val incremental = noPrinter
2627
val config = noPrinter
2728
}

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -359,12 +359,6 @@ class Definitions {
359359
*/
360360
def hkTrait(vcs: List[Int]) = {
361361

362-
def varianceSuffix(v: Int) = v match {
363-
case -1 => "N"
364-
case 0 => "I"
365-
case 1 => "P"
366-
}
367-
368362
def varianceFlags(v: Int) = v match {
369363
case -1 => Contravariant
370364
case 0 => Covariant
@@ -375,14 +369,13 @@ class Definitions {
375369
def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
376370
val cls = denot.asClass.classSymbol
377371
val paramDecls = newScope
378-
for ((v, i) <- vcs.zipWithIndex)
379-
newTypeParam(cls, tpnme.higherKindedParamName(i), varianceFlags(v), paramDecls)
372+
for (i <- 0 until vcs.length)
373+
newTypeParam(cls, tpnme.higherKindedParamName(i), EmptyFlags, paramDecls)
380374
denot.info = ClassInfo(ScalaPackageClass.thisType, cls, List(ObjectClass.typeRef), paramDecls)
381375
}
382376
}
383377

384-
val traitName =
385-
tpnme.higherKindedTraitName(vcs.length) ++ (vcs map varianceSuffix).mkString
378+
val traitName = tpnme.higherKindedTraitName(vcs)
386379

387380
def createTrait = {
388381
val cls = newClassSymbol(

src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,19 @@ object NameOps {
168168
}
169169
}
170170

171+
/** The variances of the higherKinded parameters of the trait named
172+
* by this name.
173+
* @pre The name is a higher-kinded trait name, i.e. it starts with HK_TRAIT_PREFIX
174+
*/
175+
def hkVariances: List[Int] = {
176+
def varianceOfSuffix(suffix: Char): Int = {
177+
val idx = tpnme.varianceSuffixes.indexOf(suffix)
178+
assert(idx >= 0)
179+
idx - 1
180+
}
181+
name.drop(tpnme.HK_TRAIT_PREFIX.length).toList.map(varianceOfSuffix)
182+
}
183+
171184
/** If name length exceeds allowable limit, replace part of it by hash */
172185
def compactified(implicit ctx: Context): TermName = termName(compactify(name.toString))
173186
}

src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ object StdNames {
248248
val SPECIALIZED_INSTANCE: N = "specInstance$"
249249
val THIS: N = "_$this"
250250
val HK_PARAM_PREFIX: N = "_$hk$"
251+
val HK_TRAIT_PREFIX: N = "$HigherKinded$"
251252

252253
final val Nil: N = "Nil"
253254
final val Predef: N = "Predef"
@@ -281,7 +282,6 @@ object StdNames {
281282
val ConstantType: N = "ConstantType"
282283
val ExistentialTypeTree: N = "ExistentialTypeTree"
283284
val Flag : N = "Flag"
284-
val HigherKinded: N = "HigherKinded"
285285
val Ident: N = "Ident"
286286
val Import: N = "Import"
287287
val Literal: N = "Literal"
@@ -645,10 +645,14 @@ object StdNames {
645645
def syntheticTypeParamNames(num: Int): List[TypeName] =
646646
(0 until num).map(syntheticTypeParamName)(breakOut)
647647

648-
def higherKindedTraitName(n: Int) = HigherKinded ++ n.toString
648+
def higherKindedTraitName(vcs: List[Int]): TypeName = HK_TRAIT_PREFIX ++ vcs.map(varianceSuffix).mkString
649649
def higherKindedParamName(n: Int) = HK_PARAM_PREFIX ++ n.toString
650650

651651
final val Conforms = encode("<:<")
652+
653+
def varianceSuffix(v: Int): Char = varianceSuffixes.charAt(v + 1)
654+
655+
val varianceSuffixes = "NIP"
652656
}
653657

654658
abstract class JavaNames[N <: Name] extends DefinedNames[N] {

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import util.common._
1010
import Names._
1111
import Flags._
1212
import util.Positions.Position
13+
import config.Printers._
1314
import collection.mutable
1415

1516
object TypeApplications {
@@ -137,6 +138,8 @@ class TypeApplications(val self: Type) extends AnyVal {
137138
tp.underlying.appliedTo(args)
138139
case AndType(l, r) =>
139140
l.appliedTo(args) & r
141+
case tp: PolyType =>
142+
tp.instantiate(args)
140143
case ErrorType =>
141144
self
142145
}
@@ -193,13 +196,32 @@ class TypeApplications(val self: Type) extends AnyVal {
193196
NoType
194197
}
195198

196-
/** The base type including all type arguments of this type.
199+
/** The base type including all type arguments and applicable refinements
200+
* of this type. Refinements are applicable if they refine a member of
201+
* the parent type which furthermore is not a name-mangled type parameter.
197202
* Existential types in arguments are returned as TypeBounds instances.
198203
*/
199-
final def baseTypeWithArgs(base: Symbol)(implicit ctx: Context): Type = self.dealias match {
200-
case AndType(tp1, tp2) => tp1.baseTypeWithArgs(base) & tp2.baseTypeWithArgs(base)
201-
case OrType(tp1, tp2) => tp1.baseTypeWithArgs(base) | tp2.baseTypeWithArgs(base)
202-
case _ => self.baseTypeRef(base).appliedTo(baseArgInfos(base))
204+
final def baseTypeWithArgs(base: Symbol)(implicit ctx: Context): Type = ctx.traceIndented(s"btwa ${self.show} wrt $base", core, show = true) {
205+
def default = self.baseTypeRef(base).appliedTo(baseArgInfos(base))
206+
self match {
207+
case tp: TypeRef =>
208+
tp.info match {
209+
case TypeBounds(_, hi) => hi.baseTypeWithArgs(base)
210+
case _ => default
211+
}
212+
case tp @ RefinedType(parent, name) if !tp.member(name).symbol.is(ExpandedTypeParam) =>
213+
val pbase = parent.baseTypeWithArgs(base)
214+
if (pbase.member(name).exists) RefinedType(pbase, name, tp.refinedInfo)
215+
else pbase
216+
case tp: TermRef =>
217+
tp.underlying.baseTypeWithArgs(base)
218+
case AndType(tp1, tp2) =>
219+
tp1.baseTypeWithArgs(base) & tp2.baseTypeWithArgs(base)
220+
case OrType(tp1, tp2) =>
221+
tp1.baseTypeWithArgs(base) | tp2.baseTypeWithArgs(base)
222+
case _ =>
223+
default
224+
}
203225
}
204226

205227
/** Translate a type of the form From[T] to To[T], keep other types as they are.

src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,11 @@ class TypeComparer(initctx: Context) extends DotClass {
201201
def isNonBottomSubType(tp1: Type, tp2: Type): Boolean =
202202
!(tp2 isRef NothingClass) && isSubType(tp1, tp2)
203203

204-
def isSubType(tp1: Type, tp2: Type): Boolean = /*>|>*/ ctx.traceIndented(s"isSubType ${tp1.show} <:< ${tp2.show}", subtyping) /*<|<*/ {
204+
private def traceInfo(tp1: Type, tp2: Type) =
205+
s"${tp1.show} <:< ${tp2.show}" +
206+
(if (ctx.settings.verbose.value) s"${tp1.getClass} ${tp2.getClass}" else "")
207+
208+
def isSubType(tp1: Type, tp2: Type): Boolean = /*>|>*/ ctx.traceIndented(s"isSubType ${traceInfo(tp1, tp2)}", subtyping) /*<|<*/ {
205209
if (tp2 eq NoType) false
206210
else if (tp1 eq tp2) true
207211
else {
@@ -408,8 +412,7 @@ class TypeComparer(initctx: Context) extends DotClass {
408412
val base = tp1.baseTypeRef(cls2)
409413
if (base.exists && (base ne tp1)) return isSubType(base, tp2)
410414
if ( cls2 == defn.SingletonClass && tp1.isStable
411-
|| cls2 == defn.NotNullClass && tp1.isNotNull
412-
|| (defn.hkTraits contains cls2) && isSubTypeHK(tp1, tp2)) return true
415+
|| cls2 == defn.NotNullClass && tp1.isNotNull) return true
413416
}
414417
fourthTry(tp1, tp2)
415418
}
@@ -426,7 +429,9 @@ class TypeComparer(initctx: Context) extends DotClass {
426429
}
427430
case _ => tp2
428431
}
429-
def compareRefined: Boolean = tp1.widen match {
432+
def compareRefined: Boolean =
433+
if (defn.hkTraits contains parent2.typeSymbol) isSubTypeHK(tp1, tp2)
434+
else tp1.widen match {
430435
case tp1 @ RefinedType(parent1, name1) if nameMatches(name1, name2, tp1, tp2) =>
431436
// optimized case; all info on tp1.name2 is in refinement tp1.refinedInfo.
432437
isSubType(tp1.refinedInfo, tp2.refinedInfo) && {
@@ -439,7 +444,7 @@ class TypeComparer(initctx: Context) extends DotClass {
439444
case mbr: SingleDenotation => qualifies(mbr)
440445
case _ => mbr hasAltWith qualifies
441446
}
442-
def hasMatchingMember(name: Name): Boolean = /*>|>*/ ctx.traceIndented(s"hasMatchingMember($name) ${tp1.member(name)}", subtyping) /*<|<*/ (
447+
def hasMatchingMember(name: Name): Boolean = /*>|>*/ ctx.traceIndented(s"hasMatchingMember($name) ${tp1.member(name).info.show}", subtyping) /*<|<*/ (
443448
memberMatches(tp1 member name)
444449
||
445450
{ // special case for situations like:
@@ -467,7 +472,7 @@ class TypeComparer(initctx: Context) extends DotClass {
467472
case tp2 @ MethodType(_, formals2) =>
468473
def compareMethod = tp1 match {
469474
case tp1 @ MethodType(_, formals1) =>
470-
tp1.signature == tp2.signature &&
475+
(tp1.signature sameParams tp2.signature) &&
471476
(if (Config.newMatch) subsumeParams(formals1, formals2, tp1.isJava, tp2.isJava)
472477
else matchingParams(formals1, formals2, tp1.isJava, tp2.isJava)) &&
473478
tp1.isImplicit == tp2.isImplicit && // needed?
@@ -532,7 +537,20 @@ class TypeComparer(initctx: Context) extends DotClass {
532537
(tp1.symbol eq NullClass) && tp2.dealias.typeSymbol.isNullableClass
533538
}
534539
case tp1: SingletonType =>
535-
isNewSubType(tp1.underlying.widenExpr, tp2)
540+
isNewSubType(tp1.underlying.widenExpr, tp2) || {
541+
// if tp2 == p.type and p: q.type then try tp1 <:< q.type as a last effort.
542+
tp2 match {
543+
case tp2: TermRef =>
544+
tp2.info match {
545+
case tp2i: TermRef =>
546+
isSubType(tp1, tp2i)
547+
case _ =>
548+
false
549+
}
550+
case _ =>
551+
false
552+
}
553+
}
536554
case tp1: RefinedType =>
537555
isNewSubType(tp1.parent, tp2)
538556
case AndType(tp11, tp12) =>
@@ -612,20 +630,33 @@ class TypeComparer(initctx: Context) extends DotClass {
612630
* This is the case if `tp1` and `tp2` have the same number
613631
* of type parameters, the bounds of tp1's paremeters
614632
* are contained in the corresponding bounds of tp2's parameters
615-
* and the variances of correesponding parameters agree.
633+
* and the variances of the parameters agree.
634+
* The variances agree if the supertype parameter is invariant,
635+
* or both parameters have the same variance.
636+
*
637+
* Note: When we get to isSubTypeHK, it might be that tp1 is
638+
* instantiated, or not. If it is instantiated, we compare
639+
* actual argument infos against higher-kinded bounds,
640+
* if it is not instantiated we compare type parameter bounds
641+
* and also compare variances.
616642
*/
617-
def isSubTypeHK(tp1: Type, tp2: Type): Boolean = {
643+
def isSubTypeHK(tp1: Type, tp2: Type): Boolean = ctx.traceIndented(s"isSubTypeHK(${tp1.show}, ${tp2.show}", subtyping) {
618644
val tparams = tp1.typeParams
619-
val hkArgs = tp2.argInfos
620-
(hkArgs.length == tparams.length) && {
621-
val base = tp1.narrow
622-
(tparams, hkArgs).zipped.forall { (tparam, hkArg) =>
623-
isSubType(base.memberInfo(tparam), hkArg.bounds) // TODO: base.memberInfo needed?
624-
} &&
625-
(tparams, tp2.typeSymbol.typeParams).zipped.forall { (tparam, tparam2) =>
626-
tparam.variance == tparam2.variance
627-
}
628-
}
645+
val argInfos1 = tp1.argInfos
646+
val args1 =
647+
if (argInfos1.nonEmpty) argInfos1 // tp1 is instantiated, use the argument infos
648+
else { // tp1 is uninstantiated, use the parameter bounds
649+
val base = tp1.narrow
650+
tparams.map(base.memberInfo)
651+
}
652+
val hkBounds = tp2.argInfos.map(_.asInstanceOf[TypeBounds])
653+
val boundsOK = (hkBounds corresponds args1)(_ contains _)
654+
val variancesOK =
655+
argInfos1.nonEmpty || (tparams corresponds tp2.typeSymbol.name.hkVariances) { (tparam, v) =>
656+
v == 0 || tparam.variance == v
657+
}
658+
hk.println(s"isSubTypeHK: args1 = $args1, hk-bounds = $hkBounds $boundsOK $variancesOK")
659+
boundsOK && variancesOK
629660
}
630661

631662
def trySetType(tr: NamedType, bounds: TypeBounds): Boolean =

0 commit comments

Comments
 (0)