Skip to content

Commit 3b91efb

Browse files
committed
Abort implicit search for types with errors
If the searched-for type has errors, fail implicit search immediately. Error types match everything, so we risk traversing many implicit candidates for nothing. This change uncovered the problem with parameter-dependent using clauses with default arguments that was fixed in the last commit.
1 parent 8120430 commit 3b91efb

File tree

4 files changed

+14
-4
lines changed

4 files changed

+14
-4
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,13 +332,17 @@ object Types {
332332
/** Is this type produced as a repair for an error? */
333333
final def isError(using Context): Boolean = stripTypeVar.isInstanceOf[ErrorType]
334334

335+
/** A conservative approximation whether a type might have errors.
336+
* It's OK to predict "no errors" even though errors might be present.
337+
* But one should never force or loop.
338+
*/
335339
def hasErrors(using Context): Boolean = widenDealias match
336-
case _: NamedType => false
337340
case AppliedType(tycon, args) => tycon.hasErrors || args.exists(_.hasErrors)
338341
case RefinedType(parent, _, rinfo) => parent.hasErrors || rinfo.hasErrors
339342
case TypeBounds(lo, hi) => lo.hasErrors || hi.hasErrors
340343
case tp: AndOrType => tp.tp1.hasErrors || tp.tp2.hasErrors
341-
case tp: TypeProxy => tp.underlying.hasErrors
344+
case tp: LambdaType => tp.resultType.hasErrors || tp.paramInfos.exists(_.hasErrors)
345+
case WildcardType(optBounds) => optBounds.hasErrors
342346
case _: ErrorType => true
343347
case _ => false
344348

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,9 @@ trait Applications extends Compatibility {
473473
def success: Boolean = ok
474474

475475
protected def methodType: MethodType = methType.asInstanceOf[MethodType]
476-
private def methString: String = i"${err.refStr(methRef)}: ${methType.show}"
476+
private def methString: String =
477+
def infoStr = if methType.hasErrors then "" else i": $methType"
478+
i"${err.refStr(methRef)}$infoStr"
477479

478480
/** Re-order arguments to correctly align named arguments */
479481
def reorder[T >: Untyped](args: List[Trees.Tree[T]]): List[Trees.Tree[T]] = {

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,10 @@ trait Implicits:
954954
assert(ctx.phase.allowsImplicitSearch,
955955
if (argument.isEmpty) i"missing implicit parameter of type $pt after typer"
956956
else i"type error: ${argument.tpe} does not conform to $pt${err.whyNoMatchStr(argument.tpe, pt)}")
957+
958+
if pt.hasErrors || !argument.isEmpty && argument.tpe.hasErrors then
959+
return NoMatchingImplicitsFailure
960+
957961
val result0 =
958962
try ImplicitSearch(pt, argument, span).bestImplicit
959963
catch case ce: CyclicReference =>

tests/neg/i7750a.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
def foo: Unit = {
22
val a = (x: Int, y: String) => x + + y // error
33
implicit def f[X](x: (X, String) => String) = (z: X) => (z, null) // error
4-
a(1)
4+
a(1) // error
55
}

0 commit comments

Comments
 (0)