From ea03640c3581f3ad39868dabadf918e8c336f183 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 2 Jul 2022 10:58:53 +0200 Subject: [PATCH] Check type arguments for bad bounds Fixes #15569 --- .../dotty/tools/dotc/inlines/InlineReducer.scala | 2 +- .../dotty/tools/dotc/transform/PostTyper.scala | 12 +++++++++++- tests/neg/i15569.scala | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 tests/neg/i15569.scala diff --git a/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala b/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala index 7be63fc8ba3a..b5e2e7d475ad 100644 --- a/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala +++ b/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala @@ -14,7 +14,7 @@ import util.SimpleIdentityMap import collection.mutable -/** A utility object offering methods for rewriting inlined code */ +/** A utility class offering methods for rewriting inlined code */ class InlineReducer(inliner: Inliner)(using Context): import tpd.* import Inliner.{isElideableExpr, DefBuffer} diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index dda4b89f6d1c..a5ac0d7ba50f 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -14,6 +14,7 @@ import Decorators._ import Symbols._, SymUtils._, NameOps._ import ContextFunctionResults.annotateContextResults import config.Printers.typr +import util.SrcPos import reporting._ object PostTyper { @@ -180,6 +181,13 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase => Checking.checkAppliedTypesIn(tree) case _ => + private def checkGoodBounds(tpe: Type, pos: SrcPos)(using Context): Unit = tpe.dealias match + case tpe: TypeRef => + checkGoodBounds(tpe.info, pos) + case TypeBounds(lo, hi) if !(lo <:< hi) => + report.error(i"type argument has unrealizable bounds $tpe", pos) + case _ => + private def removeUnwantedAnnotations(sym: Symbol, metaAnnotSym: Symbol, metaAnnotSymBackup: Symbol, keepIfNoRelevantAnnot: Boolean)(using Context): Unit = def shouldKeep(annot: Annotation): Boolean = @@ -342,7 +350,9 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase if tree.symbol.is(Inline) then ctx.compilationUnit.needsInlining = true val tree1 @ TypeApply(fn, args) = normalizeTypeArgs(tree) - args.foreach(checkInferredWellFormed) + for arg <- args do + checkInferredWellFormed(arg) + checkGoodBounds(arg.tpe, arg.srcPos) if (fn.symbol != defn.ChildAnnot.primaryConstructor) // Make an exception for ChildAnnot, which should really have AnyKind bounds Checking.checkBounds(args, fn.tpe.widen.asInstanceOf[PolyType]) diff --git a/tests/neg/i15569.scala b/tests/neg/i15569.scala new file mode 100644 index 000000000000..f98345a61691 --- /dev/null +++ b/tests/neg/i15569.scala @@ -0,0 +1,15 @@ +trait Foo[X >: Any <: Nothing] + +def andThenSub[A, B, C](f: A <:< B, g: B <:< C): A <:< C = + f.andThen(g) + +@main def Test = (None: Option[Foo[?]]) match { + case _: Option[Foo[t]] => + val unsound: Any <:< Nothing = andThenSub[Any, t, Nothing](summon, summon) // error + unsound("hi :)") +} +@main def Test2 = + type t >: Any <: Nothing + val unsound: Any <:< Nothing = andThenSub[Any, t, Nothing](summon, summon) // error + unsound("hi :)") +