From 792469bfabb235638a41b6fa7fd4715346df7b51 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 21 Mar 2022 09:31:49 +0100 Subject: [PATCH] Don't replace typevars by their f-bounds in error messages Fixes #14363 --- .../dotty/tools/dotc/reporting/messages.scala | 19 ++++++++++++++----- tests/neg/i14363.check | 16 ++++++++++++++++ tests/neg/i14363.scala | 2 ++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 tests/neg/i14363.check create mode 100644 tests/neg/i14363.scala diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 0262e0190677..34b08870fd42 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -245,12 +245,15 @@ import transform.SymUtils._ extends TypeMismatchMsg(found, expected)(TypeMismatchID): // replace constrained TypeParamRefs and their typevars by their bounds where possible - // the idea is that if the bounds are also not-subtypes of each other to report + // and the bounds are not f-bounds. + // The idea is that if the bounds are also not-subtypes of each other to report // the type mismatch on the bounds instead of the original TypeParamRefs, since - // these are usually easier to analyze. + // these are usually easier to analyze. We exclude F-bounds since these would + // lead to a recursive infinite expansion. object reported extends TypeMap: def setVariance(v: Int) = variance = v val constraint = mapCtx.typerState.constraint + var fbounded = false def apply(tp: Type): Type = tp match case tp: TypeParamRef => constraint.entry(tp) match @@ -260,15 +263,21 @@ import transform.SymUtils._ else tp case NoType => tp case instType => apply(instType) - case tp: TypeVar => apply(tp.stripTypeVar) - case _ => mapOver(tp) + case tp: TypeVar => + apply(tp.stripTypeVar) + case tp: LazyRef => + fbounded = true + tp + case _ => + mapOver(tp) def msg = val found1 = reported(found) reported.setVariance(-1) val expected1 = reported(expected) val (found2, expected2) = - if (found1 frozen_<:< expected1) (found, expected) else (found1, expected1) + if (found1 frozen_<:< expected1) || reported.fbounded then (found, expected) + else (found1, expected1) val postScript = addenda.find(!_.isEmpty) match case Some(p) => p case None => diff --git a/tests/neg/i14363.check b/tests/neg/i14363.check new file mode 100644 index 000000000000..4da37612f28b --- /dev/null +++ b/tests/neg/i14363.check @@ -0,0 +1,16 @@ +-- [E007] Type Mismatch Error: tests/neg/i14363.scala:2:13 ------------------------------------------------------------- +2 |def test = f(1) // error + | ^ + | Found: (1 : Int) + | Required: T + | + | where: T is a type variable with constraint <: Ordered[T] + | + | + | One of the following imports might fix the problem: + | + | import math.BigDecimal.int2bigDecimal + | import math.BigInt.int2bigInt + | + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i14363.scala b/tests/neg/i14363.scala new file mode 100644 index 000000000000..12d7b926a554 --- /dev/null +++ b/tests/neg/i14363.scala @@ -0,0 +1,2 @@ +def f[T <: Ordered[T]](t: T): T = t +def test = f(1) // error \ No newline at end of file