13
13
package scala
14
14
package tools .nsc .transform .patmat
15
15
16
- import scala .collection .mutable
17
16
import scala .collection .immutable .ArraySeq
18
- import scala .collection .IterableOps
17
+ import scala .collection .{ IterableOps , mutable }
19
18
import scala .reflect .internal .util .Collections ._
20
19
import scala .reflect .internal .util .HashSet
20
+ import scala .tools .nsc .transform .patmat .Logic .LogicLinkedHashSet
21
21
22
22
trait Logic extends Debugging {
23
23
import global ._
@@ -114,22 +114,21 @@ trait Logic extends Debugging {
114
114
def implications : List [(Sym , List [Sym ], List [Sym ])]
115
115
}
116
116
117
- // The error message of t7020 assumes the ops are ordered implicitly
118
- // However, ListSet is slow (concatenate cost?), so use
119
- // scala.collection.mutable.LinkedHashSet (which grantees "the order in which elements were inserted into the set")
117
+ // Using LogicLinkedHashSet (a custom mutable.LinkedHashSet subclass) to ensure deterministic exhaustivity
118
+ // messages. immutable.ListSet was too slow (concatenate cost? scala/bug#12499).
120
119
121
120
// would be nice to statically check whether a prop is equational or pure,
122
121
// but that requires typing relations like And(x: Tx, y: Ty) : (if(Tx == PureProp && Ty == PureProp) PureProp else Prop)
123
- final case class And (ops : mutable. LinkedHashSet [Prop ]) extends Prop
122
+ final case class And (ops : LogicLinkedHashSet [Prop ]) extends Prop
124
123
object And {
125
124
def apply (ps : Prop * ) = create(ps)
126
- def create (ps : Iterable [Prop ]) = new And (ps.to(mutable. LinkedHashSet ))
125
+ def create (ps : Iterable [Prop ]) = new And (ps.to(LogicLinkedHashSet ))
127
126
}
128
127
129
- final case class Or (ops : mutable. LinkedHashSet [Prop ]) extends Prop
128
+ final case class Or (ops : LogicLinkedHashSet [Prop ]) extends Prop
130
129
object Or {
131
130
def apply (ps : Prop * ) = create(ps)
132
- def create (ps : Iterable [Prop ]) = new Or (ps.to(mutable. LinkedHashSet ))
131
+ def create (ps : Iterable [Prop ]) = new Or (ps.to(LogicLinkedHashSet ))
133
132
}
134
133
135
134
final case class Not (a : Prop ) extends Prop
@@ -286,7 +285,7 @@ trait Logic extends Debugging {
286
285
def simplifyAnd (ps : Iterable [Prop ]): Prop = {
287
286
// recurse for nested And (pulls all Ands up)
288
287
// build up Set in order to remove duplicates
289
- val props = mutable. LinkedHashSet .empty[Prop ]
288
+ val props = LogicLinkedHashSet .empty[Prop ]
290
289
for (prop <- ps) {
291
290
simplifyProp(prop) match {
292
291
case True => // ignore `True`
@@ -302,7 +301,7 @@ trait Logic extends Debugging {
302
301
def simplifyOr (ps : Iterable [Prop ]): Prop = {
303
302
// recurse for nested Or (pulls all Ors up)
304
303
// build up Set in order to remove duplicates
305
- val props = mutable. LinkedHashSet .empty[Prop ]
304
+ val props = LogicLinkedHashSet .empty[Prop ]
306
305
for (prop <- ps) {
307
306
simplifyProp(prop) match {
308
307
case False => // ignore `False`
@@ -343,15 +342,15 @@ trait Logic extends Debugging {
343
342
}
344
343
345
344
def gatherVariables (p : Prop ): collection.Set [Var ] = {
346
- val vars = new mutable. LinkedHashSet [Var ]()
345
+ val vars = new LogicLinkedHashSet [Var ]()
347
346
(new PropTraverser {
348
347
override def applyVar (v : Var ) = vars += v
349
348
})(p)
350
349
vars
351
350
}
352
351
353
352
def gatherSymbols (p : Prop ): collection.Set [Sym ] = {
354
- val syms = new mutable. LinkedHashSet [Sym ]()
353
+ val syms = new LogicLinkedHashSet [Sym ]()
355
354
(new PropTraverser {
356
355
override def applySymbol (s : Sym ) = syms += s
357
356
})(p)
@@ -409,7 +408,7 @@ trait Logic extends Debugging {
409
408
def removeVarEq (props : List [Prop ], modelNull : Boolean = false ): (Prop , List [Prop ]) = {
410
409
val start = if (settings.areStatisticsEnabled) statistics.startTimer(statistics.patmatAnaVarEq) else null
411
410
412
- val vars = new mutable. LinkedHashSet [Var ]
411
+ val vars = new LogicLinkedHashSet [Var ]
413
412
414
413
object gatherEqualities extends PropTraverser {
415
414
override def apply (p : Prop ) = p match {
@@ -516,6 +515,31 @@ trait Logic extends Debugging {
516
515
}
517
516
}
518
517
518
+ object Logic {
519
+ import scala .annotation .nowarn
520
+ import scala .collection .mutable .{Growable , GrowableBuilder , SetOps }
521
+ import scala .collection .{IterableFactory , IterableFactoryDefaults , StrictOptimizedIterableOps }
522
+
523
+ // Local subclass because we can't override `addAll` in the collections (bin compat), see PR scala/scala#10361
524
+ @ nowarn(" msg=inheritance from class LinkedHashSet" )
525
+ class LogicLinkedHashSet [A ] extends mutable.LinkedHashSet [A ]
526
+ with SetOps [A , LogicLinkedHashSet , LogicLinkedHashSet [A ]]
527
+ with StrictOptimizedIterableOps [A , LogicLinkedHashSet , LogicLinkedHashSet [A ]]
528
+ with IterableFactoryDefaults [A , LogicLinkedHashSet ] {
529
+ override def iterableFactory : IterableFactory [LogicLinkedHashSet ] = LogicLinkedHashSet
530
+ override def addAll (xs : IterableOnce [A ]): this .type = {
531
+ sizeHint(xs.knownSize)
532
+ super .addAll(xs)
533
+ }
534
+ }
535
+
536
+ object LogicLinkedHashSet extends IterableFactory [LogicLinkedHashSet ] {
537
+ override def from [A ](source : IterableOnce [A ]): LogicLinkedHashSet [A ] = Growable .from(empty[A ], source)
538
+ override def empty [A ]: LogicLinkedHashSet [A ] = new LogicLinkedHashSet [A ]
539
+ override def newBuilder [A ]: mutable.Builder [A , LogicLinkedHashSet [A ]] = new GrowableBuilder (empty[A ])
540
+ }
541
+ }
542
+
519
543
trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
520
544
trait TreesAndTypesDomain extends PropositionalLogic with CheckableTreeAndTypeAnalysis {
521
545
type Type = global.Type
@@ -733,8 +757,8 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
733
757
}
734
758
735
759
736
- import global .{ConstantType , SingletonType , Literal , Ident , singleType , TypeBounds , NoSymbol }
737
760
import global .definitions ._
761
+ import global .{ConstantType , Ident , Literal , NoSymbol , SingletonType , TypeBounds , singleType }
738
762
739
763
740
764
// all our variables range over types
0 commit comments