Skip to content

Commit ea03640

Browse files
committed
Check type arguments for bad bounds
Fixes #15569
1 parent 6062192 commit ea03640

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import util.SimpleIdentityMap
1414

1515
import collection.mutable
1616

17-
/** A utility object offering methods for rewriting inlined code */
17+
/** A utility class offering methods for rewriting inlined code */
1818
class InlineReducer(inliner: Inliner)(using Context):
1919
import tpd.*
2020
import Inliner.{isElideableExpr, DefBuffer}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Decorators._
1414
import Symbols._, SymUtils._, NameOps._
1515
import ContextFunctionResults.annotateContextResults
1616
import config.Printers.typr
17+
import util.SrcPos
1718
import reporting._
1819

1920
object PostTyper {
@@ -180,6 +181,13 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
180181
=> Checking.checkAppliedTypesIn(tree)
181182
case _ =>
182183

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+
183191
private def removeUnwantedAnnotations(sym: Symbol, metaAnnotSym: Symbol,
184192
metaAnnotSymBackup: Symbol, keepIfNoRelevantAnnot: Boolean)(using Context): Unit =
185193
def shouldKeep(annot: Annotation): Boolean =
@@ -342,7 +350,9 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
342350
if tree.symbol.is(Inline) then
343351
ctx.compilationUnit.needsInlining = true
344352
val tree1 @ TypeApply(fn, args) = normalizeTypeArgs(tree)
345-
args.foreach(checkInferredWellFormed)
353+
for arg <- args do
354+
checkInferredWellFormed(arg)
355+
checkGoodBounds(arg.tpe, arg.srcPos)
346356
if (fn.symbol != defn.ChildAnnot.primaryConstructor)
347357
// Make an exception for ChildAnnot, which should really have AnyKind bounds
348358
Checking.checkBounds(args, fn.tpe.widen.asInstanceOf[PolyType])

tests/neg/i15569.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
trait Foo[X >: Any <: Nothing]
2+
3+
def andThenSub[A, B, C](f: A <:< B, g: B <:< C): A <:< C =
4+
f.andThen(g)
5+
6+
@main def Test = (None: Option[Foo[?]]) match {
7+
case _: Option[Foo[t]] =>
8+
val unsound: Any <:< Nothing = andThenSub[Any, t, Nothing](summon, summon) // error
9+
unsound("hi :)")
10+
}
11+
@main def Test2 =
12+
type t >: Any <: Nothing
13+
val unsound: Any <:< Nothing = andThenSub[Any, t, Nothing](summon, summon) // error
14+
unsound("hi :)")
15+

0 commit comments

Comments
 (0)