Skip to content

Commit 337dce8

Browse files
committed
Check for good bounds before reporting other bounds violations
Fixes scala#15568
1 parent 4994420 commit 337dce8

File tree

4 files changed

+22
-12
lines changed

4 files changed

+22
-12
lines changed

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,6 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
181181
=> Checking.checkAppliedTypesIn(tree)
182182
case _ =>
183183

184-
private def checkGoodBounds(tpe: Type, pos: SrcPos)(using Context): Unit = tpe.dealias match
185-
case tpe: TypeRef =>
186-
checkGoodBounds(tpe.info, pos)
187-
case TypeBounds(lo, hi) if !(lo <:< hi) =>
188-
report.error(i"type argument has unrealizable bounds $tpe", pos)
189-
case _ =>
190-
191184
private def removeUnwantedAnnotations(sym: Symbol, metaAnnotSym: Symbol,
192185
metaAnnotSymBackup: Symbol, keepIfNoRelevantAnnot: Boolean)(using Context): Unit =
193186
def shouldKeep(annot: Annotation): Boolean =
@@ -352,7 +345,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
352345
val tree1 @ TypeApply(fn, args) = normalizeTypeArgs(tree)
353346
for arg <- args do
354347
checkInferredWellFormed(arg)
355-
checkGoodBounds(arg.tpe, arg.srcPos)
348+
Checking.checkGoodBounds(arg.tpe, arg.srcPos)
356349
if (fn.symbol != defn.ChildAnnot.primaryConstructor)
357350
// Make an exception for ChildAnnot, which should really have AnyKind bounds
358351
Checking.checkBounds(args, fn.tpe.widen.asInstanceOf[PolyType])

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,11 @@ object Checking {
7373
showInferred(MissingTypeParameterInTypeApp(arg.tpe), app, tpt))
7474
}
7575
for (arg, which, bound) <- TypeOps.boundsViolations(args, boundss, instantiate, app) do
76-
report.error(
77-
showInferred(DoesNotConformToBound(arg.tpe, which, bound),
78-
app, tpt),
79-
arg.srcPos.focus)
76+
if checkGoodBounds(arg.tpe, arg.srcPos.focus) then
77+
report.error(
78+
showInferred(DoesNotConformToBound(arg.tpe, which, bound),
79+
app, tpt),
80+
arg.srcPos.focus)
8081

8182
/** Check that type arguments `args` conform to corresponding bounds in `tl`
8283
* Note: This does not check the bounds of AppliedTypeTrees. These
@@ -85,6 +86,15 @@ object Checking {
8586
def checkBounds(args: List[tpd.Tree], tl: TypeLambda)(using Context): Unit =
8687
checkBounds(args, tl.paramInfos, _.substParams(tl, _))
8788

89+
def checkGoodBounds(tpe: Type, pos: SrcPos)(using Context): Boolean = tpe.dealias match
90+
case tpe: TypeRef =>
91+
checkGoodBounds(tpe.info, pos)
92+
case TypeBounds(lo, hi) if !(lo <:< hi) =>
93+
report.error(i"type argument has unrealizable bounds $tpe", pos)
94+
false
95+
case _ =>
96+
true
97+
8898
/** Check applied type trees for well-formedness. This means
8999
* - all arguments are within their corresponding bounds
90100
* - if type is a higher-kinded application with wildcard arguments,

tests/neg/i15568.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Error: tests/neg/i15568.scala:3:15 ----------------------------------------------------------------------------------
2+
3 |type Bar = Foo[? >: Int <: String] // error
3+
| ^
4+
| type argument has unrealizable bounds >: Int <: String

tests/neg/i15568.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
trait Foo[X >: Int <: String]
2+
3+
type Bar = Foo[? >: Int <: String] // error

0 commit comments

Comments
 (0)