Skip to content

Commit 80a1e95

Browse files
authored
Merge pull request #15268 from dotty-staging/mb/revert-compiletime-ops-covariance
Revert #14452 and make compile-time operations on stable arguments stable
2 parents 741587d + 9205cc6 commit 80a1e95

File tree

15 files changed

+220
-102
lines changed

15 files changed

+220
-102
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package dotty.tools.benchmarks
2+
3+
import org.openjdk.jmh.annotations.*
4+
import java.util.concurrent.TimeUnit.SECONDS
5+
import dotty.tools.dotc.{Driver, Run, Compiler}
6+
import dotty.tools.dotc.core.Mode
7+
import dotty.tools.dotc.core.Types.{TermRef, Type}
8+
import dotty.tools.dotc.core.Contexts.{ContextBase, Context, ctx, withMode}
9+
10+
@Fork(value = 5)
11+
@Warmup(iterations = 5, time = 1, timeUnit = SECONDS)
12+
@Measurement(iterations = 5, time = 1, timeUnit = SECONDS)
13+
@State(Scope.Thread)
14+
class TypeOpsBenchmark:
15+
var tp: Type = null
16+
var context: Context = null
17+
18+
@Param(Array("int", "singletonsSum", "intsSum", "deepSingletonsSum", "deepIntsSum", "singletonsIntersection", "singletonsUnion"))
19+
var valName: String = "int"
20+
21+
@Setup(Level.Iteration)
22+
def setup(): Unit =
23+
val driver = new Driver:
24+
override def finish(compiler: Compiler, run: Run)(using Context): Unit =
25+
withMode(Mode.Printing) {
26+
val pkg = run.units(0).tpdTree.symbol
27+
tp = pkg.requiredClass("Test").requiredValueRef(valName).underlying
28+
context = ctx
29+
}
30+
super.finish(compiler, run)
31+
driver.process(Array(
32+
"-classpath", System.getProperty("BENCH_CLASS_PATH"),
33+
"-Ystop-after:typer",
34+
"tests/someTypes.scala"
35+
))
36+
37+
@Benchmark
38+
def isStable(): Unit = tp.isStable(using context)
39+
40+
@Benchmark
41+
def normalized(): Unit = tp.normalized(using context)
42+
43+
@Benchmark
44+
def simplified(): Unit = tp.simplified(using context)
45+
46+
@Benchmark
47+
def dealias(): Unit = tp.dealias(using context)
48+
49+
@Benchmark
50+
def widen(): Unit = tp.widen(using context)
51+
52+
@Benchmark
53+
def atoms(): Unit = tp.atoms(using context)
54+
55+
@Benchmark
56+
def isProvisional(): Unit = tp.isProvisional(using context)

bench-micro/tests/someTypes.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import compiletime.ops.int.+
2+
3+
class Test:
4+
val int: Int = 5
5+
6+
val int2: Int = 6
7+
8+
val singletonsSum: int.type + int2.type = ???
9+
10+
val intsSum: Int + Int = ???
11+
12+
val deepSingletonsSum:
13+
((int.type + int2.type) + (int.type + int2.type)) + ((int.type + int2.type) + (int.type + int2.type)) +
14+
((int.type + int2.type) + (int.type + int2.type)) + ((int.type + int2.type) + (int.type + int2.type)) = ???
15+
16+
val deepIntsSum:
17+
((Int + Int) + (Int + Int)) + ((Int + Int) + (Int + Int)) +
18+
((Int + Int) + (Int + Int)) + ((Int + Int) + (Int + Int)) = ???
19+
20+
val singletonsIntersection: int.type & int2.type = ???
21+
22+
val singletonsUnion: int.type | int2.type = ???

build.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ val `scala3-tasty-inspector` = Build.`scala3-tasty-inspector`
1313
val `scala3-language-server` = Build.`scala3-language-server`
1414
val `scala3-bench` = Build.`scala3-bench`
1515
val `scala3-bench-bootstrapped` = Build.`scala3-bench-bootstrapped`
16+
val `scala3-bench-micro` = Build.`scala3-bench-micro`
1617
val `stdlib-bootstrapped` = Build.`stdlib-bootstrapped`
1718
val `stdlib-bootstrapped-tasty-tests` = Build.`stdlib-bootstrapped-tasty-tests`
1819
val `tasty-core` = Build.`tasty-core`

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ object Types {
175175
// see: tests/explicit-nulls/pos/flow-stable.scala.disabled
176176
tp.tp1.isStable && (realizability(tp.tp2) eq Realizable) ||
177177
tp.tp2.isStable && (realizability(tp.tp1) eq Realizable)
178+
case tp: AppliedType => tp.cachedIsStable
178179
case _ => false
179180
}
180181

@@ -4162,10 +4163,32 @@ object Types {
41624163
private var myStableHash: Byte = 0
41634164
private var myGround: Byte = 0
41644165

4166+
private var myIsStablePeriod: Period = Nowhere
4167+
private var myIsStable: Boolean = false
4168+
41654169
def isGround(acc: TypeAccumulator[Boolean])(using Context): Boolean =
41664170
if myGround == 0 then myGround = if acc.foldOver(true, this) then 1 else -1
41674171
myGround > 0
41684172

4173+
private[Types] def cachedIsStable(using Context): Boolean =
4174+
// We need to invalidate the cache when the period changes because the
4175+
// case `TermRef` of `Type#isStable` reads denotations, which depend on
4176+
// the period. See docs/_docs/internals/periods.md for more information.
4177+
if myIsStablePeriod != ctx.period then
4178+
val res: Boolean = computeIsStable
4179+
// We don't cache if the type is provisional because `Type#isStable`
4180+
// calls `Type#stripTypeVar` which might return different results later.
4181+
if !isProvisional then
4182+
myIsStablePeriod = ctx.period
4183+
myIsStable = res
4184+
res
4185+
else
4186+
myIsStable
4187+
4188+
private def computeIsStable(using Context): Boolean = tycon match
4189+
case tycon: TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) && args.forall(_.isStable) => true
4190+
case _ => false
4191+
41694192
override def underlying(using Context): Type = tycon
41704193

41714194
override def superType(using Context): Type =
@@ -4243,7 +4266,7 @@ object Types {
42434266
// final val one = 1
42444267
// type Two = one.type + one.type
42454268
// ```
4246-
case tp: TermRef => tp.underlying
4269+
case tp: TypeProxy if tp.underlying.isStable => tp.underlying.fixForEvaluation
42474270
case tp => tp
42484271
}
42494272

compiler/src/dotty/tools/dotc/plugins/Plugins.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ trait Plugins {
5151
}
5252
else _roughPluginsList
5353

54-
/** Load all available plugins. Skips plugins that
54+
/** Load all available plugins. Skips plugins that
5555
* either have the same name as another one, or which
5656
* define a phase name that another one does.
5757
*/

library/src/scala/compiletime/ops/any.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ object any:
1313
* ```
1414
* @syntax markdown
1515
*/
16-
type ==[+X, +Y] <: Boolean
16+
type ==[X, Y] <: Boolean
1717

1818
/** Inequality comparison of two singleton types.
1919
* ```scala
@@ -26,7 +26,7 @@ object any:
2626
* ```
2727
* @syntax markdown
2828
*/
29-
type !=[+X, +Y] <: Boolean
29+
type !=[X, Y] <: Boolean
3030

3131
/** Tests if a type is a constant.
3232
* ```scala
@@ -63,4 +63,4 @@ object any:
6363
* ```
6464
* @syntax markdown
6565
*/
66-
type ToString[+X] <: String
66+
type ToString[X] <: String

library/src/scala/compiletime/ops/boolean.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ object boolean:
1313
* ```
1414
* @syntax markdown
1515
*/
16-
type ![+X <: Boolean] <: Boolean
16+
type ![X <: Boolean] <: Boolean
1717

1818
/** Exclusive disjunction of two `Boolean` singleton types.
1919
* ```scala
@@ -25,7 +25,7 @@ object boolean:
2525
* ```
2626
* @syntax markdown
2727
*/
28-
type ^[+X <: Boolean, +Y <: Boolean] <: Boolean
28+
type ^[X <: Boolean, Y <: Boolean] <: Boolean
2929

3030
/** Conjunction of two `Boolean` singleton types.
3131
* ```scala
@@ -37,7 +37,7 @@ object boolean:
3737
* ```
3838
* @syntax markdown
3939
*/
40-
type &&[+X <: Boolean, +Y <: Boolean] <: Boolean
40+
type &&[X <: Boolean, Y <: Boolean] <: Boolean
4141

4242
/** Disjunction of two `Boolean` singleton types.
4343
* ```scala
@@ -49,4 +49,4 @@ object boolean:
4949
* ```
5050
* @syntax markdown
5151
*/
52-
type ||[+X <: Boolean, +Y <: Boolean] <: Boolean
52+
type ||[X <: Boolean, Y <: Boolean] <: Boolean

library/src/scala/compiletime/ops/double.scala

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ object double:
1111
* ```
1212
* @syntax markdown
1313
*/
14-
type +[+X <: Double, +Y <: Double] <: Double
14+
type +[X <: Double, Y <: Double] <: Double
1515

1616
/** Subtraction of two `Double` singleton types.
1717
* ```scala
@@ -22,7 +22,7 @@ object double:
2222
* ```
2323
* @syntax markdown
2424
*/
25-
type -[+X <: Double, +Y <: Double] <: Double
25+
type -[X <: Double, Y <: Double] <: Double
2626

2727
/** Multiplication of two `Double` singleton types.
2828
* ```scala
@@ -33,7 +33,7 @@ object double:
3333
* ```
3434
* @syntax markdown
3535
*/
36-
type *[+X <: Double, +Y <: Double] <: Double
36+
type *[X <: Double, Y <: Double] <: Double
3737

3838
/** Integer division of two `Double` singleton types.
3939
* ```scala
@@ -44,7 +44,7 @@ object double:
4444
* ```
4545
* @syntax markdown
4646
*/
47-
type /[+X <: Double, +Y <: Double] <: Double
47+
type /[X <: Double, Y <: Double] <: Double
4848

4949
/** Remainder of the division of `X` by `Y`.
5050
* ```scala
@@ -55,7 +55,7 @@ object double:
5555
* ```
5656
* @syntax markdown
5757
*/
58-
type %[+X <: Double, +Y <: Double] <: Double
58+
type %[X <: Double, Y <: Double] <: Double
5959

6060
/** Less-than comparison of two `Double` singleton types.
6161
* ```scala
@@ -67,7 +67,7 @@ object double:
6767
* ```
6868
* @syntax markdown
6969
*/
70-
type <[+X <: Double, +Y <: Double] <: Boolean
70+
type <[X <: Double, Y <: Double] <: Boolean
7171

7272
/** Greater-than comparison of two `Double` singleton types.
7373
* ```scala
@@ -79,7 +79,7 @@ object double:
7979
* ```
8080
* @syntax markdown
8181
*/
82-
type >[+X <: Double, +Y <: Double] <: Boolean
82+
type >[X <: Double, Y <: Double] <: Boolean
8383

8484
/** Greater-or-equal comparison of two `Double` singleton types.
8585
* ```scala
@@ -91,7 +91,7 @@ object double:
9191
* ```
9292
* @syntax markdown
9393
*/
94-
type >=[+X <: Double, +Y <: Double] <: Boolean
94+
type >=[X <: Double, Y <: Double] <: Boolean
9595

9696
/** Less-or-equal comparison of two `Double` singleton types.
9797
* ```scala
@@ -103,7 +103,7 @@ object double:
103103
* ```
104104
* @syntax markdown
105105
*/
106-
type <=[+X <: Double, +Y <: Double] <: Boolean
106+
type <=[X <: Double, Y <: Double] <: Boolean
107107

108108
/** Absolute value of an `Double` singleton type.
109109
* ```scala
@@ -114,7 +114,7 @@ object double:
114114
* ```
115115
* @syntax markdown
116116
*/
117-
type Abs[+X <: Double] <: Double
117+
type Abs[X <: Double] <: Double
118118

119119
/** Negation of an `Double` singleton type.
120120
* ```scala
@@ -126,7 +126,7 @@ object double:
126126
* ```
127127
* @syntax markdown
128128
*/
129-
type Negate[+X <: Double] <: Double
129+
type Negate[X <: Double] <: Double
130130

131131
/** Minimum of two `Double` singleton types.
132132
* ```scala
@@ -137,7 +137,7 @@ object double:
137137
* ```
138138
* @syntax markdown
139139
*/
140-
type Min[+X <: Double, +Y <: Double] <: Double
140+
type Min[X <: Double, Y <: Double] <: Double
141141

142142
/** Maximum of two `Double` singleton types.
143143
* ```scala
@@ -148,7 +148,7 @@ object double:
148148
* ```
149149
* @syntax markdown
150150
*/
151-
type Max[+X <: Double, +Y <: Double] <: Double
151+
type Max[X <: Double, Y <: Double] <: Double
152152

153153
/** Int conversion of a `Double` singleton type.
154154
* ```scala
@@ -159,7 +159,7 @@ object double:
159159
* ```
160160
* @syntax markdown
161161
*/
162-
type ToInt[+X <: Double] <: Int
162+
type ToInt[X <: Double] <: Int
163163

164164
/** Long conversion of a `Double` singleton type.
165165
* ```scala
@@ -170,7 +170,7 @@ object double:
170170
* ```
171171
* @syntax markdown
172172
*/
173-
type ToLong[+X <: Double] <: Long
173+
type ToLong[X <: Double] <: Long
174174

175175
/** Float conversion of a `Double` singleton type.
176176
* ```scala
@@ -181,4 +181,4 @@ object double:
181181
* ```
182182
* @syntax markdown
183183
*/
184-
type ToFloat[+X <: Double] <: Float
184+
type ToFloat[X <: Double] <: Float

0 commit comments

Comments
 (0)