Skip to content

Don't replace typevars by their f-bounds in error messages #14723

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 =>
Expand Down
16 changes: 16 additions & 0 deletions tests/neg/i14363.check
Original file line number Diff line number Diff line change
@@ -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`
2 changes: 2 additions & 0 deletions tests/neg/i14363.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def f[T <: Ordered[T]](t: T): T = t
def test = f(1) // error