aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Typer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-09-25 17:04:22 +0200
committerMartin Odersky <odersky@gmail.com>2016-09-25 17:04:22 +0200
commit80cbe114cc5d641d66512c58402eca4ae69f9f2a (patch)
treec2d137266a0ae6c59e44e15f959f0ca070ec0b7c /src/dotty/tools/dotc/typer/Typer.scala
parent2d908c792fcf4287b4cb493f0e51dfbdb106cf69 (diff)
downloaddotty-80cbe114cc5d641d66512c58402eca4ae69f9f2a.tar.gz
dotty-80cbe114cc5d641d66512c58402eca4ae69f9f2a.tar.bz2
dotty-80cbe114cc5d641d66512c58402eca4ae69f9f2a.zip
Get rid of SelectFromType tree node.
Roll its functionality into Select. Since we can always tell whether a tree is a type or term there is no expressiveness gained by having a separate tree node.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Typer.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala75
1 files changed, 39 insertions, 36 deletions
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 072240248..2550da793 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -363,52 +363,45 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
else tree
def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = track("typedSelect") {
- def asSelect(implicit ctx: Context): Tree = {
- val qual1 = typedExpr(tree.qualifier, selectionProto(tree.name, pt, this))
- if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos)
- val select = typedSelect(tree, pt, qual1)
- if (select.tpe ne TryDynamicCallType) select
- else if (pt.isInstanceOf[PolyProto] || pt.isInstanceOf[FunProto] || pt == AssignProto) select
- else typedDynamicSelect(tree, Nil, pt)
- }
-
- def asJavaSelectFromTypeTree(implicit ctx: Context): Tree = {
- // Translate names in Select/Ident nodes to type names.
- def convertToTypeName(tree: untpd.Tree): Option[untpd.Tree] = tree match {
- case Select(qual, name) => Some(untpd.Select(qual, name.toTypeName))
- case Ident(name) => Some(untpd.Ident(name.toTypeName))
- case _ => None
+ def typeAsIs(implicit ctx: Context): Tree = {
+ if (tree.qualifier.isType) {
+ val qual1 = typedType(tree.qualifier, selectionProto(tree.name, pt, this))
+ assignType(cpy.Select(tree)(qual1, tree.name), qual1)
}
+ else {
+ val qual1 = typedExpr(tree.qualifier, selectionProto(tree.name, pt, this))
+ if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos)
+ val select = typedSelect(tree, pt, qual1)
+ if (select.tpe ne TryDynamicCallType) select
+ else if (pt.isInstanceOf[PolyProto] || pt.isInstanceOf[FunProto] || pt == AssignProto) select
+ else typedDynamicSelect(tree, Nil, pt)
+ }
+ }
- // Try to convert Select(qual, name) to a SelectFromTypeTree.
- def convertToSelectFromType(qual: untpd.Tree, origName: Name): Option[untpd.SelectFromTypeTree] =
- convertToTypeName(qual) match {
- case Some(qual1) => Some(untpd.SelectFromTypeTree(qual1 withPos qual.pos, origName.toTypeName))
- case _ => None
- }
-
- convertToSelectFromType(tree.qualifier, tree.name) match {
- case Some(sftt) => typedSelectFromTypeTree(sftt, pt)
- case _ => ctx.error(em"Could not convert $tree to a SelectFromTypeTree"); EmptyTree
+ def asJavaSelectFromType(implicit ctx: Context): Tree = {
+ def typeSelectOnType(qual: untpd.Tree) =
+ typedSelect(untpd.cpy.Select(tree)(qual, tree.name.toTypeName), pt)
+ tree.qualifier match {
+ case Select(qual, name) => typeSelectOnType(untpd.Select(qual, name.toTypeName))
+ case Ident(name) => typeSelectOnType(untpd.Ident(name.toTypeName))
+ case _ => errorTree(tree, "cannot convert to type selection") // will never be printed due to fallback
}
}
- def selectWithFallback(fallBack: => Tree) =
- tryEither(tryCtx => asSelect(tryCtx))((_, _) => fallBack)
+ def selectWithFallback(fallBack: Context => Tree) =
+ tryAlternatively(typeAsIs(_))(fallBack)
if (ctx.compilationUnit.isJava && tree.name.isTypeName)
// SI-3120 Java uses the same syntax, A.B, to express selection from the
// value A and from the type A. We have to try both.
- selectWithFallback(asJavaSelectFromTypeTree(ctx))
+ selectWithFallback(asJavaSelectFromType(_)) // !!! possibly exponential bcs of qualifier retyping
else if (tree.name == nme.withFilter && tree.getAttachment(desugar.MaybeFilter).isDefined)
- selectWithFallback(typedSelect(untpd.cpy.Select(tree)(tree.qualifier, nme.filter), pt))
+ selectWithFallback {
+ implicit ctx =>
+ typedSelect(untpd.cpy.Select(tree)(tree.qualifier, nme.filter), pt) // !!! possibly exponential bcs of qualifier retyping
+ }
else
- asSelect(ctx)
- }
-
- def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context): Tree = track("typedSelectFromTypeTree") {
- val qual1 = typedType(tree.qualifier, selectionProto(tree.name, pt, this))
- assignType(cpy.SelectFromTypeTree(tree)(qual1, tree.name), qual1)
+ typeAsIs(ctx)
}
def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = track("typedThis") {
@@ -1393,7 +1386,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
tree match {
case tree: untpd.Ident => typedIdent(tree, pt)
case tree: untpd.Select => typedSelect(tree, pt)
- case tree: untpd.SelectFromTypeTree => typedSelectFromTypeTree(tree, pt)
case tree: untpd.Bind => typedBind(tree, pt)
case tree: untpd.ValDef =>
if (tree.isEmpty) tpd.EmptyValDef
@@ -1516,6 +1508,17 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}
+ /** Try `op1`, if there are errors, try `op2`, if `op2` also causes errors, fall back
+ * to errors and result of `op1`.
+ */
+ def tryAlternatively[T](op1: Context => T)(op2: Context => T)(implicit ctx: Context): T =
+ tryEither(op1) { (failedVal, failedState) =>
+ tryEither(op2) { (_, _) =>
+ failedState.commit
+ failedVal
+ }
+ }
+
/** Add apply node or implicit conversions. Two strategies are tried, and the first
* that is successful is picked. If neither of the strategies are successful, continues with
* `fallBack`.