Skip to content

Commit 7ba59b1

Browse files
committed
Refactoring implicit discards
(1) Moved into refMatches, to avoid normalize on references that are discarded anyway (2) Added another check if the expected type is a value class
1 parent ceb4dd9 commit 7ba59b1

File tree

2 files changed

+42
-27
lines changed

2 files changed

+42
-27
lines changed

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

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,48 @@ object Implicits {
4343

4444
/** Return those references in `refs` that are compatible with type `pt`. */
4545
protected def filterMatching(pt: Type)(implicit ctx: Context): List[TermRef] = track("filterMatching") {
46+
4647
def refMatches(ref: TermRef)(implicit ctx: Context) = {
47-
// println(i"refmatches $ref --> ${normalize(ref, pt)}, pt = $pt")
48-
(ref.symbol isAccessibleFrom ref.prefix) && NoViewsAllowed.isCompatible(normalize(ref, pt), pt)
48+
49+
def discardForView(tpw: Type, argType: Type): Boolean = tpw match {
50+
case tpw: MethodType =>
51+
tpw.isImplicit ||
52+
tpw.paramTypes.length != 1 ||
53+
!(argType <:< tpw.paramTypes.head)(ctx.fresh.withExploreTyperState)
54+
case tpw: PolyType =>
55+
discardForView((new WildApprox) apply tpw.resultType, argType)
56+
case tpw: TermRef =>
57+
false // can't discard overloaded refs
58+
case tpw =>
59+
def isConforms(sym: Symbol) =
60+
sym.exists && sym.owner == defn.ScalaPredefModule.moduleClass && sym.name == tpnme.Conforms
61+
if (isConforms(tpw.typeSymbol)) false // todo: figure out why we need conforms
62+
else {
63+
//if (ctx.typer.isApplicable(tp, argType :: Nil, resultType))
64+
// println(i"??? $tp is applicable to $this / typeSymbol = ${tpw.typeSymbol}")
65+
true
66+
}
67+
}
68+
69+
def discardForValueType(tpw: Type): Boolean = tpw match {
70+
case mt: MethodType => !mt.isImplicit
71+
case mt: PolyType => discardForValueType(tpw.resultType)
72+
case _ => false
73+
}
74+
75+
def discard = pt match {
76+
case pt: ViewProto => discardForView(ref.widen, pt.argType)
77+
case _: ValueType => !defn.isFunctionType(pt) && discardForValueType(ref.widen)
78+
case _ => false
79+
}
80+
81+
(ref.symbol isAccessibleFrom ref.prefix) && {
82+
if (discard) {
83+
record("discarded eligible")
84+
false
85+
}
86+
else NoViewsAllowed.isCompatible(normalize(ref, pt), pt)
87+
}
4988
}
5089

5190
if (refs.isEmpty) refs

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

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -209,31 +209,7 @@ object Inferencing {
209209
// case _ => false
210210
// }
211211
def isMatchedBy(tp: Type)(implicit ctx: Context): Boolean = /*ctx.conditionalTraceIndented(lookingForInfo, i"?.info isMatchedBy $tp ${tp.getClass}")*/ {
212-
def discard(tp: Type): Boolean = tp.widen match {
213-
case tpw: MethodType =>
214-
tpw.isImplicit ||
215-
tpw.paramTypes.length != 1 ||
216-
!(argType <:< tpw.paramTypes.head)(ctx.fresh.withExploreTyperState)
217-
case tpw: PolyType =>
218-
discard((new WildApprox) apply tpw.resultType)
219-
case tpw: TermRef =>
220-
false // can't discard overloaded refs
221-
case tpw =>
222-
def isConforms(sym: Symbol) =
223-
sym.exists && sym.owner == defn.ScalaPredefModule.moduleClass && sym.name == tpnme.Conforms
224-
if (isConforms(tpw.typeSymbol)) false // todo: figure out why we need conforms
225-
else {
226-
//if (ctx.typer.isApplicable(tp, argType :: Nil, resultType))
227-
// println(i"??? $tp is applicable to $this / typeSymbol = ${tpw.typeSymbol}")
228-
true
229-
}
230-
}
231-
232-
if (discard(tp)) {
233-
Stats.record("discarded eligible")
234-
false
235-
}
236-
else ctx.typer.isApplicable(tp, argType :: Nil, resultType)
212+
ctx.typer.isApplicable(tp, argType :: Nil, resultType)
237213
}
238214

239215
def derivedViewProto(argType: Type, resultType: Type)(implicit ctx: Context) =

0 commit comments

Comments
 (0)