Skip to content

Commit 6e14664

Browse files
authored
Merge pull request #431 from scala/backport-lts-3.3-23212
Backport "Fix scala#20335: Try extensions for arguments with type mismatch error" to 3.3 LTS
2 parents 47eca05 + 7650d0a commit 6e14664

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ trait ShowMatchTrace(tps: Type*)(using Context) extends Message:
6060
override def msgPostscript(using Context): String =
6161
super.msgPostscript ++ matchReductionAddendum(tps*)
6262

63-
abstract class TypeMismatchMsg(found: Type, expected: Type)(errorId: ErrorMessageID)(using Context)
63+
abstract class TypeMismatchMsg(found: Type, val expected: Type)(errorId: ErrorMessageID)(using Context)
6464
extends Message(errorId), ShowMatchTrace(found, expected):
6565
def kind = MessageKind.TypeMismatch
6666
def explain(using Context) = err.whyNoMatchStr(found, expected)

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -391,21 +391,28 @@ object ProtoTypes {
391391
* - t2 is a ascription (t22: T) and t1 is at the outside of t22
392392
* - t2 is a closure (...) => t22 and t1 is at the outside of t22
393393
*/
394-
def hasInnerErrors(t: Tree)(using Context): Boolean = t match
395-
case Typed(expr, tpe) => hasInnerErrors(expr)
396-
case closureDef(mdef) => hasInnerErrors(mdef.rhs)
394+
def hasInnerErrors(t: Tree, argType: Type)(using Context): Boolean = t match
395+
case Typed(expr, tpe) => hasInnerErrors(expr, argType)
396+
case closureDef(mdef) => hasInnerErrors(mdef.rhs, argType)
397397
case _ =>
398398
t.existsSubTree { t1 =>
399399
if t1.typeOpt.isError
400400
&& t.span.toSynthetic != t1.span.toSynthetic
401401
&& t.typeOpt != t1.typeOpt then
402402
typr.println(i"error subtree $t1 of $t with ${t1.typeOpt}, spans = ${t1.span}, ${t.span}")
403-
true
403+
t1.typeOpt match
404+
case errorType: ErrorType if errorType.msg.isInstanceOf[TypeMismatchMsg] =>
405+
// if error is caused by an argument type mismatch,
406+
// then return false to try to find an extension.
407+
// see i20335.scala for test case.
408+
val typeMismtachMsg = errorType.msg.asInstanceOf[TypeMismatchMsg]
409+
argType != typeMismtachMsg.expected
410+
case _ => true
404411
else
405412
false
406413
}
407414

408-
private def cacheTypedArg(arg: untpd.Tree, typerFn: untpd.Tree => Tree, force: Boolean)(using Context): Tree = {
415+
private def cacheTypedArg(arg: untpd.Tree, typerFn: untpd.Tree => Tree, force: Boolean, argType: Type)(using Context): Tree = {
409416
var targ = state.typedArg(arg)
410417
if (targ == null)
411418
untpd.functionWithUnknownParamType(arg) match {
@@ -423,7 +430,7 @@ object ProtoTypes {
423430
targ = typerFn(arg)
424431
// TODO: investigate why flow typing is not working on `targ`
425432
if ctx.reporter.hasUnreportedErrors then
426-
if hasInnerErrors(targ.nn) then
433+
if hasInnerErrors(targ.nn, argType) then
427434
state.errorArgs += arg
428435
else
429436
state.typedArg = state.typedArg.updated(arg, targ.nn)
@@ -451,7 +458,7 @@ object ProtoTypes {
451458
val protoTyperState = ctx.typerState
452459
val oldConstraint = protoTyperState.constraint
453460
val args1 = args.mapWithIndexConserve((arg, idx) =>
454-
cacheTypedArg(arg, arg => typer.typed(norm(arg, idx)), force = false))
461+
cacheTypedArg(arg, arg => typer.typed(norm(arg, idx)), force = false, NoType))
455462
val newConstraint = protoTyperState.constraint
456463

457464
if !args1.exists(arg => isUndefined(arg.tpe)) then state.typedArgs = args1
@@ -498,7 +505,8 @@ object ProtoTypes {
498505
val locked = ctx.typerState.ownedVars
499506
val targ = cacheTypedArg(arg,
500507
typer.typedUnadapted(_, wideFormal, locked)(using argCtx),
501-
force = true)
508+
force = true,
509+
wideFormal)
502510
val targ1 = typer.adapt(targ, wideFormal, locked)
503511
if wideFormal eq formal then targ1
504512
else checkNoWildcardCaptureForCBN(targ1)

tests/pos/i20335.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import java.time.OffsetDateTime
2+
import scala.concurrent.duration.*
3+
4+
val dateTime: OffsetDateTime = OffsetDateTime.now()
5+
6+
implicit class DateTimeOps(val dateTime: OffsetDateTime) {
7+
def plus(amount: FiniteDuration): OffsetDateTime =
8+
dateTime
9+
}
10+
11+
def test = {
12+
dateTime.plus(Duration.Zero)
13+
dateTime.plus(if (true) Duration.Zero else Duration.Zero)
14+
}

0 commit comments

Comments
 (0)