Skip to content

Commit a331da7

Browse files
authored
Merge pull request #8212 from dotty-staging/drop-withbounds
Generalize TypeBoundsTree to bounded opaque aliases
2 parents af9e7f0 + 3e7d5af commit a331da7

16 files changed

+76
-85
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

+4-3
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ object desugar {
252252

253253
if (meth1.mods.is(Inline))
254254
meth1.tpt match {
255-
case TypeBoundsTree(_, tpt1) =>
255+
case TypeBoundsTree(_, tpt1, _) =>
256256
meth1 = cpy.DefDef(meth1)(tpt = tpt1)
257257
case tpt if !tpt.isEmpty && !meth1.rhs.isEmpty =>
258258
meth1 = cpy.DefDef(meth1)(rhs = Typed(meth1.rhs, tpt))
@@ -684,7 +684,7 @@ object desugar {
684684
val mods = constr1.mods
685685
mods.is(Private) || (!mods.is(Protected) && mods.hasPrivateWithin)
686686
}
687-
687+
688688
/** Does one of the parameter's types (in the first param clause)
689689
* mention a preceding parameter?
690690
*/
@@ -1156,7 +1156,8 @@ object desugar {
11561156
val legalOpaque: MemberDefTest = {
11571157
case TypeDef(_, rhs) =>
11581158
def rhsOK(tree: Tree): Boolean = tree match {
1159-
case _: TypeBoundsTree | _: Template => false
1159+
case bounds: TypeBoundsTree => !bounds.alias.isEmpty
1160+
case _: Template => false
11601161
case LambdaTypeTree(_, body) => rhsOK(body)
11611162
case _ => true
11621163
}

compiler/src/dotty/tools/dotc/ast/Trees.scala

+13-12
Original file line numberDiff line numberDiff line change
@@ -690,8 +690,10 @@ object Trees {
690690
type ThisTree[-T >: Untyped] = ByNameTypeTree[T]
691691
}
692692

693-
/** >: lo <: hi */
694-
case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])(implicit @constructorOnly src: SourceFile)
693+
/** >: lo <: hi
694+
* >: lo <: hi = alias for RHS of bounded opaque type
695+
*/
696+
case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T], alias: Tree[T])(implicit @constructorOnly src: SourceFile)
695697
extends TypTree[T] {
696698
type ThisTree[-T >: Untyped] = TypeBoundsTree[T]
697699
}
@@ -760,7 +762,8 @@ object Trees {
760762
/** mods class name template or
761763
* mods trait name template or
762764
* mods type name = rhs or
763-
* mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) & (lo ne hi)
765+
* mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) or
766+
* mods type name >: lo <: hi = rhs if rhs = TypeBoundsTree(lo, hi, alias) and opaque in mods
764767
*/
765768
case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T])(implicit @constructorOnly src: SourceFile)
766769
extends MemberDef[T] {
@@ -811,8 +814,6 @@ object Trees {
811814
extends ProxyTree[T] {
812815
type ThisTree[-T >: Untyped] = Annotated[T]
813816
def forwardTo: Tree[T] = arg
814-
override def disableOverlapChecks = true
815-
// disable overlaps checks since the WithBounds annotation swaps type and annotation.
816817
}
817818

818819
trait WithoutTypeOrPos[-T >: Untyped] extends Tree[T] {
@@ -1151,9 +1152,9 @@ object Trees {
11511152
case tree: ByNameTypeTree if (result eq tree.result) => tree
11521153
case _ => finalize(tree, untpd.ByNameTypeTree(result)(sourceFile(tree)))
11531154
}
1154-
def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree = tree match {
1155-
case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) => tree
1156-
case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)(sourceFile(tree)))
1155+
def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree, alias: Tree)(implicit ctx: Context): TypeBoundsTree = tree match {
1156+
case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) && (alias eq tree.alias) => tree
1157+
case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi, alias)(sourceFile(tree)))
11571158
}
11581159
def Bind(tree: Tree)(name: Name, body: Tree)(implicit ctx: Context): Bind = tree match {
11591160
case tree: Bind if (name eq tree.name) && (body eq tree.body) => tree
@@ -1304,8 +1305,8 @@ object Trees {
13041305
cpy.MatchTypeTree(tree)(transform(bound), transform(selector), transformSub(cases))
13051306
case ByNameTypeTree(result) =>
13061307
cpy.ByNameTypeTree(tree)(transform(result))
1307-
case TypeBoundsTree(lo, hi) =>
1308-
cpy.TypeBoundsTree(tree)(transform(lo), transform(hi))
1308+
case TypeBoundsTree(lo, hi, alias) =>
1309+
cpy.TypeBoundsTree(tree)(transform(lo), transform(hi), transform(alias))
13091310
case Bind(name, body) =>
13101311
cpy.Bind(tree)(name, transform(body))
13111312
case Alternative(trees) =>
@@ -1428,8 +1429,8 @@ object Trees {
14281429
this(this(this(x, bound), selector), cases)
14291430
case ByNameTypeTree(result) =>
14301431
this(x, result)
1431-
case TypeBoundsTree(lo, hi) =>
1432-
this(this(x, lo), hi)
1432+
case TypeBoundsTree(lo, hi, alias) =>
1433+
this(this(this(x, lo), hi), alias)
14331434
case Bind(name, body) =>
14341435
this(x, body)
14351436
case Alternative(trees) =>

compiler/src/dotty/tools/dotc/ast/tpd.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
179179
def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ctx: Context): MatchTypeTree =
180180
ta.assignType(untpd.MatchTypeTree(bound, selector, cases), bound, selector, cases)
181181

182-
def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
183-
ta.assignType(untpd.TypeBoundsTree(lo, hi), lo, hi)
182+
def TypeBoundsTree(lo: Tree, hi: Tree, alias: Tree = EmptyTree)(implicit ctx: Context): TypeBoundsTree =
183+
ta.assignType(untpd.TypeBoundsTree(lo, hi, alias), lo, hi, alias)
184184

185185
def Bind(sym: Symbol, body: Tree)(implicit ctx: Context): Bind =
186186
ta.assignType(untpd.Bind(sym.name, body), sym)

compiler/src/dotty/tools/dotc/ast/untpd.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
376376
def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit src: SourceFile): LambdaTypeTree = new LambdaTypeTree(tparams, body)
377377
def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit src: SourceFile): MatchTypeTree = new MatchTypeTree(bound, selector, cases)
378378
def ByNameTypeTree(result: Tree)(implicit src: SourceFile): ByNameTypeTree = new ByNameTypeTree(result)
379-
def TypeBoundsTree(lo: Tree, hi: Tree)(implicit src: SourceFile): TypeBoundsTree = new TypeBoundsTree(lo, hi)
379+
def TypeBoundsTree(lo: Tree, hi: Tree, alias: Tree = EmptyTree)(implicit src: SourceFile): TypeBoundsTree = new TypeBoundsTree(lo, hi, alias)
380380
def Bind(name: Name, body: Tree)(implicit src: SourceFile): Bind = new Bind(name, body)
381381
def Alternative(trees: List[Tree])(implicit src: SourceFile): Alternative = new Alternative(trees)
382382
def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit src: SourceFile): UnApply = new UnApply(fun, implicits, patterns)

compiler/src/dotty/tools/dotc/core/Annotations.scala

-16
Original file line numberDiff line numberDiff line change
@@ -173,22 +173,6 @@ object Annotations {
173173
else None
174174
}
175175

176-
/** Extractor for WithBounds[T] annotations */
177-
object WithBounds {
178-
def unapply(ann: Annotation)(implicit ctx: Context): Option[TypeBounds] =
179-
if (ann.symbol == defn.WithBoundsAnnot) {
180-
import ast.Trees._
181-
// We need to extract the type of the type tree in the New itself.
182-
// The annotation's type has been simplified as the type of an expression,
183-
// which means that `&` or `|` might have been lost.
184-
// Test in pos/reference/opaque.scala
185-
val Apply(TypeApply(Select(New(tpt), nme.CONSTRUCTOR), _), Nil) = ann.tree
186-
val AppliedType(_, lo :: hi :: Nil) = tpt.tpe
187-
Some(TypeBounds(lo, hi))
188-
}
189-
else None
190-
}
191-
192176
def makeSourceFile(path: String)(implicit ctx: Context): Annotation =
193177
apply(defn.SourceFileAnnot, Literal(Constant(path)))
194178
}

compiler/src/dotty/tools/dotc/core/Definitions.scala

-1
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,6 @@ class Definitions {
784784
@tu lazy val AnnotationDefaultAnnot: ClassSymbol = ctx.requiredClass("scala.annotation.internal.AnnotationDefault")
785785
@tu lazy val BodyAnnot: ClassSymbol = ctx.requiredClass("scala.annotation.internal.Body")
786786
@tu lazy val ChildAnnot: ClassSymbol = ctx.requiredClass("scala.annotation.internal.Child")
787-
@tu lazy val WithBoundsAnnot: ClassSymbol = ctx.requiredClass("scala.annotation.internal.WithBounds")
788787
@tu lazy val CovariantBetweenAnnot: ClassSymbol = ctx.requiredClass("scala.annotation.internal.CovariantBetween")
789788
@tu lazy val ContravariantBetweenAnnot: ClassSymbol = ctx.requiredClass("scala.annotation.internal.ContravariantBetween")
790789
@tu lazy val DeprecatedAnnot: ClassSymbol = ctx.requiredClass("scala.deprecated")

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

+12-12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Scopes.Scope
1111
import dotty.tools.io.AbstractFile
1212
import Decorators.SymbolIteratorDecorator
1313
import ast._
14+
import ast.Trees.{LambdaTypeTree, TypeBoundsTree}
1415
import Trees.Literal
1516
import Variances.Variance
1617
import annotation.tailrec
@@ -433,8 +434,9 @@ object SymDenotations {
433434
*
434435
* @param info Is assumed to be a (lambda-abstracted) right hand side TypeAlias
435436
* of the opaque type definition.
437+
* @param rhs The right hand side tree of the type definition
436438
*/
437-
def opaqueToBounds(info: Type)(given Context): Type =
439+
def opaqueToBounds(info: Type, rhs: tpd.Tree)(given Context): Type =
438440

439441
def setAlias(tp: Type) =
440442
def recur(self: Type): Unit = self match
@@ -446,21 +448,19 @@ object SymDenotations {
446448
recur(owner.asClass.givenSelfType)
447449
end setAlias
448450

449-
def split(tp: Type): (Type, TypeBounds) = tp match
450-
case AnnotatedType(alias, Annotation.WithBounds(bounds)) =>
451-
(alias, bounds)
452-
case tp: HKTypeLambda =>
453-
val (alias1, bounds1) = split(tp.resType)
454-
(tp.derivedLambdaType(resType = alias1),
455-
HKTypeLambda.boundsFromParams(tp.typeParams, bounds1))
451+
def bounds(t: tpd.Tree): TypeBounds = t match
452+
case LambdaTypeTree(_, body) =>
453+
bounds(body)
454+
case TypeBoundsTree(lo, hi, alias) =>
455+
assert(!alias.isEmpty)
456+
TypeBounds(lo.tpe, hi.tpe)
456457
case _ =>
457-
(tp, HKTypeLambda.boundsFromParams(tp.typeParams, TypeBounds.empty))
458+
TypeBounds.empty
458459

459460
info match
460-
case TypeAlias(tp) if isOpaqueAlias && owner.isClass =>
461-
val (alias, bounds) = split(tp)
461+
case TypeAlias(alias) if isOpaqueAlias && owner.isClass =>
462462
setAlias(alias)
463-
bounds
463+
HKTypeLambda.boundsFromParams(alias.typeParams, bounds(rhs))
464464
case _ =>
465465
info
466466
end opaqueToBounds

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

+6-2
Original file line numberDiff line numberDiff line change
@@ -588,11 +588,15 @@ class TreePickler(pickler: TastyPickler) {
588588
case LambdaTypeTree(tparams, body) =>
589589
writeByte(LAMBDAtpt)
590590
withLength { pickleParams(tparams); pickleTree(body) }
591-
case TypeBoundsTree(lo, hi) =>
591+
case TypeBoundsTree(lo, hi, alias) =>
592592
writeByte(TYPEBOUNDStpt)
593593
withLength {
594594
pickleTree(lo);
595-
if (hi ne lo) pickleTree(hi)
595+
if alias.isEmpty then
596+
if hi ne lo then pickleTree(hi)
597+
else
598+
pickleTree(hi)
599+
pickleTree(alias)
596600
}
597601
case Hole(_, idx, args) =>
598602
writeByte(HOLE)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

+7-5
Original file line numberDiff line numberDiff line change
@@ -833,11 +833,12 @@ class TreeUnpickler(reader: TastyReader,
833833
override def completerTypeParams(sym: Symbol)(implicit ctx: Context) =
834834
rhs.tpe.typeParams
835835
}
836-
sym.info = sym.opaqueToBounds {
837-
rhs.tpe match
836+
sym.info = sym.opaqueToBounds(
837+
rhs.tpe match {
838838
case _: TypeBounds | _: ClassInfo => checkNonCyclic(sym, rhs.tpe, reportErrors = false)
839839
case _ => rhs.tpe.toBounds
840-
}
840+
},
841+
rhs)
841842
if sym.isOpaqueAlias then sym.typeRef.recomputeDenot() // make sure we see the new bounds from now on
842843
sym.resetFlag(Provisional)
843844
TypeDef(rhs)
@@ -1209,8 +1210,9 @@ class TreeUnpickler(reader: TastyReader,
12091210
MatchTypeTree(bound, scrut, readCases(end))
12101211
case TYPEBOUNDStpt =>
12111212
val lo = readTpt()
1212-
val hi = if (currentAddr == end) lo else readTpt()
1213-
TypeBoundsTree(lo, hi)
1213+
val hi = if currentAddr == end then lo else readTpt()
1214+
val alias = if currentAddr == end then EmptyTree else readTpt()
1215+
TypeBoundsTree(lo, hi, alias)
12141216
case HOLE =>
12151217
readHole(end, isType = false)
12161218
case _ =>

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

+6-10
Original file line numberDiff line numberDiff line change
@@ -3344,20 +3344,16 @@ object Parsers {
33443344
rhs match {
33453345
case mtt: MatchTypeTree =>
33463346
bounds match {
3347-
case TypeBoundsTree(EmptyTree, upper) =>
3347+
case TypeBoundsTree(EmptyTree, upper, _) =>
33483348
rhs = MatchTypeTree(upper, mtt.selector, mtt.cases)
33493349
case _ =>
33503350
syntaxError(i"cannot combine lower bound and match type alias", eqOffset)
33513351
}
33523352
case _ =>
3353-
if (mods.is(Opaque)) {
3354-
val annotType = AppliedTypeTree(
3355-
TypeTree(defn.WithBoundsAnnot.typeRef),
3356-
bounds.lo.orElse(TypeTree(defn.NothingType)) ::
3357-
bounds.hi.orElse(TypeTree(defn.AnyType)) :: Nil)
3358-
rhs = Annotated(rhs, ensureApplied(wrapNew(annotType)))
3359-
}
3360-
else syntaxError(i"cannot combine bound and alias", eqOffset)
3353+
if mods.is(Opaque) then
3354+
rhs = TypeBoundsTree(bounds.lo, bounds.hi, rhs)
3355+
else
3356+
syntaxError(i"cannot combine bound and alias", eqOffset)
33613357
}
33623358
makeTypeDef(rhs)
33633359
}
@@ -3568,7 +3564,7 @@ object Parsers {
35683564
DefDef(name, tparams, vparamss, parents.head, subExpr())
35693565
else
35703566
parents match
3571-
case TypeBoundsTree(_, _) :: _ => syntaxError("`=` expected")
3567+
case (_: TypeBoundsTree) :: _ => syntaxError("`=` expected")
35723568
case _ =>
35733569
possibleTemplateStart()
35743570
val tparams1 = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal))

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
492492
}
493493
case ByNameTypeTree(tpt) =>
494494
"=> " ~ toTextLocal(tpt)
495-
case TypeBoundsTree(lo, hi) =>
496-
if (lo eq hi) optText(lo)(" = " ~ _)
497-
else optText(lo)(" >: " ~ _) ~ optText(hi)(" <: " ~ _)
495+
case TypeBoundsTree(lo, hi, alias) =>
496+
if (lo eq hi) && alias.isEmpty then optText(lo)(" = " ~ _)
497+
else optText(lo)(" >: " ~ _) ~ optText(hi)(" <: " ~ _) ~ optText(alias)(" = " ~ _)
498498
case Bind(name, body) =>
499499
keywordText("given ").provided(tree.symbol.isOneOf(GivenOrImplicit) && !homogenizedView) ~ // Used for scala.quoted.Type in quote patterns (not pickled)
500500
changePrec(InfixPrec) { toText(name) ~ " @ " ~ toText(body) }

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class ReifyQuotes extends MacroTransform {
136136
def mkTagSymbolAndAssignType(spliced: TermRef): TypeDef = {
137137
val splicedTree = tpd.ref(spliced).withSpan(expr.span)
138138
val rhs = transform(splicedTree.select(tpnme.splice))
139-
val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree(rhs, rhs), rhs, rhs)
139+
val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree(rhs, rhs), rhs, rhs, EmptyTree)
140140
val local = ctx.newSymbol(
141141
owner = ctx.owner,
142142
name = UniqueName.fresh((splicedTree.symbol.name.toString + "$_").toTermName).toTypeName,

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -997,12 +997,13 @@ class Namer { typer: Typer =>
997997
}
998998
sym.info = dummyInfo2
999999

1000-
val rhsBodyType: TypeBounds = typedAheadType(rhs).tpe.toBounds
1000+
val rhs1 = typedAheadType(rhs)
1001+
val rhsBodyType: TypeBounds = rhs1.tpe.toBounds
10011002
val unsafeInfo = if (isDerived) rhsBodyType else abstracted(rhsBodyType)
10021003
if (isDerived) sym.info = unsafeInfo
10031004
else {
10041005
sym.info = NoCompleter
1005-
sym.info = sym.opaqueToBounds(checkNonCyclic(sym, unsafeInfo, reportErrors = true))
1006+
sym.info = sym.opaqueToBounds(checkNonCyclic(sym, unsafeInfo, reportErrors = true), rhs1)
10061007
}
10071008
if sym.isOpaqueAlias then sym.typeRef.recomputeDenot() // make sure we see the new bounds from now on
10081009
sym.resetFlag(Provisional)

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -607,8 +607,11 @@ trait TypeAssigner {
607607
def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context): ByNameTypeTree =
608608
tree.withType(ExprType(result.tpe))
609609

610-
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
611-
tree.withType(if (lo eq hi) TypeAlias(lo.tpe) else TypeBounds(lo.tpe, hi.tpe))
610+
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree, alias: Tree)(implicit ctx: Context): TypeBoundsTree =
611+
tree.withType(
612+
if !alias.isEmpty then alias.tpe
613+
else if lo eq hi then TypeAlias(lo.tpe)
614+
else TypeBounds(lo.tpe, hi.tpe))
612615

613616
def assignType(tree: untpd.Bind, sym: Symbol)(implicit ctx: Context): Bind =
614617
tree.withType(NamedType(NoPrefix, sym))

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

+12-12
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ class Typer extends Namer
633633

634634
tpt1 match {
635635
case AppliedTypeTree(_, targs) =>
636-
for (targ @ TypeBoundsTree(_, _) <- targs)
636+
for case targ: TypeBoundsTree <- targs do
637637
ctx.error(WildcardOnTypeArgumentNotAllowedOnNew(), targ.sourcePos)
638638
case _ =>
639639
}
@@ -1445,7 +1445,7 @@ class Typer extends Namer
14451445
}
14461446
if (desugaredArg.isType)
14471447
arg match {
1448-
case TypeBoundsTree(EmptyTree, EmptyTree)
1448+
case TypeBoundsTree(EmptyTree, EmptyTree, _)
14491449
if tparam.paramInfo.isLambdaSub &&
14501450
tpt1.tpe.typeParamSymbols.nonEmpty &&
14511451
!ctx.mode.is(Mode.Pattern) =>
@@ -1464,7 +1464,7 @@ class Typer extends Namer
14641464
args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]]
14651465
}
14661466
val paramBounds = tparams.lazyZip(args).map {
1467-
case (tparam, TypeBoundsTree(EmptyTree, EmptyTree)) =>
1467+
case (tparam, TypeBoundsTree(EmptyTree, EmptyTree, _)) =>
14681468
// if type argument is a wildcard, suppress kind checking since
14691469
// there is no real argument.
14701470
NoType
@@ -1507,14 +1507,20 @@ class Typer extends Namer
15071507
}
15081508

15091509
def typedTypeBoundsTree(tree: untpd.TypeBoundsTree, pt: Type)(implicit ctx: Context): Tree = {
1510-
val TypeBoundsTree(lo, hi) = tree
1510+
val TypeBoundsTree(lo, hi, alias) = tree
15111511
val lo1 = typed(lo)
15121512
val hi1 = typed(hi)
1513+
val alias1 = typed(alias)
15131514

15141515
val lo2 = if (lo1.isEmpty) typed(untpd.TypeTree(defn.NothingType)) else lo1
15151516
val hi2 = if (hi1.isEmpty) typed(untpd.TypeTree(defn.AnyType)) else hi1
15161517

1517-
val tree1 = assignType(cpy.TypeBoundsTree(tree)(lo2, hi2), lo2, hi2)
1518+
if !alias1.isEmpty then
1519+
val bounds = TypeBounds(lo2.tpe, hi2.tpe)
1520+
if !bounds.contains(alias1.tpe) then
1521+
ctx.error(em"type ${alias1.tpe} outside bounds $bounds", tree.sourcePos)
1522+
1523+
val tree1 = assignType(cpy.TypeBoundsTree(tree)(lo2, hi2, alias1), lo2, hi2, alias1)
15181524
if (ctx.mode.is(Mode.Pattern))
15191525
// Associate a pattern-bound type symbol with the wildcard.
15201526
// The bounds of the type symbol can be constrained when comparing a pattern type
@@ -1951,13 +1957,7 @@ class Typer extends Namer
19511957
val arg1 = typed(tree.arg, pt)
19521958
if (ctx.mode is Mode.Type) {
19531959
if arg1.isType then
1954-
val result = assignType(cpy.Annotated(tree)(arg1, annot1), arg1, annot1)
1955-
result.tpe match {
1956-
case AnnotatedType(rhs, Annotation.WithBounds(bounds)) =>
1957-
if (!bounds.contains(rhs)) ctx.error(em"type $rhs outside bounds $bounds", tree.sourcePos)
1958-
case _ =>
1959-
}
1960-
result
1960+
assignType(cpy.Annotated(tree)(arg1, annot1), arg1, annot1)
19611961
else
19621962
assert(ctx.reporter.errorsReported)
19631963
TypeTree(UnspecifiedErrorType)

0 commit comments

Comments
 (0)