Skip to content

Commit 58b71ca

Browse files
committed
Fix handling of dependent method types
Need to use fresh PolyParams instead of WildcardTypes if constraint is committable.
1 parent e01ca04 commit 58b71ca

File tree

5 files changed

+27
-10
lines changed

5 files changed

+27
-10
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ class Definitions {
352352
enterCompleteClassSymbol(
353353
ScalaPackageClass, tpnme.Singleton, PureInterfaceCreationFlags | Final,
354354
List(AnyClass.typeRef), EmptyScope)
355+
def SingletonType = SingletonClass.typeRef
355356

356357
lazy val SeqType: TypeRef = ctx.requiredClassRef("scala.collection.Seq")
357358
def SeqClass(implicit ctx: Context) = SeqType.symbol.asClass

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ object StdNames {
9797
val EMPTY: N = ""
9898
val EMPTY_PACKAGE: N = Names.EMPTY_PACKAGE.toString
9999
val EVIDENCE_PARAM_PREFIX: N = "evidence$"
100+
val DEP_PARAM_PREFIX = "<param>"
100101
val EXCEPTION_RESULT_PREFIX: N = "exceptionResult"
101102
val EXPAND_SEPARATOR: N = "$$"
102103
val IMPL_CLASS_SUFFIX: N = "$class"

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2394,12 +2394,6 @@ object Types {
23942394
*/
23952395
def isDependent(implicit ctx: Context): Boolean = dependencyStatus == TrueDeps
23962396

2397-
/** The result type where every reference to a parameter is replaced by a Wildcard
2398-
*/
2399-
def resultTypeApprox(implicit ctx: Context): Type =
2400-
if (isDependent) resultType.substParams(this, paramTypes.map(Function.const(WildcardType)))
2401-
else resultType
2402-
24032397
protected def computeSignature(implicit ctx: Context): Signature =
24042398
resultSignature.prepend(paramTypes, isJava)
24052399

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,9 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
213213
protected def init() = methType match {
214214
case methType: MethodType =>
215215
// apply the result type constraint, unless method type is dependent
216+
val resultApprox = resultTypeApprox(methType)
216217
val savedConstraint = ctx.typerState.constraint
217-
if (!constrainResult(methType.resultTypeApprox, resultType))
218+
if (!constrainResult(resultApprox, resultType))
218219
if (ctx.typerState.isCommittable)
219220
// defer the problem until after the application;
220221
// it might be healed by an implicit conversion
@@ -1099,7 +1100,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
10991100
/** Drop any implicit parameter section */
11001101
def stripImplicit(tp: Type): Type = tp match {
11011102
case mt: ImplicitMethodType =>
1102-
mt.resultTypeApprox
1103+
resultTypeApprox(mt)
11031104
case pt: PolyType =>
11041105
pt.derivedPolyType(pt.paramNames, pt.paramBounds, stripImplicit(pt.resultType))
11051106
case _ =>

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ object ProtoTypes {
5757
case pt: FunProto =>
5858
mt match {
5959
case mt: MethodType =>
60-
constrainResult(mt.resultTypeApprox, pt.resultType)
60+
constrainResult(resultTypeApprox(mt), pt.resultType)
6161
case _ =>
6262
true
6363
}
@@ -389,6 +389,26 @@ object ProtoTypes {
389389
/** Same as `constrained(pt, EmptyTree)`, but returns just the created polytype */
390390
def constrained(pt: PolyType)(implicit ctx: Context): PolyType = constrained(pt, EmptyTree)._1
391391

392+
/** Create a new polyparam that represents a dependent method parameter singleton */
393+
def newDepPolyParam(tp: Type)(implicit ctx: Context): PolyParam = {
394+
val poly = PolyType(ctx.freshName(nme.DEP_PARAM_PREFIX).toTypeName :: Nil, 0 :: Nil)(
395+
pt => TypeBounds.upper(AndType(tp, defn.SingletonType)) :: Nil,
396+
pt => defn.AnyType)
397+
ctx.typeComparer.addToConstraint(poly, Nil)
398+
PolyParam(poly, 0)
399+
}
400+
401+
/** The result type of `mt`, where all references to parameters of `mt` are
402+
* replaced by either wildcards (if typevarsMissContext) or polyparams.
403+
*/
404+
def resultTypeApprox(mt: MethodType)(implicit ctx: Context): Type =
405+
if (mt.isDependent) {
406+
def replacement(tp: Type) =
407+
if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepPolyParam(tp)
408+
mt.resultType.substParams(mt, mt.paramTypes.map(replacement))
409+
}
410+
else mt.resultType
411+
392412
/** The normalized form of a type
393413
* - unwraps polymorphic types, tracking their parameters in the current constraint
394414
* - skips implicit parameters; if result type depends on implicit parameter,
@@ -408,7 +428,7 @@ object ProtoTypes {
408428
tp.widenSingleton match {
409429
case poly: PolyType => normalize(constrained(poly).resultType, pt)
410430
case mt: MethodType =>
411-
if (mt.isImplicit) mt.resultTypeApprox
431+
if (mt.isImplicit) resultTypeApprox(mt)
412432
else if (mt.isDependent) tp
413433
else {
414434
val rt = normalize(mt.resultType, pt)

0 commit comments

Comments
 (0)