Skip to content

Commit 54441d6

Browse files
committed
Generalize ExtMethodApply to IntegratedTypeArgs
Creator methods create new sitation where we need to integrate type arguments of the prototype in a term. Create a superclass IntegratedTypeArgs of ExtMethodApply to cover both that and extension methods.
1 parent 7ca527b commit 54441d6

File tree

3 files changed

+73
-67
lines changed

3 files changed

+73
-67
lines changed

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,29 +186,35 @@ object Applications {
186186
def wrapDefs(defs: mutable.ListBuffer[Tree], tree: Tree)(implicit ctx: Context): Tree =
187187
if (defs != null && defs.nonEmpty) tpd.Block(defs.toList, tree) else tree
188188

189-
/** A wrapper indicating that its argument is an application of an extension method.
189+
/** A wrapper indicating that its `app` argument has already integrated the type arguments
190+
* of the expected type, provided that type is a (possibly ignored) PolyProto.
190191
*/
191-
class ExtMethodApply(val app: Tree)(implicit @constructorOnly src: SourceFile) extends tpd.Tree {
192+
class IntegratedTypeArgs(val app: Tree)(implicit @constructorOnly src: SourceFile) extends tpd.Tree {
192193
override def span = app.span
193194

194195
def canEqual(that: Any): Boolean = app.canEqual(that)
195196
def productArity: Int = app.productArity
196197
def productElement(n: Int): Any = app.productElement(n)
197198
}
198199

199-
/** The unapply method of this extractor also recognizes ExtMethodApplys in closure blocks.
200+
/** The unapply method of this extractor also recognizes IntegratedTypeArgs in closure blocks.
200201
* This is necessary to deal with closures as left arguments of extension method applications.
201202
* A test case is i5606.scala
202203
*/
203-
object ExtMethodApply {
204-
def apply(app: Tree)(implicit ctx: Context) = new ExtMethodApply(app)
204+
object IntegratedTypeArgs {
205+
def apply(app: Tree)(implicit ctx: Context) = new IntegratedTypeArgs(app)
205206
def unapply(tree: Tree)(implicit ctx: Context): Option[Tree] = tree match {
206-
case tree: ExtMethodApply => Some(tree.app)
207-
case Block(stats, ExtMethodApply(app)) => Some(tpd.cpy.Block(tree)(stats, app))
207+
case tree: IntegratedTypeArgs => Some(tree.app)
208+
case Block(stats, IntegratedTypeArgs(app)) => Some(tpd.cpy.Block(tree)(stats, app))
208209
case _ => None
209210
}
210211
}
211212

213+
/** A wrapper indicating that its argument is an application of an extension method.
214+
*/
215+
class ExtMethodApply(app: Tree)(implicit @constructorOnly src: SourceFile)
216+
extends IntegratedTypeArgs(app)
217+
212218
/** 1. If we are in an inline method but not in a nested quote, mark the inline method
213219
* as a macro.
214220
*
@@ -942,7 +948,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
942948
val typedArgs = if (isNamed) typedNamedArgs(tree.args) else tree.args.mapconserve(typedType(_))
943949
record("typedTypeApply")
944950
handleMeta(typedExpr(tree.fun, PolyProto(typedArgs, pt)) match {
945-
case ExtMethodApply(app) =>
951+
case IntegratedTypeArgs(app) =>
946952
app
947953
case _: TypeApply if !ctx.isAfterTyper =>
948954
errorTree(tree, "illegal repeated type application")

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,7 @@ trait Implicits { self: Typer =>
11011101
}
11021102
else {
11031103
val returned =
1104-
if (cand.isExtension) Applications.ExtMethodApply(adapted).withType(adapted.tpe)
1104+
if (cand.isExtension) new Applications.ExtMethodApply(adapted).withType(adapted.tpe)
11051105
else adapted
11061106
SearchSuccess(returned, ref, cand.level)(ctx.typerState, ctx.gadt)
11071107
}

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

Lines changed: 58 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import EtaExpansion.etaExpand
2727
import util.Spans._
2828
import util.common._
2929
import util.Property
30-
import Applications.{ExtMethodApply, productSelectorTypes, wrapDefs}
30+
import Applications.{ExtMethodApply, IntegratedTypeArgs, productSelectorTypes, wrapDefs}
3131

3232
import collection.mutable
3333
import annotation.tailrec
@@ -448,9 +448,9 @@ class Typer extends Namer
448448

449449
def typeSelectOnTerm(implicit ctx: Context): Tree =
450450
typedExpr(tree.qualifier, selectionProto(tree.name, pt, this)) match {
451-
case qual1 @ ExtMethodApply(app) =>
451+
case qual1 @ IntegratedTypeArgs(app) =>
452452
pt.revealIgnored match {
453-
case _: PolyProto => qual1 // keep the ExtMethodApply to strip at next typedTypeApply
453+
case _: PolyProto => qual1 // keep the IntegratedTypeArgs to strip at next typedTypeApply
454454
case _ => app
455455
}
456456
case qual1 =>
@@ -2203,7 +2203,7 @@ class Typer extends Namer
22032203
def tryEither[T](op: Context => T)(fallBack: (T, TyperState) => T)(implicit ctx: Context): T = {
22042204
val nestedCtx = ctx.fresh.setNewTyperState()
22052205
val result = op(nestedCtx)
2206-
if (nestedCtx.reporter.hasErrors && !nestedCtx.reporter.hasStickyErrors)
2206+
if (nestedCtx.reporter.hasErrors && !nestedCtx.reporter.hasStickyErrors) {
22072207
record("tryEither.fallBack")
22082208
fallBack(result, nestedCtx.typerState)
22092209
}
@@ -2376,64 +2376,64 @@ class Typer extends Namer
23762376
tree.withType(mt.resultType)
23772377
}
23782378

2379-
def adaptOverloaded(ref: TermRef) = {
2380-
val altDenots = ref.denot.alternatives
2381-
typr.println(i"adapt overloaded $ref with alternatives ${altDenots map (_.info)}%, %")
2382-
val alts = altDenots.map(TermRef(ref.prefix, ref.name, _))
2383-
resolveOverloaded(alts, pt) match {
2384-
case alt :: Nil =>
2385-
readaptSimplified(tree.withType(alt))
2386-
case Nil =>
2387-
def noMatches =
2388-
errorTree(tree, NoMatchingOverload(altDenots, pt)(err))
2389-
def hasEmptyParams(denot: SingleDenotation) = denot.info.paramInfoss == ListOfNil
2390-
pt match {
2391-
case pt: FunProto if !pt.isContextual =>
2392-
// insert apply or convert qualifier only for a regular application
2393-
tryInsertApplyOrImplicit(tree, pt, locked)(noMatches)
2394-
case _ =>
2395-
if (altDenots exists (_.info.paramInfoss == ListOfNil))
2396-
typed(untpd.Apply(untpd.TypedSplice(tree), Nil), pt, locked)
2397-
else
2398-
noMatches
2399-
}
2400-
case alts =>
2401-
if (tree.tpe.isErroneous || pt.isErroneous) tree.withType(UnspecifiedErrorType)
2402-
else {
2403-
val remainingDenots = alts map (_.denot.asInstanceOf[SingleDenotation])
2404-
errorTree(tree, AmbiguousOverload(tree, remainingDenots, pt)(err))
2405-
}
2406-
}
2407-
}
2408-
2409-
def isUnary(tp: Type): Boolean = tp match {
2410-
case tp: MethodicType =>
2411-
tp.firstParamTypes match {
2412-
case ptype :: Nil => !ptype.isRepeatedParam
2413-
case _ => false
2379+
def adaptOverloaded(ref: TermRef) = {
2380+
val altDenots = ref.denot.alternatives
2381+
typr.println(i"adapt overloaded $ref with alternatives ${altDenots map (_.info)}%, %")
2382+
val alts = altDenots.map(TermRef(ref.prefix, ref.name, _))
2383+
resolveOverloaded(alts, pt) match {
2384+
case alt :: Nil =>
2385+
readaptSimplified(tree.withType(alt))
2386+
case Nil =>
2387+
def noMatches =
2388+
errorTree(tree, NoMatchingOverload(altDenots, pt)(err))
2389+
def hasEmptyParams(denot: SingleDenotation) = denot.info.paramInfoss == ListOfNil
2390+
pt match {
2391+
case pt: FunProto if !pt.isContextual =>
2392+
// insert apply or convert qualifier only for a regular application
2393+
tryInsertApplyOrImplicit(tree, pt, locked)(noMatches)
2394+
case _ =>
2395+
if (altDenots exists (_.info.paramInfoss == ListOfNil))
2396+
typed(untpd.Apply(untpd.TypedSplice(tree), Nil), pt, locked)
2397+
else
2398+
noMatches
2399+
}
2400+
case alts =>
2401+
if (tree.tpe.isErroneous || pt.isErroneous) tree.withType(UnspecifiedErrorType)
2402+
else {
2403+
val remainingDenots = alts map (_.denot.asInstanceOf[SingleDenotation])
2404+
errorTree(tree, AmbiguousOverload(tree, remainingDenots, pt)(err))
24142405
}
2415-
case tp: TermRef =>
2416-
tp.denot.alternatives.forall(alt => isUnary(alt.info))
2417-
case _ =>
2418-
false
24192406
}
2407+
}
24202408

2421-
def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match {
2422-
case wtp: MethodOrPoly =>
2423-
def methodStr = methPart(tree).symbol.showLocated
2424-
if (matchingApply(wtp, pt))
2425-
if (pt.args.lengthCompare(1) > 0 && isUnary(wtp) && ctx.canAutoTuple)
2426-
adapt(tree, pt.tupled, locked)
2427-
else
2428-
tree
2429-
else if (wtp.isContextual)
2430-
adaptNoArgs(wtp) // insert arguments implicitly
2431-
else
2432-
errorTree(tree, em"Missing arguments for $methodStr")
2433-
case _ => tryInsertApplyOrImplicit(tree, pt, locked) {
2434-
errorTree(tree, MethodDoesNotTakeParameters(tree))
2409+
def isUnary(tp: Type): Boolean = tp match {
2410+
case tp: MethodicType =>
2411+
tp.firstParamTypes match {
2412+
case ptype :: Nil => !ptype.isRepeatedParam
2413+
case _ => false
24352414
}
2415+
case tp: TermRef =>
2416+
tp.denot.alternatives.forall(alt => isUnary(alt.info))
2417+
case _ =>
2418+
false
2419+
}
2420+
2421+
def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match {
2422+
case wtp: MethodOrPoly =>
2423+
def methodStr = methPart(tree).symbol.showLocated
2424+
if (matchingApply(wtp, pt))
2425+
if (pt.args.lengthCompare(1) > 0 && isUnary(wtp) && ctx.canAutoTuple)
2426+
adapt(tree, pt.tupled, locked)
2427+
else
2428+
tree
2429+
else if (wtp.isContextual)
2430+
adaptNoArgs(wtp) // insert arguments implicitly
2431+
else
2432+
errorTree(tree, em"Missing arguments for $methodStr")
2433+
case _ => tryInsertApplyOrImplicit(tree, pt, locked) {
2434+
errorTree(tree, MethodDoesNotTakeParameters(tree))
24362435
}
2436+
}
24372437

24382438
/** If `tp` is a TypeVar which is fully constrained (i.e. its upper bound `hi` conforms
24392439
* to its lower bound `lo`), replace `tp` by `hi`. This is necessary to
@@ -2834,7 +2834,7 @@ class Typer extends Namer
28342834
val app = tryExtension(nestedCtx)
28352835
if (!app.isEmpty && !nestedCtx.reporter.hasErrors) {
28362836
nestedCtx.typerState.commit()
2837-
return ExtMethodApply(app).withType(WildcardType)
2837+
return new ExtMethodApply(app).withType(WildcardType)
28382838
// Use wildcard type in order not to prompt any further adaptations such as eta expansion
28392839
// before the method is fully applied.
28402840
}

0 commit comments

Comments
 (0)