Skip to content

Commit 4243345

Browse files
authored
Merge pull request #3061 from dotty-staging/test-applied-type
Applied types, unoptimized
2 parents 0ddf48e + 2e65bd5 commit 4243345

File tree

102 files changed

+1674
-1518
lines changed

Some content is hidden

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

102 files changed

+1674
-1518
lines changed

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class Run(comp: Compiler, ictx: Context) {
105105
compileUnits()(ctx)
106106
}
107107

108-
protected def compileUnits()(implicit ctx: Context) = Stats.monitorHeartBeat {
108+
protected def compileUnits()(implicit ctx: Context) = Stats.maybeMonitored {
109109
ctx.checkSingleThreaded()
110110

111111
// If testing pickler, make sure to stop after pickling phase:
@@ -118,20 +118,21 @@ class Run(comp: Compiler, ictx: Context) {
118118
ctx.usePhases(phases)
119119
var lastPrintedTree: PrintedTree = NoPrintedTree
120120
for (phase <- ctx.allPhases)
121-
if (phase.isRunnable) {
122-
val start = System.currentTimeMillis
123-
units = phase.runOn(units)
124-
if (ctx.settings.Xprint.value.containsPhase(phase)) {
125-
for (unit <- units) {
126-
lastPrintedTree =
127-
printTree(lastPrintedTree)(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit))
121+
if (phase.isRunnable)
122+
Stats.trackTime(s"$phase ms ") {
123+
val start = System.currentTimeMillis
124+
units = phase.runOn(units)
125+
if (ctx.settings.Xprint.value.containsPhase(phase)) {
126+
for (unit <- units) {
127+
lastPrintedTree =
128+
printTree(lastPrintedTree)(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit))
129+
}
128130
}
131+
ctx.informTime(s"$phase ", start)
132+
Stats.record(s"total trees at end of $phase", ast.Trees.ntrees)
133+
for (unit <- units)
134+
Stats.record(s"retained typed trees at end of $phase", unit.tpdTree.treeSize)
129135
}
130-
ctx.informTime(s"$phase ", start)
131-
Stats.record(s"total trees at end of $phase", ast.Trees.ntrees)
132-
for (unit <- units)
133-
Stats.record(s"retained typed trees at end of $phase", unit.tpdTree.treeSize)
134-
}
135136
if (!ctx.reporter.hasErrors) Rewrites.writeBack()
136137
}
137138

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package ast
55
import core._
66
import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
77
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
8-
import Decorators._
8+
import Decorators._, transform.SymUtils._
99
import NameKinds.{UniqueName, EvidenceParamName, DefaultGetterName}
1010
import language.higherKinds
1111
import typer.FrontEnd
@@ -70,7 +70,7 @@ object desugar {
7070
def apply(tp: Type) = tp match {
7171
case tp: NamedType if tp.symbol.exists && (tp.symbol.owner eq originalOwner) =>
7272
val defctx = ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next()
73-
var local = defctx.denotNamed(tp.name).suchThat(_ is ParamOrAccessor).symbol
73+
var local = defctx.denotNamed(tp.name).suchThat(_.isParamOrAccessor).symbol
7474
if (local.exists) (defctx.owner.thisType select local).dealias
7575
else {
7676
def msg =
@@ -238,23 +238,6 @@ object desugar {
238238
Nil
239239
}
240240

241-
/** Fill in empty type bounds with Nothing/Any. Expand private local type parameters as follows:
242-
*
243-
* class C[v T]
244-
* ==>
245-
* class C { type v C$T; type v T = C$T }
246-
*/
247-
def typeDef(tdef: TypeDef)(implicit ctx: Context): Tree = {
248-
if (tdef.mods is PrivateLocalParam) {
249-
val tparam = cpy.TypeDef(tdef)(name = tdef.name.expandedName(ctx.owner))
250-
.withMods(tdef.mods &~ PrivateLocal)
251-
val alias = cpy.TypeDef(tdef)(rhs = refOfDef(tparam))
252-
.withMods(tdef.mods & VarianceFlags | PrivateLocalParamAccessor | Synthetic)
253-
Thicket(tparam, alias)
254-
}
255-
else tdef
256-
}
257-
258241
@sharable private val synthetic = Modifiers(Synthetic)
259242

260243
private def toDefParam(tparam: TypeDef): TypeDef =
@@ -696,7 +679,7 @@ object desugar {
696679

697680
def defTree(tree: Tree)(implicit ctx: Context): Tree = tree match {
698681
case tree: ValDef => valDef(tree)
699-
case tree: TypeDef => if (tree.isClassDef) classDef(tree) else typeDef(tree)
682+
case tree: TypeDef => if (tree.isClassDef) classDef(tree) else tree
700683
case tree: DefDef => defDef(tree)
701684
case tree: ModuleDef => moduleDef(tree)
702685
case tree: PatDef => patDef(tree)
@@ -1132,7 +1115,7 @@ object desugar {
11321115
*/
11331116
def refinedTypeToClass(parent: tpd.Tree, refinements: List[Tree])(implicit ctx: Context): TypeDef = {
11341117
def stripToCore(tp: Type): List[Type] = tp match {
1135-
case tp: RefinedType if tp.argInfos.nonEmpty => tp :: Nil // parameterized class type
1118+
case tp: AppliedType => tp :: Nil
11361119
case tp: TypeRef if tp.symbol.isClass => tp :: Nil // monomorphic class type
11371120
case tp: TypeProxy => stripToCore(tp.underlying)
11381121
case AndType(tp1, tp2) => stripToCore(tp1) ::: stripToCore(tp2)

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
213213
ta.assignType(untpd.TypeDef(sym.name, TypeTree(sym.info)), sym)
214214

215215
def ClassDef(cls: ClassSymbol, constr: DefDef, body: List[Tree], superArgs: List[Tree] = Nil)(implicit ctx: Context): TypeDef = {
216-
val firstParentRef :: otherParentRefs = cls.info.parents
217-
val firstParent = cls.typeRef.baseTypeWithArgs(firstParentRef.symbol)
216+
val firstParent :: otherParents = cls.info.parents
218217
val superRef =
219218
if (cls is Trait) TypeTree(firstParent)
220219
else {
@@ -229,7 +228,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
229228
val constr = firstParent.decl(nme.CONSTRUCTOR).suchThat(constr => isApplicable(constr.info))
230229
New(firstParent, constr.symbol.asTerm, superArgs)
231230
}
232-
val parents = superRef :: otherParentRefs.map(TypeTree(_))
231+
val parents = superRef :: otherParents.map(TypeTree(_))
233232

234233
val selfType =
235234
if (cls.classInfo.selfInfo ne NoType) ValDef(ctx.newSelfSym(cls))
@@ -305,7 +304,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
305304
true
306305
case pre: ThisType =>
307306
pre.cls.isStaticOwner ||
308-
tp.symbol.is(ParamOrAccessor) && !pre.cls.is(Trait) && ctx.owner.enclosingClass == pre.cls
307+
tp.symbol.isParamOrAccessor && !pre.cls.is(Trait) && ctx.owner.enclosingClass == pre.cls
309308
// was ctx.owner.enclosingClass.derivesFrom(pre.cls) which was not tight enough
310309
// and was spuriously triggered in case inner class would inherit from outer one
311310
// eg anonymous TypeMap inside TypeMap.andThen
@@ -381,7 +380,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
381380
/** new C(args), calling given constructor `constr` of C */
382381
def New(tp: Type, constr: TermSymbol, args: List[Tree])(implicit ctx: Context): Apply = {
383382
val targs = tp.argTypes
384-
val tycon = tp.withoutArgs(targs)
383+
val tycon = tp.typeConstructor
385384
New(tycon)
386385
.select(TermRef.withSig(tycon, constr))
387386
.appliedToTypes(targs)
@@ -698,8 +697,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
698697
*/
699698
def select(sym: Symbol)(implicit ctx: Context): Select = {
700699
val tp =
701-
if (sym.isType)
700+
if (sym.isType) {
701+
assert(!sym.is(TypeParam))
702702
TypeRef(tree.tpe, sym.name.asTypeName)
703+
}
703704
else
704705
TermRef.withSigAndDenot(tree.tpe, sym.name.asTermName,
705706
sym.signature, sym.denot.asSeenFrom(tree.tpe))

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
296296
(tycon, targs)
297297
case TypedSplice(AppliedTypeTree(tycon, targs)) =>
298298
(TypedSplice(tycon), targs map (TypedSplice(_)))
299-
case TypedSplice(tpt1: Tree) =>
299+
case TypedSplice(tpt1: tpd.Tree) =>
300+
val tycon = tpt1.tpe.typeConstructor
300301
val argTypes = tpt1.tpe.argTypesLo
301-
val tycon = tpt1.tpe.withoutArgs(argTypes)
302302
def wrap(tpe: Type) = TypeTree(tpe) withPos tpt.pos
303303
(wrap(tycon), argTypes map wrap)
304304
case _ =>

compiler/src/dotty/tools/dotc/config/Config.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,12 @@ object Config {
8484
/** If this flag is set, take the fast path when comparing same-named type-aliases and types */
8585
final val fastPathForRefinedSubtype = true
8686

87-
/** If this flag is set, `TypeOps.normalizeToClassRefs` will insert forwarders
88-
* for type parameters of base classes. This is an optimization, which avoids
89-
* long alias chains. We should not rely on the optimization, though. So changing
90-
* the flag to false can be used for checking that everything works OK without it.
91-
*/
92-
final val forwardTypeParams = true
93-
94-
/** If this flag is set, and we compute `T1 { X = S1 }` & `T2 { X = S2 }` as a new
95-
* upper bound of a constrained parameter, try to align the refinements by computing
87+
/** If this flag is set, and we compute `T1[X1]` & `T2[X2]` as a new
88+
* upper bound of a constrained parameter, try to align the arguments by computing
9689
* `S1 =:= S2` (which might instantiate type parameters).
9790
* This rule is contentious because it cuts the constraint set.
9891
*
99-
* For more info, see the comment in `TypeComparer#distributeAnd`.
92+
* For more info, see the comment in `TypeComparer#glbArgs`.
10093
*/
10194
final val alignArgsInAnd = true
10295

@@ -113,6 +106,13 @@ object Config {
113106
*/
114107
final val checkTypeRefCycles = false
115108

109+
/** If this flag is set, it is checked that class type parameters are
110+
* only references with NoPrefix or ThisTypes as prefixes. This option
111+
* is usally disabled, because there are still some legitimate cases where
112+
* this can arise (e.g. for pos/Map.scala, in LambdaType.integrate).
113+
*/
114+
final val checkTypeParamRefs = false
115+
116116
/** The recursion depth for showing a summarized string */
117117
final val summarizeDepth = 2
118118

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ class ScalaSettings extends Settings.SettingGroup {
6868
val Ycheck = PhasesSetting("-Ycheck", "Check the tree at the end of")
6969
val YcheckMods = BooleanSetting("-Ycheck-mods", "Check that symbols and their defining trees have modifiers in sync")
7070
val debug = BooleanSetting("-Ydebug", "Increase the quantity of debugging output.")
71-
val debugAlias = BooleanSetting("-Ydebug-alias", "Never follow alias when printing types")
7271
val debugTrace = BooleanSetting("-Ydebug-trace", "Trace core operations")
7372
val debugFlags = BooleanSetting("-Ydebug-flags", "Print all flags of definitions")
7473
val debugNames = BooleanSetting("-Ydebug-names", "Show internal representation of names")
@@ -88,7 +87,8 @@ class ScalaSettings extends Settings.SettingGroup {
8887
val YmethodInfer = BooleanSetting("-Yinfer-argument-types", "Infer types for arguments of overriden methods.")
8988
val YtraceContextCreation = BooleanSetting("-Ytrace-context-creation", "Store stack trace of context creations.")
9089
val YshowSuppressedErrors = BooleanSetting("-Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally supressed.")
91-
val Yheartbeat = BooleanSetting("-Yheartbeat", "show heartbeat stack trace of compiler operations.")
90+
val YdetailedStats = BooleanSetting("-Ydetailed-stats", "show detailed internal compiler stats (needs Stats.enabled to be set to true).")
91+
val Yheartbeat = BooleanSetting("-Ydetailed-stats", "show heartbeat stack trace of compiler operations (needs Stats.enabled to be set to true).")
9292
val Yprintpos = BooleanSetting("-Yprintpos", "show tree positions.")
9393
val YnoDeepSubtypes = BooleanSetting("-Yno-deep-subtypes", "throw an exception on deep subtyping call stacks.")
9494
val YnoPatmatOpt = BooleanSetting("-Yno-patmat-opt", "disable all pattern matching optimizations.")

compiler/src/dotty/tools/dotc/core/Annotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ object Annotations {
103103

104104
private def resolveConstructor(atp: Type, args:List[Tree])(implicit ctx: Context): Tree = {
105105
val targs = atp.argTypes
106-
tpd.applyOverloaded(New(atp withoutArgs targs), nme.CONSTRUCTOR, args, targs, atp, isAnnotConstructor = true)
106+
tpd.applyOverloaded(New(atp.typeConstructor), nme.CONSTRUCTOR, args, targs, atp, isAnnotConstructor = true)
107107
}
108108

109109
def applyResolve(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = {

compiler/src/dotty/tools/dotc/core/CheckRealizable.scala

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ object CheckRealizable {
3333
class HasProblemBounds(typ: SingleDenotation)(implicit ctx: Context)
3434
extends Realizability(i" has a member $typ with possibly conflicting bounds ${typ.info.bounds.lo} <: ... <: ${typ.info.bounds.hi}")
3535

36+
class HasProblemBaseArg(typ: Type, argBounds: TypeBounds)(implicit ctx: Context)
37+
extends Realizability(i" has a base type $typ with possibly conflicting parameter bounds ${argBounds.lo} <: ... <: ${argBounds.hi}")
38+
39+
class HasProblemBase(base1: Type, base2: Type)(implicit ctx: Context)
40+
extends Realizability(i" has conflicting base types $base1 and $base2")
41+
3642
class HasProblemField(fld: SingleDenotation, problem: Realizability)(implicit ctx: Context)
3743
extends Realizability(i" has a member $fld which is not a legal path\n since ${fld.symbol.name}: ${fld.info}${problem.msg}")
3844

@@ -89,18 +95,39 @@ class CheckRealizable(implicit ctx: Context) {
8995
else boundsRealizability(tp).andAlso(memberRealizability(tp))
9096
}
9197

92-
/** `Realizable` if `tp` has good bounds, a `HasProblemBounds` instance
93-
* pointing to a bad bounds member otherwise.
98+
/** `Realizable` if `tp` has good bounds, a `HasProblem...` instance
99+
* pointing to a bad bounds member otherwise. "Has good bounds" means:
100+
*
101+
* - all type members have good bounds
102+
* - all base types are class types, and if their arguments are wildcards
103+
* they have good bounds.
104+
* - base types do not appear in multiple instances with different arguments.
105+
* (depending on the simplification scheme for AndTypes employed, this could
106+
* also lead to base types with bad bounds).
94107
*/
95108
private def boundsRealizability(tp: Type) = {
96-
def hasBadBounds(mbr: SingleDenotation) = {
97-
val bounds = mbr.info.bounds
98-
!(bounds.lo <:< bounds.hi)
99-
}
100-
tp.nonClassTypeMembers.find(hasBadBounds) match {
101-
case Some(mbr) => new HasProblemBounds(mbr)
102-
case _ => Realizable
109+
val mbrProblems =
110+
for {
111+
mbr <- tp.nonClassTypeMembers
112+
if !(mbr.info.loBound <:< mbr.info.hiBound)
113+
}
114+
yield new HasProblemBounds(mbr)
115+
116+
def baseTypeProblems(base: Type) = base match {
117+
case AndType(base1, base2) =>
118+
new HasProblemBase(base1, base2) :: Nil
119+
case base =>
120+
base.argInfos.collect {
121+
case bounds @ TypeBounds(lo, hi) if !(lo <:< hi) =>
122+
new HasProblemBaseArg(base, bounds)
123+
}
103124
}
125+
val baseProblems =
126+
tp.baseClasses.map(_.baseTypeOf(tp)).flatMap(baseTypeProblems)
127+
128+
(((Realizable: Realizability)
129+
/: mbrProblems)(_ andAlso _)
130+
/: baseProblems)(_ andAlso _)
104131
}
105132

106133
/** `Realizable` if all of `tp`'s non-struct fields have realizable types,

compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Types._, Contexts._, Symbols._
66
import Decorators._
77
import config.Config
88
import config.Printers.{constr, typr}
9-
import TypeApplications.EtaExpansion
9+
import TypeApplications.{EtaExpansion, TypeParamInfo}
1010
import collection.mutable
1111

1212
/** Methods for adding constraints and solving them.
@@ -194,9 +194,14 @@ trait ConstraintHandling {
194194
final def approximation(param: TypeParamRef, fromBelow: Boolean): Type = {
195195
val avoidParam = new TypeMap {
196196
override def stopAtStatic = true
197+
def avoidInArg(arg: Type): Type =
198+
if (param.occursIn(arg)) TypeBounds.empty else arg
197199
def apply(tp: Type) = mapOver {
198200
tp match {
199-
case tp: RefinedType if param occursIn tp.refinedInfo => tp.parent
201+
case tp @ AppliedType(tycon, args) =>
202+
tp.derivedAppliedType(tycon, args.mapConserve(avoidInArg))
203+
case tp: RefinedType if param occursIn tp.refinedInfo =>
204+
tp.parent
200205
case tp: WildcardType =>
201206
val bounds = tp.optBounds.orElse(TypeBounds.empty).bounds
202207
// Try to instantiate the wildcard to a type that is known to conform to it.
@@ -306,7 +311,12 @@ trait ConstraintHandling {
306311
/** The current bounds of type parameter `param` */
307312
final def bounds(param: TypeParamRef): TypeBounds = {
308313
val e = constraint.entry(param)
309-
if (e.exists) e.bounds else param.binder.paramInfos(param.paramNum)
314+
if (e.exists) e.bounds
315+
else {
316+
val pinfos = param.binder.paramInfos
317+
if (pinfos != null) pinfos(param.paramNum) // pinfos == null happens in pos/i536.scala
318+
else TypeBounds.empty
319+
}
310320
}
311321

312322
/** Add type lambda `tl`, possibly with type variables `tvars`, to current constraint
@@ -318,7 +328,7 @@ trait ConstraintHandling {
318328
checkPropagated(i"initialized $tl") {
319329
constraint = constraint.add(tl, tvars)
320330
tl.paramNames.indices.forall { i =>
321-
val param = TypeParamRef(tl, i)
331+
val param = tl.paramRefs(i)
322332
val bounds = constraint.nonParamBounds(param)
323333
val lower = constraint.lower(param)
324334
val upper = constraint.upper(param)
@@ -376,7 +386,12 @@ trait ConstraintHandling {
376386
else tp
377387

378388
def addParamBound(bound: TypeParamRef) =
379-
if (fromBelow) addLess(bound, param) else addLess(param, bound)
389+
constraint.entry(param) match {
390+
case _: TypeBounds =>
391+
if (fromBelow) addLess(bound, param) else addLess(param, bound)
392+
case tp =>
393+
if (fromBelow) isSubType(bound, tp) else isSubType(tp, bound)
394+
}
380395

381396
/** Drop all constrained parameters that occur at the toplevel in `bound` and
382397
* handle them by `addLess` calls.

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import NameOps._
1414
import Uniques._
1515
import SymDenotations._
1616
import Comments._
17-
import Flags.ParamAccessor
1817
import util.Positions._
1918
import ast.Trees._
2019
import ast.untpd
@@ -339,7 +338,7 @@ object Contexts {
339338
* from constructor parameters to class parameter accessors.
340339
*/
341340
def superCallContext: Context = {
342-
val locals = newScopeWith(owner.asClass.paramAccessors: _*)
341+
val locals = newScopeWith(owner.typeParams ++ owner.asClass.paramAccessors: _*)
343342
superOrThisCallContext(owner.primaryConstructor, locals)
344343
}
345344

@@ -609,20 +608,20 @@ object Contexts {
609608
override def hash(x: Type): Int = x.hash
610609
}
611610

612-
/** A table for hash consing unique refined types */
613-
private[dotc] val uniqueRefinedTypes = new RefinedUniques
611+
/** A table for hash consing unique applied types */
612+
private[dotc] val uniqueAppliedTypes = new AppliedUniques
614613

615614
/** A table for hash consing unique named types */
616615
private[core] val uniqueNamedTypes = new NamedTypeUniques
617616

618-
/** A table for hash consing unique type bounds */
619-
private[core] val uniqueTypeAliases = new TypeAliasUniques
617+
/** A table for hash consing unique symbolic named types */
618+
private[core] val uniqueWithFixedSyms = new WithFixedSymUniques
620619

621620
private def uniqueSets = Map(
622621
"uniques" -> uniques,
623-
"uniqueRefinedTypes" -> uniqueRefinedTypes,
624-
"uniqueNamedTypes" -> uniqueNamedTypes,
625-
"uniqueTypeAliases" -> uniqueTypeAliases)
622+
"uniqueAppliedTypes" -> uniqueAppliedTypes,
623+
"uniqueWithFixedSyms" -> uniqueWithFixedSyms,
624+
"uniqueNamedTypes" -> uniqueNamedTypes)
626625

627626
/** A map that associates label and size of all uniques sets */
628627
def uniquesSizes: Map[String, Int] = uniqueSets.mapValues(_.size)

0 commit comments

Comments
 (0)