@@ -3926,62 +3926,53 @@ trait Typers extends Modes with Adaptations with Tags {
3926
3926
*
3927
3927
*/
3928
3928
def mkInvoke (cxTree : Tree , tree : Tree , qual : Tree , name : Name ): Option [Tree ] = {
3929
- debuglog(s " mkInvoke( $cxTree, $tree, $qual, $name) " )
3929
+ log(s " dyna.mkInvoke( $cxTree, $tree, $qual, $name) " )
3930
+ val treeSelection = treeInfo.methPart(tree)
3931
+ def isDesugaredApply = treeSelection match {
3932
+ case Select (`qual`, nme.apply) => true
3933
+ case _ => false
3934
+ }
3930
3935
acceptsApplyDynamicWithType(qual, name) map { tp =>
3931
- // tp eq NoType => can call xxxDynamic, but not passing any type args (unless specified explicitly by the user)
3932
- // in scala-virtualized, when not NoType, tp is passed as type argument (for selection on a staged Struct)
3933
-
3934
- // strip off type application -- we're not doing much with outer,
3935
- // so don't bother preserving cxTree's attributes etc
3936
- val cxTree1 = cxTree match {
3937
- case t : ValOrDefDef => t.rhs
3938
- case t => t
3939
- }
3940
- val cxTree2 = cxTree1 match {
3941
- case Typed (t, tpe) => t // ignore outer type annotation
3942
- case t => t
3943
- }
3944
- val (outer, explicitTargs) = cxTree2 match {
3945
- case TypeApply (fun, targs) => (fun, targs)
3946
- case Apply (TypeApply (fun, targs), args) => (Apply (fun, args), targs)
3947
- case Select (TypeApply (fun, targs), nme) => (Select (fun, nme), targs)
3948
- case t => (t, Nil )
3949
- }
3950
- def hasNamedArg (as : List [Tree ]) = as.collectFirst{case AssignOrNamedArg (lhs, rhs) => }.nonEmpty
3951
-
3952
- def desugaredApply = tree match {
3953
- case Select (`qual`, nme.apply) => true
3954
- case _ => false
3936
+ // If tp == NoType, pass only explicit type arguments to applyXXX. Not used at all
3937
+ // here - it is for scala-virtualized, where tp will be passed as an argument (for
3938
+ // selection on a staged Struct)
3939
+ def hasNamed (args : List [Tree ]): Boolean = args exists (_.isInstanceOf [AssignOrNamedArg ])
3940
+ // not supported: foo.bar(a1,..., an: _*)
3941
+ def hasStar (args : List [Tree ]) = treeInfo.isWildcardStarArgList(args)
3942
+ def applyOp (args : List [Tree ]) = if (hasNamed(args)) nme.applyDynamicNamed else nme.applyDynamic
3943
+ def matches (t : Tree ) = isDesugaredApply || treeInfo.methPart(t) == treeSelection
3944
+
3945
+ /** Note that the trees which arrive here are potentially some distance from
3946
+ * the trees of direct interest. `cxTree` is some enclosing expression which
3947
+ * may apparently be arbitrarily larger than `tree`; and `tree` itself is
3948
+ * too small, having at least in some cases lost its explicit type parameters.
3949
+ * This logic is designed to use `tree` to pinpoint the immediately surrounding
3950
+ * Apply/TypeApply/Select node, and only then creates the dynamic call.
3951
+ * See SI-6731 among others.
3952
+ */
3953
+ def findSelection (t : Tree ): Option [(TermName , Tree )] = t match {
3954
+ case Apply (fn, args) if hasStar(args) => DynamicVarArgUnsupported (tree, applyOp(args)) ; None
3955
+ case Apply (fn, args) if matches(fn) => Some ((applyOp(args), fn))
3956
+ case Assign (lhs, _) if matches(lhs) => Some ((nme.updateDynamic, lhs))
3957
+ case _ if matches(t) => Some ((nme.selectDynamic, t))
3958
+ case _ => t.children flatMap findSelection headOption
3955
3959
}
3956
- // note: context.tree includes at most one Apply node
3957
- // thus, we can't use it to detect we're going to receive named args in expressions such as:
3958
- // qual.sel(a)(a2, arg2 = "a2")
3959
- val oper = outer match {
3960
- case Apply (q, as) if q == tree || desugaredApply =>
3961
- val oper =
3962
- if (hasNamedArg(as)) nme.applyDynamicNamed
3963
- else nme.applyDynamic
3964
- // not supported: foo.bar(a1,..., an: _*)
3965
- if (treeInfo.isWildcardStarArgList(as)) {
3966
- DynamicVarArgUnsupported (tree, oper)
3967
- return Some (setError(tree))
3968
- } else oper
3969
- case Assign (`tree`, _) => nme.updateDynamic
3970
- case _ => nme.selectDynamic
3960
+ findSelection(cxTree) match {
3961
+ case Some ((opName, tapply)) =>
3962
+ val targs = treeInfo.typeArguments(tapply)
3963
+ val fun = gen.mkTypeApply(Select (qual, opName), targs)
3964
+ atPos(qual.pos)(Apply (fun, Literal (Constant (name.decode)) :: Nil ))
3965
+ case _ =>
3966
+ setError(tree)
3971
3967
}
3972
-
3973
- val dynSel = Select (qual, oper)
3974
- val tappSel = if (explicitTargs.nonEmpty) TypeApply (dynSel, explicitTargs) else dynSel
3975
-
3976
- atPos(qual.pos)(Apply (tappSel, List (Literal (Constant (name.decode)))))
3977
3968
}
3978
3969
}
3979
3970
3980
3971
def wrapErrors (tree : Tree , typeTree : Typer => Tree ): Tree = {
3981
3972
silent(typeTree) match {
3982
3973
case SilentResultValue (r) => r
3983
3974
case SilentTypeError (err) => DynamicRewriteError (tree, err)
3984
- }
3975
+ }
3985
3976
}
3986
3977
}
3987
3978
@@ -5375,7 +5366,7 @@ trait Typers extends Modes with Adaptations with Tags {
5375
5366
case tt @ TypeTree () => tree setOriginal tt.original
5376
5367
case _ => tree
5377
5368
}
5378
- }
5369
+ }
5379
5370
else
5380
5371
// we should get here only when something before failed
5381
5372
// and we try again (@see tryTypedApply). In that case we can assign
0 commit comments