Skip to content

Commit 41791f7

Browse files
committed
Add missing cache invalidations for opaque types
Two problems: - Base types for applied opaque types were cached - Denotations for opaque types were cached This allowed knowledge about opaque aliases to leak from companion objects to the outside world.
1 parent 18dfe3a commit 41791f7

File tree

4 files changed

+69
-4
lines changed

4 files changed

+69
-4
lines changed

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ object SymDenotations {
382382
else alias
383383
addAnnotation(Annotation(tpd.TypeTree(defn.OpaqueAliasAnnot.typeRef.appliedTo(arg)).withPos(symbol.pos)))
384384
info = TypeBounds(defn.NothingType, abstractRHS(alias))
385-
setFlag(Deferred)
385+
setFlag(Deferred | Provisional)
386386
case _ =>
387387
}
388388
}
@@ -1743,15 +1743,17 @@ object SymDenotations {
17431743

17441744
def computeApplied = {
17451745
btrCache.put(tp, NoPrefix)
1746+
val tyconSym = tycon.typeSymbol
17461747
val baseTp =
1747-
if (tycon.typeSymbol eq symbol) tp
1748+
if (tyconSym `eq` symbol) tp
17481749
else (tycon.typeParams: @unchecked) match {
17491750
case LambdaParam(_, _) :: _ =>
17501751
recur(tp.superType)
17511752
case tparams: List[Symbol @unchecked] =>
17521753
recur(tycon).subst(tparams, args)
17531754
}
1754-
record(tp, baseTp)
1755+
if (!tyconSym.is(Opaque)) record(tp, baseTp)
1756+
else btrCache.remove(tp)
17551757
baseTp
17561758
}
17571759
computeApplied

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class FirstTransform extends MiniPhase with SymTransformer { thisPhase =>
5555
if (sym.is(Opaque)) {
5656
val result = sym.copySymDenotation(info = TypeAlias(sym.opaqueAlias))
5757
result.removeAnnotation(defn.OpaqueAliasAnnot)
58-
result.resetFlag(Opaque | Deferred)
58+
result.resetFlag(Opaque | Deferred | Provisional)
5959
result
6060
}
6161
else sym

tests/neg/OpaqueEscape.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object OpaqueEscape{
2+
opaque type Wrapped = Int
3+
abstract class EscaperBase {
4+
def unwrap(i:Wrapped):Int
5+
def wrap(i:Int):Wrapped
6+
}
7+
class Escaper extends EscaperBase{
8+
override def unwrap(i:Int):Int = i // error overriding method unwrap
9+
override def wrap(i:Int):Int = i // error overriding method wrap
10+
}
11+
12+
val e = new Escaper:EscaperBase
13+
val w:Wrapped = e.wrap(1)
14+
val u:Int = e.unwrap(w)
15+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
object ia {
2+
3+
import java.util.Arrays
4+
5+
opaque type IArray[A1] = Array[A1]
6+
7+
object IArray {
8+
def initialize[A](body: => Array[A]): IArray[A] = body
9+
def size[A](ia: IArray[A]): Int = ia.length
10+
def get[A](ia: IArray[A], i: Int): A = ia(i)
11+
12+
// return a sorted copy of the array
13+
def sorted[A <: AnyRef : math.Ordering](ia: IArray[A]): IArray[A] = {
14+
val arr = Arrays.copyOf(ia, ia.length)
15+
scala.util.Sorting.quickSort(arr)
16+
arr
17+
}
18+
19+
// use a standard java method to search a sorted IArray.
20+
// (note that this doesn't mutate the array).
21+
def binarySearch(ia: IArray[Long], elem: Long): Int =
22+
Arrays.binarySearch(ia, elem)
23+
}
24+
25+
// same as IArray.binarySearch but implemented by-hand.
26+
//
27+
// given a sorted IArray, returns index of `elem`,
28+
// or a negative value if not found.
29+
def binaryIndexOf(ia: IArray[Long], elem: Long): Int = {
30+
var lower: Int = 0
31+
var upper: Int = IArray.size(ia)
32+
while (lower <= upper) {
33+
val middle = (lower + upper) >>> 1
34+
val n = IArray.get(ia, middle)
35+
36+
if (n == elem) return middle
37+
else if (n < elem) lower = middle + 1
38+
else upper = middle - 1
39+
}
40+
-lower - 1
41+
}
42+
43+
def xs: IArray[Long] = ???
44+
45+
xs.length // error: not a member
46+
xs.apply(2) // error: not a member
47+
xs(1) = 0 // error: not a member
48+
}

0 commit comments

Comments
 (0)