aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala51
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala12
3 files changed, 35 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index edf97f5b8..f9862bb95 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -68,7 +68,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
// TODO fill in
}
- /** Check bounds of AppliedTypeTrees and TypeApplys.
+ /** Check bounds of AppliedTypeTrees.
* Replace type trees with TypeTree nodes.
* Replace constant expressions with Literal nodes.
* Note: Demanding idempotency instead of purity in literalize is strictly speaking too loose.
@@ -97,29 +97,17 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
* Revisit this issue once we have implemented `inline`. Then we can demand
* purity of the prefix unless the selection goes to an inline val.
*/
- private def normalizeTree(tree: Tree)(implicit ctx: Context): Tree = {
- def literalize(tp: Type): Tree = tp.widenTermRefExpr match {
- case ConstantType(value) if isIdempotentExpr(tree) => Literal(value)
- case _ => tree
- }
- def norm(tree: Tree) =
- if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
- else literalize(tree.tpe)
- tree match {
- case tree: TypeTree =>
- tree
- case AppliedTypeTree(tycon, args) =>
- val tparams = tycon.tpe.typeSymbol.typeParams
- val bounds = tparams.map(tparam =>
- tparam.info.asSeenFrom(tycon.tpe.normalizedPrefix, tparam.owner.owner).bounds)
- Checking.checkBounds(args, bounds, _.substDealias(tparams, _))
- norm(tree)
- case TypeApply(fn, args) =>
- Checking.checkBounds(args, fn.tpe.widen.asInstanceOf[PolyType])
- norm(tree)
- case _ =>
- norm(tree)
- }
+ private def normalizeTree(tree: Tree)(implicit ctx: Context): Tree = tree match {
+ case tree: TypeTree => tree
+ case _ =>
+ if (tree.isType) {
+ Checking.boundsChecker.traverse(tree)
+ TypeTree(tree.tpe).withPos(tree.pos)
+ }
+ else tree.tpe.widenTermRefExpr match {
+ case ConstantType(value) if isIdempotentExpr(tree) => Literal(value)
+ case _ => tree
+ }
}
class PostTyperTransformer extends Transformer {
@@ -161,10 +149,16 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
}
case tree: Select =>
transformSelect(paramFwd.adaptRef(tree), Nil)
- case tree @ TypeApply(sel: Select, args) =>
- val args1 = transform(args)
- val sel1 = transformSelect(sel, args1)
- if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args1)
+ case tree @ TypeApply(fn, args) =>
+ Checking.checkBounds(args, fn.tpe.widen.asInstanceOf[PolyType])
+ fn match {
+ case sel: Select =>
+ val args1 = transform(args)
+ val sel1 = transformSelect(sel, args1)
+ if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args1)
+ case _ =>
+ super.transform(tree)
+ }
case tree @ Assign(sel: Select, _) =>
superAcc.transformAssign(super.transform(tree))
case tree: Template =>
@@ -186,6 +180,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
val tree1 =
if (sym.isClass) tree
else {
+ Checking.boundsChecker.traverse(tree.rhs)
cpy.TypeDef(tree)(rhs = TypeTree(tree.symbol.info))
}
super.transform(tree1)
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index b3cda20b8..649b8088f 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -607,7 +607,6 @@ trait Applications extends Compatibility { self: Typer =>
case pt: PolyType =>
if (typedArgs.length <= pt.paramBounds.length)
typedArgs = typedArgs.zipWithConserve(pt.paramBounds)(adaptTypeArg)
- Checking.checkBounds(typedArgs, pt)
case _ =>
}
assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs)
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 6ded7c109..3e829eb50 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -48,6 +48,18 @@ object Checking {
def checkBounds(args: List[tpd.Tree], poly: PolyType)(implicit ctx: Context): Unit =
checkBounds(args, poly.paramBounds, _.substParams(poly, _))
+ /** Check all AppliedTypeTree nodes in this tree for legal bounds */
+ val boundsChecker = new TreeTraverser {
+ def traverse(tree: Tree)(implicit ctx: Context) = tree match {
+ case AppliedTypeTree(tycon, args) =>
+ val tparams = tycon.tpe.typeSymbol.typeParams
+ val bounds = tparams.map(tparam =>
+ tparam.info.asSeenFrom(tycon.tpe.normalizedPrefix, tparam.owner.owner).bounds)
+ checkBounds(args, bounds, _.substDealias(tparams, _))
+ case _ => traverseChildren(tree)
+ }
+ }
+
/** Check that `tp` refers to a nonAbstract class
* and that the instance conforms to the self type of the created class.
*/