@@ -3926,62 +3926,53 @@ trait Typers extends Modes with Adaptations with Tags {
39263926 *
39273927 */
39283928 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+ }
39303935 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
39553959 }
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)
39713967 }
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)))))
39773968 }
39783969 }
39793970
39803971 def wrapErrors (tree : Tree , typeTree : Typer => Tree ): Tree = {
39813972 silent(typeTree) match {
39823973 case SilentResultValue (r) => r
39833974 case SilentTypeError (err) => DynamicRewriteError (tree, err)
3984- }
3975+ }
39853976 }
39863977 }
39873978
@@ -5375,7 +5366,7 @@ trait Typers extends Modes with Adaptations with Tags {
53755366 case tt @ TypeTree () => tree setOriginal tt.original
53765367 case _ => tree
53775368 }
5378- }
5369+ }
53795370 else
53805371 // we should get here only when something before failed
53815372 // and we try again (@see tryTypedApply). In that case we can assign
0 commit comments