Skip to content

Commit 30aa805

Browse files
committed
Ignore selection prototypes when typing type applications
Ignore selection prototypes at first when typing type applications. If we need them later for overloading disambiguation, reveal the ignored type. The reason for doing this is that a selection might come from an extension method, and in this case we should not require the selected name as a member of the result. This change breaks one test (overloading-specifity-2.scala) that explicitly tested that we don't consult implicit arguments for disambiguation since the expected type was a selection that already determined the outcome. This is logic no longer holds. We have to see whether this change breaks any code in practice. Fixes #23773
1 parent bc5f15e commit 30aa805

File tree

6 files changed

+32
-5
lines changed

6 files changed

+32
-5
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,11 @@ object Types extends TypeUtils {
19561956
/** If this is a proto type, WildcardType, otherwise the type itself */
19571957
def dropIfProto: Type = this
19581958

1959+
/** If this is a (possibly applied) selection proto type, ignore the
1960+
* selection part
1961+
*/
1962+
def ignoreSelectionProto(using Context): Type = this
1963+
19591964
/** If this is an AndType, the number of factors, 1 for all other types */
19601965
def andFactorCount: Int = 1
19611966

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
354354
~ "]"
355355
case IgnoredProto(ignored) =>
356356
"?" ~ ("(ignored: " ~ toText(ignored) ~ ")").provided(printDebug)
357-
case tp @ PolyProto(targs, resType) =>
358-
"[applied to [" ~ toTextGlobal(targs, ", ") ~ "] returning " ~ toText(resType)
357+
case tp @ PolyProto(targs, resultType) =>
358+
"[applied to ["
359+
~ toTextGlobal(targs, ", ")
360+
~ "] returning "
361+
~ toText(resultType)
362+
~ "]"
359363
case _ =>
360364
super.toText(tp)
361365
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,7 +1422,7 @@ trait Applications extends Compatibility {
14221422
val typedArgs = if (isNamed) typedNamedArgs(tree.args) else tree.args.mapconserve(typedType(_))
14231423
record("typedTypeApply")
14241424

1425-
typedExpr(tree.fun, PolyProto(typedArgs, pt)) match {
1425+
typedExpr(tree.fun, PolyProto(typedArgs, pt.ignoreSelectionProto)) match
14261426
case fun: TypeApply if !ctx.isAfterTyper =>
14271427
val function = fun.fun
14281428
val args = (fun.args ++ tree.args).map(_.show).mkString(", ")
@@ -1446,7 +1446,6 @@ trait Applications extends Compatibility {
14461446
}
14471447
if (typedFn.tpe eq TryDynamicCallType) tryDynamicTypeApply()
14481448
else assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs)
1449-
}
14501449
}
14511450

14521451
/** Rewrite `new Array[T](....)` if T is an unbounded generic to calls to newGenericArray.

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ object ProtoTypes {
286286
override def deepenProtoTrans(using Context): SelectionProto =
287287
derivedSelectionProto(name, memberProto.deepenProtoTrans, compat, nameSpan)
288288

289+
override def ignoreSelectionProto(using Context): IgnoredProto =
290+
IgnoredProto(this)
291+
289292
override def computeHash(bs: Hashable.Binders): Int = {
290293
val delta = (if (compat eq NoViewsAllowed) 1 else 0) | (if (privateOK) 2 else 0)
291294
addDelta(doHash(bs, name, memberProto), delta)
@@ -620,6 +623,9 @@ object ProtoTypes {
620623
override def deepenProtoTrans(using Context): FunProto =
621624
derivedFunProto(args, resultType.deepenProtoTrans, constrainResultDeep = true)
622625

626+
override def ignoreSelectionProto(using Context): FunProto =
627+
derivedFunProto(args, resultType.ignoreSelectionProto)
628+
623629
override def withContext(newCtx: Context): ProtoType =
624630
if newCtx `eq` protoCtx then this
625631
else new FunProto(args, resType)(typer, applyKind, state)(using newCtx)
@@ -734,6 +740,9 @@ object ProtoTypes {
734740

735741
override def deepenProtoTrans(using Context): PolyProto =
736742
derivedPolyProto(targs, resultType.deepenProtoTrans)
743+
744+
override def ignoreSelectionProto(using Context): PolyProto =
745+
derivedPolyProto(targs, resultType.ignoreSelectionProto)
737746
}
738747

739748
/** A prototype for expressions [] that are known to be functions:

tests/run/overloading-specifity-2.scala renamed to tests/neg/overloading-specifity-2.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ object Test extends App {
2323
def foo[T]: Show[T] = new Show[T](2)
2424
}
2525

26-
assert(a.foo[Int].i == 1) // error: no implicit argument of type Test.Context was found for parameter ctx
26+
assert(a.foo[Int].i == 1) // error: no implicit argument of type Test.Context was found for parameter ctx, was OK
2727
}

tests/pos/i23773.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
trait Foo[T]
2+
3+
def foo[A]: Int = ???
4+
def foo[A: Foo]: Int = ???
5+
6+
extension (x: Int)
7+
def succ: Int = x + 1
8+
9+
val a = foo[Int]
10+
val b = foo[Int].succ // error

0 commit comments

Comments
 (0)