@@ -117,61 +117,73 @@ trait Dynamic { self: Typer with Applications =>
117117 * Given `x.a`, where `x` is of (widened) type `T` (a value type or a nullary method type),
118118 * and `x.a` is of type `U`, map `x.a` to the equivalent of:
119119 *
120- * (x: Selectable).selectDynamic("a").asInstanceOf[U]
120+ * ```scala
121+ * (x: Selectable).selectDynamic("a").asInstanceOf[U]
122+ * ```
121123 *
122- * Given `x.a(arg1 , ..., argn) `, where `x.a` is of (widened) type (T1, ..., Tn)R,
123- * map `x.a(arg1 , ..., argn)` to the equivalent of :
124+ * Given `x.a(a11 , ..., a1n)...(aN1, ..., aNn) `, where `x.a` is of (widened) type
125+ * `(T11, ..., T1n)...(TN1 , ..., TNn) => R`, it is desugared to :
124126 *
125- * (x:selectable).applyDynamic("a", CT1, ..., CTn)(arg1, ..., argn).asInstanceOf[R]
127+ * ```scala
128+ * (x:selectable).applyDynamic("a", CT11, ..., CT1n, ..., CTN1, ... CTNn)
129+ * (a11, ..., a1n, ..., aN1, ..., aNn)
130+ * .asInstanceOf[R]
131+ * ```
126132 *
127- * where CT1 , ..., CTn are the class tags representing the erasure of T1 , ..., Tn .
133+ * where CT11 , ..., CTNn are the class tags representing the erasure of T11 , ..., TNn .
128134 *
129135 * It's an error if U is neither a value nor a method type, or a dependent method
130136 * type.
131137 */
132138 def handleStructural (tree : Tree )(implicit ctx : Context ): Tree = {
139+ val (fun @ Select (qual, name), targs, vargss) = decomposeCall(tree)
133140
134- def structuralCall (qual : Tree , name : Name , selectorName : TermName , ctags : List [Tree ], args : Option [ List [ Tree ] ]) = {
141+ def structuralCall (selectorName : TermName , ctags : List [Tree ]) = {
135142 val selectable = adapt(qual, defn.SelectableType )
136143
137144 // ($qual: Selectable).$selectorName("$name", ..$ctags)
138145 val base =
139146 untpd.Apply (
140- untpd.TypedSplice (selectable.select(selectorName)).withPos(tree .pos),
147+ untpd.TypedSplice (selectable.select(selectorName)).withPos(fun .pos),
141148 (Literal (Constant (name.toString)) :: ctags).map(untpd.TypedSplice (_)))
142149
143- val scall = args match {
144- case None => base
145- case Some (args) => untpd.Apply (base, args)
146- }
150+ val scall =
151+ if (vargss.isEmpty) base
152+ else untpd.Apply (base, vargss.flatten)
147153
148154 typed(scall)
149155 }
150156
151157 def fail (name : Name , reason : String ) =
152158 errorTree(tree, em " Structural access not allowed on method $name because it $reason" )
153159
154- val tpe = tree.tpe.widen
155- tree match {
156- case Apply (fun @ Select (qual, name), args) =>
157- val funTpe = fun.tpe.widen.asInstanceOf [MethodType ]
158- if (funTpe.isParamDependent)
160+ fun.tpe.widen match {
161+ case tpe : ValueType =>
162+ structuralCall(nme.selectDynamic, Nil ).asInstance(tpe)
163+
164+ case tpe : MethodType =>
165+ def isDependentMethod (tpe : Type ): Boolean = tpe match {
166+ case tpe : MethodType =>
167+ tpe.isParamDependent ||
168+ tpe.isResultDependent ||
169+ isDependentMethod(tpe.resultType)
170+ case _ =>
171+ false
172+ }
173+
174+ if (isDependentMethod(tpe))
159175 fail(name, i " has a method type with inter-parameter dependencies " )
160176 else {
161- val ctags = funTpe.paramInfos .map(pt =>
162- implicitArgTree(defn.ClassTagType .appliedTo(pt :: Nil ), tree .pos.endPos))
163- structuralCall(qual, name, nme.applyDynamic, ctags, Some (args)) .asInstance(tpe.resultType )
177+ val ctags = tpe.paramInfoss.flatten .map(pt =>
178+ implicitArgTree(defn.ClassTagType .appliedTo(pt.widenDealias :: Nil ), fun .pos.endPos))
179+ structuralCall(nme.applyDynamic, ctags) .asInstance(tpe.finalResultType )
164180 }
165- case Select (qual, name) if tpe.isValueType =>
166- structuralCall(qual, name, nme.selectDynamic, Nil , None ).asInstance(tpe)
167- case Select (_, _) if ! tpe.isParameterless =>
168- // We return the tree unchanged; The structural call will be handled when we take care of the
169- // enclosing application.
170- tree
171- case Select (_, name) if tpe.isInstanceOf [PolyType ] =>
181+
182+ // (@allanrenucci) I think everything below is dead code
183+ case _ : PolyType =>
172184 fail(name, " is polymorphic" )
173- case Select (_, name) =>
174- fail(name, i " has an unsupported type: ${tree. tpe.widen} " )
185+ case tpe =>
186+ fail(name, i " has an unsupported type: $tpe" )
175187 }
176188 }
177189}
0 commit comments