Skip to content

Commit 0632096

Browse files
committed
Fix #20335: Try extension or implicit conversion for arguments with type mismatch error
1 parent d36e423 commit 0632096

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-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
@@ -62,7 +62,7 @@ trait ShowMatchTrace(tps: Type*)(using Context) extends Message:
6262
override def msgPostscript(using Context): String =
6363
super.msgPostscript ++ matchReductionAddendum(tps*)
6464

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

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -427,21 +427,25 @@ object ProtoTypes {
427427
* - t2 is a ascription (t22: T) and t1 is at the outside of t22
428428
* - t2 is a closure (...) => t22 and t1 is at the outside of t22
429429
*/
430-
def hasInnerErrors(t: Tree)(using Context): Boolean = t match
431-
case Typed(expr, tpe) => hasInnerErrors(expr)
432-
case closureDef(mdef) => hasInnerErrors(mdef.rhs)
430+
def hasInnerErrors(t: Tree, argType: Option[Type])(using Context): Boolean = t match
431+
case Typed(expr, tpe) => hasInnerErrors(expr, argType)
432+
case closureDef(mdef) => hasInnerErrors(mdef.rhs, argType)
433433
case _ =>
434434
t.existsSubTree { t1 =>
435435
if t1.typeOpt.isError
436436
&& t.span.toSynthetic != t1.span.toSynthetic
437437
&& t.typeOpt != t1.typeOpt then
438438
typr.println(i"error subtree $t1 of $t with ${t1.typeOpt}, spans = ${t1.span}, ${t.span}")
439-
true
439+
t1.typeOpt match
440+
case errorType: ErrorType if errorType.msg.isInstanceOf[TypeMismatchMsg] =>
441+
val typeMismtachMsg = errorType.msg.asInstanceOf[TypeMismatchMsg]
442+
!argType.contains(typeMismtachMsg.expected)
443+
case _ => true
440444
else
441445
false
442446
}
443447

444-
private def cacheTypedArg(arg: untpd.Tree, typerFn: untpd.Tree => Tree, force: Boolean)(using Context): Tree = {
448+
private def cacheTypedArg(arg: untpd.Tree, typerFn: untpd.Tree => Tree, force: Boolean, argType: Option[Type])(using Context): Tree = {
445449
var targ = state.typedArg(arg)
446450
if (targ == null)
447451
untpd.functionWithUnknownParamType(arg) match {
@@ -459,7 +463,7 @@ object ProtoTypes {
459463
targ = typerFn(arg)
460464
// TODO: investigate why flow typing is not working on `targ`
461465
if ctx.reporter.hasUnreportedErrors then
462-
if hasInnerErrors(targ.nn) then
466+
if hasInnerErrors(targ.nn, argType) then
463467
state.errorArgs += arg
464468
else
465469
state.typedArg = state.typedArg.updated(arg, targ.nn)
@@ -487,7 +491,7 @@ object ProtoTypes {
487491
val protoTyperState = ctx.typerState
488492
val oldConstraint = protoTyperState.constraint
489493
val args1 = args.mapWithIndexConserve((arg, idx) =>
490-
cacheTypedArg(arg, arg => typer.typed(norm(arg, idx)), force = false))
494+
cacheTypedArg(arg, arg => typer.typed(norm(arg, idx)), force = false, None))
491495
val newConstraint = protoTyperState.constraint
492496

493497
if !args1.exists(arg => isUndefined(arg.tpe)) then state.typedArgs = args1
@@ -534,7 +538,8 @@ object ProtoTypes {
534538
val locked = ctx.typerState.ownedVars
535539
val targ = cacheTypedArg(arg,
536540
typer.typedUnadapted(_, wideFormal, locked)(using argCtx),
537-
force = true)
541+
force = true,
542+
Some(wideFormal))
538543
val targ1 = typer.adapt(targ, wideFormal, locked)
539544
if wideFormal eq formal then targ1
540545
else checkNoWildcardCaptureForCBN(targ1)

0 commit comments

Comments
 (0)