aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala41
-rw-r--r--src/dotty/tools/dotc/transform/InterceptedMethods.scala6
2 files changed, 42 insertions, 5 deletions
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/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
}