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) {
118
118
case tp =>
119
119
def isConcrete (tp : Type ): Boolean = tp.dealias match {
120
120
case tp : TypeRef => tp.symbol.isClass
121
+ case tp : TypeParamRef => false
121
122
case tp : TypeProxy => isConcrete(tp.underlying)
122
123
case tp : AndType => isConcrete(tp.tp1) && isConcrete(tp.tp2)
123
124
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 {
919
919
@ tu lazy val ParamMetaAnnot : ClassSymbol = requiredClass(" scala.annotation.meta.param" )
920
920
@ tu lazy val SetterMetaAnnot : ClassSymbol = requiredClass(" scala.annotation.meta.setter" )
921
921
@ tu lazy val ShowAsInfixAnnot : ClassSymbol = requiredClass(" scala.annotation.showAsInfix" )
922
+ @ tu lazy val StableAnnot : ClassSymbol = requiredClass(" scala.annotation.internal.Stable" )
922
923
@ tu lazy val FunctionalInterfaceAnnot : ClassSymbol = requiredClass(" java.lang.FunctionalInterface" )
923
924
@ tu lazy val TargetNameAnnot : ClassSymbol = requiredClass(" scala.annotation.targetName" )
924
925
@ 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 {
168
168
case _ : SingletonType | NoPrefix => true
169
169
case tp : RefinedOrRecType => tp.parent.isStable
170
170
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
172
172
case tp : AndType =>
173
173
// TODO: fix And type check when tp contains type parames for explicit-nulls flow-typing
174
174
// 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
3530
3530
typr.println(i " adapt to subtype ${tree.tpe} !<:< $pt" )
3531
3531
// typr.println(TypeComparer.explained(tree.tpe <:< pt))
3532
3532
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 } =>
3534
3536
// Insert an explicit cast, so that -Ycheck in later phases succeeds.
3535
3537
// I suspect, but am not 100% sure that this might affect inferred types,
3536
3538
// if the expected type is a supertype of the GADT bound. It would be good to come
3537
3539
// 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)
3539
3552
case _ =>
3540
3553
tree
3541
3554
}
Original file line number Diff line number Diff line change @@ -64,3 +64,7 @@ i8182.scala
64
64
65
65
# local lifted value in annotation argument has different position after pickling
66
66
i2797a
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