Skip to content

Commit 7ca48e3

Browse files
committed
Don't do mode adaptation when constraining closures
Ignore the mode instead, since it will anyway be adapted later when we check the closure's type. Also: Improve error message when closure parameters don't match.
1 parent 95002c5 commit 7ca48e3

File tree

6 files changed

+27
-12
lines changed

6 files changed

+27
-12
lines changed

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import scala.collection.mutable
2020
import CaptureSet.{withCaptureSetsExplained, IdempotentCaptRefMap}
2121
import StdNames.nme
2222
import NameKinds.DefaultGetterName
23-
import reporting.trace
23+
import reporting.{trace, ClosureParameterMismatch}
2424

2525
/** The capture checker */
2626
object CheckCaptures:
@@ -506,7 +506,9 @@ class CheckCaptures extends Recheck, SymTransformer:
506506

507507
def constrainParams(ptformals: List[Type], params: ParamClause) =
508508
for (param, ptformal) <- params.lazyZip(ptformals) do
509-
checkConformsExpr(ptformal, param.symbol.info, param)
509+
withMode(Mode.CCIgnoreBoxing):
510+
if !isCompatible(ptformal, param.symbol.info, param) then
511+
report.error(ClosureParameterMismatch(ptformal, param.symbol.info), param.srcPos)
510512

511513
def constrain(pt: Type, paramss: List[ParamClause]): Unit = (pt: @unchecked) match
512514
case RefinedType(_, nme.apply, rinfo) =>

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,14 @@ object Mode {
153153
*/
154154
val ForceInline: Mode = newMode(29, "ForceInline")
155155

156+
val CCIgnoreBoxing = ForceInline // Reuse mode bit in checkCaptures phase to indicate relaxed boxing
157+
156158
/** This mode is enabled when we check Java overriding in explicit nulls.
157159
* Type `Null` becomes a subtype of non-primitive value types in TypeComparer.
158160
*/
159161
val RelaxedOverriding: Mode = newMode(30, "RelaxedOverriding")
160162

161163
/** We are checking the original call of an Inlined node */
162164
val InlinedCall: Mode = newMode(31, "InlinedCall")
165+
163166
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2696,6 +2696,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
26962696
*/
26972697
protected def sameBoxed(tp1: Type, tp2: Type, refs1: CaptureSet)(using Context): Boolean =
26982698
(tp1.isBoxedCapturing == tp2.isBoxedCapturing)
2699+
|| ctx.mode.is(Mode.CCIgnoreBoxing)
26992700
|| refs1.subCaptures(CaptureSet.empty, frozenConstraint).isOK
27002701

27012702
// ----------- Diagnostics --------------------------------------------------

compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
202202
case ImplausiblePatternWarningID // erorNumber: 186
203203
case SynchronizedCallOnBoxedClassID // errorNumber: 187
204204
case VarArgsParamCannotBeGivenID // erorNumber: 188
205+
case ClosureParameterMismatchID // errorNumber 189
205206

206207
def errorNumber = ordinal - 1
207208

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,14 @@ class IllegalParameterInit(found: Type, expected: Type, param: Symbol, cls: Symb
15841584
| The argument passed for $param has type: $found
15851585
| but $cls expects $param to have type: $expected"""
15861586

1587+
class ClosureParameterMismatch(inferred: Type, declared: Type)(using Context)
1588+
extends TypeMismatchMsg(inferred, declared)(ClosureParameterMismatchID):
1589+
def msg(using Context) =
1590+
i"""Inferred closure parameter type is incompatible with declared parameter type.
1591+
|
1592+
|Inferred type: $inferred
1593+
|Declared type: $declared"""
1594+
15871595
class AbstractMemberMayNotHaveModifier(sym: Symbol, flag: FlagSet)(
15881596
implicit ctx: Context)
15891597
extends SyntaxMsg(AbstractMemberMayNotHaveModifierID) {

compiler/src/dotty/tools/dotc/transform/Recheck.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -562,18 +562,18 @@ abstract class Recheck extends Phase, SymTransformer:
562562
case _ =>
563563
checkConformsExpr(tpe.widenExpr, pt.widenExpr, tree)
564564

565+
def isCompatible(actual: Type, expected: Type, tree: Tree)(using Context): Boolean =
566+
actual <:< expected
567+
|| expected.isRepeatedParam
568+
&& isCompatible(actual, expected.translateFromRepeated(toArray = tree.tpe.widen.isRef(defn.ArrayClass)), tree)
569+
|| {
570+
val widened = widenSkolems(expected)
571+
(widened ne expected) && isCompatible(actual, widened, tree)
572+
}
573+
565574
def checkConformsExpr(actual: Type, expected: Type, tree: Tree)(using Context): Unit =
566575
//println(i"check conforms $actual <:< $expected")
567-
568-
def isCompatible(expected: Type): Boolean =
569-
actual <:< expected
570-
|| expected.isRepeatedParam
571-
&& isCompatible(expected.translateFromRepeated(toArray = tree.tpe.isRef(defn.ArrayClass)))
572-
|| {
573-
val widened = widenSkolems(expected)
574-
(widened ne expected) && isCompatible(widened)
575-
}
576-
if !isCompatible(expected) then
576+
if !isCompatible(actual, expected, tree) then
577577
recheckr.println(i"conforms failed for ${tree}: $actual vs $expected")
578578
err.typeMismatch(tree.withType(actual), expected)
579579
else if debugSuccesses then

0 commit comments

Comments
 (0)