aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDmitry Petrashko <dark@d-d.me>2015-04-09 13:35:58 +0200
committerDmitry Petrashko <dark@d-d.me>2015-04-09 13:35:58 +0200
commit6fc0a0ff71c0692ae7ed49c31bfc4533625b5764 (patch)
tree6e4770c45eb2ad58b70b25644463a3aaaa45e135 /src
parentb8ffaf83984dd385fdab187ab83893a64b785519 (diff)
parent673842f94e68beb6f8bfa8136b37578464b0e55b (diff)
downloaddotty-6fc0a0ff71c0692ae7ed49c31bfc4533625b5764.tar.gz
dotty-6fc0a0ff71c0692ae7ed49c31bfc4533625b5764.tar.bz2
dotty-6fc0a0ff71c0692ae7ed49c31bfc4533625b5764.zip
Merge pull request #456 from dotty-staging/patmat-eqeq
Fix #453, patternMatcher should use ==
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/ast/TreeTypeMap.scala2
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala41
-rw-r--r--src/dotty/tools/dotc/config/ScalaSettings.scala2
-rw-r--r--src/dotty/tools/dotc/transform/InterceptedMethods.scala6
-rw-r--r--src/dotty/tools/dotc/transform/PatternMatcher.scala3
5 files changed, 46 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
index d2ec3ea10..ec66fcdb8 100644
--- a/src/dotty/tools/dotc/ast/TreeTypeMap.scala
+++ b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
@@ -30,7 +30,7 @@ import dotty.tools.dotc.transform.SymUtils._
* have two substitutons S1 = [outer#1 := outer#3], S2 = [inner#2 := inner#4] where
* hashtags precede symbol ids. If we do S1 first, we get outer#2.inner#3. If we then
* do S2 we get outer#2.inner#4. But that means that the named type outer#2.inner
- * gets two different denotations in the same period. Hence, if -YnoDoubleBindings is
+ * gets two different denotations in the same period. Hence, if -Yno-double-bindings is
* set, we would get a data race assertion error.
*/
final class TreeTypeMap(
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 9e799a8d3..0f4585a53 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -588,63 +588,97 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
tree
}
+ /** A select node with the given selector name and a computed type */
def select(name: Name)(implicit ctx: Context): Select =
Select(tree, name)
+ /** A select node with the given type */
def select(tp: NamedType)(implicit ctx: Context): Select =
untpd.Select(tree, tp.name).withType(tp)
+ /** A select node that selects the given symbol. Note: Need to make sure this
+ * is in fact the symbol you would get when you select with the symbol's name,
+ * otherwise a data race may occur which would be flagged by -Yno-double-bindings.
+ */
def select(sym: Symbol)(implicit ctx: Context): Select =
untpd.Select(tree, sym.name).withType(
TermRef.withSigAndDenot(tree.tpe, sym.name.asTermName, sym.signature, sym.denot.asSeenFrom(tree.tpe)))
- def selectWithSig(name: Name, sig: Signature)(implicit ctx: Context) =
+ /** A select node with the given selector name and signature and a computed type */
+ def selectWithSig(name: Name, sig: Signature)(implicit ctx: Context): Tree =
untpd.SelectWithSig(tree, name, sig)
.withType(TermRef.withSig(tree.tpe, name.asTermName, sig))
+ /** A select node with selector name and signature taken from `sym`.
+ * Note: Use this method instead of select(sym) if the referenced symbol
+ * might be overridden in the type of the qualifier prefix. See note
+ * on select(sym: Symbol).
+ */
+ def selectWithSig(sym: Symbol)(implicit ctx: Context): Tree =
+ selectWithSig(sym.name, sym.signature)
+
+ /** A unary apply node with given argument: `tree(arg)` */
def appliedTo(arg: Tree)(implicit ctx: Context): Tree =
appliedToArgs(arg :: Nil)
+ /** An apply node with given arguments: `tree(arg, args0, ..., argsN)` */
def appliedTo(arg: Tree, args: Tree*)(implicit ctx: Context): Tree =
appliedToArgs(arg :: args.toList)
+ /** An apply node with given argument list `tree(args(0), ..., args(args.length - 1))` */
def appliedToArgs(args: List[Tree])(implicit ctx: Context): Apply =
Apply(tree, args)
+ /** The current tree applied to given argument lists:
+ * `tree (argss(0)) ... (argss(argss.length -1))`
+ */
def appliedToArgss(argss: List[List[Tree]])(implicit ctx: Context): Tree =
((tree: Tree) /: argss)(Apply(_, _))
+ /** The current tree applied to (): `tree()` */
def appliedToNone(implicit ctx: Context): Apply = appliedToArgs(Nil)
+ /** The current tree applied to given type argument: `tree[targ]` */
def appliedToType(targ: Type)(implicit ctx: Context): Tree =
appliedToTypes(targ :: Nil)
+ /** The current tree applied to given type arguments: `tree[targ0, ..., targN]` */
def appliedToTypes(targs: List[Type])(implicit ctx: Context): Tree =
appliedToTypeTrees(targs map (TypeTree(_)))
+ /** The current tree applied to given type argument list: `tree[targs(0), ..., targs(targs.length - 1)]` */
def appliedToTypeTrees(targs: List[Tree])(implicit ctx: Context): Tree =
if (targs.isEmpty) tree else TypeApply(tree, targs)
+ /** Apply to `()` unless tree's widened type is parameterless */
def ensureApplied(implicit ctx: Context): Tree =
if (tree.tpe.widen.isParameterless) tree else tree.appliedToNone
+ /** `tree.isInstanceOf[tp]` */
def isInstance(tp: Type)(implicit ctx: Context): Tree =
tree.select(defn.Any_isInstanceOf).appliedToType(tp)
+ /** tree.asInstanceOf[`tp`] */
def asInstance(tp: Type)(implicit ctx: Context): Tree = {
assert(tp.isValueType, i"bad cast: $tree.asInstanceOf[$tp]")
tree.select(defn.Any_asInstanceOf).appliedToType(tp)
}
+ /** `tree.asInstanceOf[tp]` unless tree's type already conforms to `tp` */
def ensureConforms(tp: Type)(implicit ctx: Context): Tree =
if (tree.tpe <:< tp) tree else asInstance(tp)
+ /** `this && that`, for boolean trees `this`, `that` */
def and(that: Tree)(implicit ctx: Context): Tree =
tree.select(defn.Boolean_&&).appliedTo(that)
+ /** `this || that`, for boolean trees `this`, `that` */
def or(that: Tree)(implicit ctx: Context): Tree =
tree.select(defn.Boolean_||).appliedTo(that)
+ /** The translation of `tree = rhs`.
+ * This is either the tree as an assignment, to a setter call.
+ */
def becomes(rhs: Tree)(implicit ctx: Context): Tree =
if (tree.symbol is Method) {
val setr = tree match {
@@ -660,13 +694,15 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
// --- Higher order traversal methods -------------------------------
- def foreachSubTree(f: Tree => Unit)(implicit ctx: Context): Unit = { //TODO should go in tpd.
+ /** Apply `f` to each subtree of this tree */
+ def foreachSubTree(f: Tree => Unit)(implicit ctx: Context): Unit = {
val traverser = new TreeTraverser {
def traverse(tree: Tree)(implicit ctx: Context) = foldOver(f(tree), tree)
}
traverser.traverse(tree)
}
+ /** Is there a subtree of this tree that satisfies predicate `p`? */
def existsSubTree(p: Tree => Boolean)(implicit ctx: Context): Boolean = {
val acc = new TreeAccumulator[Boolean] {
def apply(x: Boolean, t: Tree)(implicit ctx: Context) = x || p(t) || foldOver(x, t)
@@ -674,6 +710,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
acc(false, tree)
}
+ /** All subtrees of this tree that satisfy predicate `p`. */
def filterSubTrees(f: Tree => Boolean)(implicit ctx: Context): List[Tree] = {
val buf = new mutable.ListBuffer[Tree]
foreachSubTree { tree => if (f(tree)) buf += tree }
diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala
index 1c1f3e494..0d4034db2 100644
--- a/src/dotty/tools/dotc/config/ScalaSettings.scala
+++ b/src/dotty/tools/dotc/config/ScalaSettings.scala
@@ -170,7 +170,7 @@ class ScalaSettings extends Settings.SettingGroup {
val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.")
val Ypatmatdebug = BooleanSetting("-Ypatmat-debug", "Trace pattern matching translation.")
val Yexplainlowlevel = BooleanSetting("-Yexplain-lowlevel", "When explaining type errors, show types at a lower level.")
- val YnoDoubleBindings = BooleanSetting("-YnoDoubleBindings", "Assert no namedtype is bound twice (should be enabled only if program is error-free).")
+ val YnoDoubleBindings = BooleanSetting("-Yno-double-bindings", "Assert no namedtype is bound twice (should be enabled only if program is error-free).")
val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize"
diff --git a/src/dotty/tools/dotc/transform/InterceptedMethods.scala b/src/dotty/tools/dotc/transform/InterceptedMethods.scala
index 87a5c1a4c..458527c46 100644
--- a/src/dotty/tools/dotc/transform/InterceptedMethods.scala
+++ b/src/dotty/tools/dotc/transform/InterceptedMethods.scala
@@ -111,9 +111,9 @@ class InterceptedMethods extends MiniPhaseTransform { thisTransform =>
poundPoundValue(qual)
} else if (Any_comparisons contains tree.fun.symbol.asTerm) {
if (tree.fun.symbol eq defn.Any_==) {
- qual.select(defn.Any_equals).appliedToArgs(tree.args)
+ qual.selectWithSig(defn.Any_equals).appliedToArgs(tree.args)
} else if (tree.fun.symbol eq defn.Any_!=) {
- qual.select(defn.Any_equals).appliedToArgs(tree.args).select(defn.Boolean_!)
+ qual.selectWithSig(defn.Any_equals).appliedToArgs(tree.args).select(defn.Boolean_!)
} else unknown
} /* else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) {
// todo: this is needed to support value classes
@@ -130,7 +130,7 @@ class InterceptedMethods extends MiniPhaseTransform { thisTransform =>
// we get a primitive form of _getClass trying to target a boxed value
// so we need replace that method name with Object_getClass to get correct behavior.
// See SI-5568.
- qual.select(defn.Any_getClass).appliedToNone
+ qual.selectWithSig(defn.Any_getClass).appliedToNone
} else {
unknown
}
diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala
index 33e52e068..1336d39e4 100644
--- a/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -141,7 +141,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
}
// NOTE: checker must be the target of the ==, that's the patmat semantics for ya
- def _equals(checker: Tree, binder: Symbol): Tree = checker.select(nme.equals_).appliedTo(ref(binder))
+ def _equals(checker: Tree, binder: Symbol): Tree =
+ tpd.applyOverloaded(checker, nme.EQ, List(ref(binder)), List.empty, defn.BooleanType)
// the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly)
def _asInstanceOf(b: Symbol, tp: Type): Tree = ref(b).ensureConforms(tp) // andType here breaks t1048