Skip to content

Commit f0cf5d0

Browse files
committed
Drop ExtMethodApply
1 parent 327327f commit f0cf5d0

File tree

5 files changed

+73
-98
lines changed

5 files changed

+73
-98
lines changed

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,8 +645,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
645645
keywordStr("${") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}")
646646
case TypSplice(tree) =>
647647
keywordStr("${") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}")
648-
case tree: Applications.ExtMethodApply =>
649-
toText(tree.app) ~ Str("(ext method apply)").provided(printDebug)
650648
case Thicket(trees) =>
651649
"Thicket {" ~~ toTextGlobal(trees, "\n") ~~ "}"
652650
case MacroTree(call) =>

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

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -195,23 +195,6 @@ object Applications {
195195

196196
def wrapDefs(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree =
197197
if (defs != null && defs.nonEmpty) tpd.Block(defs.toList, tree) else tree
198-
199-
abstract class AppProxy(implicit @constructorOnly src: SourceFile) extends ProxyTree {
200-
def app: Tree
201-
override def span = app.span
202-
203-
def forwardTo = app
204-
def canEqual(that: Any): Boolean = app.canEqual(that)
205-
def productArity: Int = app.productArity
206-
def productElement(n: Int): Any = app.productElement(n)
207-
}
208-
209-
/** A wrapper indicating that its argument is an application of an extension method.
210-
*/
211-
class ExtMethodApply(val app: Tree)(implicit @constructorOnly src: SourceFile) extends AppProxy:
212-
overwriteType(app.tpe)
213-
// ExtMethodApply always has wildcard type in order not to prompt any further adaptations
214-
// such as eta expansion before the method is fully applied.
215198
}
216199

217200
trait Applications extends Compatibility {

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

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -396,12 +396,13 @@ object Implicits:
396396
}
397397

398398
/** A successful search
399-
* @param tree The typed tree that needs to be inserted
400-
* @param ref The implicit reference that succeeded
401-
* @param level The level where the reference was found
399+
* @param tree The typed tree that needs to be inserted
400+
* @param ref The implicit reference that succeeded
401+
* @param level The level where the reference was found
402+
* @param isExtension Whether the result is an extension method application
402403
* @param tstate The typer state to be committed if this alternative is chosen
403404
*/
404-
case class SearchSuccess(tree: Tree, ref: TermRef, level: Int)(val tstate: TyperState, val gstate: GadtConstraint)
405+
case class SearchSuccess(tree: Tree, ref: TermRef, level: Int, isExtension: Boolean = false)(val tstate: TyperState, val gstate: GadtConstraint)
405406
extends SearchResult with RefAndLevel with Showable
406407

407408
/** A failed search */
@@ -802,8 +803,8 @@ trait Implicits:
802803
val inferred = inferImplicit(adjust(to), from, from.span)
803804

804805
inferred match {
805-
case SearchSuccess(tree, ref, _)
806-
if isOldStyleFunctionConversion(ref.underlying) && !tree.isInstanceOf[Applications.ExtMethodApply] =>
806+
case SearchSuccess(_, ref, _, isExtension)
807+
if isOldStyleFunctionConversion(ref.underlying) && !isExtension =>
807808
report.migrationWarning(
808809
i"The conversion ${ref} will not be applied implicitly here in Scala 3 because only implicit methods and instances of Conversion class will continue to work as implicit views.",
809810
from
@@ -829,7 +830,7 @@ trait Implicits:
829830
*/
830831
def inferImplicitArg(formal: Type, span: Span)(using Context): Tree =
831832
inferImplicit(formal, EmptyTree, span) match
832-
case SearchSuccess(arg, _, _) => arg
833+
case SearchSuccess(arg, _, _, _) => arg
833834
case fail @ SearchFailure(failed) =>
834835
if fail.isAmbiguous then failed
835836
else
@@ -937,7 +938,6 @@ trait Implicits:
937938
case Select(qual, _) => apply(x, qual)
938939
case Apply(fn, _) => apply(x, fn)
939940
case TypeApply(fn, _) => apply(x, fn)
940-
case tree: Applications.AppProxy => apply(x, tree.app)
941941
case _: This => false
942942
case _ => foldOver(x, tree)
943943
}
@@ -1073,10 +1073,7 @@ trait Implicits:
10731073
SearchFailure(adapted.withType(new MismatchedImplicit(ref, pt, argument)))
10741074
}
10751075
else
1076-
val returned =
1077-
if (cand.isExtension) Applications.ExtMethodApply(adapted)
1078-
else adapted
1079-
SearchSuccess(returned, ref, cand.level)(ctx.typerState, ctx.gadt)
1076+
SearchSuccess(adapted, ref, cand.level, cand.isExtension)(ctx.typerState, ctx.gadt)
10801077
}
10811078

10821079
/** An implicit search; parameters as in `inferImplicit` */
@@ -1139,20 +1136,13 @@ trait Implicits:
11391136
case alt1: SearchSuccess =>
11401137
var diff = compareAlternatives(alt1, alt2)
11411138
assert(diff <= 0) // diff > 0 candidates should already have been eliminated in `rank`
1142-
if diff == 0 then
1139+
if diff == 0 && alt1.isExtension && alt2.isExtension then
11431140
// Fall back: if both results are extension method applications,
11441141
// compare the extension methods instead of their wrappers.
1145-
object extMethodApply:
1146-
def unapply(t: Tree): Option[Type] = t match
1147-
case t: Applications.ExtMethodApply => Some(methPart(stripApply(t.app)).tpe)
1148-
case _ => None
1149-
end extMethodApply
1150-
1151-
(alt1.tree, alt2.tree) match
1152-
case (extMethodApply(ref1: TermRef), extMethodApply(ref2: TermRef)) =>
1153-
diff = compare(ref1, ref2)
1142+
def stripExtension(alt: SearchSuccess) = methPart(stripApply(alt.tree)).tpe
1143+
(stripExtension(alt1), stripExtension(alt2)) match
1144+
case (ref1: TermRef, ref2: TermRef) => diff = compare(ref1, ref2)
11541145
case _ =>
1155-
11561146
if diff < 0 then alt2
11571147
else if diff > 0 then alt1
11581148
else SearchFailure(new AmbiguousImplicits(alt1, alt2, pt, argument), span)
@@ -1578,7 +1568,7 @@ final class SearchRoot extends SearchHistory:
15781568
else
15791569
result match {
15801570
case failure: SearchFailure => failure
1581-
case success @ SearchSuccess(tree, _, _) =>
1571+
case success: SearchSuccess =>
15821572
import tpd._
15831573

15841574
// We might have accumulated dictionary entries for by name implicit arguments
@@ -1601,7 +1591,7 @@ final class SearchRoot extends SearchHistory:
16011591
else prune(in.map(_._2) ++ trees, out, in ++ acc)
16021592
}
16031593

1604-
val pruned = prune(List(tree), implicitDictionary.map(_._2).toList, Nil)
1594+
val pruned = prune(List(success.tree), implicitDictionary.map(_._2).toList, Nil)
16051595
myImplicitDictionary = null
16061596
if (pruned.isEmpty) result
16071597
else if (pruned.exists(_._2 == EmptyTree)) NoMatchingImplicitsFailure
@@ -1658,7 +1648,7 @@ final class SearchRoot extends SearchHistory:
16581648
case tree => tree
16591649
})
16601650

1661-
val res = resMap(tree)
1651+
val res = resMap(success.tree)
16621652

16631653
val blk = Block(classDef :: inst :: Nil, res).withSpan(span)
16641654

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

Lines changed: 47 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import TypeComparer.CompareResult
3131
import util.Spans._
3232
import util.common._
3333
import util.{Property, SimpleIdentityMap, SrcPos}
34-
import Applications.{ExtMethodApply, productSelectorTypes, wrapDefs}
34+
import Applications.{productSelectorTypes, wrapDefs}
3535

3636
import collection.mutable
3737
import annotation.tailrec
@@ -551,41 +551,39 @@ class Typer extends Namer
551551
then
552552
report.error(StableIdentPattern(tree, pt), tree.srcPos)
553553

554-
def typedSelect(tree0: untpd.Select, pt: Type, qual: Tree)(using Context): Tree = qual match
555-
case qual: ExtMethodApply =>
556-
qual.app
557-
case qual =>
558-
val selName = tree0.name
559-
val tree = cpy.Select(tree0)(qual, selName)
560-
def finalize(tp: Type) = assignType(tree, tp)
561-
val superAccess = qual.isInstanceOf[Super]
562-
val rawType = selectionType(tree, qual)
563-
val checkedType = accessibleType(rawType, superAccess)
564-
if checkedType.exists then
565-
val select = toNotNullTermRef(assignType(tree, checkedType), pt)
566-
if selName.isTypeName then checkStable(qual.tpe, qual.srcPos, "type prefix")
567-
checkStableIdentPattern(select, pt)
568-
ConstFold(select)
569-
else if couldInstantiateTypeVar(qual.tpe.widen) then
570-
// try again with more defined qualifier type
571-
typedSelect(tree, pt, qual)
572-
else
573-
val tree1 = tryExtensionOrConversion(
574-
tree, pt, IgnoredProto(pt), qual, ctx.typerState.ownedVars, this, privateOK = true)
575-
if !tree1.isEmpty then
576-
tree1
577-
else if qual.tpe.derivesFrom(defn.DynamicClass)
578-
&& selName.isTermName && !isDynamicExpansion(tree)
579-
then
580-
if pt.isInstanceOf[FunOrPolyProto] || pt == AssignProto then finalize(TryDynamicCallType)
581-
else typedDynamicSelect(tree0, Nil, pt)
554+
def typedSelect(tree0: untpd.Select, pt: Type, qual: Tree)(using Context): Tree =
555+
val selName = tree0.name
556+
val tree = cpy.Select(tree0)(qual, selName)
557+
val superAccess = qual.isInstanceOf[Super]
558+
val rawType = selectionType(tree, qual)
559+
val checkedType = accessibleType(rawType, superAccess)
560+
if checkedType.exists then
561+
val select = toNotNullTermRef(assignType(tree, checkedType), pt)
562+
if selName.isTypeName then checkStable(qual.tpe, qual.srcPos, "type prefix")
563+
checkStableIdentPattern(select, pt)
564+
ConstFold(select)
565+
else if couldInstantiateTypeVar(qual.tpe.widen) then
566+
// try again with more defined qualifier type
567+
typedSelect(tree, pt, qual)
568+
else
569+
val tree1 = tryExtensionOrConversion(
570+
tree, pt, IgnoredProto(pt), qual, ctx.typerState.ownedVars, this, privateOK = true)
571+
if !tree1.isEmpty then
572+
tree1
573+
else if qual.tpe.derivesFrom(defn.DynamicClass)
574+
&& selName.isTermName && !isDynamicExpansion(tree)
575+
then
576+
if pt.isInstanceOf[FunOrPolyProto] || pt == AssignProto then
577+
assignType(tree, TryDynamicCallType)
582578
else
583-
finalize(
584-
rawType match
585-
case rawType: NamedType =>
586-
inaccessibleErrorType(rawType, superAccess, tree.srcPos)
587-
case _ =>
588-
notAMemberErrorType(tree, qual))
579+
typedDynamicSelect(tree0, Nil, pt)
580+
else
581+
assignType(tree,
582+
rawType match
583+
case rawType: NamedType =>
584+
inaccessibleErrorType(rawType, superAccess, tree.srcPos)
585+
case _ =>
586+
notAMemberErrorType(tree, qual))
589587
end typedSelect
590588

591589
def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = {
@@ -681,7 +679,7 @@ class Typer extends Namer
681679
case Floating => defn.FromDigits_FloatingClass
682680
}
683681
inferImplicit(fromDigitsCls.typeRef.appliedTo(target), EmptyTree, tree.span) match {
684-
case SearchSuccess(arg, _, _) =>
682+
case SearchSuccess(arg, _, _, _) =>
685683
val fromDigits = untpd.Select(untpd.TypedSplice(arg), nme.fromDigits).withSpan(tree.span)
686684
val firstArg = Literal(Constant(digits))
687685
val otherArgs = tree.kind match {
@@ -842,7 +840,7 @@ class Typer extends Namer
842840
withoutMode(Mode.Pattern)(
843841
inferImplicit(tpe, EmptyTree, tree.tpt.span)
844842
) match
845-
case SearchSuccess(clsTag, _, _) =>
843+
case SearchSuccess(clsTag, _, _, _) =>
846844
withMode(Mode.InTypeTest) {
847845
Some(typed(untpd.Apply(untpd.TypedSplice(clsTag), untpd.TypedSplice(tree.expr)), pt))
848846
}
@@ -2627,9 +2625,7 @@ class Typer extends Namer
26272625

26282626
/** Interpolate and simplify the type of the given tree. */
26292627
protected def simplify(tree: Tree, pt: Type, locked: TypeVars)(using Context): tree.type =
2630-
if !tree.denot.isOverloaded // for overloaded trees: resolve overloading before simplifying
2631-
&& !tree.isInstanceOf[Applications.AppProxy] // don't interpolate in the middle of an extension method application
2632-
then
2628+
if !tree.denot.isOverloaded then // for overloaded trees: resolve overloading before simplifying
26332629
if !tree.tpe.widen.isInstanceOf[MethodOrPoly] // wait with simplifying until method is fully applied
26342630
|| tree.isDef // ... unless tree is a definition
26352631
then
@@ -2959,12 +2955,12 @@ class Typer extends Namer
29592955
trace(i"try insert impl on qualifier $tree $pt") {
29602956
val selProto = selectionProto
29612957
inferView(qual, selProto) match
2962-
case SearchSuccess(found: ExtMethodApply, _, _) =>
2963-
return found.app // nothing to check or adapt for extension method applications
2964-
case SearchSuccess(found, _, _) =>
2965-
checkImplicitConversionUseOK(found)
2966-
val qual1 = withoutMode(Mode.ImplicitsEnabled)(adapt(found, selProto, locked))
2967-
return typedSelect(tree, pt, qual1)
2958+
case SearchSuccess(found, _, _, isExtension) =>
2959+
if isExtension then return found
2960+
else
2961+
checkImplicitConversionUseOK(found)
2962+
val qual1 = withoutMode(Mode.ImplicitsEnabled)(adapt(found, selProto, locked))
2963+
return typedSelect(tree, pt, qual1)
29682964
case failure: SearchFailure =>
29692965
if failure.isAmbiguous then
29702966
return (
@@ -3590,11 +3586,11 @@ class Typer extends Namer
35903586
else if ctx.mode.is(Mode.ImplicitsEnabled) && tree.tpe.isValueType then
35913587
checkConversionsSpecific(wtp, pt, tree.srcPos)
35923588
inferView(tree, pt) match {
3593-
case SearchSuccess(found: ExtMethodApply, _, _) =>
3594-
found // nothing to check or adapt for extension method applications
3595-
case SearchSuccess(found, _, _) =>
3596-
checkImplicitConversionUseOK(found)
3597-
withoutMode(Mode.ImplicitsEnabled)(readapt(found))
3589+
case SearchSuccess(found, _, _, isExtension) =>
3590+
if isExtension then found
3591+
else
3592+
checkImplicitConversionUseOK(found)
3593+
withoutMode(Mode.ImplicitsEnabled)(readapt(found))
35983594
case failure: SearchFailure =>
35993595
if (pt.isInstanceOf[ProtoType] && !failure.isAmbiguous) then
36003596
// don't report the failure but return the tree unchanged. This
@@ -3686,8 +3682,6 @@ class Typer extends Namer
36863682
else adaptToArgs(wtp, pt)
36873683
case pt: PolyProto =>
36883684
tryInsertApplyOrImplicit(tree, pt, locked)(tree) // error will be reported in typedTypeApply
3689-
case pt: SelectionProto if tree.isInstanceOf[ExtMethodApply] =>
3690-
tree
36913685
case _ =>
36923686
if (ctx.mode is Mode.Type) adaptType(tree.tpe)
36933687
else adaptNoArgs(wtp)

tests/pos/i8182.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package example
2+
3+
trait Show[-A]:
4+
extension (a: A) def show: String
5+
6+
given (using rec: Show[String]): Show[String] = ??? // must be Show[String] as the argument
7+
8+
given (using rec: => Show[String]): Show[Option[String]] = ??? // must be byname argument
9+
10+
def test = Option("").show

0 commit comments

Comments
 (0)