File tree Expand file tree Collapse file tree 8 files changed +61
-3
lines changed
library/src/scala/annotation/internal Expand file tree Collapse file tree 8 files changed +61
-3
lines changed Original file line number Diff line number Diff line change @@ -118,6 +118,7 @@ class CheckRealizable(using Context) {
118118 case tp =>
119119 def isConcrete (tp : Type ): Boolean = tp.dealias match {
120120 case tp : TypeRef => tp.symbol.isClass
121+ case tp : TypeParamRef => false
121122 case tp : TypeProxy => isConcrete(tp.underlying)
122123 case tp : AndType => isConcrete(tp.tp1) && isConcrete(tp.tp2)
123124 case tp : OrType => isConcrete(tp.tp1) && isConcrete(tp.tp2)
Original file line number Diff line number Diff line change @@ -919,6 +919,7 @@ class Definitions {
919919 @ tu lazy val ParamMetaAnnot : ClassSymbol = requiredClass(" scala.annotation.meta.param" )
920920 @ tu lazy val SetterMetaAnnot : ClassSymbol = requiredClass(" scala.annotation.meta.setter" )
921921 @ tu lazy val ShowAsInfixAnnot : ClassSymbol = requiredClass(" scala.annotation.showAsInfix" )
922+ @ tu lazy val StableAnnot : ClassSymbol = requiredClass(" scala.annotation.internal.Stable" )
922923 @ tu lazy val FunctionalInterfaceAnnot : ClassSymbol = requiredClass(" java.lang.FunctionalInterface" )
923924 @ tu lazy val TargetNameAnnot : ClassSymbol = requiredClass(" scala.annotation.targetName" )
924925 @ tu lazy val VarargsAnnot : ClassSymbol = requiredClass(" scala.annotation.varargs" )
Original file line number Diff line number Diff line change @@ -168,7 +168,7 @@ object Types {
168168 case _ : SingletonType | NoPrefix => true
169169 case tp : RefinedOrRecType => tp.parent.isStable
170170 case tp : ExprType => tp.resultType.isStable
171- case tp : AnnotatedType => tp.parent.isStable
171+ case tp : AnnotatedType => tp.annot.symbol == defn. StableAnnot || tp. parent.isStable
172172 case tp : AndType =>
173173 // TODO: fix And type check when tp contains type parames for explicit-nulls flow-typing
174174 // see: tests/explicit-nulls/pos/flow-stable.scala.disabled
Original file line number Diff line number Diff line change @@ -3530,12 +3530,25 @@ class Typer extends Namer
35303530 typr.println(i " adapt to subtype ${tree.tpe} !<:< $pt" )
35313531 // typr.println(TypeComparer.explained(tree.tpe <:< pt))
35323532 adaptToSubType(wtp)
3533- case CompareResult .OKwithGADTUsed if pt.isValueType =>
3533+ case CompareResult .OKwithGADTUsed
3534+ if pt.isValueType
3535+ && ! inContext(ctx.fresh.setGadt(EmptyGadtConstraint )) { tree.tpe.widenExpr frozen_<:< pt } =>
35343536 // Insert an explicit cast, so that -Ycheck in later phases succeeds.
35353537 // I suspect, but am not 100% sure that this might affect inferred types,
35363538 // if the expected type is a supertype of the GADT bound. It would be good to come
35373539 // up with a test case for this.
3538- tree.cast(pt)
3540+ val target =
3541+ if tree.tpe.isSingleton then
3542+ val conj = AndType (tree.tpe, pt)
3543+ if tree.tpe.isStable && ! conj.isStable then
3544+ // this is needed for -Ycheck. Without the annotation Ycheck will
3545+ // skolemize the result type which will lead to different types before
3546+ // and after checking. See i11955.scala.
3547+ AnnotatedType (conj, Annotation (defn.StableAnnot ))
3548+ else conj
3549+ else pt
3550+ gadts.println(i " insert GADT cast from $tree to $target" )
3551+ tree.cast(target)
35393552 case _ =>
35403553 tree
35413554 }
Original file line number Diff line number Diff line change @@ -64,3 +64,7 @@ i8182.scala
6464
6565# local lifted value in annotation argument has different position after pickling
6666i2797a
67+
68+ # GADT cast applied to singleton type difference
69+ i4176-gadt.scala
70+
Original file line number Diff line number Diff line change 1+ package scala .annotation .internal
2+
3+ import scala .annotation .Annotation
4+
5+ /** An annotation asserting that the annotated type is stable */
6+ final class Stable () extends Annotation
Original file line number Diff line number Diff line change 1+ import scala .annotation .tailrec
2+ class Context {
3+ type Tree
4+ }
5+
6+ final def loop3 [C <: Context ](): Unit =
7+ @ tailrec
8+ def loop4 [A <: C ](c : A ): c.Tree = loop4(c)
Original file line number Diff line number Diff line change 1+ object Hello {
2+
3+ sealed abstract class X [+ A ] {
4+ type This [+ A ] <: X [A ]
5+ def asThis : This [A ]
6+ }
7+
8+ class Y [+ A ] extends X [A ] {
9+ override type This [+ AA ] = Y [AA ]
10+ override def asThis : This [A ] = this
11+ }
12+
13+ def hackBackToSelf [F [+ u] <: X [u], A ](f : F [Any ])(f2 : f.This [A ]): F [A ] =
14+ f2.asInstanceOf [F [A ]]
15+
16+ case class G [F [+ u] <: X [u], A ](wrapped : F [A ]) {
17+
18+ def mapF [F2 [+ u] <: X [u]](f : F [A ] => F2 [A ]): G [F2 , A ] =
19+ G [F2 , A ](f(wrapped))
20+
21+ def test_ko_1 : G [F , A ] = mapF(ct => hackBackToSelf(ct)(ct.asThis)) // error
22+ def test_ko_2 : G [F , A ] = mapF[F ](ct => hackBackToSelf(ct)(ct.asThis)) // error
23+ def test_ok : G [F , A ] = mapF(ct => hackBackToSelf[F , A ](ct)(ct.asThis)) // ok
24+ }
25+ }
You can’t perform that action at this time.
0 commit comments