Skip to content

Commit c71004e

Browse files
authored
Revert "Fix #3945: Fix eta expansion for partially applied methods"
1 parent 8d07271 commit c71004e

File tree

5 files changed

+18
-77
lines changed

5 files changed

+18
-77
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -3389,7 +3389,7 @@ object Types {
33893389
* `owningTree` and `owner` are used to determine whether a type-variable can be instantiated
33903390
* at some given point. See `Inferencing#interpolateUndetVars`.
33913391
*/
3392-
final class TypeVar(val origin: TypeParamRef, creatorState: TyperState, var bindingTree: untpd.Tree, val owner: Symbol) extends CachedProxyType with ValueType {
3392+
final class TypeVar(val origin: TypeParamRef, creatorState: TyperState, val bindingTree: untpd.Tree, val owner: Symbol) extends CachedProxyType with ValueType {
33933393

33943394
/** The permanent instance type of the variable, or NoType is none is given yet */
33953395
private[this] var myInst: Type = NoType

compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala

+13-29
Original file line numberDiff line numberDiff line change
@@ -167,53 +167,37 @@ object EtaExpansion extends LiftImpure {
167167
*
168168
* { val xs = es; expr }
169169
*
170-
* The result of the eta-expansion is either (1)
170+
* If xarity matches the number of parameters in `mt`, the eta-expansion is
171171
*
172172
* { val xs = es; (x1, ..., xn) => expr(x1, ..., xn) }
173173
*
174-
* or (2)
174+
* Note that the function value's parameters are untyped, hence the type will
175+
* be supplied by the environment (or if missing be supplied by the target
176+
* method as a fallback). On the other hand, if `xarity` is different from
177+
* the number of parameters in `mt`, then we cannot propagate parameter types
178+
* from the expected type, and we fallback to using the method's original
179+
* parameter types instead.
175180
*
176-
* { val xs = es; (x1: T1, ..., xn: Tn) => expr(x1, ..., xn) }
177-
*
178-
* or (3)
179-
*
180-
* { val xs = es; (x1: T1, ..., xn: Tn) => expr(x1, ..., xn) _ }
181-
*
182-
* where `T1, ..., Tn` are the paremeter types of the expanded method.
183-
*
184-
* Case (3) applies if the method is curried, i.e. its result type is again a method
185-
* type. Case (2) applies if the expected arity of the function type `xarity` differs
186-
* from the number of parameters in `mt`. Case (1) applies if `mt` is uncurried
187-
* and its number of parameters equals `xarity`. In this case we can always infer
188-
* the parameter types later from the callee even if parameter types could not be
189-
* inferred from the expected type. Hence, we lose nothing by omitting parameter types
190-
* in the eta expansion. On the other hand omitting these parameters keeps the possibility
191-
* open that different parameters are inferred from the expected type, so we keep
192-
* more options open.
193-
*
194-
* In each case, the result is an untyped tree, with `es` and `expr` as typed splices.
195-
*
196-
* F[V](x) ==> (x => F[X])
181+
* In either case, the result is an untyped tree, with `es` and `expr` as typed splices.
197182
*/
198183
def etaExpand(tree: Tree, mt: MethodType, xarity: Int)(implicit ctx: Context): untpd.Tree = {
199184
import untpd._
200185
assert(!ctx.isAfterTyper)
201186
val defs = new mutable.ListBuffer[tpd.Tree]
202187
val lifted: Tree = TypedSplice(liftApp(defs, tree))
203-
val isLastApplication = mt.resultType match {
204-
case rt: MethodType => rt.isImplicitMethod
205-
case _ => true
206-
}
207188
val paramTypes: List[Tree] =
208-
if (isLastApplication && mt.paramInfos.length == xarity) mt.paramInfos map (_ => TypeTree())
189+
if (mt.paramInfos.length == xarity) mt.paramInfos map (_ => TypeTree())
209190
else mt.paramInfos map TypeTree
210191
val params = (mt.paramNames, paramTypes).zipped.map((name, tpe) =>
211192
ValDef(name, tpe, EmptyTree).withFlags(Synthetic | Param).withPos(tree.pos.startPos))
212193
var ids: List[Tree] = mt.paramNames map (name => Ident(name).withPos(tree.pos.startPos))
213194
if (mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam)
214195
ids = ids.init :+ repeated(ids.last)
215196
var body: Tree = Apply(lifted, ids)
216-
if (!isLastApplication) body = PostfixOp(body, Ident(nme.WILDCARD))
197+
mt.resultType match {
198+
case rt: MethodType if !rt.isImplicitMethod => body = PostfixOp(body, Ident(nme.WILDCARD))
199+
case _ =>
200+
}
217201
val fn = untpd.Function(params, body)
218202
if (defs.nonEmpty) untpd.Block(defs.toList map (untpd.TypedSplice(_)), fn) else fn
219203
}

compiler/src/dotty/tools/dotc/typer/Inferencing.scala

+1-15
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ object Inferencing {
166166
case Apply(fn, _) => boundVars(fn, acc)
167167
case TypeApply(fn, targs) =>
168168
val tvars = targs.tpes.collect {
169-
case tvar: TypeVar if !tvar.isInstantiated && targs.contains(tvar.bindingTree) => tvar
169+
case tvar: TypeVar if !tvar.isInstantiated => tvar
170170
}
171171
boundVars(fn, acc ::: tvars)
172172
case Select(pre, _) => boundVars(pre, acc)
@@ -394,20 +394,6 @@ trait Inferencing { this: Typer =>
394394
}
395395
if (constraint.uninstVars exists qualifies) interpolate()
396396
}
397-
398-
/** The uninstantiated type variables introduced somehwere in `tree` */
399-
def uninstBoundVars(tree: Tree)(implicit ctx: Context): List[TypeVar] = {
400-
val buf = new mutable.ListBuffer[TypeVar]
401-
tree.foreachSubTree {
402-
case TypeApply(_, args) =>
403-
args.tpes.foreach {
404-
case tv: TypeVar if !tv.isInstantiated && tree.contains(tv.bindingTree) => buf += tv
405-
case _ =>
406-
}
407-
case _ =>
408-
}
409-
buf.toList
410-
}
411397
}
412398

413399
/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */

compiler/src/dotty/tools/dotc/typer/Typer.scala

+3-13
Original file line numberDiff line numberDiff line change
@@ -1972,7 +1972,7 @@ class Typer extends Namer
19721972
if (!tree.denot.isOverloaded) {
19731973
// for overloaded trees: resolve overloading before simplifying
19741974
if (tree.isDef) interpolateUndetVars(tree, tree.symbol, pt)
1975-
else if (!tree.tpe.widen.isInstanceOf[MethodOrPoly]) interpolateUndetVars(tree, NoSymbol, pt)
1975+
else if (!tree.tpe.widen.isInstanceOf[LambdaType]) interpolateUndetVars(tree, NoSymbol, pt)
19761976
tree.overwriteType(tree.tpe.simplified)
19771977
}
19781978
adaptInterpolated(tree, pt)
@@ -2240,18 +2240,8 @@ class Typer extends Namer
22402240
if (arity >= 0 &&
22412241
!tree.symbol.isConstructor &&
22422242
!ctx.mode.is(Mode.Pattern) &&
2243-
!(isSyntheticApply(tree) && !isExpandableApply)) {
2244-
// Eta expansion interacts in tricky ways with type variable instantiation
2245-
// because it can extend the region where type variables are bound (and therefore may not
2246-
// be interpolated). To avoid premature interpolations, we need to extend the
2247-
// bindingTree of variables as we go along. Test case in pos/i3945.scala.
2248-
val boundtvs = uninstBoundVars(tree)
2249-
val uexpanded = etaExpand(tree, wtp, arity)
2250-
boundtvs.foreach(_.bindingTree = uexpanded) // make boundtvs point to uexpanded so that they are _not_ interpolated
2251-
val texpanded = typedUnadapted(uexpanded, pt)
2252-
boundtvs.foreach(_.bindingTree = texpanded) // make boundtvs point to texpanded so that they _can_ be interpolated
2253-
adapt(texpanded, pt)
2254-
}
2243+
!(isSyntheticApply(tree) && !isExpandableApply))
2244+
typed(etaExpand(tree, wtp, arity), pt)
22552245
else if (wtp.paramInfos.isEmpty && isAutoApplied(tree.symbol))
22562246
adaptInterpolated(tpd.Apply(tree, Nil), pt)
22572247
else if (wtp.isImplicitMethod)

tests/pos/i3945.scala

-19
This file was deleted.

0 commit comments

Comments
 (0)