Skip to content

Commit 7995851

Browse files
committed
Roll some of FirstTransform functionaility into PostTyper
Everything that needs to be done before pickling moves to PostTyper. The idea is that we want to make Pickler come before FirstTransform.
1 parent 1d4e4a6 commit 7995851

File tree

3 files changed

+76
-75
lines changed

3 files changed

+76
-75
lines changed

src/dotty/tools/dotc/transform/FirstTransform.scala

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ import StdNames._
2424

2525
/** The first tree transform
2626
* - ensures there are companion objects for all classes except module classes
27-
* - eliminates some kinds of trees: Imports, NamedArgs, all TypTrees other than TypeTree
28-
* - converts Select/Ident/SelectFromTypeTree nodes that refer to types to TypeTrees.
29-
* - inserts `.package` for selections of package object members
30-
* - checks the bounds of AppliedTypeTrees
27+
* - eliminates some kinds of trees: Imports, NamedArgs
3128
* - stubs out native methods
3229
*/
3330
class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer with AnnotationTransformer { thisTransformer =>
@@ -111,47 +108,10 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
111108
override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] =
112109
ast.Trees.flatten(reorderAndComplete(trees)(ctx.withPhase(thisTransformer.next)))
113110

114-
private def normalizeType(tree: Tree)(implicit ctx: Context) =
115-
if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else tree
116-
117-
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = tree.tpe match {
118-
case tpe: ThisType =>
119-
/*
120-
A this reference hide in a self ident, and be subsequently missed
121-
when deciding on whether outer accessors are needed and computing outer paths.
122-
We do this normalization directly after Typer, because during typer the
123-
ident should rest available for hyperlinking.*/
124-
This(tpe.cls).withPos(tree.pos)
125-
case _ => normalizeType(tree)
126-
}
127-
128-
129-
130-
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
131-
normalizeType {
132-
val qual = tree.qualifier
133-
qual.symbol.moduleClass.denot match {
134-
case pkg: PackageClassDenotation if !tree.symbol.maybeOwner.is(Package) =>
135-
cpy.Select(tree)(qual select pkg.packageObj.symbol, tree.name)
136-
case _ =>
137-
tree
138-
}
139-
}
140-
141-
override def transformSelectFromTypeTree(tree: SelectFromTypeTree)(implicit ctx: Context, info: TransformerInfo) =
142-
normalizeType(tree)
143-
144111
override def transformOther(tree: Tree)(implicit ctx: Context, info: TransformerInfo) = tree match {
145112
case tree: Import => EmptyTree
146113
case tree: NamedArg => transform(tree.arg)
147-
case AppliedTypeTree(tycon, args) =>
148-
val tparams = tycon.tpe.typeSymbol.typeParams
149-
val bounds = tparams.map(tparam =>
150-
tparam.info.asSeenFrom(tycon.tpe.normalizedPrefix, tparam.owner.owner).bounds)
151-
Checking.checkBounds(args, bounds, _.substDealias(tparams, _))
152-
normalizeType(tree)
153-
case tree =>
154-
normalizeType(tree)
114+
case tree => tree
155115
}
156116

157117
// invariants: all modules have companion objects

src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import ValueClasses._
88
import scala.annotation.tailrec
99
import core._
1010
import typer.ErrorReporting._
11+
import typer.Checking
1112
import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._
1213
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
1314
import util.Positions._
@@ -27,6 +28,14 @@ import Symbols._, TypeUtils._
2728
*
2829
* (4) Check that `New` nodes can be instantiated, and that annotations are valid
2930
*
31+
* (5) Convert all trees representing types to TypeTrees.
32+
*
33+
* (6) Check the bounds of AppliedTypeTrees
34+
*
35+
* (7) Insert `.package` for selections of package object members
36+
*
37+
* (8) Replaces self references by name with `this`
38+
*
3039
* The reason for making this a macro transform is that some functions (in particular
3140
* super and protected accessors and instantiation checks) are naturally top-down and
3241
* don't lend themselves to the bottom-up approach of a mini phase. The other two functions
@@ -49,24 +58,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
4958
val superAcc = new SuperAccessors(thisTransformer)
5059
val paramFwd = new ParamForwarding(thisTransformer)
5160
val synthMth = new SyntheticMethods(thisTransformer)
52-
53-
/** Check that `tp` refers to a nonAbstract class
54-
* and that the instance conforms to the self type of the created class.
55-
*/
56-
private def checkInstantiable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
57-
tp.underlyingClassRef(refinementOK = false) match {
58-
case tref: TypeRef =>
59-
val cls = tref.symbol
60-
if (cls.is(AbstractOrTrait))
61-
ctx.error(d"$cls is abstract; cannot be instantiated", pos)
62-
if (!cls.is(Module)) {
63-
val selfType = tp.givenSelfType.asSeenFrom(tref.prefix, cls.owner)
64-
if (selfType.exists && !(tp <:< selfType))
65-
ctx.error(d"$tp does not conform to its self type $selfType; cannot be instantiated")
66-
}
67-
case _ =>
68-
}
69-
61+
7062
private def newPart(tree: Tree): Option[New] = methPart(tree) match {
7163
case Select(nu: New, _) => Some(nu)
7264
case _ => None
@@ -76,6 +68,22 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
7668
// TODO fill in
7769
}
7870

71+
private def normalizeTypeTree(tree: Tree)(implicit ctx: Context) = {
72+
def norm(tree: Tree) = if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else tree
73+
tree match {
74+
case tree: TypeTree =>
75+
tree
76+
case AppliedTypeTree(tycon, args) =>
77+
val tparams = tycon.tpe.typeSymbol.typeParams
78+
val bounds = tparams.map(tparam =>
79+
tparam.info.asSeenFrom(tycon.tpe.normalizedPrefix, tparam.owner.owner).bounds)
80+
Checking.checkBounds(args, bounds, _.substDealias(tparams, _))
81+
norm(tree)
82+
case _ =>
83+
norm(tree)
84+
}
85+
}
86+
7987
class PostTyperTransformer extends Transformer {
8088

8189
private var inJavaAnnot: Boolean = false
@@ -96,35 +104,51 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
96104
private def transformAnnots(tree: MemberDef)(implicit ctx: Context): Unit =
97105
tree.symbol.transformAnnotations(transformAnnot)
98106

107+
private def transformSelect(tree: Select, targs: List[Tree])(implicit ctx: Context) = {
108+
val qual = tree.qualifier
109+
qual.symbol.moduleClass.denot match {
110+
case pkg: PackageClassDenotation if !tree.symbol.maybeOwner.is(Package) =>
111+
assert(targs.isEmpty)
112+
cpy.Select(tree)(qual select pkg.packageObj.symbol, tree.name)
113+
case _ =>
114+
superAcc.transformSelect(super.transform(tree), targs)
115+
}
116+
}
117+
99118
override def transform(tree: Tree)(implicit ctx: Context): Tree =
100-
try tree match {
101-
case impl: Template =>
119+
try normalizeTypeTree(tree) match {
120+
case tree: Ident =>
121+
tree.tpe match {
122+
case tpe: ThisType => This(tpe.cls).withPos(tree.pos)
123+
case _ => tree
124+
}
125+
case tree: Select =>
126+
transformSelect(tree, Nil)
127+
case tree @ TypeApply(sel: Select, args) =>
128+
val args1 = transform(args)
129+
val sel1 = transformSelect(sel, args1)
130+
if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args1)
131+
case tree @ Assign(sel: Select, _) =>
132+
superAcc.transformAssign(super.transform(tree))
133+
case tree: Template =>
102134
val saved = parentNews
103-
parentNews ++= impl.parents.flatMap(newPart)
135+
parentNews ++= tree.parents.flatMap(newPart)
104136
try
105137
synthMth.addSyntheticMethods(
106138
paramFwd.forwardParamAccessors(
107-
superAcc.wrapTemplate(impl)(
139+
superAcc.wrapTemplate(tree)(
108140
super.transform(_).asInstanceOf[Template])))
109141
finally parentNews = saved
110-
case tree @ TypeApply(sel: Select, args) =>
111-
val args1 = transform(args)
112-
val sel1 = superAcc.transformSelect(super.transform(sel), args1)
113-
if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args1)
114-
case sel: Select =>
115-
superAcc.transformSelect(super.transform(sel), Nil)
116-
case tree @ Assign(sel: Select, _) =>
117-
superAcc.transformAssign(super.transform(tree))
118142
case tree: DefDef =>
119143
transformAnnots(tree)
120144
superAcc.wrapDefDef(tree)(super.transform(tree).asInstanceOf[DefDef])
121145
case tree: MemberDef =>
122146
transformAnnots(tree)
123147
super.transform(tree)
124148
case tree: New if !inJavaAnnot && !parentNews.contains(tree) =>
125-
checkInstantiable(tree.tpe, tree.pos)
149+
Checking.checkInstantiable(tree.tpe, tree.pos)
126150
super.transform(tree)
127-
case Annotated(annot, annotated) =>
151+
case tree @ Annotated(annot, annotated) =>
128152
cpy.Annotated(tree)(transformAnnot(annot), transform(annotated))
129153
case tree: TypeTree =>
130154
tree.withType(
@@ -133,7 +157,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
133157
case tpe => tpe
134158
}
135159
)
136-
case _ =>
160+
case tree =>
137161
super.transform(tree)
138162
}
139163
catch {

src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,23 @@ object Checking {
3939
d"Type argument ${arg.tpe} does not conform to $which bound $bound ${err.whyNoMatchStr(arg.tpe, bound)}",
4040
arg.pos)
4141

42+
/** Check that `tp` refers to a nonAbstract class
43+
* and that the instance conforms to the self type of the created class.
44+
*/
45+
def checkInstantiable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
46+
tp.underlyingClassRef(refinementOK = false) match {
47+
case tref: TypeRef =>
48+
val cls = tref.symbol
49+
if (cls.is(AbstractOrTrait))
50+
ctx.error(d"$cls is abstract; cannot be instantiated", pos)
51+
if (!cls.is(Module)) {
52+
val selfType = tp.givenSelfType.asSeenFrom(tref.prefix, cls.owner)
53+
if (selfType.exists && !(tp <:< selfType))
54+
ctx.error(d"$tp does not conform to its self type $selfType; cannot be instantiated")
55+
}
56+
case _ =>
57+
}
58+
4259
/** A type map which checks that the only cycles in a type are F-bounds
4360
* and that protects all F-bounded references by LazyRefs.
4461
*/

0 commit comments

Comments
 (0)