diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 0607b3729654..f85075cd2de8 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1858,6 +1858,8 @@ object desugar { Annotated( AppliedTypeTree(ref(defn.SeqType), t), New(ref(defn.RepeatedAnnot.typeRef), Nil :: Nil)) + else if op.name == nme.CC_REACH then + Apply(ref(defn.Caps_reachCapability), t :: Nil) else assert(ctx.mode.isExpr || ctx.reporter.errorsReported || ctx.mode.is(Mode.Interactive), ctx.mode) Select(t, op.name) diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index ea8dd028dc01..eae62dde41e6 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -376,17 +376,6 @@ trait TreeInfo[T <: Untyped] { self: Trees.Instance[T] => case _ => tree.tpe.isInstanceOf[ThisType] } - - /** Under capture checking, an extractor for qualified roots `cap[Q]`. - */ - object QualifiedRoot: - - def unapply(tree: Apply)(using Context): Option[String] = tree match - case Apply(fn, Literal(lit) :: Nil) if fn.symbol == defn.Caps_capIn => - Some(lit.value.asInstanceOf[String]) - case _ => - None - end QualifiedRoot } trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] => diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureAnnotation.scala b/compiler/src/dotty/tools/dotc/cc/CaptureAnnotation.scala index 206734bccc18..e437a8ad5d5f 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureAnnotation.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureAnnotation.scala @@ -63,7 +63,7 @@ case class CaptureAnnotation(refs: CaptureSet, boxed: Boolean)(cls: Symbol) exte val elems = refs.elems.toList val elems1 = elems.mapConserve(tm) if elems1 eq elems then this - else if elems1.forall(_.isInstanceOf[CaptureRef]) + else if elems1.forall(_.isTrackableRef) then derivedAnnotation(CaptureSet(elems1.asInstanceOf[List[CaptureRef]]*), boxed) else EmptyAnnotation diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala index 40e94ebde5dd..a9e4ce42087d 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala @@ -59,9 +59,6 @@ class IllegalCaptureRef(tpe: Type) extends Exception(tpe.toString) /** Capture checking state, which is known to other capture checking components */ class CCState: - /** Associates nesting level owners with the local roots valid in their scopes. */ - val localRoots: mutable.HashMap[Symbol, Symbol] = new mutable.HashMap - /** The last pair of capture reference and capture set where * the reference could not be added to the set due to a level conflict. */ @@ -81,13 +78,13 @@ extension (tree: Tree) /** Map tree with CaptureRef type to its type, throw IllegalCaptureRef otherwise */ def toCaptureRef(using Context): CaptureRef = tree match - case QualifiedRoot(outer) => - ctx.owner.levelOwnerNamed(outer) - .orElse(defn.RootClass) // non-existing outer roots are reported in Setup's checkQualifiedRoots - .localRoot.termRef + case ReachCapabilityApply(arg) => + arg.toCaptureRef.reach case _ => tree.tpe match - case ref: CaptureRef => ref - case tpe => throw IllegalCaptureRef(tpe) // if this was compiled from cc syntax, problem should have been reported at Typer + case ref: CaptureRef if ref.isTrackableRef => + ref + case tpe => + throw IllegalCaptureRef(tpe) // if this was compiled from cc syntax, problem should have been reported at Typer /** Convert a @retains or @retainsByName annotation tree to the capture set it represents. * For efficience, the result is cached as an Attachment on the tree. @@ -166,7 +163,7 @@ extension (tp: Type) def forceBoxStatus(boxed: Boolean)(using Context): Type = tp.widenDealias match case tp @ CapturingType(parent, refs) if tp.isBoxed != boxed => val refs1 = tp match - case ref: CaptureRef if ref.isTracked => ref.singletonCaptureSet + case ref: CaptureRef if ref.isTracked || ref.isReach => ref.singletonCaptureSet case _ => refs CapturingType(parent, refs1, boxed) case _ => @@ -206,12 +203,6 @@ extension (tp: Type) case _: TypeRef | _: AppliedType => tp.typeSymbol.hasAnnotation(defn.CapabilityAnnot) case _ => false - def isSealed(using Context): Boolean = tp match - case tp: TypeParamRef => tp.underlying.isSealed - case tp: TypeBounds => tp.hi.hasAnnotation(defn.Caps_SealedAnnot) - case tp: TypeRef => tp.symbol.is(Sealed) || tp.info.isSealed // TODO: drop symbol flag? - case _ => false - /** Drop @retains annotations everywhere */ def dropAllRetains(using Context): Type = // TODO we should drop retains from inferred types before unpickling val tm = new TypeMap: @@ -222,6 +213,62 @@ extension (tp: Type) mapOver(t) tm(tp) + /** If `x` is a capture ref, its reach capability `x*`, represented internally + * as `x @reachCapability`. `x*` stands for all capabilities reachable through `x`". + * We have `{x} <: {x*} <: dcs(x)}` where the deep capture set `dcs(x)` of `x` + * is the union of all capture sets that appear in covariant position in the + * type of `x`. If `x` and `y` are different variables then `{x*}` and `{y*}` + * are unrelated. + */ + def reach(using Context): CaptureRef = + assert(tp.isTrackableRef) + AnnotatedType(tp, Annotation(defn.ReachCapabilityAnnot, util.Spans.NoSpan)) + + /** If `ref` is a trackable capture ref, and `tp` has only covariant occurrences of a + * universal capture set, replace all these occurrences by `{ref*}`. This implements + * the new aspect of the (Var) rule, which can now be stated as follows: + * + * x: T in E + * ----------- + * E |- x: T' + * + * where T' is T with (1) the toplevel capture set replaced by `{x}` and + * (2) all covariant occurrences of cap replaced by `x*`, provided there + * are no occurrences in `T` at other variances. (1) is standard, whereas + * (2) is new. + * + * Why is this sound? Covariant occurrences of cap must represent capabilities + * that are reachable from `x`, so they are included in the meaning of `{x*}`. + * At the same time, encapsulation is still maintained since no covariant + * occurrences of cap are allowed in instance types of type variables. + */ + def withReachCaptures(ref: Type)(using Context): Type = + object narrowCaps extends TypeMap: + var ok = true + def apply(t: Type) = t.dealias match + case t1 @ CapturingType(p, cs) if cs.isUniversal => + if variance > 0 then + t1.derivedCapturingType(apply(p), ref.reach.singletonCaptureSet) + else + ok = false + t + case _ => t match + case t @ CapturingType(p, cs) => + t.derivedCapturingType(apply(p), cs) // don't map capture set variables + case t => + mapOver(t) + ref match + case ref: CaptureRef if ref.isTrackableRef => + val tp1 = narrowCaps(tp) + if narrowCaps.ok then + if tp1 ne tp then capt.println(i"narrow $tp of $ref to $tp1") + tp1 + else + capt.println(i"cannot narrow $tp of $ref to $tp1") + tp + case _ => + tp + extension (cls: ClassSymbol) def pureBaseClass(using Context): Option[Symbol] = @@ -281,24 +328,13 @@ extension (sym: Symbol) && sym != defn.Caps_unsafeBox && sym != defn.Caps_unsafeUnbox - /** Can this symbol possibly own a local root? - * TODO: Disallow anonymous functions? + /** Does this symbol define a level where we do not want to let local variables + * escape into outer capture sets? */ def isLevelOwner(using Context): Boolean = sym.isClass || sym.is(Method, butNot = Accessor) - /** The level owner enclosing `sym` which has the given name, or NoSymbol - * if none exists. - */ - def levelOwnerNamed(name: String)(using Context): Symbol = - def recur(sym: Symbol): Symbol = - if sym.name.toString == name then - if sym.isLevelOwner then sym else NoSymbol - else if sym == defn.RootClass then NoSymbol - else recur(sym.owner) - recur(sym) - /** The owner of the current level. Qualifying owners are * - methods other than constructors and anonymous functions * - anonymous functions, provided they either define a local @@ -313,14 +349,6 @@ extension (sym: Symbol) else recur(sym.owner) recur(sym) - /** The local root corresponding to sym's level owner */ - def localRoot(using Context): Symbol = - val owner = sym.levelOwner - assert(owner.exists) - def newRoot = newSymbol(if owner.isClass then newLocalDummy(owner) else owner, - nme.LOCAL_CAPTURE_ROOT, Synthetic, defn.Caps_Cap.typeRef) - ccState.localRoots.getOrElseUpdate(owner, newRoot) - /** The outermost symbol owned by both `sym` and `other`. if none exists * since the owning scopes of `sym` and `other` are not nested, invoke * `onConflict` to return a symbol. @@ -342,3 +370,21 @@ extension (tp: AnnotatedType) def isBoxed(using Context): Boolean = tp.annot match case ann: CaptureAnnotation => ann.boxed case _ => false + +/** An extractor for `caps.reachCapability(ref)`, which is used to express a reach + * capability as a tree in a @retains annotation. + */ +object ReachCapabilityApply: + def unapply(tree: Apply)(using Context): Option[Tree] = tree match + case Apply(reach, arg :: Nil) if reach.symbol == defn.Caps_reachCapability => Some(arg) + case _ => None + +/** An extractor for `ref @annotation.internal.reachCapability`, which is used to express + * the reach capability `ref*` as a type. + */ +object ReachCapability: + def unapply(tree: AnnotatedType)(using Context): Option[SingletonCaptureRef] = tree match + case AnnotatedType(parent: SingletonCaptureRef, ann) + if ann.symbol == defn.ReachCapabilityAnnot => Some(parent) + case _ => None + diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala b/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala index 7261c760aa01..fb086ca0399b 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala @@ -77,19 +77,8 @@ sealed abstract class CaptureSet extends Showable: /** Does this capture set contain the root reference `cap` as element? */ final def isUniversal(using Context) = - elems.exists(_.isUniversalRootCapability) - - /** Does this capture set contain the root reference `cap` as element? */ - final def containsRoot(using Context) = elems.exists(_.isRootCapability) - /** Does this capture set disallow an addiiton of `cap`, whereas it - * might allow an addition of a local root? - */ - final def disallowsUniversal(using Context) = - if isConst then !isUniversal && elems.exists(_.isLocalRootCapability) - else asVar.noUniversal - /** Try to include an element in this capture set. * @param elem The element to be added * @param origin The set that originated the request, or `empty` if the request came from outside. @@ -154,39 +143,21 @@ sealed abstract class CaptureSet extends Showable: cs.addDependent(this)(using ctx, UnrecordedState) this - extension (x: CaptureRef)(using Context) - - /* x subsumes y if one of the following is true: - * - x is the same as y, - * - x is a this reference and y refers to a field of x - * - x is a super root of y - */ - private def subsumes(y: CaptureRef) = + /** x subsumes x + * this subsumes this.f + * x subsumes y ==> x* subsumes y + * x subsumes y ==> x* subsumes y* + */ + extension (x: CaptureRef) + private def subsumes(y: CaptureRef)(using Context): Boolean = (x eq y) - || x.isSuperRootOf(y) + || x.isRootCapability || y.match - case y: TermRef => y.prefix eq x + case y: TermRef => !y.isReach && (y.prefix eq x) + case _ => false + || x.match + case ReachCapability(x1) => x1.subsumes(y.stripReach) case _ => false - - /** x <:< cap, cap[x] <:< cap - * cap[y] <:< cap[x] if y encloses x - * y <:< cap[x] if y's level owner encloses x's local root owner - */ - private def isSuperRootOf(y: CaptureRef): Boolean = x match - case x: TermRef => - x.isUniversalRootCapability - || x.isLocalRootCapability && !y.isUniversalRootCapability && { - val xowner = x.localRootOwner - y match - case y: TermRef => - xowner.isContainedIn(y.symbol.levelOwner) - case y: ThisType => - xowner.isContainedIn(y.cls) - case _ => - false - } - case _ => false - end extension /** {x} <:< this where <:< is subcapturing, but treating all variables * as frozen. @@ -210,7 +181,7 @@ sealed abstract class CaptureSet extends Showable: */ def mightAccountFor(x: CaptureRef)(using Context): Boolean = reporting.trace(i"$this mightAccountFor $x, ${x.captureSetOfInfo}?", show = true) { - elems.exists(elem => elem.subsumes(x) || elem.isRootCapability) + elems.exists(_.subsumes(x)) || !x.isRootCapability && { val elems = x.captureSetOfInfo.elems @@ -516,7 +487,7 @@ object CaptureSet: else //if id == 34 then assert(!elem.isUniversalRootCapability) elems += elem - if elem.isUniversalRootCapability then + if elem.isRootCapability then rootAddedHandler() newElemAddedHandler(elem) // assert(id != 5 || elems.size != 3, this) @@ -527,19 +498,17 @@ object CaptureSet: res.addToTrace(this) private def levelOK(elem: CaptureRef)(using Context): Boolean = - if elem.isUniversalRootCapability then !noUniversal + if elem.isRootCapability then !noUniversal else elem match - case elem: TermRef => - if levelLimit.exists then - var sym = elem.symbol - if sym.isLevelOwner then sym = sym.owner - levelLimit.isContainedIn(sym.levelOwner) - else true - case elem: ThisType => - if levelLimit.exists then - levelLimit.isContainedIn(elem.cls.levelOwner) - else true - case elem: TermParamRef => + case elem: TermRef if levelLimit.exists => + var sym = elem.symbol + if sym.isLevelOwner then sym = sym.owner + levelLimit.isContainedIn(sym.levelOwner) + case elem: ThisType if levelLimit.exists => + levelLimit.isContainedIn(elem.cls.levelOwner) + case ReachCapability(elem1) => + levelOK(elem1) + case _ => true def addDependent(cs: CaptureSet)(using Context, VarState): CompareResult = @@ -567,10 +536,9 @@ object CaptureSet: * of this set. The universal set {cap} is a sound fallback. */ final def upperApprox(origin: CaptureSet)(using Context): CaptureSet = - if isConst then this - else if elems.exists(_.isRootCapability) then - CaptureSet(elems.filter(_.isRootCapability).toList*) - else if computingApprox then + if isConst then + this + else if elems.exists(_.isRootCapability) || computingApprox then universal else computingApprox = true @@ -633,6 +601,13 @@ object CaptureSet: override def toString = s"Var$id$elems" end Var + /** Variables that represent refinements of class parameters can have the universal + * capture set, since they represent only what is the result of the constructor. + * Test case: Without that tweak, logger.scala would not compile. + */ + class RefiningVar(directOwner: Symbol)(using Context) extends Var(directOwner): + override def disallowRootCapability(handler: () => Context ?=> Unit)(using Context) = this + /** A variable that is derived from some other variable via a map or filter. */ abstract class DerivedVar(owner: Symbol, initialElems: Refs)(using @constructorOnly ctx: Context) extends Var(owner, initialElems): @@ -1037,6 +1012,8 @@ object CaptureSet: /** The capture set of the type underlying CaptureRef */ def ofInfo(ref: CaptureRef)(using Context): CaptureSet = ref match case ref: TermRef if ref.isRootCapability => ref.singletonCaptureSet + case ReachCapability(ref1) => deepCaptureSet(ref1.widen) + .showing(i"Deep capture set of $ref: ${ref1.widen} = $result", capt) case _ => ofType(ref.underlying, followResult = true) /** Capture set of a type */ @@ -1078,6 +1055,16 @@ object CaptureSet: recur(tp) .showing(i"capture set of $tp = $result", captDebug) + private def deepCaptureSet(tp: Type)(using Context): CaptureSet = + val collect = new TypeAccumulator[CaptureSet]: + def apply(cs: CaptureSet, t: Type) = t.dealias match + case t @ CapturingType(p, cs1) => + val cs2 = apply(cs, p) + if variance > 0 then cs2 ++ cs1 else cs2 + case _ => + foldOver(cs, t) + collect(CaptureSet.empty, tp) + private val ShownVars: Property.Key[mutable.Set[Var]] = Property.Key() /** Perform `op`. Under -Ycc-debug, collect and print info about all variables reachable @@ -1115,7 +1102,7 @@ object CaptureSet: override def toAdd(using Context) = for CompareResult.LevelError(cs, ref) <- ccState.levelError.toList yield ccState.levelError = None - if ref.isUniversalRootCapability then + if ref.isRootCapability then i""" | |Note that the universal capability `cap` diff --git a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala index d6a03667311a..7c35568d7ce9 100644 --- a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala +++ b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala @@ -130,15 +130,15 @@ object CheckCaptures: report.error(em"Singleton type $parent cannot have capture set", parent.srcPos) case _ => for elem <- ann.retainedElems do - elem match - case QualifiedRoot(outer) => - // Will be checked by Setup's checkOuterRoots - case _ => elem.tpe match - case ref: CaptureRef => - if !ref.isTrackableRef then - report.error(em"$elem cannot be tracked since it is not a parameter or local value", elem.srcPos) - case tpe => - report.error(em"$elem: $tpe is not a legal element of a capture set", elem.srcPos) + val elem1 = elem match + case ReachCapabilityApply(arg) => arg + case _ => elem + elem1.tpe match + case ref: CaptureRef => + if !ref.isTrackableRef then + report.error(em"$elem cannot be tracked since it is not a parameter or local value", elem.srcPos) + case tpe => + report.error(em"$elem: $tpe is not a legal element of a capture set", elem.srcPos) /** Report an error if some part of `tp` contains the root capability in its capture set * or if it refers to an unsealed type parameter that could possibly be instantiated with @@ -173,22 +173,7 @@ object CheckCaptures: t.dealiasKeepAnnots match case t: TypeRef => if !seen.contains(t) then - capt.println(i"disallow $t, $tp, $what, ${t.isSealed}") seen += t - t.info match - case TypeBounds(_, hi) if !t.isSealed && !t.symbol.isParametricIn(carrier) => - if hi.isAny then - val detailStr = - if t eq tp then "variable" - else i"refers to the type variable $t, which" - report.error( - em"""$what cannot $have $tp since - |that type $detailStr is not sealed. - |$addendum""", - pos) - else - traverse(hi) - case _ => traverseChildren(t) case AnnotatedType(_, ann) if ann.symbol == defn.UncheckedCapturesAnnot => () @@ -560,7 +545,7 @@ class CheckCaptures extends Recheck, SymTransformer: val polyType = atPhase(thisPhase.prev): fn.tpe.widen.asInstanceOf[TypeLambda] for case (arg: TypeTree, formal, pname) <- args.lazyZip(polyType.paramRefs).lazyZip((polyType.paramNames)) do - if formal.isSealed then + if !tree.symbol.isTypeTestOrCast then def where = if fn.symbol.exists then i" in an argument of ${fn.symbol}" else "" disallowRootCapabilitiesIn(arg.knownType, NoSymbol, i"Sealed type variable $pname", "be instantiated to", @@ -837,13 +822,9 @@ class CheckCaptures extends Recheck, SymTransformer: } checkNotUniversal(parent) case _ => - val adapted = - if ccConfig.allowUniversalInBoxed then - adaptUniversal(tpe, pt, tree) - else - if needsUniversalCheck then checkNotUniversal(tpe) - tpe - super.recheckFinish(adapted, tree, pt) + if !ccConfig.allowUniversalInBoxed && needsUniversalCheck then + checkNotUniversal(tpe) + super.recheckFinish(tpe, tree, pt) end recheckFinish // ------------------ Adaptation ------------------------------------- @@ -855,56 +836,7 @@ class CheckCaptures extends Recheck, SymTransformer: // - Relax expected capture set containing `this.type`s by adding references only // accessible through those types (c.f. addOuterRefs, also #14930 for a discussion). // - Adapt box status and environment capture sets by simulating box/unbox operations. - // - Instantiate `cap` in actual as needed to a local root. - - /** The local root that is implied for the expression `tree`. - * This is the local root of the outermost level owner that includes - * all free variables of the expression that have in their types - * some capturing type occuring in covariant or invariant position. - */ - def impliedRoot(tree: Tree)(using Context) = - def isTrackedSomewhere(sym: Symbol): Boolean = - val search = new TypeAccumulator[Boolean]: - def apply(found: Boolean, tp: Type) = - def isTrackedHere = variance >= 0 && !tp.captureSet.isAlwaysEmpty - found || isTrackedHere || foldOver(found, tp) - if sym.is(Method) - then !capturedVars(sym).elems.isEmpty || search(false, sym.info.finalResultType) - else search(false, sym.info) - - val acc = new TreeAccumulator[Symbol]: - val locals = mutable.Set[Symbol]() - private def max(sym1: Symbol, sym2: Symbol)(using Context) = - sym1.maxNested(sym2, onConflict = (_, _) => throw NoCommonRoot(sym1, sym2)) - def apply(s: Symbol, t: Tree)(using Context) = t match - case t: (Ident | This) - if !locals.contains(t.symbol) && isTrackedSomewhere(t.symbol) => - max(s, t.symbol.levelOwner) - case t: DefTree => - locals += t.symbol - foldOver(s, t) - case _ => - foldOver(s, t) - acc(NoSymbol, tree).orElse(ctx.owner).localRoot - - /** Assume `actual` is the type of an expression `tree` with the given - * `expected` type. If `actual` captures `cap` and `cap` is not allowed - * in the capture set of `expected`, narrow `cap` to the root capability - * that is implied for `tree`. - */ - def adaptUniversal(actual: Type, expected: Type, tree: Tree)(using Context): Type = - if expected.captureSet.disallowsUniversal && actual.captureSet.isUniversal then - if actual.isInstanceOf[SingletonType] then - // capture set is only exposed when widening - adaptUniversal(actual.widen, expected, tree) - else - val localRoot = impliedRoot(tree) - CapturingType( - actual.stripCapturing, - localRoot.termRef.singletonCaptureSet, - actual.isBoxedCapturing) - .showing(i"adapt universal $actual vs $expected = $result", capt) - else actual + // - Instantiate covariant occurrenves of `cap` in actual to reach capabilities. private inline val debugSuccesses = false @@ -1152,7 +1084,7 @@ class CheckCaptures extends Recheck, SymTransformer: // given `a: T^C`, improve `T^C` to `T^{a}` case _ => case _ => - val adapted = adapt(actualw, expected, covariant = true) + val adapted = adapt(actualw.withReachCaptures(actual), expected, covariant = true) if adapted ne actualw then capt.println(i"adapt boxed $actual vs $expected ===> $adapted") adapted @@ -1328,7 +1260,7 @@ class CheckCaptures extends Recheck, SymTransformer: cs.ensureWellformed: elem => ctx ?=> var seen = new util.HashSet[CaptureRef] - def recur(ref: CaptureRef): Unit = ref match + def recur(ref: CaptureRef): Unit = ref.stripReach match case ref: TermParamRef if !allowed.contains(ref) && !seen.contains(ref) => seen += ref @@ -1369,20 +1301,6 @@ class CheckCaptures extends Recheck, SymTransformer: checker.traverse(tree.knownType) end healTypeParam - def checkNoLocalRootIn(sym: Symbol, info: Type, pos: SrcPos)(using Context): Unit = - val check = new TypeTraverser: - def traverse(tp: Type) = tp match - case tp: TermRef if tp.isLocalRootCapability => - if tp.localRootOwner == sym then - report.error(i"local root $tp cannot appear in type of $sym", pos) - case tp: ClassInfo => - traverseChildren(tp) - for mbr <- tp.decls do - if !mbr.is(Private) then checkNoLocalRootIn(sym, mbr.info, mbr.srcPos) - case _ => - traverseChildren(tp) - check.traverse(info) - def checkArraysAreSealedIn(tp: Type, pos: SrcPos)(using Context): Unit = val check = new TypeTraverser: def traverse(t: Type): Unit = @@ -1426,8 +1344,6 @@ class CheckCaptures extends Recheck, SymTransformer: checkBounds(normArgs, tl) args.lazyZip(tl.paramNames).foreach(healTypeParam(_, _, fun.symbol)) case _ => - case _: ValOrDefDef | _: TypeDef => - checkNoLocalRootIn(tree.symbol, tree.symbol.info, tree.symbol.srcPos) case tree: TypeTree => checkArraysAreSealedIn(tree.tpe, tree.srcPos) case _ => diff --git a/compiler/src/dotty/tools/dotc/cc/Setup.scala b/compiler/src/dotty/tools/dotc/cc/Setup.scala index 690ed464eec2..74e67bda5fab 100644 --- a/compiler/src/dotty/tools/dotc/cc/Setup.scala +++ b/compiler/src/dotty/tools/dotc/cc/Setup.scala @@ -174,7 +174,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: val getterType = mapInferred(refine = false)(tp.memberInfo(getter)).strippedDealias RefinedType(core, getter.name, - CapturingType(getterType, CaptureSet.Var(ctx.owner))) + CapturingType(getterType, CaptureSet.RefiningVar(ctx.owner))) .showing(i"add capture refinement $tp --> $result", capt) else core @@ -275,23 +275,16 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: then CapturingType(tp, defn.expandedUniversalSet, boxed = false) else tp - private def checkQualifiedRoots(tree: Tree): Unit = - for case elem @ QualifiedRoot(outer) <- tree.retainedElems do - if !ctx.owner.levelOwnerNamed(outer).exists then - report.error(em"`$outer` does not name an outer definition that represents a capture level", elem.srcPos) - private def recur(t: Type): Type = normalizeCaptures(mapOver(t)) def apply(t: Type) = t match case t @ CapturingType(parent, refs) => - checkQualifiedRoots(t.annot.tree) // TODO: NEEDED? t.derivedCapturingType(this(parent), refs) case t @ AnnotatedType(parent, ann) => val parent1 = this(parent) if ann.symbol == defn.RetainsAnnot then for tpt <- tptToCheck do - checkQualifiedRoots(ann.tree) checkWellformedLater(parent1, ann.tree, tpt) CapturingType(parent1, ann.tree.toCaptureSet) else @@ -333,15 +326,17 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: def apply(t: Type): Type = t match case t: NamedType => - val sym = t.symbol - def outer(froms: List[List[Symbol]], tos: List[LambdaType]): Type = - def inner(from: List[Symbol], to: List[ParamRef]): Type = - if from.isEmpty then outer(froms.tail, tos.tail) - else if sym eq from.head then to.head - else inner(from.tail, to.tail) - if tos.isEmpty then t - else inner(froms.head, tos.head.paramRefs) - outer(from, to) + if t.prefix == NoPrefix then + val sym = t.symbol + def outer(froms: List[List[Symbol]], tos: List[LambdaType]): Type = + def inner(from: List[Symbol], to: List[ParamRef]): Type = + if from.isEmpty then outer(froms.tail, tos.tail) + else if sym eq from.head then to.head + else inner(from.tail, to.tail) + if tos.isEmpty then t + else inner(froms.head, tos.head.paramRefs) + outer(from, to) + else t.derivedSelect(apply(t.prefix)) case _ => mapOver(t) @@ -586,11 +581,11 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: case CapturingType(parent, refs) => needsVariable(parent) && refs.isConst // if refs is a variable, no need to add another - && !refs.containsRoot // if refs is {cap}, an added variable would not change anything + && !refs.isUniversal // if refs is {cap}, an added variable would not change anything case RetainingType(parent, refs) => needsVariable(parent) && !refs.tpes.exists: - case ref: TermRef => ref.isUniversalRootCapability + case ref: TermRef => ref.isRootCapability case _ => false case AnnotatedType(parent, _) => needsVariable(parent) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 070a71e8f671..1a99c19baaf4 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -978,13 +978,12 @@ class Definitions { @tu lazy val CapsModule: Symbol = requiredModule("scala.caps") @tu lazy val captureRoot: TermSymbol = CapsModule.requiredValue("cap") @tu lazy val Caps_Cap: TypeSymbol = CapsModule.requiredType("Cap") - @tu lazy val Caps_capIn: TermSymbol = CapsModule.requiredMethod("capIn") + @tu lazy val Caps_reachCapability: TermSymbol = CapsModule.requiredMethod("reachCapability") @tu lazy val CapsUnsafeModule: Symbol = requiredModule("scala.caps.unsafe") @tu lazy val Caps_unsafeAssumePure: Symbol = CapsUnsafeModule.requiredMethod("unsafeAssumePure") @tu lazy val Caps_unsafeBox: Symbol = CapsUnsafeModule.requiredMethod("unsafeBox") @tu lazy val Caps_unsafeUnbox: Symbol = CapsUnsafeModule.requiredMethod("unsafeUnbox") @tu lazy val Caps_unsafeBoxFunArg: Symbol = CapsUnsafeModule.requiredMethod("unsafeBoxFunArg") - @tu lazy val Caps_SealedAnnot: ClassSymbol = requiredClass("scala.caps.Sealed") @tu lazy val expandedUniversalSet: CaptureSet = CaptureSet(captureRoot.termRef) @tu lazy val PureClass: Symbol = requiredClass("scala.Pure") @@ -1054,6 +1053,7 @@ class Definitions { @tu lazy val TargetNameAnnot: ClassSymbol = requiredClass("scala.annotation.targetName") @tu lazy val VarargsAnnot: ClassSymbol = requiredClass("scala.annotation.varargs") @tu lazy val SinceAnnot: ClassSymbol = requiredClass("scala.annotation.since") + @tu lazy val ReachCapabilityAnnot = requiredClass("scala.annotation.internal.reachCapability") @tu lazy val RequiresCapabilityAnnot: ClassSymbol = requiredClass("scala.annotation.internal.requiresCapability") @tu lazy val RetainsAnnot: ClassSymbol = requiredClass("scala.annotation.retains") @tu lazy val RetainsByNameAnnot: ClassSymbol = requiredClass("scala.annotation.retainsByName") diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 1436b41b521c..253a45ffd7a8 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -120,6 +120,7 @@ object StdNames { val BITMAP_TRANSIENT: N = s"${BITMAP_PREFIX}trans$$" // initialization bitmap for transient lazy vals val BITMAP_CHECKINIT: N = s"${BITMAP_PREFIX}init$$" // initialization bitmap for checkinit values val BITMAP_CHECKINIT_TRANSIENT: N = s"${BITMAP_PREFIX}inittrans$$" // initialization bitmap for transient checkinit values + val CC_REACH: N = "$reach" val DEFAULT_GETTER: N = str.DEFAULT_GETTER val DEFAULT_GETTER_INIT: N = "$lessinit$greater" val DO_WHILE_PREFIX: N = "doWhile$" @@ -287,7 +288,6 @@ object StdNames { // Compiler-internal val CAPTURE_ROOT: N = "cap" - val LOCAL_CAPTURE_ROOT: N = "" val CONSTRUCTOR: N = "" val STATIC_CONSTRUCTOR: N = "" val EVT2U: N = "evt2u$" diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 77aa5e021390..be55347649b3 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -980,11 +980,15 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling def tp1widened = val tp1w = tp1.underlying.widenExpr - tp1 match - case tp1: CaptureRef if isCaptureCheckingOrSetup && tp1.isTracked => - CapturingType(tp1w.stripCapturing, tp1.singletonCaptureSet) - case _ => - tp1w + if isCaptureCheckingOrSetup then + tp1 + .match + case tp1: CaptureRef if tp1.isTracked => + CapturingType(tp1w.stripCapturing, tp1.singletonCaptureSet) + case _ => + tp1w + .withReachCaptures(tp1) + else tp1w comparePaths || isSubType(tp1widened, tp2, approx.addLow) case tp1: RefinedType => diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index c4be8af1cb51..c3fd07017cd0 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2181,7 +2181,7 @@ object Types { } /** A trait for references in CaptureSets. These can be NamedTypes, ThisTypes or ParamRefs */ - trait CaptureRef extends SingletonType: + trait CaptureRef extends TypeProxy, ValueType: private var myCaptureSet: CaptureSet | Null = uninitialized private var myCaptureSetRunId: Int = NoRunId private var mySingletonCaptureSet: CaptureSet.Const | Null = null @@ -2192,19 +2192,13 @@ object Types { final def isTracked(using Context): Boolean = isTrackableRef && (isRootCapability || !captureSetOfInfo.isAlwaysEmpty) - /** Is this reference the generic root capability `cap` ? */ - def isUniversalRootCapability(using Context): Boolean = false + /** Is this a reach reference of the form `x*`? */ + def isReach(using Context): Boolean = false // overridden in AnnotatedType - /** Is this reference a local root capability `{}` - * for some level owner? - */ - def isLocalRootCapability(using Context): Boolean = this match - case tp: TermRef => tp.localRootOwner.exists - case _ => false + def stripReach(using Context): CaptureRef = this // overridden in AnnotatedType - /** Is this reference the a (local or generic) root capability? */ - def isRootCapability(using Context): Boolean = - isUniversalRootCapability || isLocalRootCapability + /** Is this reference the generic root capability `cap` ? */ + def isRootCapability(using Context): Boolean = false /** Normalize reference so that it can be compared with `eq` for equality */ def normalizedRef(using Context): CaptureRef = this @@ -2238,6 +2232,8 @@ object Types { end CaptureRef + trait SingletonCaptureRef extends SingletonType, CaptureRef + /** A trait for types that bind other types that refer to them. * Instances are: LambdaType, RecType. */ @@ -2901,7 +2897,7 @@ object Types { */ abstract case class TermRef(override val prefix: Type, private var myDesignator: Designator) - extends NamedType, ImplicitRef, CaptureRef { + extends NamedType, ImplicitRef, SingletonCaptureRef { type ThisType = TermRef type ThisName = TermName @@ -2938,15 +2934,9 @@ object Types { || isRootCapability ) && !symbol.isOneOf(UnstableValueFlags) - override def isUniversalRootCapability(using Context): Boolean = + override def isRootCapability(using Context): Boolean = name == nme.CAPTURE_ROOT && symbol == defn.captureRoot - def localRootOwner(using Context): Symbol = - // TODO Try to make local class roots be NonMembers owned directly by the class - val owner = symbol.maybeOwner - def normOwner = if owner.isLocalDummy then owner.owner else owner - if name == nme.LOCAL_CAPTURE_ROOT then normOwner else NoSymbol - override def normalizedRef(using Context): CaptureRef = if isTrackableRef then symbol.termRef else this } @@ -3087,7 +3077,8 @@ object Types { * Note: we do not pass a class symbol directly, because symbols * do not survive runs whereas typerefs do. */ - abstract case class ThisType(tref: TypeRef) extends CachedProxyType, CaptureRef { + abstract case class ThisType(tref: TypeRef) + extends CachedProxyType, SingletonCaptureRef { def cls(using Context): ClassSymbol = tref.stableInRunSymbol match { case cls: ClassSymbol => cls case _ if ctx.mode.is(Mode.Interactive) => defn.AnyClass // was observed to happen in IDE mode @@ -4096,15 +4087,10 @@ object Types { protected def toPInfo(tp: Type)(using Context): PInfo - /** If `tparam` is a sealed type parameter symbol of a polymorphic method, add - * a @caps.Sealed annotation to the upperbound in `tp`. - */ - protected def addSealed(tparam: ParamInfo, tp: Type)(using Context): Type = tp - def fromParams[PI <: ParamInfo.Of[N]](params: List[PI], resultType: Type)(using Context): Type = if (params.isEmpty) resultType else apply(params.map(_.paramName))( - tl => params.map(param => toPInfo(addSealed(param, tl.integrate(params, param.paramInfo)))), + tl => params.map(param => toPInfo(tl.integrate(params, param.paramInfo))), tl => tl.integrate(params, resultType)) } @@ -4426,16 +4412,6 @@ object Types { resultTypeExp: PolyType => Type)(using Context): PolyType = unique(new PolyType(paramNames)(paramInfosExp, resultTypeExp)) - override protected def addSealed(tparam: ParamInfo, tp: Type)(using Context): Type = - tparam match - case tparam: Symbol if tparam.is(Sealed) => - tp match - case tp @ TypeBounds(lo, hi) => - tp.derivedTypeBounds(lo, - AnnotatedType(hi, Annotation(defn.Caps_SealedAnnot, tparam.span))) - case _ => tp - case _ => tp - def unapply(tl: PolyType): Some[(List[LambdaParam], Type)] = Some((tl.typeParams, tl.resType)) } @@ -4715,7 +4691,8 @@ object Types { /** Only created in `binder.paramRefs`. Use `binder.paramRefs(paramNum)` to * refer to `TermParamRef(binder, paramNum)`. */ - abstract case class TermParamRef(binder: TermLambda, paramNum: Int) extends ParamRef, CaptureRef { + abstract case class TermParamRef(binder: TermLambda, paramNum: Int) + extends ParamRef, SingletonCaptureRef { type BT = TermLambda def kindString: String = "Term" def copyBoundType(bt: BT): Type = bt.paramRefs(paramNum) @@ -5424,7 +5401,7 @@ object Types { // ----- Annotated and Import types ----------------------------------------------- /** An annotated type tpe @ annot */ - abstract case class AnnotatedType(parent: Type, annot: Annotation) extends CachedProxyType, ValueType { + abstract case class AnnotatedType(parent: Type, annot: Annotation) extends CachedProxyType, CaptureRef { override def underlying(using Context): Type = parent @@ -5453,6 +5430,23 @@ object Types { isRefiningCache } + override def isTrackableRef(using Context) = + isReach && parent.isTrackableRef + + /** Is this a reach reference of the form `x*`? */ + override def isReach(using Context): Boolean = + annot.symbol == defn.ReachCapabilityAnnot + + override def stripReach(using Context): SingletonCaptureRef = + (if isReach then parent else this).asInstanceOf[SingletonCaptureRef] + + override def normalizedRef(using Context): CaptureRef = + if isReach then AnnotatedType(stripReach.normalizedRef, annot) else this + + override def captureSet(using Context): CaptureSet = + if isReach then super.captureSet + else CaptureSet.ofType(this, followResult = false) + // equals comes from case class; no matching override is needed override def computeHash(bs: Binders): Int = diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 23eeb711f965..aec3ad42feef 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1474,19 +1474,13 @@ object Parsers { */ def captureRef(): Tree = if in.token == THIS then simpleRef() - else termIdent() match - case id @ Ident(nme.CAPTURE_ROOT) => - if in.token == LBRACKET then - val ref = atSpan(id.span.start)(captureRootIn) - val qual = - inBrackets: - atSpan(in.offset): - Literal(Constant(ident().toString)) - atSpan(id.span.start)(Apply(ref, qual :: Nil)) - else - atSpan(id.span.start)(captureRoot) - case id => - id + else + val id = termIdent() + if isIdent(nme.raw.STAR) then + in.nextToken() + atSpan(startOffset(id)): + PostfixOp(id, Ident(nme.CC_REACH)) + else id /** CaptureSet ::= `{` CaptureRef {`,` CaptureRef} `}` -- under captureChecking */ @@ -3278,9 +3272,6 @@ object Parsers { val start = in.offset var mods = annotsAsMods() | Param if ownerKind == ParamOwner.Class then mods |= PrivateLocal - if Feature.ccEnabled && in.token == SEALED then - mods |= Sealed - in.nextToken() if isIdent(nme.raw.PLUS) && checkVarianceOK() then mods |= Covariant else if isIdent(nme.raw.MINUS) && checkVarianceOK() then diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index d5c60cf44579..7fed5bc97f35 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -15,7 +15,7 @@ import util.SourcePosition import scala.util.control.NonFatal import scala.annotation.switch import config.{Config, Feature} -import cc.{CapturingType, RetainingType, CaptureSet, isBoxed, levelOwner, retainedElems} +import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, isBoxed, levelOwner, retainedElems} class PlainPrinter(_ctx: Context) extends Printer { @@ -162,13 +162,11 @@ class PlainPrinter(_ctx: Context) extends Printer { private def toTextRetainedElem[T <: Untyped](ref: Tree[T]): Text = ref match case ref: RefTree[?] if ref.typeOpt.exists => toTextCaptureRef(ref.typeOpt) - case Apply(fn, Literal(str) :: Nil) if fn.symbol == defn.Caps_capIn => - s"cap[${str.stringValue}]" case _ => toText(ref) private def toTextRetainedElems[T <: Untyped](refs: List[Tree[T]]): Text = - "{" ~ Text(refs.map(ref => toTextRetainedElem(ref))) ~ "}" + "{" ~ Text(refs.map(ref => toTextRetainedElem(ref)), ", ") ~ "}" /** Print capturing type, overridden in RefinedPrinter to account for * capturing function types. @@ -180,11 +178,6 @@ class PlainPrinter(_ctx: Context) extends Printer { final protected def rootSetText = Str("{cap}") // TODO Use disambiguation - // Lazy version of isRootCapability; used to not force completers when printing - private def isRootCap(tp: CaptureRef): Boolean = tp match - case tp: TermRef => tp.symbol.isCompleted && tp.isRootCapability - case _ => tp.isRootCapability - def toText(tp: Type): Text = controlled { homogenize(tp) match { case tp: TypeType => @@ -192,7 +185,7 @@ class PlainPrinter(_ctx: Context) extends Printer { case tp: TermRef if !tp.denotationIsCurrent && !homogenizedView // always print underlying when testing picklers - && !isRootCap(tp) + && !tp.isRootCapability || tp.symbol.is(Module) || tp.symbol.name == nme.IMPORT => toTextRef(tp) ~ ".type" @@ -244,14 +237,7 @@ class PlainPrinter(_ctx: Context) extends Printer { }.close case tp @ CapturingType(parent, refs) => val boxText: Text = Str("box ") provided tp.isBoxed //&& ctx.settings.YccDebug.value - val rootsInRefs = refs.elems.filter(isRootCap(_)).toList - val showAsCap = rootsInRefs match - case (tp: TermRef) :: Nil => - tp.symbol == defn.captureRoot && (refs.elems.size == 1 || !printDebug) - // {caps.cap} gets printed as `{cap}` even under printDebug as long as there - // are no other elements in the set - case _ => - false + val showAsCap = refs.isUniversal && (refs.elems.size == 1 || !printDebug) val refsText = if showAsCap then rootSetText else toTextCaptureSet(refs) toTextCapturing(parent, refsText, boxText) case tp @ RetainingType(parent, refs) => @@ -391,9 +377,7 @@ class PlainPrinter(_ctx: Context) extends Printer { def toTextRef(tp: SingletonType): Text = controlled { tp match { case tp: TermRef => - if tp.symbol.name == nme.LOCAL_CAPTURE_ROOT then // TODO: Move to toTextCaptureRef - Str(s"cap[${nameString(tp.localRootOwner)}]") - else toTextPrefixOf(tp) ~ selectionString(tp) + toTextPrefixOf(tp) ~ selectionString(tp) case tp: ThisType => nameString(tp.cls) + ".this" case SuperType(thistpe: SingletonType, _) => @@ -419,6 +403,7 @@ class PlainPrinter(_ctx: Context) extends Printer { homogenize(tp) match case tp: TermRef if tp.symbol == defn.captureRoot => Str("cap") case tp: SingletonType => toTextRef(tp) + case ReachCapability(tp1) => toTextRef(tp1) ~ "*" case _ => toText(tp) protected def isOmittablePrefix(sym: Symbol): Boolean = diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 9426842363a7..73c83f847061 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -703,7 +703,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { val opPrec = parsing.precedence(op.name) changePrec(opPrec) { toText(l) ~ " " ~ toText(op) ~ " " ~ toText(r) } case PostfixOp(l, op) => - changePrec(InfixPrec) { toText(l) ~ " " ~ toText(op) } + if op.name == nme.CC_REACH then + changePrec(DotPrec) { toText(l) ~ "*" } + else + changePrec(InfixPrec) { toText(l) ~ " " ~ toText(op) } case PrefixOp(op, r) => changePrec(DotPrec) { toText(op) ~ " " ~ toText(r) } case Parens(t) => diff --git a/compiler/src/dotty/tools/dotc/transform/Recheck.scala b/compiler/src/dotty/tools/dotc/transform/Recheck.scala index def0f1e1b98f..be058ae3a41a 100644 --- a/compiler/src/dotty/tools/dotc/transform/Recheck.scala +++ b/compiler/src/dotty/tools/dotc/transform/Recheck.scala @@ -328,7 +328,9 @@ abstract class Recheck extends Phase, SymTransformer: assert(false, i"unexpected type of ${tree.fun}: $tp") def recheckTypeApply(tree: TypeApply, pt: Type)(using Context): Type = - recheck(tree.fun).widen match + val funtpe = recheck(tree.fun) + tree.fun.rememberType(funtpe) // remember type to support later bounds checks + funtpe.widen match case fntpe: PolyType => assert(fntpe.paramInfos.hasSameLengthAs(tree.args)) val argTypes = tree.args.map(recheck(_)) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 21bf0bc81cd0..90c26e279d01 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -519,11 +519,7 @@ object Checking { // but they can never be one of ClassOnlyFlags if !sym.isClass && sym.isOneOf(ClassOnlyFlags) then val illegal = sym.flags & ClassOnlyFlags - if sym.is(TypeParam) - && illegal == Sealed - && Feature.ccEnabled && cc.ccConfig.allowUniversalInBoxed - then () // OK - else fail(em"only classes can be ${illegal.flagsString}") + fail(em"only classes can be ${illegal.flagsString}") if (sym.is(AbsOverride) && !sym.owner.is(Trait)) fail(AbstractOverrideOnlyInTraits(sym)) if sym.is(Trait) then diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 91a7a03abb36..cca26abdd1ec 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1042,14 +1042,7 @@ class Namer { typer: Typer => tp val rhs1 = typedAheadType(rhs) - val rhsBodyType: TypeBounds = - val bounds = addVariances(rhs1.tpe).toBounds - if sym.is(Sealed) then - sym.resetFlag(Sealed) - bounds.derivedTypeBounds(bounds.lo, - AnnotatedType(bounds.hi, Annotation(defn.Caps_SealedAnnot, rhs1.span))) - else bounds - + val rhsBodyType: TypeBounds = addVariances(rhs1.tpe).toBounds val unsafeInfo = if (isDerived) rhsBodyType else abstracted(rhsBodyType) def opaqueToBounds(info: Type): Type = diff --git a/docs/_docs/internals/cc/alternatives-to-sealed.md b/docs/_docs/internals/cc/alternatives-to-sealed.md new file mode 100644 index 000000000000..cca3b2b65e0a --- /dev/null +++ b/docs/_docs/internals/cc/alternatives-to-sealed.md @@ -0,0 +1,171 @@ +A capture checking variant +========================== + + - Our starting point is the currently implemented system, where encapsulation is achieved by disallowing root capabilities in + the types of sealed type variables. By contrast no restrictions apply + to boxing or unboxing. + + - We now treat all type variables as sealed (so no special `sealed` modifier is necessary anymore). A type variable cannot be instantiated to a type that contains a covariant occurrence of `cap`. The same restriction applies to the types of mutable variables and try expressions. + + - For any immutable variable `x`, introduce a _reach_ capability `x*` which stands for + "all capabilities reachable through `x`". We have `{x} <: {x*} <: dcs(x)}` where the deep capture set `dcs(x)` of `x` + is the union of all capture sets that appear in covariant position in the type of `x`. If `x` and `y` are different + variables then `{x*}` and `{y*}` are unrelated. + + - We modify the VAR rule as follows: + + x: T in E + ----------- + E |- x: T' + + where T' is T with (1) the toplevel capture set replaced by `{x}` and + (2) all covariant occurrences of cap replaced by `x*`, provided there + are no occurrences in `T` at other variances. (1) is standard, + whereas (2) is new. + +- Why is this sound? Covariant occurrences of cap must represent capabilities that are reachable from `x`, so they are included in the meaning of `{x*}`. At the same time, encapsulation is still maintained since no covariant occurrences of cap are allowed in instance types of +type variables. + +## Examples: + +Assume +```scala +type Proc = () => Unit + +class Ref[T](init: T): + private var x: T = init + def get: T = x + def set(y: T) = { x = y } +``` +Note that type parameters no longer need (or can) be annotated with `sealed`. + +The following example does not work. +```scala +def runAll(xs: List[Proc]): Unit = + var cur: List[Proc] = xs // error: Illegal type for var + while cur.nonEmpty do + val next: () => Unit = cur.head + next() + cur = cur.tail + + usingFile: f => + cur = ((() => f.write()): (() ->{f*} Unit)) :: Nil +``` +Same with refs: +```scala +def runAll(xs: List[Proc]): Unit = + val cur = Ref[List[Proc]](xs) // error, illegal type for type argument to Ref + while cur.get.nonEmpty do + val next: () => Unit = cur.get.head + next() + cur.set(cur.get.tail: List[Proc]) + + usingFile: f => + cur.set: + (() => f.write(): () ->{f*} Unit) :: Nil +``` + +The following variant makes the loop typecheck, but +still rejects the incorrect leakage in `usingFile`. +```scala +def runAll(xs: List[Proc]): Unit = + var cur: List[() ->{xs*} Unit] = xs // OK, by revised VAR + while cur.nonEmpty do + val next: () ->{xs*} Unit = cur.head + next() + cur = cur.tail: List[() ->{xs*} Unit] + + usingFile: f => + cur = (() => f.write(): () ->{f*} Unit) :: Nil // error since {f*} !<: {xs*} +``` + +Same with refs: +```scala +def runAll(xs: List[Proc]): Unit = + val cur = Ref[List[() ->{xs*} Unit]](xs) // OK, by revised VAR + while cur.get.nonEmpty do + val next: () ->{xs*} Unit = cur.get.head + next() + cur.set(cur.get.tail: List[() ->{xs*} Unit]) + + usingFile: f => + cur.set: + (() => f.write(): () ->{f*} Unit) :: Nil // error since {f*} !<: {xs*} +``` + +More examples. This works: +```scala +def cons(x: Proc, xs: List[Proc]): List[() ->{x, xs*} Unit] = + List.cons[() ->{x, xs*} Unit](x, xs) +``` +And this works as well +```scala +def addOneProc(xs: List[Proc]): List[Proc] = + def x: Proc = () => write("hello") + val result: List[() ->{x, xs*} Unit] = x :: xs + result // OK, we can widen () ->{x, xs*} Unit to cap here. +``` +This doesn't work: +```scala +def cons(x: Proc, xs: Set[Proc]) = + Set.include[Proc](x, xs) // error: can't instantiate type parameter to Proc +``` +But this works: +```scala +def cons(x: Proc, xs: Set[Proc]): Set[() ->{x,xs*} Unit] = + Set.include[() ->{x,xs*} Unit](x, xs) // ok +``` +Say we have `a: () ->{io} Unit` and `as: List[() ->{io} Unit]`. Then `cons(a, as)` +is of type `() ->{a, as*} Unit`, which is a subtype of `() ->{io} Unit`. This follows from +`{a} <: {io}` by rule (Var) and `{as*} <: dcs(as) = {io}` by the subcapturing rules for +reach capabilities. + +This also works: +```scala +def compose1[A, B, C](f: A => B, g: B => C): A ->{f, g} C = + z => g(f(z)) +``` +And this works as well: +```scala +def compose2[A, B, C](f: A => B, g: B => C): A => C = + z => g(f(z)) +``` +Even this should work: +```scala +def mapCompose[A](ps: List[(A => A, A => A)]): List[A ->{ps*} A] = + ps.map(compose1) + // ps: List[(A ->{ps*} A, A ->{ps*} A)] + // Hence compose1's parameters are both of type A ->{ps*} A + // Hence its result type is A ->{ps*} A + // So map's type parameter is A ->{ps*} A + // Expanded typing: + // (ps: List[(A ->{ps*} A, A ->{ps*} A)]) + // .map[A ->{ps*} A]: (f: A ->{ps*} A, g: A ->{ps*} A) => + // compose1[A ->{ps*} A, A ->{ps*} A, A ->{ps*} A](f, g) + // : A -> {f, g} A + // The closure is widened to the non-dependent function type + // (f: A ->{ps*} A, g: A ->{ps*} A) -> A ->{ps*} A +``` +But it does not work with `compose2`, since the type variable of `map` cannot be instantiated to `A => A`. + +Syntax Considerations: + + - `x*` is short and has the right connotations. For the spread operator, `xs*` means + _everything contained in x_. Likewise `x*` in capture sets would mean all capabilities + reachable through `x`. + - But then we have capabilities that are not values, undermining the OCap model a bit. + On the other hand, even if we make `x*` values then these would have to be erased in any case. + +Work items: +=========== + + - Implement `x*` references. + - internal representation: maybe have a synthetic private member `*` of + `Any` to which `x*` maps, i.e. `x*` is `x.*`. Advantage: maps like substitutions + and asSeenFrom work out of the box. + - subcapturing: `x <:< x* <: dcs(x)`. + - Narrowing code: in `adaptBoxed` where `x.type` gets widened to `T^{x}`, also + do the covariant `cap` to `x*` replacement. Similarly in `fourthTry` of `TypeComparer`. + - Drop local roots + - Make all type paraneters sealed + diff --git a/library/src/scala/annotation/internal/reach.scala b/library/src/scala/annotation/internal/reach.scala new file mode 100644 index 000000000000..9f5e344adbe9 --- /dev/null +++ b/library/src/scala/annotation/internal/reach.scala @@ -0,0 +1,8 @@ +package scala.annotation +package internal + +/** An annotation that marks a capture ref as a reach capability. + * `x*` is encoded as `x.type @reachCapability` + */ +class reachCapability extends StaticAnnotation + diff --git a/library/src/scala/caps.scala b/library/src/scala/caps.scala index 20d1eb124d84..c7fc8e7ba584 100644 --- a/library/src/scala/caps.scala +++ b/library/src/scala/caps.scala @@ -15,7 +15,11 @@ import annotation.experimental given Cap = cap - def capIn(scope: String): Cap = cap + /** Reach capabilities x* which appear as terms in @retains annotations are encoded + * as `caps.reachCapability(x)`. When converted to CaptureRef types in capture sets + * they are represented as `x.type @annotation.internal.reachCapability`. + */ + extension (x: Any) def reachCapability: Any = x object unsafe: @@ -46,9 +50,3 @@ import annotation.experimental def unsafeBoxFunArg: T => U = f end unsafe - - /** An annotation that expresses the sealed modifier on a type parameter - * Should not be directly referred to in source - */ - @deprecated("The Sealed annotation should not be directly used in source code.\nUse the `sealed` modifier on type parameters instead.") - class Sealed extends annotation.Annotation diff --git a/tests/neg-custom-args/captures/box-adapt-cases.scala b/tests/neg-custom-args/captures/box-adapt-cases.scala index 7010444eecb5..3dac26a98318 100644 --- a/tests/neg-custom-args/captures/box-adapt-cases.scala +++ b/tests/neg-custom-args/captures/box-adapt-cases.scala @@ -7,21 +7,21 @@ def test1(): Unit = { x(cap => cap.use()) // was error, now OK } -def test2(io: Cap^{cap}): Unit = { +def test2(io: Cap^): Unit = { type Id[X] = [T] -> (op: X -> T) -> T val x: Id[Cap^{io}] = ??? x(cap => cap.use()) // error } -def test3(io: Cap^{cap}): Unit = { +def test3(io: Cap^): Unit = { type Id[X] = [T] -> (op: X ->{io} T) -> T val x: Id[Cap^{io}] = ??? x(cap => cap.use()) // ok } -def test4(io: Cap^{cap}, fs: Cap^{cap}): Unit = { +def test4(io: Cap^, fs: Cap^): Unit = { type Id[X] = [T] -> (op: X ->{io} T) -> T val x: Id[Cap^{io, fs}] = ??? diff --git a/tests/neg-custom-args/captures/box-adapt-contra.scala b/tests/neg-custom-args/captures/box-adapt-contra.scala index 5541d0a5fdff..2dc79a66d932 100644 --- a/tests/neg-custom-args/captures/box-adapt-contra.scala +++ b/tests/neg-custom-args/captures/box-adapt-contra.scala @@ -15,4 +15,4 @@ def test2(c: Cap^, d: Cap^): Unit = val f2: (Cap^{c} -> Unit) ->{c} Unit = useCap2[Cap^{c}](c) // ok def useCap3[X](x: X): (X ->{d} Unit) -> Unit = ??? - val f3: (Cap^{c} -> Unit) ->{cap} Unit = useCap3[Cap^{c}](c) // error + val f3: (Cap^{c} -> Unit) => Unit = useCap3[Cap^{c}](c) // error diff --git a/tests/neg-custom-args/captures/box-adapt-cov.scala b/tests/neg-custom-args/captures/box-adapt-cov.scala index 96901e81458d..2c1f15a5c77f 100644 --- a/tests/neg-custom-args/captures/box-adapt-cov.scala +++ b/tests/neg-custom-args/captures/box-adapt-cov.scala @@ -1,12 +1,12 @@ trait Cap -def test1(io: Cap^{cap}) = { +def test1(io: Cap^) = { type Op[X] = [T] -> Unit -> X val f: Op[Cap^{io}] = ??? val x: [T] -> Unit -> Cap^{io} = f // error } -def test2(io: Cap^{cap}) = { +def test2(io: Cap^) = { type Op[X] = [T] -> Unit -> X^{io} val f: Op[Cap^{io}] = ??? val x: Unit -> Cap^{io} = f[Unit] // error diff --git a/tests/neg-custom-args/captures/box-adapt-cs.scala b/tests/neg-custom-args/captures/box-adapt-cs.scala index a39ed0200151..a2a9232fb264 100644 --- a/tests/neg-custom-args/captures/box-adapt-cs.scala +++ b/tests/neg-custom-args/captures/box-adapt-cs.scala @@ -1,14 +1,14 @@ trait Cap { def use(): Int } -def test1(io: Cap^{cap}): Unit = { +def test1(io: Cap^): Unit = { type Id[X] = [T] -> (op: X ->{io} T) -> T val x: Id[Cap^{io}] = ??? - val f: (Cap^{cap}) -> Unit = ??? + val f: (Cap^) -> Unit = ??? x(f) // ok } -def test2(io: Cap^{cap}): Unit = { +def test2(io: Cap^): Unit = { type Id[X] = [T] -> (op: X => T) -> T val x: Id[Cap^] = ??? diff --git a/tests/neg-custom-args/captures/box-adapt-depfun.scala b/tests/neg-custom-args/captures/box-adapt-depfun.scala index 9416ffa040ab..d1c1c73f8207 100644 --- a/tests/neg-custom-args/captures/box-adapt-depfun.scala +++ b/tests/neg-custom-args/captures/box-adapt-depfun.scala @@ -15,7 +15,7 @@ def test2(io: Cap^): Unit = { // should work when the expected type is a dependent function } -def test3(io: Cap^{cap}): Unit = { +def test3(io: Cap^): Unit = { type Id[X] = [T] -> (op: (x: X) ->{} T) -> T val x: Id[Cap^{io}] = ??? diff --git a/tests/neg-custom-args/captures/box-adapt-typefun.scala b/tests/neg-custom-args/captures/box-adapt-typefun.scala index 65a06cd68ed9..175acdda1c8f 100644 --- a/tests/neg-custom-args/captures/box-adapt-typefun.scala +++ b/tests/neg-custom-args/captures/box-adapt-typefun.scala @@ -1,12 +1,12 @@ trait Cap { def use(): Int } -def test1(io: Cap^{cap}): Unit = { +def test1(io: Cap^): Unit = { type Op[X] = [T] -> X -> Unit val f: [T] -> (Cap^{io}) -> Unit = ??? val op: Op[Cap^{io}] = f // error } -def test2(io: Cap^{cap}): Unit = { +def test2(io: Cap^): Unit = { type Lazy[X] = [T] -> Unit -> X val f: Lazy[Cap^{io}] = ??? val test: [T] -> Unit -> (Cap^{io}) = f // error diff --git a/tests/neg-custom-args/captures/capt-test.scala b/tests/neg-custom-args/captures/capt-test.scala index 3ebdeca84c9c..80ee1aba84e1 100644 --- a/tests/neg-custom-args/captures/capt-test.scala +++ b/tests/neg-custom-args/captures/capt-test.scala @@ -14,7 +14,7 @@ def raise[E <: Exception](e: E): Nothing throws E = throw e def foo(x: Boolean): Int throws Fail = if x then 1 else raise(Fail()) -def handle[E <: Exception, sealed R <: Top](op: (CT[E] @retains(caps.cap)) => R)(handler: E => R): R = +def handle[E <: Exception, R <: Top](op: (CT[E] @retains(caps.cap)) => R)(handler: E => R): R = val x: CT[E] = ??? try op(x) catch case ex: E => handler(ex) diff --git a/tests/neg-custom-args/captures/capt1.check b/tests/neg-custom-args/captures/capt1.check index 124bd61a0109..74b9db728983 100644 --- a/tests/neg-custom-args/captures/capt1.check +++ b/tests/neg-custom-args/captures/capt1.check @@ -33,8 +33,22 @@ 27 | def m() = if x == null then y else y | | longer explanation available when compiling with `-explain` +-- Error: tests/neg-custom-args/captures/capt1.scala:32:12 ------------------------------------------------------------- +32 | val z2 = h[() -> Cap](() => x) // error // error + | ^^^^^^^^^^^^ + | Sealed type variable X cannot be instantiated to () -> box C^ since + | the part box C^ of that type captures the root capability `cap`. + | This is often caused by a local capability in an argument of method h + | leaking as part of its result. -- Error: tests/neg-custom-args/captures/capt1.scala:32:30 ------------------------------------------------------------- -32 | val z2 = h[() -> Cap](() => x) // error +32 | val z2 = h[() -> Cap](() => x) // error // error | ^ | (x : C^) cannot be referenced here; it is not included in the allowed capture set {} | of an enclosing function literal with expected type () -> box C^ +-- Error: tests/neg-custom-args/captures/capt1.scala:34:12 ------------------------------------------------------------- +34 | val z3 = h[(() -> Cap) @retains(x)](() => x)(() => C()) // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Sealed type variable X cannot be instantiated to box () ->{x} Cap since + | the part C^ of that type captures the root capability `cap`. + | This is often caused by a local capability in an argument of method h + | leaking as part of its result. diff --git a/tests/neg-custom-args/captures/capt1.scala b/tests/neg-custom-args/captures/capt1.scala index 651184e8d2c9..48c4d889bf8d 100644 --- a/tests/neg-custom-args/captures/capt1.scala +++ b/tests/neg-custom-args/captures/capt1.scala @@ -29,8 +29,7 @@ def h4(x: Cap, y: Int): A = def foo() = val x: C @retains(caps.cap) = ??? def h[X](a: X)(b: X) = a - val z2 = h[() -> Cap](() => x) // error + val z2 = h[() -> Cap](() => x) // error // error (() => C()) - val z3 = h[(() -> Cap) @retains(x)](() => x)(() => C()) // ok - val z4 = h[(() -> Cap) @retains(x)](() => x)(() => C()) // what was inferred for z3 + val z3 = h[(() -> Cap) @retains(x)](() => x)(() => C()) // error diff --git a/tests/neg-custom-args/captures/cc-glb.scala b/tests/neg-custom-args/captures/cc-glb.scala index c22f1a36a300..ec54611915b4 100644 --- a/tests/neg-custom-args/captures/cc-glb.scala +++ b/tests/neg-custom-args/captures/cc-glb.scala @@ -3,6 +3,6 @@ trait Cap trait Foo[+T] def magic[T](io: Cap^, x: Foo[T]^{io}): Foo[T]^{} = - val x1: Foo[T]^{cap} & Foo[Any]^{io} = x + val x1: (Foo[T]^) & Foo[Any]^{io} = x val x2: Foo[T] = x1 // error x2 // boom, an impure value becomes pure diff --git a/tests/neg-custom-args/captures/filevar.scala b/tests/neg-custom-args/captures/filevar.scala index 34588617c0b8..59b8415d6e0f 100644 --- a/tests/neg-custom-args/captures/filevar.scala +++ b/tests/neg-custom-args/captures/filevar.scala @@ -5,7 +5,7 @@ class File: def write(x: String): Unit = ??? class Service: - var file: File^{cap[Service]} = uninitialized // error + var file: File^ = uninitialized // error def log = file.write("log") def withFile[T](op: (l: caps.Cap) ?-> (f: File^{l}) => T): T = @@ -14,5 +14,5 @@ def withFile[T](op: (l: caps.Cap) ?-> (f: File^{l}) => T): T = def test = withFile: f => val o = Service() - o.file = f // error + o.file = f o.log diff --git a/tests/neg-custom-args/captures/heal-tparam-cs.scala b/tests/neg-custom-args/captures/heal-tparam-cs.scala index 8987614eec38..498292166297 100644 --- a/tests/neg-custom-args/captures/heal-tparam-cs.scala +++ b/tests/neg-custom-args/captures/heal-tparam-cs.scala @@ -2,17 +2,17 @@ import language.experimental.captureChecking trait Capp { def use(): Unit } -def localCap[sealed T](op: (c: Capp^{cap}) => T): T = ??? +def localCap[T](op: (c: Capp^) => T): T = ??? -def main(io: Capp^{cap}, net: Capp^{cap}): Unit = { +def main(io: Capp^, net: Capp^): Unit = { val test1 = localCap { c => // error () => { c.use() } } - val test2: (c: Capp^{cap}) -> () ->{cap} Unit = + val test2: (c: Capp^) -> () => Unit = localCap { c => // should work - (c1: Capp^{cap}) => () => { c1.use() } + (c1: Capp^) => () => { c1.use() } } val test3: (c: Capp^{io}) -> () ->{io} Unit = @@ -25,7 +25,7 @@ def main(io: Capp^{cap}, net: Capp^{cap}): Unit = { (c1: Capp^{io}) => () => { c1.use() } } - def localCap2[sealed T](op: (c: Capp^{io}) => T): T = ??? + def localCap2[T](op: (c: Capp^{io}) => T): T = ??? val test5: () ->{io} Unit = localCap2 { c => // ok diff --git a/tests/neg-custom-args/captures/i15049.scala b/tests/neg-custom-args/captures/i15049.scala index b5a696729d18..ff6b17c360de 100644 --- a/tests/neg-custom-args/captures/i15049.scala +++ b/tests/neg-custom-args/captures/i15049.scala @@ -1,8 +1,8 @@ class Session: def request = "Response" class Foo: - private val session: Session^{cap} = new Session - def withSession[sealed T](f: Session^ => T): T = f(session) + private val session: Session^ = new Session + def withSession[T](f: Session^ => T): T = f(session) def Test: Unit = val f = new Foo diff --git a/tests/pos-custom-args/captures/i15749a.scala b/tests/neg-custom-args/captures/i15749a.scala similarity index 54% rename from tests/pos-custom-args/captures/i15749a.scala rename to tests/neg-custom-args/captures/i15749a.scala index fe5f4d75dae1..0158928f4e39 100644 --- a/tests/pos-custom-args/captures/i15749a.scala +++ b/tests/neg-custom-args/captures/i15749a.scala @@ -1,21 +1,22 @@ +import caps.cap class Unit object u extends Unit type Top = Any^ -type Wrapper[T] = [X] -> (op: T ->{cap} X) -> X +type Wrapper[+T] = [X] -> (op: T ->{cap} X) -> X def test = def wrapper[T](x: T): Wrapper[T] = [X] => (op: T ->{cap} X) => op(x) - def strictMap[A <: Top, sealed B <: Top](mx: Wrapper[A])(f: A ->{cap} B): Wrapper[B] = + def strictMap[A <: Top, B <: Top](mx: Wrapper[A])(f: A ->{cap} B): Wrapper[B] = mx((x: A) => wrapper(f(x))) def force[A](thunk: Unit ->{cap} A): A = thunk(u) - def forceWrapper[sealed A](mx: Wrapper[Unit ->{cap} A]): Wrapper[A] = + def forceWrapper[A](mx: Wrapper[Unit ->{cap} A]): Wrapper[A] = // Γ ⊢ mx: Wrapper[□ {cap} Unit => A] // `force` should be typed as ∀(□ {cap} Unit -> A) A, but it can not - strictMap[Unit ->{cap} A, A](mx)(t => force[A](t)) // error + strictMap[Unit ->{mx*} A, A](mx)(t => force[A](t)) // error // should work diff --git a/tests/neg-custom-args/captures/i15772.check b/tests/neg-custom-args/captures/i15772.check index 39f3fff911c6..cce58da1b93b 100644 --- a/tests/neg-custom-args/captures/i15772.check +++ b/tests/neg-custom-args/captures/i15772.check @@ -22,11 +22,14 @@ | Required: (C^ => Unit) -> Unit | | longer explanation available when compiling with `-explain` --- [E007] Type Mismatch Error: tests/neg-custom-args/captures/i15772.scala:33:33 --------------------------------------- +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/i15772.scala:33:34 --------------------------------------- 33 | val boxed2 : Observe[C]^ = box2(c) // error - | ^^^^^^^ - | Found: (C{val arg: C^}^ => Unit) ->? Unit - | Required: Observe[C]^ + | ^ + | Found: box C^ + | Required: box C{val arg: C^?}^? + | + | Note that the universal capability `cap` + | cannot be included in capture set ? | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/i15772.scala:44:2 ---------------------------------------- diff --git a/tests/pos-custom-args/captures/i15922.scala b/tests/neg-custom-args/captures/i15922.scala similarity index 73% rename from tests/pos-custom-args/captures/i15922.scala rename to tests/neg-custom-args/captures/i15922.scala index 23109a3ba8f4..974870cd769c 100644 --- a/tests/pos-custom-args/captures/i15922.scala +++ b/tests/neg-custom-args/captures/i15922.scala @@ -11,4 +11,6 @@ def withCap[X](op: (Cap^) => X): X = { def leaking(c: Cap^): Id[Cap^{c}] = mkId(c) def test = - val bad = withCap(leaking) + val ll = (c: Cap^) => leaking(c) + val bad1 = withCap(ll) // error + val bad2 = withCap(leaking) // error diff --git a/tests/neg-custom-args/captures/i16114.scala b/tests/neg-custom-args/captures/i16114.scala index ce7a1b3dbc2f..d363bb665dc3 100644 --- a/tests/neg-custom-args/captures/i16114.scala +++ b/tests/neg-custom-args/captures/i16114.scala @@ -11,21 +11,21 @@ def withCap[T](op: Cap^ => T): T = { } def main(fs: Cap^): Unit = { - def badOp(io: Cap^{cap}): Unit ->{} Unit = { + def badOp(io: Cap^): Unit ->{} Unit = { val op1: Unit ->{io} Unit = (x: Unit) => - expect[Cap^] { + expect[Cap^] { // error io.use() fs // error (limitation) } val op2: Unit ->{fs} Unit = (x: Unit) => - expect[Cap^] { + expect[Cap^] { // error fs.use() io // error (limitation) } - val op3: Unit ->{io} Unit = (x: Unit) => // ok - expect[Cap^] { + val op3: Unit ->{io} Unit = (x: Unit) => + expect[Cap^] { // error io.use() io } @@ -34,7 +34,7 @@ def main(fs: Cap^): Unit = { expect[Cap^](io) // error val op: Unit -> Unit = (x: Unit) => - expect[Cap^] { + expect[Cap^] { // error io.use() // error io // error } diff --git a/tests/neg-custom-args/captures/lazylists1.scala b/tests/neg-custom-args/captures/lazylists1.scala index 99472c13ebec..dfa556e38144 100644 --- a/tests/neg-custom-args/captures/lazylists1.scala +++ b/tests/neg-custom-args/captures/lazylists1.scala @@ -1,8 +1,8 @@ class CC -type Cap = CC^{cap} +type Cap = CC^ trait LazyList[+A]: - this: LazyList[A]^{cap} => + this: LazyList[A]^ => def isEmpty: Boolean def head: A @@ -13,7 +13,7 @@ object LazyNil extends LazyList[Nothing]: def head = ??? def tail = ??? -extension [A](xs: LazyList[A]^{cap}) +extension [A](xs: LazyList[A]^) def map[B](f: A => B): LazyList[B]^{xs, f} = final class Mapped extends LazyList[B]: this: (Mapped^{xs, f}) => diff --git a/tests/neg-custom-args/captures/lazyref.check b/tests/neg-custom-args/captures/lazyref.check index 8c91ec13b5d8..8683615c07d8 100644 --- a/tests/neg-custom-args/captures/lazyref.check +++ b/tests/neg-custom-args/captures/lazyref.check @@ -8,21 +8,21 @@ -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazyref.scala:21:35 -------------------------------------- 21 | val ref2c: LazyRef[Int]^{cap2} = ref2 // error | ^^^^ - | Found: (ref2 : LazyRef[Int]{val elem: () => Int}^{cap2, ref1}) + | Found: LazyRef[Int]{val elem: () ->{ref2*} Int}^{ref2} | Required: LazyRef[Int]^{cap2} | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazyref.scala:23:35 -------------------------------------- 23 | val ref3c: LazyRef[Int]^{ref1} = ref3 // error | ^^^^ - | Found: (ref3 : LazyRef[Int]{val elem: () => Int}^{cap2, ref1}) + | Found: LazyRef[Int]{val elem: () ->{ref3*} Int}^{ref3} | Required: LazyRef[Int]^{ref1} | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazyref.scala:25:35 -------------------------------------- 25 | val ref4c: LazyRef[Int]^{cap1} = ref4 // error | ^^^^ - | Found: (ref4 : LazyRef[Int]{val elem: () => Int}^{cap2, cap1}) + | Found: LazyRef[Int]{val elem: () ->{ref4*} Int}^{ref4} | Required: LazyRef[Int]^{cap1} | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/leaked-curried.scala b/tests/neg-custom-args/captures/leaked-curried.scala index f9238259e065..d765955ee6ce 100644 --- a/tests/neg-custom-args/captures/leaked-curried.scala +++ b/tests/neg-custom-args/captures/leaked-curried.scala @@ -4,7 +4,7 @@ trait Cap: def withCap[T](op: (x: Cap^) => T): T = ??? trait Box: - val get: () ->{} () ->{cap} Cap^ + val get: () ->{} () => Cap^ def main(): Unit = val leaked = withCap: (io: Cap^) => diff --git a/tests/neg-custom-args/captures/leaking-iterators.scala b/tests/neg-custom-args/captures/leaking-iterators.scala index 99d50a27336b..ad5958e91e5b 100644 --- a/tests/neg-custom-args/captures/leaking-iterators.scala +++ b/tests/neg-custom-args/captures/leaking-iterators.scala @@ -39,7 +39,7 @@ end Iterator private final class ConcatIteratorCell[A](head: => IterableOnce[A]^): def headIterator: Iterator[A]^{this} = head.iterator -def usingLogFile[sealed R](op: FileOutputStream^ => R): R = +def usingLogFile[R](op: FileOutputStream^ => R): R = val logFile = FileOutputStream("log") val result = op(logFile) logFile.close() diff --git a/tests/neg-custom-args/captures/levels.check b/tests/neg-custom-args/captures/levels.check index c0cc7f0a759c..a5f8d73ccf7a 100644 --- a/tests/neg-custom-args/captures/levels.check +++ b/tests/neg-custom-args/captures/levels.check @@ -1,8 +1,3 @@ --- Error: tests/neg-custom-args/captures/levels.scala:6:16 ------------------------------------------------------------- -6 | private var v: T = init // error - | ^ - | Mutable variable v cannot have type T since - | that type variable is not sealed. -- Error: tests/neg-custom-args/captures/levels.scala:17:13 ------------------------------------------------------------ 17 | val _ = Ref[String => String]((x: String) => x) // error | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/neg-custom-args/captures/levels.scala b/tests/neg-custom-args/captures/levels.scala index f8bd6e77c449..b28e87f03ef7 100644 --- a/tests/neg-custom-args/captures/levels.scala +++ b/tests/neg-custom-args/captures/levels.scala @@ -3,13 +3,13 @@ class CC def test1(cap1: CC^) = class Ref[T](init: T): - private var v: T = init // error + private var v: T = init def setV(x: T): Unit = v = x def getV: T = v def test2(cap1: CC^) = - class Ref[sealed T](init: T): + class Ref[T](init: T): private var v: T = init def setV(x: T): Unit = v = x def getV: T = v diff --git a/tests/neg-custom-args/captures/localcaps.check b/tests/neg-custom-args/captures/localcaps.check deleted file mode 100644 index b09702749d10..000000000000 --- a/tests/neg-custom-args/captures/localcaps.check +++ /dev/null @@ -1,12 +0,0 @@ --- Error: tests/neg-custom-args/captures/localcaps.scala:4:12 ---------------------------------------------------------- -4 | def x: C^{cap[d]} = ??? // error - | ^^^^^^ - | `d` does not name an outer definition that represents a capture level --- Error: tests/neg-custom-args/captures/localcaps.scala:9:47 ---------------------------------------------------------- -9 | private val z2 = identity((x: Int) => (c: C^{cap[z2]}) => x) // error - | ^^^^^^^ - | `z2` does not name an outer definition that represents a capture level --- Error: tests/neg-custom-args/captures/localcaps.scala:6:6 ----------------------------------------------------------- -6 | def y: C^{cap[C]} = ??? // error - | ^ - | local root (cap[C] : caps.Cap) cannot appear in type of class C diff --git a/tests/neg-custom-args/captures/localcaps.scala b/tests/neg-custom-args/captures/localcaps.scala deleted file mode 100644 index 049a1ee0d775..000000000000 --- a/tests/neg-custom-args/captures/localcaps.scala +++ /dev/null @@ -1,9 +0,0 @@ -class C: - this: C^ => - - def x: C^{cap[d]} = ??? // error - - def y: C^{cap[C]} = ??? // error - private val z = (c0: caps.Cap) => (x: Int) => (c: C^{cap[C]}) => x // ok - - private val z2 = identity((x: Int) => (c: C^{cap[z2]}) => x) // error diff --git a/tests/neg-custom-args/captures/nesting-inversion.scala b/tests/neg-custom-args/captures/nesting-inversion.scala deleted file mode 100644 index 0460f1243cca..000000000000 --- a/tests/neg-custom-args/captures/nesting-inversion.scala +++ /dev/null @@ -1,43 +0,0 @@ -def f(x: (() => Unit)): (() => Unit) => (() => Unit) = - def g(y: (() => Unit)): (() => Unit) = x - g - -def test1(x: (() => Unit)): Unit = - def test2(y: (() => Unit)) = - val a: (() => Unit) => (() => Unit) = f(y) - a(x) // OK, but should be error - test2(() => ()) - -def test2(x1: (() => Unit), x2: (() => Unit) => Unit) = - class C1(x1: (() => Unit), xx2: (() => Unit) => Unit): - def c2(y1: (() => Unit), y2: (() => Unit) => Unit): C2^{cap} = C2(y1, y2) - class C2(y1: (() => Unit), y2: (() => Unit) => Unit): - val a: (() => Unit) => (() => Unit) = f(y1) - a(x1) //OK, but should be error - C2(() => (), x => ()) - - def test3(y1: (() => Unit), y2: (() => Unit) => Unit) = - val cc1 = C1(y1, y2) - val cc2 = cc1.c2(x1, x2) - val cc3: cc1.C2^{cap[test2]} = cc2 // error - -def test4(x1: () => Unit) = - class C1: - this: C1^ => - class C2(z: () => Unit): - this: C2^ => - val foo: () => Unit = ??? - - def test5(x2: () => Unit) = - val xx1: C1^{cap[test5]} = C1() - val y1 = - val xx2 = xx1.C2(x1) - val xx3: xx1.C2^{cap[test4]} = xx2 // ok, but dubious - // actual capture set is in test4 - // but level constraints would determine that the root should be in test5 - // only, there is no root in the set to be mapped - xx2 - val f1 = y1.foo - val xx4 = xx1.C2(x2) - val xx5: xx1.C2^{cap[test4]} = xx4 // error - diff --git a/tests/neg-custom-args/captures/outer-var.check b/tests/neg-custom-args/captures/outer-var.check index b7a438f30092..c250280961d9 100644 --- a/tests/neg-custom-args/captures/outer-var.check +++ b/tests/neg-custom-args/captures/outer-var.check @@ -2,24 +2,27 @@ 11 | x = q // error | ^ | Found: () ->{q} Unit - | Required: () ->{cap[test]} Unit + | Required: () ->{p, q²} Unit + | + | where: q is a parameter in method inner + | q² is a parameter in method test | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/outer-var.scala:12:9 ------------------------------------- 12 | x = (q: Proc) // error | ^^^^^^^ - | Found: () ->{cap[inner]} Unit - | Required: () ->{cap[test]} Unit + | Found: Proc + | Required: () ->{p, q} Unit | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/outer-var.scala:13:9 ------------------------------------- 13 | y = (q: Proc) // error | ^^^^^^^ - | Found: () ->{cap[inner]} Unit + | Found: Proc | Required: () ->{p} Unit | - | Note that reference (cap[inner] : caps.Cap), defined in method inner - | cannot be included in outer capture set {p} of variable y which is associated with method test + | Note that the universal capability `cap` + | cannot be included in capture set {p} of variable y | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/outer-var.scala:14:8 ------------------------------------- @@ -32,13 +35,10 @@ | cannot be included in outer capture set {p} of variable y which is associated with method test | | longer explanation available when compiling with `-explain` --- [E007] Type Mismatch Error: tests/neg-custom-args/captures/outer-var.scala:16:65 ------------------------------------ +-- Error: tests/neg-custom-args/captures/outer-var.scala:16:53 --------------------------------------------------------- 16 | var finalizeActions = collection.mutable.ListBuffer[() => Unit]() // error - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | Found: scala.collection.mutable.ListBuffer[box () => Unit] - | Required: scala.collection.mutable.ListBuffer[box () ->? Unit]^? - | - | Note that the universal capability `cap` - | cannot be included in capture set ? of variable finalizeActions - | - | longer explanation available when compiling with `-explain` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Sealed type variable A cannot be instantiated to box () => Unit since + | that type captures the root capability `cap`. + | This is often caused by a local capability in an argument of method apply + | leaking as part of its result. diff --git a/tests/neg-custom-args/captures/outer-var.scala b/tests/neg-custom-args/captures/outer-var.scala index c59efefb51c4..39c3a6da4ca3 100644 --- a/tests/neg-custom-args/captures/outer-var.scala +++ b/tests/neg-custom-args/captures/outer-var.scala @@ -4,7 +4,7 @@ type Cap = CC^ type Proc = () => Unit def test(p: Proc, q: () => Unit) = - var x: () ->{cap[test]} Unit = p + var x: () ->{p, q} Unit = p var y = p // OK, y has type () ->{p} Proc def inner(q: Proc) = diff --git a/tests/neg-custom-args/captures/override-adapt-box-selftype.scala b/tests/neg-custom-args/captures/override-adapt-box-selftype.scala index f44add78e246..bf7e88d84213 100644 --- a/tests/neg-custom-args/captures/override-adapt-box-selftype.scala +++ b/tests/neg-custom-args/captures/override-adapt-box-selftype.scala @@ -15,7 +15,7 @@ object Test1 { } } -def Test2(io: IO^{cap}, fs: IO^{io}, ct: IO^) = { +def Test2(io: IO^, fs: IO^{io}, ct: IO^) = { abstract class A[X] { this: A[X]^{io} => def foo(x: X): X } diff --git a/tests/neg-custom-args/captures/override-adapt-box.scala b/tests/neg-custom-args/captures/override-adapt-box.scala index 70023dfbc941..9592c30a5025 100644 --- a/tests/neg-custom-args/captures/override-adapt-box.scala +++ b/tests/neg-custom-args/captures/override-adapt-box.scala @@ -7,7 +7,7 @@ abstract class A[X] { this: A[X]^{} => class IO class C -def test(io: IO^{cap}) = { +def test(io: IO^) = { class B extends A[C^{io}] { // X =:= {io} C // error override def foo(x: C^{io}): C^{io} = ??? } diff --git a/tests/neg-custom-args/captures/override-boxed.scala b/tests/neg-custom-args/captures/override-boxed.scala index d66d28d15aaa..cf1c49cef5a6 100644 --- a/tests/neg-custom-args/captures/override-boxed.scala +++ b/tests/neg-custom-args/captures/override-boxed.scala @@ -1,7 +1,7 @@ class A -def test(x: Any^{cap}) = +def test(x: Any^) = abstract class Getter: def get(): A^{x} class PolyGetter[T <: A^{x}] extends Getter: diff --git a/tests/neg-custom-args/captures/pairs.check b/tests/neg-custom-args/captures/pairs.check deleted file mode 100644 index 9d1b3a76e164..000000000000 --- a/tests/neg-custom-args/captures/pairs.check +++ /dev/null @@ -1,22 +0,0 @@ --- [E007] Type Mismatch Error: tests/neg-custom-args/captures/pairs.scala:14:30 ---------------------------------------- -14 | val x1c: Cap ->{c} Unit = x1 // error - | ^^ - | Found: (x$0: Cap^?) ->{x1} Unit - | Required: Cap^ ->{c} Unit - | - | longer explanation available when compiling with `-explain` --- [E007] Type Mismatch Error: tests/neg-custom-args/captures/pairs.scala:16:30 ---------------------------------------- -16 | val y1c: Cap ->{d} Unit = y1 // error - | ^^ - | Found: (x$0: Cap^?) ->{y1} Unit - | Required: Cap^ ->{d} Unit - | - | longer explanation available when compiling with `-explain` --- Error: tests/neg-custom-args/captures/pairs.scala:6:8 --------------------------------------------------------------- -6 | def fst: Cap^{cap[Pair]} ->{x} Unit = x // error - | ^ - | local root (cap[Pair] : caps.Cap) cannot appear in type of class Pair --- Error: tests/neg-custom-args/captures/pairs.scala:7:8 --------------------------------------------------------------- -7 | def snd: Cap^{cap[Pair]} ->{y} Unit = y // error - | ^ - | local root (cap[Pair] : caps.Cap) cannot appear in type of class Pair diff --git a/tests/neg-custom-args/captures/pairs.scala b/tests/neg-custom-args/captures/pairs.scala deleted file mode 100644 index 99b27639f729..000000000000 --- a/tests/neg-custom-args/captures/pairs.scala +++ /dev/null @@ -1,17 +0,0 @@ -@annotation.capability class Cap - -object Monomorphic2: - - class Pair(x: Cap => Unit, y: Cap => Unit): - def fst: Cap^{cap[Pair]} ->{x} Unit = x // error - def snd: Cap^{cap[Pair]} ->{y} Unit = y // error - - def test(c: Cap, d: Cap) = - def f(x: Cap): Unit = if c == x then () - def g(x: Cap): Unit = if d == x then () - val p = Pair(f, g) - val x1 = p.fst - val x1c: Cap ->{c} Unit = x1 // error - val y1 = p.snd - val y1c: Cap ->{d} Unit = y1 // error - diff --git a/tests/neg-custom-args/captures/reaches.check b/tests/neg-custom-args/captures/reaches.check new file mode 100644 index 000000000000..ee628a212ce7 --- /dev/null +++ b/tests/neg-custom-args/captures/reaches.check @@ -0,0 +1,43 @@ +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/reaches.scala:21:11 -------------------------------------- +21 | cur = (() => f.write()) :: Nil // error since {f*} !<: {xs*} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | Found: List[box () ->{f} Unit] + | Required: List[box () ->{xs*} Unit] + | + | longer explanation available when compiling with `-explain` +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/reaches.scala:32:7 --------------------------------------- +32 | (() => f.write()) :: Nil // error since {f*} !<: {xs*} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | Found: List[box () ->{f} Unit] + | Required: box List[box () ->{xs*} Unit]^? + | + | Note that reference (f : File^), defined in method $anonfun + | cannot be included in outer capture set {xs*} of value cur which is associated with method runAll1 + | + | longer explanation available when compiling with `-explain` +-- Error: tests/neg-custom-args/captures/reaches.scala:35:6 ------------------------------------------------------------ +35 | var cur: List[Proc] = xs // error: Illegal type for var + | ^ + | Mutable variable cur cannot have type List[box () => Unit] since + | the part box () => Unit of that type captures the root capability `cap`. +-- Error: tests/neg-custom-args/captures/reaches.scala:42:15 ----------------------------------------------------------- +42 | val cur = Ref[List[Proc]](xs) // error: illegal type for type argument to Ref + | ^^^^^^^^^^^^^^^ + | Sealed type variable T cannot be instantiated to List[box () => Unit] since + | the part box () => Unit of that type captures the root capability `cap`. + | This is often caused by a local capability in an argument of constructor Ref + | leaking as part of its result. +-- Error: tests/neg-custom-args/captures/reaches.scala:52:31 ----------------------------------------------------------- +52 | val id: Id[Proc, Proc] = new Id[Proc, () -> Unit] // error + | ^^^^^^^^^^^^^^^^^^^^ + | Sealed type variable A cannot be instantiated to box () => Unit since + | that type captures the root capability `cap`. + | This is often caused by a local capability in an argument of constructor Id + | leaking as part of its result. +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/reaches.scala:60:27 -------------------------------------- +60 | val f1: File^{id*} = id(f) // error + | ^^^^^ + | Found: File^{id, f} + | Required: File^{id*} + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/reaches.scala b/tests/neg-custom-args/captures/reaches.scala new file mode 100644 index 000000000000..8ba7f60d6335 --- /dev/null +++ b/tests/neg-custom-args/captures/reaches.scala @@ -0,0 +1,61 @@ +class File: + def write(): Unit = ??? + +def usingFile[T](f: File^ => T): T = ??? + +type Proc = () => Unit + +class Ref[T](init: T): + private var x: T = init + def get: T = x + def set(y: T) = { x = y } + +def runAll0(xs: List[Proc]): Unit = + var cur: List[() ->{xs*} Unit] = xs // OK, by revised VAR + while cur.nonEmpty do + val next: () ->{xs*} Unit = cur.head + next() + cur = cur.tail: List[() ->{xs*} Unit] + + usingFile: f => + cur = (() => f.write()) :: Nil // error since {f*} !<: {xs*} + +def runAll1(xs: List[Proc]): Unit = + val cur = Ref[List[() ->{xs*} Unit]](xs) // OK, by revised VAR + while cur.get.nonEmpty do + val next: () ->{xs*} Unit = cur.get.head + next() + cur.set(cur.get.tail: List[() ->{xs*} Unit]) + + usingFile: f => + cur.set: + (() => f.write()) :: Nil // error since {f*} !<: {xs*} + +def runAll2(xs: List[Proc]): Unit = + var cur: List[Proc] = xs // error: Illegal type for var + while cur.nonEmpty do + val next: () => Unit = cur.head + next() + cur = cur.tail + +def runAll3(xs: List[Proc]): Unit = + val cur = Ref[List[Proc]](xs) // error: illegal type for type argument to Ref + while cur.get.nonEmpty do + val next: () => Unit = cur.get.head + next() + cur.set(cur.get.tail: List[Proc]) + +class Id[-A, +B >: A](): + def apply(a: A): B = a + +def test = + val id: Id[Proc, Proc] = new Id[Proc, () -> Unit] // error + usingFile: f => + id(() => f.write()) // escape, if it was not for the error above + +def attack2 = + val id: File^ -> File^ = x => x + + val leaked = usingFile[File^{id*}]: f => + val f1: File^{id*} = id(f) // error + f1 diff --git a/tests/neg-custom-args/captures/recursive-leaking-local-cap.scala b/tests/neg-custom-args/captures/recursive-leaking-local-cap.scala index 0daecafbf9d0..5cf3f8b29c2b 100644 --- a/tests/neg-custom-args/captures/recursive-leaking-local-cap.scala +++ b/tests/neg-custom-args/captures/recursive-leaking-local-cap.scala @@ -2,21 +2,18 @@ import language.experimental.captureChecking trait Cap: def use: Int = 42 -def usingCap[sealed T](op: Cap^ => T): T = ??? +def usingCap[T](op: Cap^ => T): T = ??? def badTest(): Unit = - def bad(b: Boolean)(c: Cap^): Cap^{cap[bad]} = // error + def bad(b: Boolean)(c: Cap^): Cap^{c} = if b then c else - val leaked = usingCap[Cap^{cap[bad]}](bad(true)) + val leaked = usingCap(bad(true)) // error leaked.use // boom c usingCap[Unit]: c0 => bad(false)(c0) -class Bad: - def foo: Cap^{cap[Bad]} = ??? // error - private def bar: Cap^{cap[Bad]} = ??? // ok diff --git a/tests/neg-custom-args/captures/sealed-classes.scala b/tests/neg-custom-args/captures/sealed-classes.scala deleted file mode 100644 index b8cb0acbf5c5..000000000000 --- a/tests/neg-custom-args/captures/sealed-classes.scala +++ /dev/null @@ -1,21 +0,0 @@ -abstract class C1[A1]: - def set(x: A1): Unit - def get: A1 - -trait Co[+A]: - def get: A - -class C2[sealed A2] extends C1[A2], Co[A2]: // ok - private var x: A2 = ??? - def set(x: A2): Unit = - this.x = x - def get: A2 = x - -class C3[A3] extends C2[A3] // error - -abstract class C4[sealed A4] extends Co[A4] // ok - -abstract class C5[sealed +A5] extends Co[A5] // ok - -abstract class C6[A6] extends C5[A6] // error - diff --git a/tests/neg-custom-args/captures/sealed-leaks.check b/tests/neg-custom-args/captures/sealed-leaks.check deleted file mode 100644 index f7098eba32b6..000000000000 --- a/tests/neg-custom-args/captures/sealed-leaks.check +++ /dev/null @@ -1,50 +0,0 @@ --- [E129] Potential Issue Warning: tests/neg-custom-args/captures/sealed-leaks.scala:31:6 ------------------------------ -31 | () - | ^^ - | A pure expression does nothing in statement position - | - | longer explanation available when compiling with `-explain` --- Error: tests/neg-custom-args/captures/sealed-leaks.scala:12:27 ------------------------------------------------------ -12 | val later2 = usingLogFile[(() => Unit) | Null] { f => () => f.write(0) } // error - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | Sealed type variable T cannot be instantiated to (() => Unit) | Null since - | that type captures the root capability `cap`. - | This is often caused by a local capability in an argument of method usingLogFile - | leaking as part of its result. --- [E007] Type Mismatch Error: tests/neg-custom-args/captures/sealed-leaks.scala:19:26 --------------------------------- -19 | usingLogFile { f => x = f } // error - | ^ - | Found: (f : java.io.FileOutputStream^) - | Required: (java.io.FileOutputStream | Null)^{cap[Test2]} - | - | longer explanation available when compiling with `-explain` --- Error: tests/neg-custom-args/captures/sealed-leaks.scala:30:10 ------------------------------------------------------ -30 | var x: T = y // error - | ^ - | Mutable variable x cannot have type T since - | that type variable is not sealed. --- Error: tests/neg-custom-args/captures/sealed-leaks.scala:39:8 ------------------------------------------------------- -39 | var x: T = y // error - | ^ - | Mutable variable x cannot have type T since - | that type variable is not sealed. - | - | Note that variable x does not count as local since it is captured by an anonymous function --- Error: tests/neg-custom-args/captures/sealed-leaks.scala:43:8 ------------------------------------------------------- -43 | var x: T = y // error - | ^ - |Mutable variable x cannot have type T since - |that type variable is not sealed. - | - |Note that variable x does not count as local since it is captured by an anonymous function argument in a call to method identity --- Error: tests/neg-custom-args/captures/sealed-leaks.scala:47:8 ------------------------------------------------------- -47 | var x: T = y // error - | ^ - | Mutable variable x cannot have type T since - | that type variable is not sealed. - | - | Note that variable x does not count as local since it is captured by method foo --- Error: tests/neg-custom-args/captures/sealed-leaks.scala:11:14 ------------------------------------------------------ -11 | val later = usingLogFile { f => () => f.write(0) } // error - | ^^^^^^^^^^^^ - | local reference f leaks into outer capture set of type parameter T of method usingLogFile diff --git a/tests/neg-custom-args/captures/sealed-leaks.scala b/tests/neg-custom-args/captures/sealed-leaks.scala deleted file mode 100644 index 2555ba8a3e07..000000000000 --- a/tests/neg-custom-args/captures/sealed-leaks.scala +++ /dev/null @@ -1,51 +0,0 @@ - -import java.io.* -def Test2 = - - def usingLogFile[sealed T](op: FileOutputStream^ => T): T = - val logFile = FileOutputStream("log") - val result = op(logFile) - logFile.close() - result - - val later = usingLogFile { f => () => f.write(0) } // error - val later2 = usingLogFile[(() => Unit) | Null] { f => () => f.write(0) } // error - - var x: (FileOutputStream^{cap[Test2]}) | Null = null - def foo(f: FileOutputStream^, g: FileOutputStream^) = - var y = if ??? then f else g // ok - val yc: FileOutputStream^{f,g} = y - - usingLogFile { f => x = f } // error - - later() - -def Test3 = - def f[T](y: T) = - var x: T = y - () - - class C[T](y: T): - object o: - var x: T = y // error - () - - class C2[T](y: T): - def f = - var x: T = y // ok - () - - def g1[T](y: T): T => Unit = - var x: T = y // error - y => x = y - - def g2[T](y: T): T => Unit = - var x: T = y // error - identity(y => x = y) - - def g3[T](y: T): Unit = - var x: T = y // error - def foo = - x = y - () - diff --git a/tests/neg-custom-args/captures/sealed-refs.scala b/tests/neg-custom-args/captures/sealed-refs.scala deleted file mode 100644 index 05fa483acf28..000000000000 --- a/tests/neg-custom-args/captures/sealed-refs.scala +++ /dev/null @@ -1,42 +0,0 @@ -class Ref[sealed A](init: A): - this: Ref[A]^ => - private var x: A = init - def get: A = x - def set(x: A): Unit = this.x = x - -class It[X]: - this: It[X]^ => - -def f1[B1](x: B1, next: B1 -> B1) = - var r = x // ok - r = next(x) - r - -def f2[B2](x: B2, next: B2 -> B2) = - val r = Ref[B2](x) // error - r.set(next(x)) - r.get - -def g[sealed B](x: B, next: B -> B) = - val r = Ref[B](x) // ok - r.set(next(x)) - r.get - -import annotation.unchecked.uncheckedCaptures - -def h[B](x: B, next: B -> B) = - val r = Ref[B @uncheckedCaptures](x) // ok - r.set(next(x)) - r.get - -def f3[B](x: B, next: B -> B) = - val r: Ref[B^{cap[f3]}] = Ref[B^{cap[f3]}](x) // error - r.set(next(x)) - val y = r.get - () - -def f4[B](x: B, next: B -> B) = - val r: Ref[B]^{cap[f4]} = Ref[B](x) // error - r.set(next(x)) - val y = r.get - () \ No newline at end of file diff --git a/tests/neg-custom-args/captures/simple-escapes.check b/tests/neg-custom-args/captures/simple-escapes.check deleted file mode 100644 index a3b096bbf3c0..000000000000 --- a/tests/neg-custom-args/captures/simple-escapes.check +++ /dev/null @@ -1,11 +0,0 @@ --- [E007] Type Mismatch Error: tests/neg-custom-args/captures/simple-escapes.scala:16:10 ------------------------------- -16 | foo = f // error - | ^ - | Found: (f : FileOutputStream^{local}) - | Required: FileOutputStream^{cap[Test1]} - | - | longer explanation available when compiling with `-explain` --- Error: tests/neg-custom-args/captures/simple-escapes.scala:19:15 ---------------------------------------------------- -19 | val later2 = usingLogFile { local => f => // error - | ^^^^^^^^^^^^ - | escaping local reference local.type diff --git a/tests/neg-custom-args/captures/simple-escapes.scala b/tests/neg-custom-args/captures/simple-escapes.scala deleted file mode 100644 index 14f38fef0795..000000000000 --- a/tests/neg-custom-args/captures/simple-escapes.scala +++ /dev/null @@ -1,24 +0,0 @@ -class FileOutputStream(str: String): - def close(): Unit = () - def write(x: Int): Unit = () - -def Test1 = - - def usingLogFile[T](op: (local: caps.Cap) -> FileOutputStream^{local} => T): T = - val logFile = FileOutputStream("log") - val result = op(caps.cap)(logFile) - logFile.close() - result - - var foo: FileOutputStream^{cap[Test1]} = FileOutputStream("") - - val later1 = usingLogFile { local => f => - foo = f // error - () => () - } - val later2 = usingLogFile { local => f => // error - () => f.write(0) - } - later1() - later2() - diff --git a/tests/neg-custom-args/captures/simple-using.scala b/tests/neg-custom-args/captures/simple-using.scala index 9dcd9dc34c8e..16350eecc8c5 100644 --- a/tests/neg-custom-args/captures/simple-using.scala +++ b/tests/neg-custom-args/captures/simple-using.scala @@ -1,5 +1,5 @@ import java.io.* -def usingLogFile[sealed T](op: FileOutputStream^ => T): T = +def usingLogFile[T](op: FileOutputStream^ => T): T = val logFile = FileOutputStream("log") val result = op(logFile) logFile.close() diff --git a/tests/neg-custom-args/captures/singletons.scala b/tests/neg-custom-args/captures/singletons.scala index 733c771e8b2c..194e6e850dcd 100644 --- a/tests/neg-custom-args/captures/singletons.scala +++ b/tests/neg-custom-args/captures/singletons.scala @@ -3,4 +3,4 @@ val x = () => () val y1: x.type = x // ok val y2: x.type^{} = x // error: singleton type cannot have capture set val y3: x.type^{x} = x // error: singleton type cannot have capture set // error -val y4: x.type^{cap} = x // error: singleton type cannot have capture set +val y4: x.type^ = x // error: singleton type cannot have capture set diff --git a/tests/neg-custom-args/captures/try.scala b/tests/neg-custom-args/captures/try.scala index 0d593b67f77b..3d25dff4cd2c 100644 --- a/tests/neg-custom-args/captures/try.scala +++ b/tests/neg-custom-args/captures/try.scala @@ -14,7 +14,7 @@ def raise[E <: Exception](e: E): Nothing throws E = throw e def foo(x: Boolean): Int throws Fail = if x then 1 else raise(Fail()) -def handle[E <: Exception, sealed R <: Top](op: CT[E]^ => R)(handler: E => R): R = +def handle[E <: Exception, R <: Top](op: CT[E]^ => R)(handler: E => R): R = val x: CT[E] = ??? try op(x) catch case ex: E => handler(ex) diff --git a/tests/neg-custom-args/captures/usingFile.scala b/tests/neg-custom-args/captures/usingFile.scala index 7cfbac9540e7..3927be5ff506 100644 --- a/tests/neg-custom-args/captures/usingFile.scala +++ b/tests/neg-custom-args/captures/usingFile.scala @@ -7,7 +7,7 @@ object Test: class Logger(f: OutputStream^): def log(msg: String): Unit = ??? - def usingFile[sealed T](name: String, op: OutputStream^ => T): T = + def usingFile[T](name: String, op: OutputStream^ => T): T = val f = new FileOutputStream(name) val result = op(f) f.close() diff --git a/tests/neg-custom-args/captures/usingLogFile.check b/tests/neg-custom-args/captures/usingLogFile.check index 4bb30d27825f..476bf99ef0ef 100644 --- a/tests/neg-custom-args/captures/usingLogFile.check +++ b/tests/neg-custom-args/captures/usingLogFile.check @@ -1,15 +1,3 @@ --- Error: tests/neg-custom-args/captures/usingLogFile.scala:32:37 ------------------------------------------------------ -32 | usingLogFile { f => later3 = () => f.write(0) } // error - | ^ - |(f : java.io.FileOutputStream^) cannot be referenced here; it is not included in the allowed capture set {cap[]} - |of an enclosing function literal with expected type () ->{cap[]} Unit --- [E007] Type Mismatch Error: tests/neg-custom-args/captures/usingLogFile.scala:36:35 --------------------------------- -36 | usingLogFile { f => later4 = Cell(() => f.write(0)) } // error - | ^^^^^^^^^^^^^^^^^^^^^^ - | Found: Test2.Cell[box () ->{f} Unit]^? - | Required: Test2.Cell[box () ->{cap[]} Unit] - | - | longer explanation available when compiling with `-explain` -- Error: tests/neg-custom-args/captures/usingLogFile.scala:23:14 ------------------------------------------------------ 23 | val later = usingLogFile { f => () => f.write(0) } // error | ^^^^^^^^^^^^ @@ -18,11 +6,11 @@ 28 | private val later2 = usingLogFile { f => Cell(() => f.write(0)) } // error | ^^^^^^^^^^^^ | local reference f leaks into outer capture set of type parameter T of method usingLogFile --- Error: tests/neg-custom-args/captures/usingLogFile.scala:52:16 ------------------------------------------------------ -52 | val later = usingFile("out", f => (y: Int) => xs.foreach(x => f.write(x + y))) // error +-- Error: tests/neg-custom-args/captures/usingLogFile.scala:44:16 ------------------------------------------------------ +44 | val later = usingFile("out", f => (y: Int) => xs.foreach(x => f.write(x + y))) // error | ^^^^^^^^^ | local reference f leaks into outer capture set of type parameter T of method usingFile --- Error: tests/neg-custom-args/captures/usingLogFile.scala:60:16 ------------------------------------------------------ -60 | val later = usingFile("logfile", // error !!! but should be ok, since we can widen `l` to `file` instead of to `cap` +-- Error: tests/neg-custom-args/captures/usingLogFile.scala:52:16 ------------------------------------------------------ +52 | val later = usingFile("logfile", // error !!! but should be ok, since we can widen `l` to `file` instead of to `cap` | ^^^^^^^^^ | local reference l leaks into outer capture set of type parameter T of method usingFile diff --git a/tests/neg-custom-args/captures/usingLogFile.scala b/tests/neg-custom-args/captures/usingLogFile.scala index 8246cfd9377e..e5dc271975b0 100644 --- a/tests/neg-custom-args/captures/usingLogFile.scala +++ b/tests/neg-custom-args/captures/usingLogFile.scala @@ -14,7 +14,7 @@ object Test1: object Test2: - def usingLogFile[sealed T](op: FileOutputStream^ => T): T = + def usingLogFile[T](op: FileOutputStream^ => T): T = val logFile = FileOutputStream("log") val result = op(logFile) logFile.close() @@ -28,19 +28,11 @@ object Test2: private val later2 = usingLogFile { f => Cell(() => f.write(0)) } // error later2.x() - var later3: () ->{cap[``]} Unit = () => () - usingLogFile { f => later3 = () => f.write(0) } // error - later3() - - var later4: Cell[() ->{cap[``]} Unit] = Cell(() => ()) - usingLogFile { f => later4 = Cell(() => f.write(0)) } // error - later4.x() - object Test3: class Logger(f: OutputStream^): def log(msg: String): Unit = ??? - def usingFile[sealed T](name: String, op: OutputStream^ => T): T = + def usingFile[T](name: String, op: OutputStream^ => T): T = val f = new FileOutputStream(name) val result = op(f) f.close() @@ -52,7 +44,7 @@ object Test3: val later = usingFile("out", f => (y: Int) => xs.foreach(x => f.write(x + y))) // error later(1) - def usingLogger[sealed T](f: OutputStream^, op: Logger^{f} => T): T = + def usingLogger[T](f: OutputStream^, op: Logger^{f} => T): T = val logger = Logger(f) op(logger) diff --git a/tests/neg-custom-args/captures/vars-simple.check b/tests/neg-custom-args/captures/vars-simple.check index 873435b8a1aa..2bc014e9a4e7 100644 --- a/tests/neg-custom-args/captures/vars-simple.check +++ b/tests/neg-custom-args/captures/vars-simple.check @@ -1,21 +1,21 @@ -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/vars-simple.scala:15:9 ----------------------------------- 15 | a = (g: String => String) // error | ^^^^^^^^^^^^^^^^^^^ - | Found: String ->{cap[g]} String - | Required: String ->{cap[test]} String + | Found: String => String + | Required: String ->{cap1, cap2} String | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/vars-simple.scala:16:8 ----------------------------------- 16 | a = g // error | ^ | Found: (x: String) ->{cap3} String - | Required: (x: String) ->{cap[test]} String + | Required: (x: String) ->{cap1, cap2} String | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/vars-simple.scala:17:12 ---------------------------------- 17 | b = List(g) // error | ^^^^^^^ | Found: List[box (x$0: String) ->{cap3} String] - | Required: List[box String ->{cap[test]} String] + | Required: List[box String ->{cap1, cap2} String] | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/vars-simple.scala b/tests/neg-custom-args/captures/vars-simple.scala index e7b9723e5b82..161d74591e7b 100644 --- a/tests/neg-custom-args/captures/vars-simple.scala +++ b/tests/neg-custom-args/captures/vars-simple.scala @@ -2,8 +2,8 @@ class CC type Cap = CC^ def test(cap1: Cap, cap2: Cap) = - var a: String ->{cap[test]} String = ??? - var b: List[String ->{cap[test]} String] = Nil + var a: String ->{cap1, cap2} String = ??? + var b: List[String ->{cap1, cap2} String] = Nil def f(x: String): String = if cap1 == cap1 then "" else "a" a = f // ok val x = List(f) diff --git a/tests/neg-custom-args/captures/vars.check b/tests/neg-custom-args/captures/vars.check index 844fa90a35cd..22d13d8e26e7 100644 --- a/tests/neg-custom-args/captures/vars.check +++ b/tests/neg-custom-args/captures/vars.check @@ -19,7 +19,7 @@ 25 | b = List(g) // error | ^^^^^^^ | Found: List[box (x$0: String) ->{cap3} String] - | Required: List[box String ->{cap[test]} String] + | Required: List[box String ->{cap1, cap2} String] | | longer explanation available when compiling with `-explain` -- Error: tests/neg-custom-args/captures/vars.scala:34:2 --------------------------------------------------------------- diff --git a/tests/neg-custom-args/captures/vars.scala b/tests/neg-custom-args/captures/vars.scala index ede287e26010..ab5a2f43acc7 100644 --- a/tests/neg-custom-args/captures/vars.scala +++ b/tests/neg-custom-args/captures/vars.scala @@ -11,7 +11,7 @@ def test(cap1: Cap, cap2: Cap) = val z2c: () -> Unit = z2 var a = f - var b: List[String ->{cap[test]} String] = Nil + var b: List[String ->{cap1, cap2} String] = Nil val u = a a("") b.head @@ -29,7 +29,7 @@ def test(cap1: Cap, cap2: Cap) = val s = scope(new CC) val sc: String => String = scope(new CC) - def local[sealed T](op: CC^ -> T): T = op(CC()) + def local[T](op: CC^ -> T): T = op(CC()) local { cap3 => // error def g(x: String): String = if cap3 == cap3 then "" else "a" diff --git a/tests/neg-custom-args/captures/withFile.scala b/tests/neg-custom-args/captures/withFile.scala index 0f7701289aa5..b8cdf96f9143 100644 --- a/tests/neg-custom-args/captures/withFile.scala +++ b/tests/neg-custom-args/captures/withFile.scala @@ -1,7 +1,7 @@ import java.io.* object Test2: - def usingLogFile[sealed T](op: FileOutputStream^ => T): T = + def usingLogFile[T](op: FileOutputStream^ => T): T = val logFile = FileOutputStream("log") val result = op(logFile) logFile.close() diff --git a/tests/neg/capt-wf.scala b/tests/neg/capt-wf.scala index 0e1e4be2ca67..fbd334726e55 100644 --- a/tests/neg/capt-wf.scala +++ b/tests/neg/capt-wf.scala @@ -1,5 +1,5 @@ //> using options -language:experimental.captureChecking -Xfatal-warnings - +import caps.cap class C type Cap = C^ diff --git a/tests/neg-custom-args/captures/buffers.scala b/tests/pos-custom-args/captures/buffers.scala similarity index 56% rename from tests/neg-custom-args/captures/buffers.scala rename to tests/pos-custom-args/captures/buffers.scala index 760ddab96ae5..7fcf96291ccb 100644 --- a/tests/neg-custom-args/captures/buffers.scala +++ b/tests/pos-custom-args/captures/buffers.scala @@ -2,24 +2,24 @@ import reflect.ClassTag class Buffer[A] -class ArrayBuffer[sealed A: ClassTag] extends Buffer[A]: +class ArrayBuffer[A: ClassTag] extends Buffer[A]: var elems: Array[A] = new Array[A](10) def add(x: A): this.type = ??? def at(i: Int): A = ??? class ArrayBufferBAD[A: ClassTag] extends Buffer[A]: - var elems: Array[A] = new Array[A](10) // error // error + var elems: Array[A] = new Array[A](10) def add(x: A): this.type = ??? def at(i: Int): A = ??? object ArrayBuffer: - def make[A: ClassTag](xs: A*) = new ArrayBuffer: // error + def make[A: ClassTag](xs: A*) = new ArrayBuffer: elems = xs.toArray - def apply[sealed A: ClassTag](xs: A*) = new ArrayBuffer: + def apply[A: ClassTag](xs: A*) = new ArrayBuffer: elems = xs.toArray // ok class EncapsArray[A: ClassTag]: - val x: Array[A] = new Array[A](10) // error + val x: Array[A] = new Array[A](10) diff --git a/tests/pos-custom-args/captures/byname.scala b/tests/pos-custom-args/captures/byname.scala index efd76618469d..761496185a0d 100644 --- a/tests/pos-custom-args/captures/byname.scala +++ b/tests/pos-custom-args/captures/byname.scala @@ -1,4 +1,5 @@ import annotation.retainsByName +import caps.cap class CC type Cap = CC^ diff --git a/tests/pos-custom-args/captures/capt1.scala b/tests/pos-custom-args/captures/capt1.scala index 8d2285f1fa50..e3f5c20e724e 100644 --- a/tests/pos-custom-args/captures/capt1.scala +++ b/tests/pos-custom-args/captures/capt1.scala @@ -3,7 +3,7 @@ type Cap = C^ def f1(c: Cap): () ->{c} c.type = () => c // ok def f2: Int = - val g: Boolean ->{cap} Int = ??? + val g: Boolean => Int = ??? val x = g(true) x diff --git a/tests/pos-custom-args/captures/foreach.scala b/tests/pos-custom-args/captures/foreach.scala index 0656025da657..28225c3dee7b 100644 --- a/tests/pos-custom-args/captures/foreach.scala +++ b/tests/pos-custom-args/captures/foreach.scala @@ -1,3 +1,4 @@ +import annotation.unchecked.uncheckedCaptures def test = - val tasks = new collection.mutable.ArrayBuffer[() => Unit] + val tasks = new collection.mutable.ArrayBuffer[(() => Unit) @uncheckedCaptures] val _: Unit = tasks.foreach(((task: () => Unit) => task())) diff --git a/tests/pos-custom-args/captures/function-combinators.scala b/tests/pos-custom-args/captures/function-combinators.scala index 7369f8399f2f..4354af4c7636 100644 --- a/tests/pos-custom-args/captures/function-combinators.scala +++ b/tests/pos-custom-args/captures/function-combinators.scala @@ -2,7 +2,7 @@ class ContextClass type Context = ContextClass^ def Test(using ctx1: Context, ctx2: Context) = - val f: Int ->{cap[Test]} Int = identity + val f: Int => Int = identity val g1: Int ->{ctx1} Int = identity val g2: Int ->{ctx2} Int = identity val h: Int -> Int = identity @@ -19,7 +19,7 @@ def Test(using ctx1: Context, ctx2: Context) = val c3 = h.andThen(g2); val _: Int ->{g2} Int = c3 val c4 = h.andThen(h); val _: Int -> Int = c4 - val f2: (Int, Int) ->{cap[Test]} Int = _ + _ + val f2: (Int, Int) => Int = _ + _ val f2c = f2.curried; val _: Int -> Int ->{f2} Int = f2c val f2t = f2.tupled; val _: ((Int, Int)) ->{f2} Int = f2t diff --git a/tests/pos-custom-args/captures/future-traverse.scala b/tests/pos-custom-args/captures/future-traverse.scala index 5aedc5d29852..743984660af0 100644 --- a/tests/pos-custom-args/captures/future-traverse.scala +++ b/tests/pos-custom-args/captures/future-traverse.scala @@ -9,7 +9,8 @@ trait Future[+T] { this: Future[T]^ => import Future.* def foldLeft[R](r: R): R = r def traverse[A, B, M[X] <: IterableOnce[X]](in: M[A]^, bf: BuildFrom[M[A]^, B, M[B]^]): Unit = - foldLeft(successful(bf.newBuilder(in))) + val builder = bf.newBuilder(in) + foldLeft(successful(builder)) } object Future { def successful[T](result: T): Future[T] = ??? diff --git a/tests/pos-custom-args/captures/i15749.scala b/tests/pos-custom-args/captures/i15749.scala index 4959c003a918..0a552ae1a3c5 100644 --- a/tests/pos-custom-args/captures/i15749.scala +++ b/tests/pos-custom-args/captures/i15749.scala @@ -1,9 +1,9 @@ class Unit object unit extends Unit -type Top = Any^{cap} +type Top = Any^ -type LazyVal[T] = Unit ->{cap} T +type LazyVal[T] = Unit => T class Foo[T](val x: T) diff --git a/tests/pos-custom-args/captures/i15923-cases.scala b/tests/pos-custom-args/captures/i15923-cases.scala index 136b8950eb26..7c5635f7b3dd 100644 --- a/tests/pos-custom-args/captures/i15923-cases.scala +++ b/tests/pos-custom-args/captures/i15923-cases.scala @@ -2,14 +2,14 @@ trait Cap { def use(): Int } type Id[X] = [T] -> (op: X => T) -> T def mkId[X](x: X): Id[X] = [T] => (op: X => T) => op(x) -def foo(x: Id[Cap^{cap}]) = { +def foo(x: Id[Cap^]) = { x(_.use()) // was error, now OK } -def bar(io: Cap^{cap}, x: Id[Cap^{io}]) = { +def bar(io: Cap^, x: Id[Cap^{io}]) = { x(_.use()) } -def barAlt(a: Cap^{cap}, b: Cap^{cap}, x: Id[Cap]^{a, b}) = { +def barAlt(a: Cap^, b: Cap^, x: Id[Cap]^{a, b}) = { x(_.use()) } diff --git a/tests/pos-custom-args/captures/lists.scala b/tests/pos-custom-args/captures/lists.scala index c3a604128942..99505f0bb7a2 100644 --- a/tests/pos-custom-args/captures/lists.scala +++ b/tests/pos-custom-args/captures/lists.scala @@ -30,7 +30,7 @@ def test(c: Cap, d: Cap, e: Cap) = CONS(z, ys) val zsc: LIST[Cap ->{d, y} Unit] = zs val z1 = zs.head - val z1c: Cap^{cap[test]} ->{y, d} Unit = z1 + val z1c: Cap^ ->{y, d} Unit = z1 val ys1 = zs.tail val y1 = ys1.head diff --git a/tests/pos-custom-args/captures/logger.scala b/tests/pos-custom-args/captures/logger.scala index 3f417da8c1be..d95eeaae74cf 100644 --- a/tests/pos-custom-args/captures/logger.scala +++ b/tests/pos-custom-args/captures/logger.scala @@ -52,7 +52,8 @@ class Pair[+A, +B](x: A, y: B): def test2(ct: CanThrow[Exception], fs: FileSystem) = def x: Int ->{ct} String = ??? def y: Logger^{fs} = ??? - def p = Pair(x, y) + def p = Pair[Int ->{ct} String, Logger^{fs}](x, y) + def p3 = Pair(x, y) def f = () => p.fst diff --git a/tests/pos-custom-args/captures/nested-classes-2.scala b/tests/pos-custom-args/captures/nested-classes-2.scala index e9e74dedb7c1..744635ee949b 100644 --- a/tests/pos-custom-args/captures/nested-classes-2.scala +++ b/tests/pos-custom-args/captures/nested-classes-2.scala @@ -11,14 +11,14 @@ def test1(x: (() => Unit)): Unit = def test2(x1: (() => Unit), x2: (() => Unit) => Unit) = class C1(x1: (() => Unit), xx2: (() => Unit) => Unit): - def c2(y1: (() => Unit), y2: (() => Unit) => Unit): C2^{cap} = C2(y1, y2) + def c2(y1: (() => Unit), y2: (() => Unit) => Unit): C2^ = C2(y1, y2) class C2(y1: (() => Unit), y2: (() => Unit) => Unit): val a: (() => Unit) => (() => Unit) = f(y1) a(x1) //OK, but should be error C2(() => (), x => ()) def test3(y1: (() => Unit), y2: (() => Unit) => Unit) = - val cc1/*: C1^{cap[test3]}*/ = C1(y1, y2) // error (but should be OK) - val cc2 = cc1.c2(x1, x2) // error (but should be OK) - //val cc3: cc1.C2^{cap[test2]} = cc2 + val cc1: C1^{y1, y2} = C1(y1, y2) + val cc2 = cc1.c2(x1, x2) + val cc3: cc1.C2^{cc1, x1, x2} = cc2 diff --git a/tests/pos-custom-args/captures/reaches.scala b/tests/pos-custom-args/captures/reaches.scala new file mode 100644 index 000000000000..0f7df02e13b1 --- /dev/null +++ b/tests/pos-custom-args/captures/reaches.scala @@ -0,0 +1,49 @@ +class C +def f(xs: List[C^]) = + val y = xs + val z: List[C^{xs*}] = y + +type Proc = () => Unit + +class Ref[T](init: T): + private var x: T = init + def get: T = x + def set(y: T) = { x = y } + +def runAll(xs: List[Proc]): Unit = + var cur: List[() ->{xs*} Unit] = xs // OK, by revised VAR + while cur.nonEmpty do + val next: () ->{xs*} Unit = cur.head + next() + cur = cur.tail: List[() ->{xs*} Unit] + +def id1(x: Proc): () ->{x} Unit = x +def id2(xs: List[Proc]): List[() ->{xs*} Unit] = xs + +def cons(x: Proc, xs: List[Proc]): List[() ->{x, xs*} Unit] = + val y = x :: xs + y + +def addOneProc(xs: List[Proc]): List[Proc] = + val x: Proc = () => println("hello") + val result: List[() ->{x, xs*} Unit] = x :: xs + result // OK, we can widen () ->{x, xs*} Unit to cap here. + +def compose1[A, B, C](f: A => B, g: B => C): A ->{f, g} C = + z => g(f(z)) + +def compose2[A, B, C](f: A => B, g: B => C): A => C = + z => g(f(z)) + +def mapCompose[A](ps: List[(A => A, A => A)]): List[A ->{ps*} A] = + ps.map((x, y) => compose1(x, y)) + +@annotation.capability class IO + +def test(io: IO) = + val a: () ->{io} Unit = () => () + val as: List[() ->{io} Unit] = Nil + val bs: List[() ->{io} Unit] = cons(a, as) + val cs = cons(a, as) + val ds: List[() ->{io} Unit] = cs + diff --git a/tests/pos-custom-args/captures/sealed-lowerbound.scala b/tests/pos-custom-args/captures/sealed-lowerbound.scala index e848f784cddc..0894d7aad50d 100644 --- a/tests/pos-custom-args/captures/sealed-lowerbound.scala +++ b/tests/pos-custom-args/captures/sealed-lowerbound.scala @@ -1,10 +1,10 @@ -def foo[sealed B](x: B): B = x +def foo[B](x: B): B = x -def bar[B, sealed A >: B](x: A): A = foo[A](x) +def bar[B, A >: B](x: A): A = foo[A](x) -class C[sealed A] +class C[A] -class CV[sealed A](x: Int): +class CV[A](x: Int): def this() = this: val x = new C[A]: println("foo") diff --git a/tests/pos-custom-args/captures/sealed-value-class.scala b/tests/pos-custom-args/captures/sealed-value-class.scala index b5f25bf2d203..7d2a223be91f 100644 --- a/tests/pos-custom-args/captures/sealed-value-class.scala +++ b/tests/pos-custom-args/captures/sealed-value-class.scala @@ -1,3 +1,3 @@ -class Ops[sealed A](xs: Array[A]) extends AnyVal: +class Ops[A](xs: Array[A]) extends AnyVal: def f(p: A => Boolean): Array[A] = xs diff --git a/tests/pos-custom-args/captures/steppers.scala b/tests/pos-custom-args/captures/steppers.scala index 815ac938b492..6169abab21dc 100644 --- a/tests/pos-custom-args/captures/steppers.scala +++ b/tests/pos-custom-args/captures/steppers.scala @@ -11,7 +11,7 @@ trait IterableOnce[+A] extends Any: this: IterableOnce[A]^ => def stepper[S <: Stepper[_]^{this}](implicit shape: StepperShape[A, S]): S = ??? -sealed abstract class ArraySeq[sealed T] extends IterableOnce[T], Pure: +sealed abstract class ArraySeq[T] extends IterableOnce[T], Pure: def array: Array[_] def sorted[B >: T](implicit ord: Ordering[B]): ArraySeq[T] = @@ -20,7 +20,7 @@ sealed abstract class ArraySeq[sealed T] extends IterableOnce[T], Pure: object ArraySeq: - def make[sealed T](x: Array[T]): ArraySeq[T] = ??? + def make[T](x: Array[T]): ArraySeq[T] = ??? final class ofRef[T <: AnyRef](val array: Array[T]) extends ArraySeq[T], Pure: override def stepper[S <: Stepper[_]](implicit shape: StepperShape[T, S]): S & Stepper.EfficientSplit = ??? diff --git a/tests/pos-custom-args/captures/test.scala b/tests/pos-custom-args/captures/test.scala index 0664b2172198..979f3d34ec17 100644 --- a/tests/pos-custom-args/captures/test.scala +++ b/tests/pos-custom-args/captures/test.scala @@ -3,7 +3,7 @@ type Cap = C^ type Proc = () => Unit -class Ref[sealed T](p: T): +class Ref[T](p: T): private var x: T = p def set(x: T): Unit = this.x = x def get: T = x diff --git a/tests/pos-custom-args/captures/unsafe-unbox.scala b/tests/pos-custom-args/captures/unsafe-unbox.scala index 63a32d58f640..1c523490e19d 100644 --- a/tests/pos-custom-args/captures/unsafe-unbox.scala +++ b/tests/pos-custom-args/captures/unsafe-unbox.scala @@ -1,7 +1,7 @@ import annotation.unchecked.uncheckedCaptures def test = - @uncheckedCaptures - var finalizeActions = collection.mutable.ListBuffer[() => Unit]() + val finalizeActionsInit = collection.mutable.ListBuffer[(() => Unit) @uncheckedCaptures]() + var finalizeActions = finalizeActionsInit val action = finalizeActions.remove(0) diff --git a/tests/pos-special/stdlib/Test1.scala b/tests/pos-special/stdlib/Test1.scala index 9ee4e7cfa6a1..312756ad4ef5 100644 --- a/tests/pos-special/stdlib/Test1.scala +++ b/tests/pos-special/stdlib/Test1.scala @@ -6,7 +6,7 @@ import java.io.* object Test0: - def usingLogFile[sealed T](op: FileOutputStream^ => T): T = + def usingLogFile[T](op: FileOutputStream^ => T): T = val logFile = FileOutputStream("log") val result = op(logFile) logFile.close() @@ -20,7 +20,7 @@ object Test0: object Test1: def test(it: Iterator[Int]^, v: View[Int]^) = - val isEven: Int ->{cap[test]} Boolean = _ % 2 == 0 + val isEven: Int => Boolean = _ % 2 == 0 val it2 = it.filter(isEven) val _: Iterator[Int]^{it, isEven} = it2 val it2c: Iterator[Int]^{it2} = it2 diff --git a/tests/pos-special/stdlib/Test2.scala b/tests/pos-special/stdlib/Test2.scala index a59da522b183..cab9440c17db 100644 --- a/tests/pos-special/stdlib/Test2.scala +++ b/tests/pos-special/stdlib/Test2.scala @@ -64,7 +64,7 @@ object Test { def iterOps(xs: => Iterator[Int]^) = val strPlusInt: (String, Int) => String = _ + _ val intPlusStr: (Int, String) => String = _ + _ - val isEven: Int ->{cap[iterOps]} Boolean = _ % 2 == 0 + val isEven: Int => Boolean = _ % 2 == 0 val isNonNeg: Int => Boolean = _ > 0 val flips: Int => List[Int] = x => x :: -x :: Nil val x1 = xs.foldLeft("")(strPlusInt) @@ -116,7 +116,7 @@ object Test { def viewOps(xs: View[Int]^) = { val strPlusInt: (String, Int) => String = _ + _ val intPlusStr: (Int, String) => String = _ + _ - val isEven: Int ->{cap[viewOps]} Boolean = _ % 2 == 0 + val isEven: Int => Boolean = _ % 2 == 0 val isNonNeg: Int => Boolean = _ > 0 val flips: Int => List[Int] = x => x :: -x :: Nil val x1 = xs.foldLeft("")(strPlusInt) diff --git a/tests/pos-special/stdlib/collection/ArrayOps.scala b/tests/pos-special/stdlib/collection/ArrayOps.scala index a52fd0dbd162..bb6174f59598 100644 --- a/tests/pos-special/stdlib/collection/ArrayOps.scala +++ b/tests/pos-special/stdlib/collection/ArrayOps.scala @@ -54,14 +54,14 @@ import scala.util.Sorting object ArrayOps { @SerialVersionUID(3L) - private class ArrayView[sealed A](xs: Array[A]) extends AbstractIndexedSeqView[A] { + private class ArrayView[A](xs: Array[A]) extends AbstractIndexedSeqView[A] { def length = xs.length def apply(n: Int) = xs(n) override def toString: String = immutable.ArraySeq.unsafeWrapArray(xs).mkString("ArrayView(", ", ", ")") } /** A lazy filtered array. No filtering is applied until one of `foreach`, `map` or `flatMap` is called. */ - class WithFilter[sealed A](p: A => Boolean, xs: Array[A]) { + class WithFilter[A](p: A => Boolean, xs: Array[A]) { /** Apply `f` to each element for its side effects. * Note: [U] parameter needed to help scalac's type inference. @@ -83,7 +83,7 @@ object ArrayOps { * @return a new array resulting from applying the given function * `f` to each element of this array and collecting the results. */ - def map[sealed B: ClassTag](f: A => B): Array[B] = { + def map[B: ClassTag](f: A => B): Array[B] = { val b = ArrayBuilder.make[B] var i = 0 while (i < xs.length) { @@ -102,7 +102,7 @@ object ArrayOps { * @return a new array resulting from applying the given collection-valued function * `f` to each element of this array and concatenating the results. */ - def flatMap[sealed B: ClassTag](f: A => IterableOnce[B]): Array[B] = { + def flatMap[B: ClassTag](f: A => IterableOnce[B]): Array[B] = { val b = ArrayBuilder.make[B] var i = 0 while(i < xs.length) { @@ -113,7 +113,7 @@ object ArrayOps { b.result() } - def flatMap[BS, sealed B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] = + def flatMap[BS, B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] = flatMap[B](x => asIterable(f(x))) /** Creates a new non-strict filter which combines this filter with the given predicate. */ @@ -121,7 +121,7 @@ object ArrayOps { } @SerialVersionUID(3L) - private[collection] final class ArrayIterator[@specialized(Specializable.Everything) sealed A](xs: Array[A]) extends AbstractIterator[A] with Serializable { + private[collection] final class ArrayIterator[@specialized(Specializable.Everything) A](xs: Array[A]) extends AbstractIterator[A] with Serializable { private[this] var pos = 0 private[this] val len = xs.length override def knownSize: Int = len - pos @@ -144,7 +144,7 @@ object ArrayOps { } @SerialVersionUID(3L) - private final class ReverseIterator[@specialized(Specializable.Everything) sealed A](xs: Array[A]) extends AbstractIterator[A] with Serializable { + private final class ReverseIterator[@specialized(Specializable.Everything) A](xs: Array[A]) extends AbstractIterator[A] with Serializable { private[this] var pos = xs.length-1 def hasNext: Boolean = pos >= 0 def next(): A = { @@ -161,7 +161,7 @@ object ArrayOps { } @SerialVersionUID(3L) - private final class GroupedIterator[sealed A](xs: Array[A], groupSize: Int) extends AbstractIterator[Array[A]] with Serializable { + private final class GroupedIterator[A](xs: Array[A], groupSize: Int) extends AbstractIterator[Array[A]] with Serializable { private[this] var pos = 0 def hasNext: Boolean = pos < xs.length def next(): Array[A] = { @@ -197,7 +197,7 @@ object ArrayOps { * * @tparam A type of the elements contained in this array. */ -final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { +final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { @`inline` private[this] implicit def elemTag: ClassTag[A] = ClassTag(xs.getClass.getComponentType) @@ -505,7 +505,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * * @return a pair of arrays: the first one made of those values returned by `f` that were wrapped in [[scala.util.Left]], * and the second one made of those wrapped in [[scala.util.Right]]. */ - def partitionMap[sealed A1: ClassTag, sealed A2: ClassTag](f: A => Either[A1, A2]): (Array[A1], Array[A2]) = { + def partitionMap[A1: ClassTag, A2: ClassTag](f: A => Either[A1, A2]): (Array[A1], Array[A2]) = { val res1 = ArrayBuilder.make[A1] val res2 = ArrayBuilder.make[A2] var i = 0 @@ -777,7 +777,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * Returns `z` if this array is empty. */ def foldLeft[B](z: B)(op: (B, A) => B): B = { - def f[@specialized(Specializable.Everything) sealed T](xs: Array[T], op: (Any, Any) => Any, z: Any): Any = { + def f[@specialized(Specializable.Everything) T](xs: Array[T], op: (Any, Any) => Any, z: Any): Any = { val length = xs.length var v: Any = z var i = 0 @@ -816,7 +816,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * }}} * */ - def scanLeft[sealed B : ClassTag](z: B)(op: (B, A) => B): Array[B] = { + def scanLeft[B : ClassTag](z: B)(op: (B, A) => B): Array[B] = { var v = z var i = 0 val res = new Array[B](xs.length + 1) @@ -839,7 +839,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * * @return a new array containing the prefix scan of the elements in this array */ - def scan[sealed B >: A : ClassTag](z: B)(op: (B, B) => B): Array[B] = scanLeft(z)(op) + def scan[B >: A : ClassTag](z: B)(op: (B, B) => B): Array[B] = scanLeft(z)(op) /** Produces an array containing cumulative results of applying the binary * operator going right to left. @@ -855,7 +855,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * }}} * */ - def scanRight[sealed B : ClassTag](z: B)(op: (A, B) => B): Array[B] = { + def scanRight[B : ClassTag](z: B)(op: (A, B) => B): Array[B] = { var v = z var i = xs.length - 1 val res = new Array[B](xs.length + 1) @@ -883,7 +883,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * Returns `z` if this array is empty. */ def foldRight[B](z: B)(op: (A, B) => B): B = { - def f[@specialized(Specializable.Everything) sealed T](xs: Array[T], op: (Any, Any) => Any, z: Any): Any = { + def f[@specialized(Specializable.Everything) T](xs: Array[T], op: (Any, Any) => Any, z: Any): Any = { var v = z var i = xs.length - 1 while(i >= 0) { @@ -926,7 +926,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @return a new array resulting from applying the given function * `f` to each element of this array and collecting the results. */ - def map[sealed B](f: A => B)(implicit ct: ClassTag[B]): Array[B] = { + def map[B](f: A => B)(implicit ct: ClassTag[B]): Array[B] = { val len = xs.length val ys = new Array[B](len) if(len > 0) { @@ -963,7 +963,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @return a new array resulting from applying the given collection-valued function * `f` to each element of this array and concatenating the results. */ - def flatMap[sealed B : ClassTag](f: A => IterableOnce[B]): Array[B] = { + def flatMap[B : ClassTag](f: A => IterableOnce[B]): Array[B] = { val b = ArrayBuilder.make[B] var i = 0 while(i < xs.length) { @@ -973,7 +973,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { b.result() } - def flatMap[BS, sealed B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] = + def flatMap[BS, B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] = flatMap[B](x => asIterable(f(x))) /** Flattens a two-dimensional array by concatenating all its rows @@ -983,7 +983,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @param asIterable A function that converts elements of this array to rows - Iterables of type `B`. * @return An array obtained by concatenating rows of this array. */ - def flatten[sealed B](implicit asIterable: A => IterableOnce[B], m: ClassTag[B]): Array[B] = { + def flatten[B](implicit asIterable: A => IterableOnce[B], m: ClassTag[B]): Array[B] = { val b = ArrayBuilder.make[B] val len = xs.length var size = 0 @@ -1016,7 +1016,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * `pf` to each element on which it is defined and collecting the results. * The order of the elements is preserved. */ - def collect[sealed B: ClassTag](pf: PartialFunction[A, B]): Array[B] = { + def collect[B: ClassTag](pf: PartialFunction[A, B]): Array[B] = { val fallback: Any => Any = ArrayOps.fallback val b = ArrayBuilder.make[B] var i = 0 @@ -1050,7 +1050,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @return a new array containing pairs consisting of corresponding elements of this array and `that`. * The length of the returned array is the minimum of the lengths of this array and `that`. */ - def zip[sealed B](that: IterableOnce[B]): Array[(A, B)] = { + def zip[B](that: IterableOnce[B]): Array[(A, B)] = { val b = new ArrayBuilder.ofRef[(A, B)]() val k = that.knownSize b.sizeHint(if(k >= 0) min(k, xs.length) else xs.length) @@ -1095,7 +1095,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * If this array is shorter than `that`, `thisElem` values are used to pad the result. * If `that` is shorter than this array, `thatElem` values are used to pad the result. */ - def zipAll[sealed A1 >: A, sealed B](that: Iterable[B], thisElem: A1, thatElem: B): Array[(A1, B)] = { + def zipAll[A1 >: A, B](that: Iterable[B], thisElem: A1, thatElem: B): Array[(A1, B)] = { val b = new ArrayBuilder.ofRef[(A1, B)]() val k = that.knownSize b.sizeHint(max(k, xs.length)) @@ -1132,26 +1132,26 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { } /** A copy of this array with an element appended. */ - def appended[sealed B >: A : ClassTag](x: B): Array[B] = { + def appended[B >: A : ClassTag](x: B): Array[B] = { val dest = Array.copyAs[B](xs, xs.length+1) dest(xs.length) = x dest } - @`inline` final def :+ [sealed B >: A : ClassTag](x: B): Array[B] = appended(x) + @`inline` final def :+ [B >: A : ClassTag](x: B): Array[B] = appended(x) /** A copy of this array with an element prepended. */ - def prepended[sealed B >: A : ClassTag](x: B): Array[B] = { + def prepended[B >: A : ClassTag](x: B): Array[B] = { val dest = new Array[B](xs.length + 1) dest(0) = x Array.copy(xs, 0, dest, 1, xs.length) dest } - @`inline` final def +: [sealed B >: A : ClassTag](x: B): Array[B] = prepended(x) + @`inline` final def +: [B >: A : ClassTag](x: B): Array[B] = prepended(x) /** A copy of this array with all elements of a collection prepended. */ - def prependedAll[sealed B >: A : ClassTag](prefix: IterableOnce[B]): Array[B] = { + def prependedAll[B >: A : ClassTag](prefix: IterableOnce[B]): Array[B] = { val b = ArrayBuilder.make[B] val k = prefix.knownSize if(k >= 0) b.sizeHint(k + xs.length) @@ -1162,18 +1162,18 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { } /** A copy of this array with all elements of an array prepended. */ - def prependedAll[sealed B >: A : ClassTag](prefix: Array[_ <: B]): Array[B] = { + def prependedAll[B >: A : ClassTag](prefix: Array[_ <: B]): Array[B] = { val dest = Array.copyAs[B](prefix, prefix.length+xs.length) Array.copy(xs, 0, dest, prefix.length, xs.length) dest } - @`inline` final def ++: [sealed B >: A : ClassTag](prefix: IterableOnce[B]): Array[B] = prependedAll(prefix) + @`inline` final def ++: [B >: A : ClassTag](prefix: IterableOnce[B]): Array[B] = prependedAll(prefix) - @`inline` final def ++: [sealed B >: A : ClassTag](prefix: Array[_ <: B]): Array[B] = prependedAll(prefix) + @`inline` final def ++: [B >: A : ClassTag](prefix: Array[_ <: B]): Array[B] = prependedAll(prefix) /** A copy of this array with all elements of a collection appended. */ - def appendedAll[sealed B >: A : ClassTag](suffix: IterableOnce[B]): Array[B] = { + def appendedAll[B >: A : ClassTag](suffix: IterableOnce[B]): Array[B] = { val b = ArrayBuilder.make[B] val k = suffix.knownSize if(k >= 0) b.sizeHint(k + xs.length) @@ -1183,23 +1183,23 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { } /** A copy of this array with all elements of an array appended. */ - def appendedAll[sealed B >: A : ClassTag](suffix: Array[_ <: B]): Array[B] = { + def appendedAll[B >: A : ClassTag](suffix: Array[_ <: B]): Array[B] = { val dest = Array.copyAs[B](xs, xs.length+suffix.length) Array.copy(suffix, 0, dest, xs.length, suffix.length) dest } - @`inline` final def :++ [sealed B >: A : ClassTag](suffix: IterableOnce[B]): Array[B] = appendedAll(suffix) + @`inline` final def :++ [B >: A : ClassTag](suffix: IterableOnce[B]): Array[B] = appendedAll(suffix) - @`inline` final def :++ [sealed B >: A : ClassTag](suffix: Array[_ <: B]): Array[B] = appendedAll(suffix) + @`inline` final def :++ [B >: A : ClassTag](suffix: Array[_ <: B]): Array[B] = appendedAll(suffix) - @`inline` final def concat[sealed B >: A : ClassTag](suffix: IterableOnce[B]): Array[B] = appendedAll(suffix) + @`inline` final def concat[B >: A : ClassTag](suffix: IterableOnce[B]): Array[B] = appendedAll(suffix) - @`inline` final def concat[sealed B >: A : ClassTag](suffix: Array[_ <: B]): Array[B] = appendedAll(suffix) + @`inline` final def concat[B >: A : ClassTag](suffix: Array[_ <: B]): Array[B] = appendedAll(suffix) - @`inline` final def ++[sealed B >: A : ClassTag](xs: IterableOnce[B]): Array[B] = appendedAll(xs) + @`inline` final def ++[B >: A : ClassTag](xs: IterableOnce[B]): Array[B] = appendedAll(xs) - @`inline` final def ++[sealed B >: A : ClassTag](xs: Array[_ <: B]): Array[B] = appendedAll(xs) + @`inline` final def ++[B >: A : ClassTag](xs: Array[_ <: B]): Array[B] = appendedAll(xs) /** Tests whether this array contains a given value as an element. * @@ -1218,7 +1218,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @param other The patch values * @param replaced The number of values in the original array that are replaced by the patch. */ - def patch[sealed B >: A : ClassTag](from: Int, other: IterableOnce[B], replaced: Int): Array[B] = { + def patch[B >: A : ClassTag](from: Int, other: IterableOnce[B], replaced: Int): Array[B] = { val b = ArrayBuilder.make[B] val k = other.knownSize val r = if(replaced < 0) 0 else replaced @@ -1244,7 +1244,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @return a pair of Arrays, containing, respectively, the first and second half * of each element pair of this Array. */ - def unzip[sealed A1, sealed A2](implicit asPair: A => (A1, A2), ct1: ClassTag[A1], ct2: ClassTag[A2]): (Array[A1], Array[A2]) = { + def unzip[A1, A2](implicit asPair: A => (A1, A2), ct1: ClassTag[A1], ct2: ClassTag[A2]): (Array[A1], Array[A2]) = { val a1 = new Array[A1](xs.length) val a2 = new Array[A2](xs.length) var i = 0 @@ -1273,7 +1273,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @return a triple of Arrays, containing, respectively, the first, second, and third * elements from each element triple of this Array. */ - def unzip3[sealed A1, sealed A2, sealed A3](implicit asTriple: A => (A1, A2, A3), ct1: ClassTag[A1], ct2: ClassTag[A2], + def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3), ct1: ClassTag[A1], ct2: ClassTag[A2], ct3: ClassTag[A3]): (Array[A1], Array[A2], Array[A3]) = { val a1 = new Array[A1](xs.length) val a2 = new Array[A2](xs.length) @@ -1295,7 +1295,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @param asArray A function that converts elements of this array to rows - arrays of type `B`. * @return An array obtained by replacing elements of this arrays with rows the represent. */ - def transpose[sealed B](implicit asArray: A => Array[B]): Array[Array[B]] = { + def transpose[B](implicit asArray: A => Array[B]): Array[Array[B]] = { val aClass = xs.getClass.getComponentType val bb = new ArrayBuilder.ofRef[Array[B]]()(ClassTag[Array[B]](aClass)) if (xs.length == 0) bb.result() @@ -1358,7 +1358,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * all elements of this array followed by the minimal number of occurrences of `elem` so * that the resulting collection has a length of at least `len`. */ - def padTo[sealed B >: A : ClassTag](len: Int, elem: B): Array[B] = { + def padTo[B >: A : ClassTag](len: Int, elem: B): Array[B] = { var i = xs.length val newlen = max(i, len) val dest = Array.copyAs[B](xs, newlen) @@ -1418,7 +1418,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @tparam K the type of keys returned by the discriminator function * @tparam B the type of values returned by the transformation function */ - def groupMap[K, sealed B : ClassTag](key: A => K)(f: A => B): immutable.Map[K, Array[B]] = { + def groupMap[K, B : ClassTag](key: A => K)(f: A => B): immutable.Map[K, Array[B]] = { val m = mutable.Map.empty[K, ArrayBuilder[B]] val len = xs.length var i = 0 @@ -1445,7 +1445,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @param xs the array to fill. * @tparam B the type of the elements of the array. */ - def copyToArray[sealed B >: A](xs: Array[B]): Int = copyToArray(xs, 0) + def copyToArray[B >: A](xs: Array[B]): Int = copyToArray(xs, 0) /** Copy elements of this array to another array. * Fills the given array `xs` starting at index `start`. @@ -1456,7 +1456,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @param start the starting index within the destination array. * @tparam B the type of the elements of the array. */ - def copyToArray[sealed B >: A](xs: Array[B], start: Int): Int = copyToArray(xs, start, Int.MaxValue) + def copyToArray[B >: A](xs: Array[B], start: Int): Int = copyToArray(xs, start, Int.MaxValue) /** Copy elements of this array to another array. * Fills the given array `xs` starting at index `start` with at most `len` values. @@ -1468,7 +1468,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @param len the maximal number of elements to copy. * @tparam B the type of the elements of the array. */ - def copyToArray[sealed B >: A](xs: Array[B], start: Int, len: Int): Int = { + def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = { val copied = IterableOnce.elemsToCopyToArray(this.xs.length, xs.length, start, len) if (copied > 0) { Array.copy(this.xs, 0, xs, start, copied) @@ -1477,7 +1477,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { } /** Create a copy of this array with the specified element type. */ - def toArray[sealed B >: A: ClassTag]: Array[B] = { + def toArray[B >: A: ClassTag]: Array[B] = { val destination = new Array[B](xs.length) copyToArray(destination, 0) destination @@ -1496,7 +1496,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { // can't use a default arg because we already have another overload with a default arg /** Tests whether this array starts with the given array. */ - @`inline` def startsWith[sealed B >: A](that: Array[B]): Boolean = startsWith(that, 0) + @`inline` def startsWith[B >: A](that: Array[B]): Boolean = startsWith(that, 0) /** Tests whether this array contains the given array at a given index. * @@ -1505,7 +1505,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @return `true` if the array `that` is contained in this array at * index `offset`, otherwise `false`. */ - def startsWith[sealed B >: A](that: Array[B], offset: Int): Boolean = { + def startsWith[B >: A](that: Array[B], offset: Int): Boolean = { val safeOffset = offset.max(0) val thatl = that.length if(thatl > xs.length-safeOffset) thatl == 0 @@ -1524,7 +1524,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @param that the array to test * @return `true` if this array has `that` as a suffix, `false` otherwise. */ - def endsWith[sealed B >: A](that: Array[B]): Boolean = { + def endsWith[B >: A](that: Array[B]): Boolean = { val thatl = that.length val off = xs.length - thatl if(off < 0) false @@ -1544,7 +1544,7 @@ final class ArrayOps[sealed A](private val xs: Array[A]) extends AnyVal { * @return a new array which is a copy of this array with the element at position `index` replaced by `elem`. * @throws IndexOutOfBoundsException if `index` does not satisfy `0 <= index < length`. */ - def updated[sealed B >: A : ClassTag](index: Int, elem: B): Array[B] = { + def updated[B >: A : ClassTag](index: Int, elem: B): Array[B] = { if(index < 0 || index >= xs.length) throw new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${xs.length-1})") val dest = toArray[B] dest(index) = elem diff --git a/tests/pos-special/stdlib/collection/BuildFrom.scala b/tests/pos-special/stdlib/collection/BuildFrom.scala index 0a3cc199d4dc..05df32856d82 100644 --- a/tests/pos-special/stdlib/collection/BuildFrom.scala +++ b/tests/pos-special/stdlib/collection/BuildFrom.scala @@ -81,13 +81,13 @@ object BuildFrom extends BuildFromLowPriority1 { def newBuilder(from: WrappedString): mutable.Builder[Char, WrappedString] = WrappedString.newBuilder } - implicit def buildFromArray[sealed A : ClassTag]: BuildFrom[Array[_], A, Array[A]] = + implicit def buildFromArray[A : ClassTag]: BuildFrom[Array[_], A, Array[A]] = new BuildFrom[Array[_], A, Array[A]] { def fromSpecific(from: Array[_])(it: IterableOnce[A]^): Array[A] = Factory.arrayFactory[A].fromSpecific(it) def newBuilder(from: Array[_]): Builder[A, Array[A]] = Factory.arrayFactory[A].newBuilder } - implicit def buildFromView[A, sealed B]: BuildFrom[View[A], B, View[B]] = + implicit def buildFromView[A, B]: BuildFrom[View[A], B, View[B]] = new BuildFrom[View[A], B, View[B]] { def fromSpecific(from: View[A])(it: IterableOnce[B]^): View[B] = View.from(it).unsafeAssumePure def newBuilder(from: View[A]): Builder[B, View[B]] = View.newBuilder diff --git a/tests/pos-special/stdlib/collection/Factory.scala b/tests/pos-special/stdlib/collection/Factory.scala index c45776b62b9c..c50fa395a0fb 100644 --- a/tests/pos-special/stdlib/collection/Factory.scala +++ b/tests/pos-special/stdlib/collection/Factory.scala @@ -58,9 +58,9 @@ object Factory { def newBuilder: Builder[Char, String] = new mutable.StringBuilder() } - implicit def arrayFactory[sealed A: ClassTag]: Factory[A, Array[A]] = new ArrayFactory[A] + implicit def arrayFactory[A: ClassTag]: Factory[A, Array[A]] = new ArrayFactory[A] @SerialVersionUID(3L) - private class ArrayFactory[sealed A: ClassTag] extends Factory[A, Array[A]] with Serializable { + private class ArrayFactory[A: ClassTag] extends Factory[A, Array[A]] with Serializable { def fromSpecific(it: IterableOnce[A]^): Array[A] = { val b = newBuilder b.sizeHint(scala.math.max(0, it.knownSize)) diff --git a/tests/pos-special/stdlib/collection/IterableOnce.scala b/tests/pos-special/stdlib/collection/IterableOnce.scala index a88be4943c58..a0b184410428 100644 --- a/tests/pos-special/stdlib/collection/IterableOnce.scala +++ b/tests/pos-special/stdlib/collection/IterableOnce.scala @@ -14,7 +14,7 @@ package scala package collection import scala.annotation.tailrec -import scala.annotation.unchecked.{uncheckedVariance, uncheckedCaptures} +import scala.annotation.unchecked.uncheckedVariance import scala.collection.mutable.StringBuilder import scala.language.implicitConversions import scala.math.{Numeric, Ordering} @@ -162,10 +162,10 @@ final class IterableOnceExtensionMethods[A](private val it: IterableOnce[A]) ext def to[C1](factory: Factory[A, C1]): C1 = factory.fromSpecific(it) @deprecated("Use .iterator.to(ArrayBuffer) instead", "2.13.0") - def toBuffer[sealed B >: A]: mutable.Buffer[B] = mutable.ArrayBuffer.from(it) + def toBuffer[B >: A]: mutable.Buffer[B] = mutable.ArrayBuffer.from(it) @deprecated("Use .iterator.toArray", "2.13.0") - def toArray[sealed B >: A: ClassTag]: Array[B] = it match { + def toArray[B >: A: ClassTag]: Array[B] = it match { case it: Iterable[B] => it.toArray[B] case _ => it.iterator.toArray[B] } @@ -272,7 +272,7 @@ object IterableOnce { math.max(math.min(math.min(len, srcLen), destLen - start), 0) /** Calls `copyToArray` on the given collection, regardless of whether or not it is an `Iterable`. */ - @inline private[collection] def copyElemsToArray[A, sealed B >: A]( + @inline private[collection] def copyElemsToArray[A, B >: A]( elems: IterableOnce[A]^, xs: Array[B], start: Int = 0, @@ -890,7 +890,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A]^ => * @note Reuse: $consumesIterator */ @deprecatedOverriding("This should always forward to the 3-arg version of this method", since = "2.13.4") - def copyToArray[sealed B >: A](xs: Array[B]): Int = copyToArray(xs, 0, Int.MaxValue) + def copyToArray[B >: A](xs: Array[B]): Int = copyToArray(xs, 0, Int.MaxValue) /** Copy elements to an array, returning the number of elements written. * @@ -907,7 +907,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A]^ => * @note Reuse: $consumesIterator */ @deprecatedOverriding("This should always forward to the 3-arg version of this method", since = "2.13.4") - def copyToArray[sealed B >: A](xs: Array[B], start: Int): Int = copyToArray(xs, start, Int.MaxValue) + def copyToArray[B >: A](xs: Array[B], start: Int): Int = copyToArray(xs, start, Int.MaxValue) /** Copy elements to an array, returning the number of elements written. * @@ -924,7 +924,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A]^ => * * @note Reuse: $consumesIterator */ - def copyToArray[sealed B >: A](xs: Array[B], start: Int, len: Int): Int = { + def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = { val it = iterator var i = start val end = start + math.min(len, xs.length - start) @@ -1313,13 +1313,13 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A]^ => @deprecated("Use .to(LazyList) instead of .toStream", "2.13.0") @`inline` final def toStream: immutable.Stream[A] = to(immutable.Stream) - @`inline` final def toBuffer[sealed B >: A]: mutable.Buffer[B] = mutable.Buffer.from(this) + @`inline` final def toBuffer[B >: A]: mutable.Buffer[B] = mutable.Buffer.from(this) /** Convert collection to array. * * Implementation note: DO NOT call [[Array.from]] from this method. */ - def toArray[sealed B >: A: ClassTag]: Array[B] = + def toArray[B >: A: ClassTag]: Array[B] = if (knownSize >= 0) { val destination = new Array[B](knownSize) copyToArray(destination, 0) @@ -1341,8 +1341,8 @@ object IterableOnceOps: // Moved out of trait IterableOnceOps to here, since universal traits cannot // have nested classes in Scala 3 private class Maximized[X, B](descriptor: String)(f: X -> B)(cmp: (B, B) -> Boolean) extends AbstractFunction2[Maximized[X, B], X, Maximized[X, B]] { - var maxElem: X @uncheckedCaptures = null.asInstanceOf[X] - var maxF: B @uncheckedCaptures = null.asInstanceOf[B] + var maxElem: X = null.asInstanceOf[X] + var maxF: B = null.asInstanceOf[B] var nonEmpty = false def toOption: Option[X] = if (nonEmpty) Some(maxElem) else None def result: X = if (nonEmpty) maxElem else throw new UnsupportedOperationException(s"empty.$descriptor") diff --git a/tests/pos-special/stdlib/collection/Iterator.scala b/tests/pos-special/stdlib/collection/Iterator.scala index 90fd387069b0..57a12767320a 100644 --- a/tests/pos-special/stdlib/collection/Iterator.scala +++ b/tests/pos-special/stdlib/collection/Iterator.scala @@ -14,10 +14,9 @@ package scala.collection import scala.collection.mutable.{ArrayBuffer, ArrayBuilder, Builder, ImmutableBuilder} import scala.annotation.tailrec -import scala.annotation.unchecked.{uncheckedVariance, uncheckedCaptures} +import scala.annotation.unchecked.uncheckedVariance import scala.runtime.Statics import language.experimental.captureChecking -import annotation.unchecked.uncheckedCaptures /** Iterators are data structures that allow to iterate over a sequence @@ -161,12 +160,12 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite require(size >= 1 && step >= 1, f"size=$size%d and step=$step%d, but both must be positive") - private[this] var buffer: Array[B @uncheckedCaptures] = null // current result - private[this] var prev: Array[B @uncheckedCaptures] = null // if sliding, overlap from previous result + private[this] var buffer: Array[B] = null // current result + private[this] var prev: Array[B] = null // if sliding, overlap from previous result private[this] var first = true // if !first, advancing may skip ahead private[this] var filled = false // whether the buffer is "hot" private[this] var partial = true // whether to emit partial sequence - private[this] var padding: () -> B @uncheckedCaptures = null // what to pad short sequences with + private[this] var padding: () -> B = null // what to pad short sequences with private[this] def pad = padding != null // irrespective of partial flag private[this] def newBuilder = { val b = ArrayBuilder.make[Any] @@ -258,7 +257,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite } // segment must have data, and must be complete unless they allow partial val ok = index > 0 && (partial || index == size) - if (ok) buffer = builder.result().asInstanceOf[Array[B @uncheckedCaptures]] + if (ok) buffer = builder.result().asInstanceOf[Array[B]] else prev = null ok } @@ -417,8 +416,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite @deprecated("Call scanRight on an Iterable instead.", "2.13.0") def scanRight[B](z: B)(op: (A, B) => B): Iterator[B]^{this} = - ArrayBuffer.from[A @uncheckedCaptures](this).scanRight(z)(op).iterator - // @uncheckedCaptures is safe since the ArrayBuffer is local temporrary storage + ArrayBuffer.from[A](this).scanRight(z)(op).iterator def indexWhere(p: A => Boolean, from: Int = 0): Int = { var i = math.max(from, 0) @@ -561,7 +559,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite */ def distinctBy[B](f: A -> B): Iterator[A]^{this} = new AbstractIterator[A] { - private[this] val traversedValues = mutable.HashSet.empty[B @uncheckedCaptures] + private[this] val traversedValues = mutable.HashSet.empty[B] private[this] var nextElementDefined: Boolean = false private[this] var nextElement: A = _ @@ -704,7 +702,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite */ private[this] var status = 0 private def store(a: A): Unit = { - if (lookahead == null) lookahead = new mutable.Queue[A @uncheckedCaptures] + if (lookahead == null) lookahead = new mutable.Queue[A] lookahead += a } def hasNext = { @@ -867,8 +865,8 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * @note Reuse: $consumesOneAndProducesTwoIterators */ def duplicate: (Iterator[A]^{this}, Iterator[A]^{this}) = { - val gap = new scala.collection.mutable.Queue[A @uncheckedCaptures] - var ahead: Iterator[A @uncheckedCaptures] = null // ahead is captured by Partner, so A is not recognized as parametric + val gap = new scala.collection.mutable.Queue[A] + var ahead: Iterator[A] = null // ahead is captured by Partner, so A is not recognized as parametric class Partner extends AbstractIterator[A] { override def knownSize: Int = self.synchronized { val thisSize = self.knownSize @@ -1145,9 +1143,9 @@ object Iterator extends IterableFactory[Iterator] { * Nested ConcatIterators are merged to avoid blowing the stack. */ private final class ConcatIterator[+A](val from: Iterator[A]^) extends AbstractIterator[A] { - private var current: Iterator[A @uncheckedCaptures]^{cap[ConcatIterator]} = from - private var tail: ConcatIteratorCell[A @uncheckedVariance @uncheckedCaptures] = null - private var last: ConcatIteratorCell[A @uncheckedVariance @uncheckedCaptures] = null + private var current: Iterator[A]^{from*} = from + private var tail: ConcatIteratorCell[A @uncheckedVariance] = null + private var last: ConcatIteratorCell[A @uncheckedVariance] = null private var currentHasNextChecked = false def hasNext = @@ -1216,7 +1214,7 @@ object Iterator extends IterableFactory[Iterator] { } } - private[this] final class ConcatIteratorCell[A](head: => IterableOnce[A]^, var tail: ConcatIteratorCell[A @uncheckedCaptures]) { + private[this] final class ConcatIteratorCell[A](head: => IterableOnce[A]^, var tail: ConcatIteratorCell[A]) { def headIterator: Iterator[A]^{this} = head.iterator // CC todo: can't use {head} as capture set, gives "cannot establish a reference" } @@ -1277,8 +1275,8 @@ object Iterator extends IterableFactory[Iterator] { * type `A` and update an internal state of type `S`. */ private final class UnfoldIterator[A, S](init: S)(f: S => Option[(A, S)])extends AbstractIterator[A] { - private[this] var state: S @uncheckedCaptures = init - private[this] var nextResult: Option[(A, S)] @uncheckedCaptures = null + private[this] var state: S = init + private[this] var nextResult: Option[(A, S)] = null override def hasNext: Boolean = { if (nextResult eq null) { diff --git a/tests/pos-special/stdlib/collection/MapView.scala b/tests/pos-special/stdlib/collection/MapView.scala index ac9e88466052..595fe20538d3 100644 --- a/tests/pos-special/stdlib/collection/MapView.scala +++ b/tests/pos-special/stdlib/collection/MapView.scala @@ -161,7 +161,7 @@ object MapView extends MapViewFactory { override def isEmpty: Boolean = underlying.isEmpty } - override def newBuilder[sealed X, sealed Y]: Builder[(X, Y), MapView[X, Y]] = mutable.HashMap.newBuilder[X, Y].mapResult(_.view) + override def newBuilder[X, Y]: Builder[(X, Y), MapView[X, Y]] = mutable.HashMap.newBuilder[X, Y].mapResult(_.view) override def empty[K, V]: MapView[K, V] = EmptyMapView.asInstanceOf[MapView[K, V]] diff --git a/tests/pos-special/stdlib/collection/Seq.scala b/tests/pos-special/stdlib/collection/Seq.scala index 365a1db1b849..334546d67dad 100644 --- a/tests/pos-special/stdlib/collection/Seq.scala +++ b/tests/pos-special/stdlib/collection/Seq.scala @@ -18,7 +18,6 @@ import Searching.{Found, InsertionPoint, SearchResult} import scala.annotation.nowarn import language.experimental.captureChecking import caps.unsafe.unsafeAssumePure -import scala.annotation.unchecked.uncheckedCaptures /** Base trait for sequence collections * @@ -601,8 +600,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => if (!hasNext) Iterator.empty.next() - val forcedElms = new mutable.ArrayBuffer[A @uncheckedCaptures](elms.size) ++= elms - // uncheckedCaptures OK since used only locally + val forcedElms = new mutable.ArrayBuffer[A](elms.size) ++= elms val result = (newSpecificBuilder ++= forcedElms).result() var i = idxs.length - 2 while(i >= 0 && idxs(i) >= idxs(i+1)) @@ -893,7 +891,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * part of the result, but any following occurrences will. */ def diff[B >: A](that: Seq[B]): C = { - val occ = occCounts[B @uncheckedCaptures](that) + val occ = occCounts[B](that) fromSpecific(iterator.filter { x => var include = false occ.updateWith(x) { @@ -918,7 +916,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * in the result, but any following occurrences will be omitted. */ def intersect[B >: A](that: Seq[B]): C = { - val occ = occCounts[B @uncheckedCaptures](that) + val occ = occCounts[B](that) fromSpecific(iterator.filter { x => var include = true occ.updateWith(x) { @@ -966,7 +964,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => iterableFactory.from(new View.Updated(this, index, elem)) } - protected[collection] def occCounts[sealed B](sq: Seq[B]): mutable.Map[B, Int] = { + protected[collection] def occCounts[B](sq: Seq[B]): mutable.Map[B, Int] = { val occ = new mutable.HashMap[B, Int]() for (y <- sq) occ.updateWith(y) { case None => Some(1) diff --git a/tests/pos-special/stdlib/collection/SeqView.scala b/tests/pos-special/stdlib/collection/SeqView.scala index a4ca1143f8b4..7ec22cd54c83 100644 --- a/tests/pos-special/stdlib/collection/SeqView.scala +++ b/tests/pos-special/stdlib/collection/SeqView.scala @@ -196,7 +196,7 @@ object SeqView { // contains items of another type, we'd get a CCE anyway) // - the cast doesn't actually do anything in the runtime because the // type of A is not known and Array[_] is Array[AnyRef] - immutable.ArraySeq.unsafeWrapArray(arr.asInstanceOf[Array[A @uncheckedCaptures]]) + immutable.ArraySeq.unsafeWrapArray(arr.asInstanceOf[Array[A]]) } } evaluated = true diff --git a/tests/pos-special/stdlib/collection/StrictOptimizedSeqOps.scala b/tests/pos-special/stdlib/collection/StrictOptimizedSeqOps.scala index bfea9eda8bd3..b8af7e5f172b 100644 --- a/tests/pos-special/stdlib/collection/StrictOptimizedSeqOps.scala +++ b/tests/pos-special/stdlib/collection/StrictOptimizedSeqOps.scala @@ -12,7 +12,6 @@ package scala.collection import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** * Trait that overrides operations on sequences in order @@ -25,7 +24,7 @@ trait StrictOptimizedSeqOps [+A, +CC[_], +C] override def distinctBy[B](f: A -> B): C = { val builder = newSpecificBuilder - val seen = mutable.HashSet.empty[B @uncheckedCaptures] + val seen = mutable.HashSet.empty[B] val it = this.iterator while (it.hasNext) { val next = it.next() @@ -80,7 +79,7 @@ trait StrictOptimizedSeqOps [+A, +CC[_], +C] override def diff[B >: A](that: Seq[B]): C = if (isEmpty || that.isEmpty) coll else { - val occ = occCounts[B @uncheckedCaptures](that) + val occ = occCounts[B](that) val b = newSpecificBuilder for (x <- this) { occ.updateWith(x) { @@ -98,7 +97,7 @@ trait StrictOptimizedSeqOps [+A, +CC[_], +C] override def intersect[B >: A](that: Seq[B]): C = if (isEmpty || that.isEmpty) empty else { - val occ = occCounts[B @uncheckedCaptures](that) + val occ = occCounts[B](that) val b = newSpecificBuilder for (x <- this) { occ.updateWith(x) { diff --git a/tests/pos-special/stdlib/collection/StringOps.scala b/tests/pos-special/stdlib/collection/StringOps.scala index 3e3e2f8d872e..f570531def98 100644 --- a/tests/pos-special/stdlib/collection/StringOps.scala +++ b/tests/pos-special/stdlib/collection/StringOps.scala @@ -964,7 +964,7 @@ final class StringOps(private val s: String) extends AnyVal { else if (s.equalsIgnoreCase("false")) false else throw new IllegalArgumentException("For input string: \""+s+"\"") - def toArray[sealed B >: Char](implicit tag: ClassTag[B]): Array[B] = + def toArray[B >: Char](implicit tag: ClassTag[B]): Array[B] = if (tag == ClassTag.Char) s.toCharArray.asInstanceOf[Array[B]] else new WrappedString(s).toArray[B] diff --git a/tests/pos-special/stdlib/collection/View.scala b/tests/pos-special/stdlib/collection/View.scala index d91fc0c49939..8e2ee3ad9e32 100644 --- a/tests/pos-special/stdlib/collection/View.scala +++ b/tests/pos-special/stdlib/collection/View.scala @@ -15,7 +15,6 @@ package scala.collection import scala.annotation.{nowarn, tailrec} import scala.collection.mutable.{ArrayBuffer, Builder} import scala.collection.immutable.LazyList -import scala.annotation.unchecked.uncheckedCaptures import language.experimental.captureChecking /** Views are collections whose transformation operations are non strict: the resulting elements @@ -78,7 +77,7 @@ object View extends IterableFactory[View] { def empty[A]: View[A] = Empty - def newBuilder[sealed A]: Builder[A, View[A]] = ArrayBuffer.newBuilder[A].mapResult(from) + def newBuilder[A]: Builder[A, View[A]] = ArrayBuffer.newBuilder[A].mapResult(from) override def apply[A](xs: A*): View[A] = new Elems(xs: _*) @@ -449,7 +448,7 @@ object View extends IterableFactory[View] { } private final class TakeRightIterator[A](underlying: Iterator[A]^, maxlen: Int) extends AbstractIterator[A] { - private[this] var current: Iterator[A @uncheckedCaptures]^{underlying} = underlying + private[this] var current: Iterator[A]^{underlying} = underlying private[this] var len: Int = -1 private[this] var pos: Int = 0 private[this] var buf: ArrayBuffer[AnyRef] = _ diff --git a/tests/pos-special/stdlib/collection/concurrent/TrieMap.scala b/tests/pos-special/stdlib/collection/concurrent/TrieMap.scala index 0824ecc44519..8a34eddf0bdb 100644 --- a/tests/pos-special/stdlib/collection/concurrent/TrieMap.scala +++ b/tests/pos-special/stdlib/collection/concurrent/TrieMap.scala @@ -24,9 +24,8 @@ import scala.collection.mutable.GrowableBuilder import scala.util.Try import scala.util.hashing.Hashing import language.experimental.captureChecking -import caps.unsafe.unsafeAssumePure -private[collection] final class INode[sealed K, sealed V](bn: MainNode[K, V], g: Gen, equiv: Equiv[K]) extends INodeBase[K, V](g) { +private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen, equiv: Equiv[K]) extends INodeBase[K, V](g) { import INodeBase._ WRITE(bn) @@ -429,7 +428,7 @@ private[concurrent] object INode { final val KEY_ABSENT = new AnyRef final val KEY_PRESENT_OR_ABSENT = new AnyRef - def newRootNode[sealed K, sealed V](equiv: Equiv[K]) = { + def newRootNode[K, V](equiv: Equiv[K]) = { val gen = new Gen val cn = new CNode[K, V](0, new Array(0), gen) new INode[K, V](cn, gen, equiv) @@ -437,7 +436,7 @@ private[concurrent] object INode { } -private[concurrent] final class FailedNode[sealed K, sealed V](p: MainNode[K, V]) extends MainNode[K, V] { +private[concurrent] final class FailedNode[K, V](p: MainNode[K, V]) extends MainNode[K, V] { WRITE_PREV(p) def string(lev: Int) = throw new UnsupportedOperationException @@ -450,12 +449,12 @@ private[concurrent] final class FailedNode[sealed K, sealed V](p: MainNode[K, V] } -private[concurrent] trait KVNode[sealed K, sealed V] { +private[concurrent] trait KVNode[K, V] { def kvPair: (K, V) } -private[collection] final class SNode[sealed K, sealed V](final val k: K, final val v: V, final val hc: Int) +private[collection] final class SNode[K, V](final val k: K, final val v: V, final val hc: Int) extends BasicNode with KVNode[K, V] { def copy = new SNode(k, v, hc) def copyTombed = new TNode(k, v, hc) @@ -465,7 +464,7 @@ private[collection] final class SNode[sealed K, sealed V](final val k: K, final } // Tomb Node, used to ensure proper ordering during removals -private[collection] final class TNode[sealed K, sealed V](final val k: K, final val v: V, final val hc: Int) +private[collection] final class TNode[K, V](final val k: K, final val v: V, final val hc: Int) extends MainNode[K, V] with KVNode[K, V] { def copy = new TNode(k, v, hc) def copyTombed = new TNode(k, v, hc) @@ -477,7 +476,7 @@ private[collection] final class TNode[sealed K, sealed V](final val k: K, final } // List Node, leaf node that handles hash collisions -private[collection] final class LNode[sealed K, sealed V](val entries: List[(K, V)], equiv: Equiv[K]) +private[collection] final class LNode[K, V](val entries: List[(K, V)], equiv: Equiv[K]) extends MainNode[K, V] { def this(k: K, v: V, equiv: Equiv[K]) = this((k -> v) :: Nil, equiv) @@ -519,7 +518,7 @@ private[collection] final class LNode[sealed K, sealed V](val entries: List[(K, } // Ctrie Node, contains bitmap and array of references to branch nodes -private[collection] final class CNode[sealed K, sealed V](val bitmap: Int, val array: Array[BasicNode], val gen: Gen) extends CNodeBase[K, V] { +private[collection] final class CNode[K, V](val bitmap: Int, val array: Array[BasicNode], val gen: Gen) extends CNodeBase[K, V] { // this should only be called from within read-only snapshots def cachedSize(ct: AnyRef): Int = { val currsz = READ_SIZE() @@ -655,7 +654,7 @@ private[collection] final class CNode[sealed K, sealed V](val bitmap: Int, val a private[concurrent] object CNode { - def dual[sealed K, sealed V](x: SNode[K, V], xhc: Int, y: SNode[K, V], yhc: Int, lev: Int, gen: Gen, equiv: Equiv[K]): MainNode[K, V] = if (lev < 35) { + def dual[K, V](x: SNode[K, V], xhc: Int, y: SNode[K, V], yhc: Int, lev: Int, gen: Gen, equiv: Equiv[K]): MainNode[K, V] = if (lev < 35) { val xidx = (xhc >>> lev) & 0x1f val yidx = (yhc >>> lev) & 0x1f val bmp = (1 << xidx) | (1 << yidx) @@ -690,7 +689,7 @@ private[concurrent] case class RDCSS_Descriptor[K, V](old: INode[K, V], expected * For details, see: [[http://lampwww.epfl.ch/~prokopec/ctries-snapshot.pdf]] */ @SerialVersionUID(-5212455458703321708L) -final class TrieMap[sealed K, sealed V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater[TrieMap[K, V], AnyRef], hashf: Hashing[K], ef: Equiv[K]) +final class TrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater[TrieMap[K, V], AnyRef], hashf: Hashing[K], ef: Equiv[K]) extends scala.collection.mutable.AbstractMap[K, V] with scala.collection.concurrent.Map[K, V] with scala.collection.mutable.MapOps[K, V, TrieMap, TrieMap[K, V]] @@ -1043,11 +1042,11 @@ final class TrieMap[sealed K, sealed V] private (r: AnyRef, rtupd: AtomicReferen @SerialVersionUID(3L) object TrieMap extends MapFactory[TrieMap] { - def empty[sealed K, sealed V]: TrieMap[K, V] = new TrieMap[K, V] + def empty[K, V]: TrieMap[K, V] = new TrieMap[K, V] - def from[sealed K, sealed V](it: IterableOnce[(K, V)]^): TrieMap[K, V] = new TrieMap[K, V]() ++= it + def from[K, V](it: IterableOnce[(K, V)]^): TrieMap[K, V] = new TrieMap[K, V]() ++= it - def newBuilder[sealed K, sealed V]: mutable.GrowableBuilder[(K, V), TrieMap[K, V]] = new GrowableBuilder(empty[K, V]) + def newBuilder[K, V]: mutable.GrowableBuilder[(K, V), TrieMap[K, V]] = new GrowableBuilder(empty[K, V]) @transient val inodeupdater: AtomicReferenceFieldUpdater[INodeBase[_, _], MainNode[_, _]] = AtomicReferenceFieldUpdater.newUpdater(classOf[INodeBase[_, _]], classOf[MainNode[_, _]], "mainnode") @@ -1071,7 +1070,7 @@ object TrieMap extends MapFactory[TrieMap] { } // non-final as an extension point for parallel collections -private[collection] class TrieMapIterator[sealed K, sealed V](var level: Int, private var ct: TrieMap[K, V], mustInit: Boolean = true) extends AbstractIterator[(K, V)] { +private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: TrieMap[K, V], mustInit: Boolean = true) extends AbstractIterator[(K, V)] { private val stack = new Array[Array[BasicNode]](7) private val stackpos = new Array[Int](7) private var depth = -1 diff --git a/tests/pos-special/stdlib/collection/generic/DefaultSerializationProxy.scala b/tests/pos-special/stdlib/collection/generic/DefaultSerializationProxy.scala index 7eba9433b8d5..e36bb77ebdb8 100644 --- a/tests/pos-special/stdlib/collection/generic/DefaultSerializationProxy.scala +++ b/tests/pos-special/stdlib/collection/generic/DefaultSerializationProxy.scala @@ -17,7 +17,6 @@ import java.io.{ObjectInputStream, ObjectOutputStream} import scala.collection.{Factory, Iterable} import scala.collection.mutable.Builder import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** The default serialization proxy for collection implementations. * @@ -29,8 +28,7 @@ import scala.annotation.unchecked.uncheckedCaptures @SerialVersionUID(3L) final class DefaultSerializationProxy[A](factory: Factory[A, Any], @transient private[this] val coll: Iterable[A]) extends Serializable { - @transient protected var builder: Builder[A @uncheckedCaptures, Any] = _ - // @uncheckedCaptures OK since builder is used only locally when reading objects + @transient protected var builder: Builder[A, Any] = _ private[this] def writeObject(out: ObjectOutputStream): Unit = { out.defaultWriteObject() diff --git a/tests/pos-special/stdlib/collection/generic/IsSeq.scala b/tests/pos-special/stdlib/collection/generic/IsSeq.scala index 8ad344c4d4fc..041d74f84d9c 100644 --- a/tests/pos-special/stdlib/collection/generic/IsSeq.scala +++ b/tests/pos-special/stdlib/collection/generic/IsSeq.scala @@ -16,7 +16,6 @@ package generic import scala.reflect.ClassTag import language.experimental.captureChecking import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** Type class witnessing that a collection representation type `Repr` has * elements of type `A` and has a conversion to `SeqOps[A, Iterable, C]`, for @@ -92,7 +91,7 @@ object IsSeq { } } - implicit def arrayIsSeq[sealed A0 : ClassTag]: IsSeq[Array[A0]] { type A = A0; type C = Array[A0] } = + implicit def arrayIsSeq[A0 : ClassTag]: IsSeq[Array[A0]] { type A = A0; type C = Array[A0] } = new IsSeq[Array[A0]] { type A = A0 type C = Array[A0] @@ -100,7 +99,7 @@ object IsSeq { new SeqOps[A, mutable.ArraySeq, Array[A]] { def apply(i: Int): A = a(i) def length: Int = a.length - def toIterable: Iterable[A] = mutable.ArraySeq.make[A @uncheckedCaptures](a) + def toIterable: Iterable[A] = mutable.ArraySeq.make[A](a) protected def coll: Array[A] = a protected def fromSpecific(coll: IterableOnce[A]^): Array[A] = Array.from(coll) def iterableFactory: FreeSeqFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged diff --git a/tests/pos-special/stdlib/collection/immutable/ArraySeq.scala b/tests/pos-special/stdlib/collection/immutable/ArraySeq.scala index 3a221fc76b6c..e21490571d29 100644 --- a/tests/pos-special/stdlib/collection/immutable/ArraySeq.scala +++ b/tests/pos-special/stdlib/collection/immutable/ArraySeq.scala @@ -24,7 +24,6 @@ import scala.runtime.ScalaRunTime import scala.util.Sorting import scala.util.hashing.MurmurHash3 import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** * An immutable array. @@ -59,7 +58,7 @@ sealed abstract class ArraySeq[+A] def unsafeArrayAsAnyArray = unsafeArray.asInstanceOf[Array[Any]] protected def evidenceIterableFactory: ArraySeq.type = ArraySeq - protected def iterableEvidence: ClassTag[A @uncheckedVariance @uncheckedCaptures] = elemTag.asInstanceOf[ClassTag[A]] + protected def iterableEvidence: ClassTag[A @uncheckedVariance] = elemTag.asInstanceOf[ClassTag[A]] def stepper[S <: Stepper[_]](implicit shape: StepperShape[A, S]): S with EfficientSplit @@ -109,8 +108,8 @@ sealed abstract class ArraySeq[+A] null else if (thisIsObj) { // A and B are objects - val ax = this.unsafeArray.asInstanceOf[Array[A @uncheckedCaptures]] - val ay = that.unsafeArray.asInstanceOf[Array[B @uncheckedCaptures]] + val ax = this.unsafeArray.asInstanceOf[Array[A]] + val ay = that.unsafeArray.asInstanceOf[Array[B]] val len = ax.length + ay.length val a = new Array[AnyRef](len) System.arraycopy(ax, 0, a, 0, ax.length) @@ -118,8 +117,8 @@ sealed abstract class ArraySeq[+A] ArraySeq.unsafeWrapArray(a).asInstanceOf[ArraySeq[B]] } else { // A is a primative and B = A. Use this instance's protected ClassTag. - val ax = this.unsafeArray.asInstanceOf[Array[A @uncheckedCaptures]] - val ay = that.unsafeArray.asInstanceOf[Array[A @uncheckedCaptures]] + val ax = this.unsafeArray.asInstanceOf[Array[A]] + val ay = that.unsafeArray.asInstanceOf[Array[A]] val len = ax.length + ay.length val a = iterableEvidence.newArray(len) System.arraycopy(ax, 0, a, 0, ax.length) @@ -186,7 +185,7 @@ sealed abstract class ArraySeq[+A] strictOptimizedZip[B, ArraySeq[(A, B)]](that, iterableFactory.newBuilder) } - private inline def ops[A](xs: Array[A @uncheckedCaptures]): ArrayOps[A] = new ArrayOps[A @uncheckedCaptures](xs) + private inline def ops[A](xs: Array[A]): ArrayOps[A] = new ArrayOps[A](xs) override def take(n: Int): ArraySeq[A] = if (unsafeArray.length <= n) @@ -252,7 +251,7 @@ sealed abstract class ArraySeq[+A] override protected[this] def className = "ArraySeq" - override def copyToArray[sealed B >: A](xs: Array[B], start: Int, len: Int): Int = { + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = { val copied = IterableOnce.elemsToCopyToArray(length, xs.length, start, len) if(copied > 0) { Array.copy(unsafeArray, 0, xs, start, copied) @@ -290,12 +289,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => } def newBuilder[A : ClassTag]: Builder[A, ArraySeq[A]] = - ArrayBuffer.newBuilder[A @uncheckedCaptures].mapResult(b => unsafeWrapArray[A](b.toArray)) + ArrayBuffer.newBuilder[A].mapResult(b => unsafeWrapArray[A](b.toArray)) override def fill[A : ClassTag](n: Int)(elem: => A): ArraySeq[A] = tabulate(n)(_ => elem) override def tabulate[A : ClassTag](n: Int)(f: Int => A): ArraySeq[A] = { - val elements = Array.ofDim[A @uncheckedCaptures](scala.math.max(n, 0)) + val elements = Array.ofDim[A](scala.math.max(n, 0)) var i = 0 while (i < n) { ScalaRunTime.array_update(elements, i, f(i)) @@ -316,7 +315,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => * `ArraySeq.unsafeWrapArray(a.asInstanceOf[Array[Int]])` does not work, it throws a * `ClassCastException` at runtime. */ - def unsafeWrapArray[T](x: Array[T @uncheckedCaptures]): ArraySeq[T] = ((x: @unchecked) match { + def unsafeWrapArray[T](x: Array[T]): ArraySeq[T] = ((x: @unchecked) match { case null => null case x: Array[AnyRef] => new ofRef[AnyRef](x) case x: Array[Int] => new ofInt(x) diff --git a/tests/pos-special/stdlib/collection/immutable/HashMap.scala b/tests/pos-special/stdlib/collection/immutable/HashMap.scala index c364924db3a3..8faa37625d51 100644 --- a/tests/pos-special/stdlib/collection/immutable/HashMap.scala +++ b/tests/pos-special/stdlib/collection/immutable/HashMap.scala @@ -26,7 +26,6 @@ import scala.runtime.AbstractFunction2 import scala.runtime.Statics.releaseFence import scala.util.hashing.MurmurHash3 import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** This class implements immutable maps using a Compressed Hash-Array Mapped Prefix-tree. * See paper https://michael.steindorfer.name/publications/oopsla15.pdf for more details. @@ -1768,7 +1767,7 @@ private final class BitmapIndexedMapNode[K, +V]( } else { mapOfNewNodes |= bitpos if (newNodes eq null) { - newNodes = mutable.Queue.empty[MapNode[K, V] @uncheckedCaptures] + newNodes = mutable.Queue.empty[MapNode[K, V]] } newNodes += newSubNode } @@ -1853,7 +1852,7 @@ private final class BitmapIndexedMapNode[K, +V]( private final class HashCollisionMapNode[K, +V ]( val originalHash: Int, val hash: Int, - var content: Vector[(K, V @uV) @uncheckedCaptures] + var content: Vector[(K, V @uV)] ) extends MapNode[K, V] { import Node._ @@ -2157,7 +2156,7 @@ private final class MapKeyValueTupleReverseIterator[K, V](rootNode: MapNode[K, V private final class MapKeyValueTupleHashIterator[K, V](rootNode: MapNode[K, V]) extends ChampBaseReverseIterator[MapNode[K, V]](rootNode) with Iterator[Any] { private[this] var hash = 0 - private[this] var value: V @uncheckedCaptures = _ + private[this] var value: V = _ override def hashCode(): Int = MurmurHash3.tuple2Hash(hash, value.##, MurmurHash3.productSeed) def next() = { if (!hasNext) @@ -2229,12 +2228,12 @@ private[immutable] final class HashMapBuilder[K, V] extends ReusableBuilder[(K, /** The last given out HashMap as a return value of `result()`, if any, otherwise null. * Indicates that on next add, the elements should be copied to an identical structure, before continuing * mutations. */ - private var aliased: HashMap[K, V] @uncheckedCaptures = _ + private var aliased: HashMap[K, V] = _ private def isAliased: Boolean = aliased != null /** The root node of the partially build hashmap */ - private var rootNode: BitmapIndexedMapNode[K, V] @uncheckedCaptures = newEmptyRootNode + private var rootNode: BitmapIndexedMapNode[K, V] = newEmptyRootNode private[immutable] def getOrElse[V0 >: V](key: K, value: V0): V0 = if (rootNode.size == 0) value diff --git a/tests/pos-special/stdlib/collection/immutable/HashSet.scala b/tests/pos-special/stdlib/collection/immutable/HashSet.scala index 38f394a7005f..9a3676705201 100644 --- a/tests/pos-special/stdlib/collection/immutable/HashSet.scala +++ b/tests/pos-special/stdlib/collection/immutable/HashSet.scala @@ -24,7 +24,6 @@ import scala.collection.mutable.ReusableBuilder import scala.runtime.Statics.releaseFence import scala.util.hashing.MurmurHash3 import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** This class implements immutable sets using a Compressed Hash-Array Mapped Prefix-tree. * See paper https://michael.steindorfer.name/publications/oopsla15.pdf for more details. @@ -1154,7 +1153,7 @@ private final class BitmapIndexedSetNode[A]( } else { mapOfNewNodes |= bitpos if (newNodes eq null) { - newNodes = mutable.Queue.empty[SetNode[A] @uncheckedCaptures] + newNodes = mutable.Queue.empty[SetNode[A]] } newNodes += newSubNode } @@ -1162,7 +1161,7 @@ private final class BitmapIndexedSetNode[A]( newDataMap |= bitpos nodeMigrateToDataTargetMap |= bitpos if (nodesToMigrateToData eq null) { - nodesToMigrateToData = mutable.Queue.empty[SetNode[A] @uncheckedCaptures] + nodesToMigrateToData = mutable.Queue.empty[SetNode[A]] } nodesToMigrateToData += newSubNode } @@ -1269,7 +1268,7 @@ private final class BitmapIndexedSetNode[A]( } else { mapOfNewNodes |= bitpos if (newNodes eq null) { - newNodes = mutable.Queue.empty[SetNode[A] @uncheckedCaptures] + newNodes = mutable.Queue.empty[SetNode[A]] } newNodes += newSubNode } @@ -1277,7 +1276,7 @@ private final class BitmapIndexedSetNode[A]( newDataMap |= bitpos nodeMigrateToDataTargetMap |= bitpos if (nodesToMigrateToData eq null) { - nodesToMigrateToData = mutable.Queue.empty[SetNode[A] @uncheckedCaptures] + nodesToMigrateToData = mutable.Queue.empty[SetNode[A]] } nodesToMigrateToData += newSubNode } @@ -1742,7 +1741,7 @@ private final class BitmapIndexedSetNode[A]( } } -private final class HashCollisionSetNode[A](val originalHash: Int, val hash: Int, var content: Vector[A] @uncheckedCaptures) extends SetNode[A] { +private final class HashCollisionSetNode[A](val originalHash: Int, val hash: Int, var content: Vector[A]) extends SetNode[A] { import Node._ @@ -1971,12 +1970,12 @@ private[collection] final class HashSetBuilder[A] extends ReusableBuilder[A, Has /** The last given out HashSet as a return value of `result()`, if any, otherwise null. * Indicates that on next add, the elements should be copied to an identical structure, before continuing * mutations. */ - private var aliased: HashSet[A] @uncheckedCaptures = _ + private var aliased: HashSet[A] = _ private def isAliased: Boolean = aliased != null /** The root node of the partially build hashmap */ - private var rootNode: BitmapIndexedSetNode[A] @uncheckedCaptures = newEmptyRootNode + private var rootNode: BitmapIndexedSetNode[A] = newEmptyRootNode /** Inserts element `elem` into array `as` at index `ix`, shifting right the trailing elems */ private def insertElement(as: Array[Int], ix: Int, elem: Int): Array[Int] = { diff --git a/tests/pos-special/stdlib/collection/immutable/IntMap.scala b/tests/pos-special/stdlib/collection/immutable/IntMap.scala index d7077845b845..88148691e5c0 100644 --- a/tests/pos-special/stdlib/collection/immutable/IntMap.scala +++ b/tests/pos-special/stdlib/collection/immutable/IntMap.scala @@ -19,7 +19,6 @@ import scala.annotation.tailrec import scala.annotation.unchecked.uncheckedVariance import scala.language.implicitConversions import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** Utility class for integer maps. */ @@ -198,7 +197,7 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] override def empty: IntMap[T] = IntMap.Nil override def toList = { - val buffer = new scala.collection.mutable.ListBuffer[(Int, T) @uncheckedCaptures] + val buffer = new scala.collection.mutable.ListBuffer[(Int, T)] foreach(buffer += _) buffer.toList } diff --git a/tests/pos-special/stdlib/collection/immutable/LazyListIterable.scala b/tests/pos-special/stdlib/collection/immutable/LazyListIterable.scala index 5684130b6048..959dfbe36679 100644 --- a/tests/pos-special/stdlib/collection/immutable/LazyListIterable.scala +++ b/tests/pos-special/stdlib/collection/immutable/LazyListIterable.scala @@ -998,7 +998,7 @@ object LazyListIterable extends IterableFactory[LazyListIterable] { private def filterImpl[A](ll: LazyListIterable[A]^, p: A => Boolean, isFlipped: Boolean): LazyListIterable[A]^{ll, p} = { // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD - var restRef: LazyListIterable[A @uncheckedCaptures]^{cap[filterImpl]} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric newLL { var elem: A = null.asInstanceOf[A] var found = false @@ -1015,7 +1015,7 @@ object LazyListIterable extends IterableFactory[LazyListIterable] { private def collectImpl[A, B](ll: LazyListIterable[A]^, pf: PartialFunction[A, B]^): LazyListIterable[B]^{ll, pf} = { // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD - var restRef: LazyListIterable[A @uncheckedCaptures]^{cap[collectImpl]} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric newLL { val marker = Statics.pfMarker val toMarker = anyToMarker.asInstanceOf[A => B] // safe because Function1 is erased @@ -1034,9 +1034,9 @@ object LazyListIterable extends IterableFactory[LazyListIterable] { private def flatMapImpl[A, B](ll: LazyListIterable[A]^, f: A => IterableOnce[B]^): LazyListIterable[B]^{ll, f} = { // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD - var restRef: LazyListIterable[A @uncheckedCaptures]^{cap[flatMapImpl]} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric newLL { - var it: Iterator[B @uncheckedCaptures]^{ll, f} = null + var it: Iterator[B]^{ll, f} = null var itHasNext = false var rest = restRef // var rest = restRef.elem while (!itHasNext && !rest.isEmpty) { @@ -1058,7 +1058,7 @@ object LazyListIterable extends IterableFactory[LazyListIterable] { private def dropImpl[A](ll: LazyListIterable[A]^, n: Int): LazyListIterable[A]^{ll} = { // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD - var restRef: LazyListIterable[A @uncheckedCaptures]^{cap[dropImpl]} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric var iRef = n // val iRef = new IntRef(n) newLL { var rest = restRef // var rest = restRef.elem @@ -1075,7 +1075,7 @@ object LazyListIterable extends IterableFactory[LazyListIterable] { private def dropWhileImpl[A](ll: LazyListIterable[A]^, p: A => Boolean): LazyListIterable[A]^{ll, p} = { // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD - var restRef: LazyListIterable[A @uncheckedCaptures]^{cap[dropWhileImpl]} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric newLL { var rest = restRef // var rest = restRef.elem while (!rest.isEmpty && p(rest.head)) { @@ -1088,8 +1088,8 @@ object LazyListIterable extends IterableFactory[LazyListIterable] { private def takeRightImpl[A](ll: LazyListIterable[A]^, n: Int): LazyListIterable[A]^{ll} = { // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD - var restRef: LazyListIterable[A @uncheckedCaptures]^{cap[takeRightImpl]} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric - var scoutRef: LazyListIterable[A @uncheckedCaptures]^{cap[takeRightImpl]} = ll // same situation + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + var scoutRef: LazyListIterable[A]^{ll*} = ll // same situation var remainingRef = n // val remainingRef = new IntRef(n) newLL { var scout = scoutRef // var scout = scoutRef.elem @@ -1284,8 +1284,8 @@ object LazyListIterable extends IterableFactory[LazyListIterable] { private final class LazyBuilder[A] extends ReusableBuilder[A, LazyListIterable[A]] { import LazyBuilder._ - private[this] var next: DeferredState[A @uncheckedCaptures] = _ - private[this] var list: LazyListIterable[A @uncheckedCaptures] = _ + private[this] var next: DeferredState[A] = _ + private[this] var list: LazyListIterable[A] = _ clear() @@ -1343,7 +1343,9 @@ object LazyListIterable extends IterableFactory[LazyListIterable] { * of long evaluated lazy lists without exhausting the stack through recursive serialization of cons cells. */ @SerialVersionUID(3L) - final class SerializationProxy[A](@transient protected var coll: LazyListIterable[A]^) extends Serializable { + final class SerializationProxy[A](_coll: LazyListIterable[A]^) extends Serializable { + + @transient protected var coll: LazyListIterable[A]^{this} = _coll private[this] def writeObject(out: ObjectOutputStream): Unit = { out.defaultWriteObject() @@ -1358,7 +1360,7 @@ object LazyListIterable extends IterableFactory[LazyListIterable] { private[this] def readObject(in: ObjectInputStream): Unit = { in.defaultReadObject() - val init = new mutable.ListBuffer[A @uncheckedCaptures] + val init = new mutable.ListBuffer[A] var initRead = false while (!initRead) in.readObject match { case SerializeEnd => initRead = true diff --git a/tests/pos-special/stdlib/collection/immutable/List.scala b/tests/pos-special/stdlib/collection/immutable/List.scala index 6a305f4ebdec..913de8b0be08 100644 --- a/tests/pos-special/stdlib/collection/immutable/List.scala +++ b/tests/pos-special/stdlib/collection/immutable/List.scala @@ -14,7 +14,7 @@ package scala package collection package immutable -import scala.annotation.unchecked.{uncheckedVariance, uncheckedCaptures} +import scala.annotation.unchecked.uncheckedVariance import scala.annotation.tailrec import mutable.{Builder, ListBuffer} import scala.collection.generic.DefaultSerializable @@ -215,7 +215,7 @@ sealed abstract class List[+A] // dropRight is inherited from LinearSeq override def splitAt(n: Int): (List[A], List[A]) = { - val b = new ListBuffer[A @uncheckedCaptures] + val b = new ListBuffer[A] var i = 0 var these = this while (!these.isEmpty && i < n) { @@ -307,7 +307,7 @@ sealed abstract class List[+A] } @inline final override def takeWhile(p: A => Boolean): List[A] = { - val b = new ListBuffer[A @uncheckedCaptures] + val b = new ListBuffer[A] var these = this while (!these.isEmpty && p(these.head)) { b += these.head @@ -317,7 +317,7 @@ sealed abstract class List[+A] } @inline final override def span(p: A => Boolean): (List[A], List[A]) = { - val b = new ListBuffer[A @uncheckedCaptures] + val b = new ListBuffer[A] var these = this while (!these.isEmpty && p(these.head)) { b += these.head @@ -652,7 +652,7 @@ sealed abstract class List[+A] // Internal code that mutates `next` _must_ call `Statics.releaseFence()` if either immediately, or // before a newly-allocated, thread-local :: instance is aliased (e.g. in ListBuffer.toList) -final case class :: [+A](override val head: A, private[scala] var next: List[A @uncheckedVariance @uncheckedCaptures]) // sound because `next` is used only locally +final case class :: [+A](override val head: A, private[scala] var next: List[A @uncheckedVariance]) // sound because `next` is used only locally extends List[A] { releaseFence() override def headOption: Some[A] = Some(head) @@ -684,7 +684,7 @@ object List extends StrictOptimizedSeqFactory[List] { def from[B](coll: collection.IterableOnce[B]^): List[B] = Nil.prependedAll(coll) - def newBuilder[A]: Builder[A, List[A]] = new ListBuffer[A @uncheckedCaptures]() + def newBuilder[A]: Builder[A, List[A]] = new ListBuffer[A]() def empty[A]: List[A] = Nil diff --git a/tests/pos-special/stdlib/collection/immutable/ListMap.scala b/tests/pos-special/stdlib/collection/immutable/ListMap.scala index c5000d785144..06f9b0e91ec1 100644 --- a/tests/pos-special/stdlib/collection/immutable/ListMap.scala +++ b/tests/pos-special/stdlib/collection/immutable/ListMap.scala @@ -20,7 +20,6 @@ import scala.collection.generic.DefaultSerializable import scala.runtime.Statics.releaseFence import scala.util.hashing.MurmurHash3 import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** * This class implements immutable maps using a list-based data structure. List map iterators and @@ -133,8 +132,8 @@ object ListMap extends MapFactory[ListMap] { */ private[immutable] final class Node[K, V]( override private[immutable] val key: K, - private[immutable] var _value: V @uncheckedCaptures, - private[immutable] var _init: ListMap[K, V] @uncheckedCaptures + private[immutable] var _value: V, + private[immutable] var _init: ListMap[K, V] ) extends ListMap[K, V] { releaseFence() @@ -287,7 +286,7 @@ object ListMap extends MapFactory[ListMap] { */ private[immutable] final class ListMapBuilder[K, V] extends mutable.ReusableBuilder[(K, V), ListMap[K, V]] { private[this] var isAliased: Boolean = false - private[this] var underlying: ListMap[K, V] @uncheckedCaptures = ListMap.empty + private[this] var underlying: ListMap[K, V] = ListMap.empty override def clear(): Unit = { underlying = ListMap.empty diff --git a/tests/pos-special/stdlib/collection/immutable/ListSet.scala b/tests/pos-special/stdlib/collection/immutable/ListSet.scala index 719abd78e1e6..ab5e8c65600b 100644 --- a/tests/pos-special/stdlib/collection/immutable/ListSet.scala +++ b/tests/pos-special/stdlib/collection/immutable/ListSet.scala @@ -18,7 +18,6 @@ import mutable.{Builder, ImmutableBuilder} import scala.annotation.tailrec import scala.collection.generic.DefaultSerializable import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** * This class implements immutable sets using a list-based data structure. List set iterators and diff --git a/tests/pos-special/stdlib/collection/immutable/LongMap.scala b/tests/pos-special/stdlib/collection/immutable/LongMap.scala index 4abf433273f2..1e32cb88767d 100644 --- a/tests/pos-special/stdlib/collection/immutable/LongMap.scala +++ b/tests/pos-special/stdlib/collection/immutable/LongMap.scala @@ -21,7 +21,6 @@ import scala.annotation.tailrec import scala.annotation.unchecked.uncheckedVariance import scala.language.implicitConversions import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** Utility class for long maps. */ @@ -193,7 +192,7 @@ sealed abstract class LongMap[+T] extends AbstractMap[Long, T] override def empty: LongMap[T] = LongMap.Nil override def toList = { - val buffer = new ListBuffer[(Long, T) @uncheckedCaptures] + val buffer = new ListBuffer[(Long, T)] foreach(buffer += _) buffer.toList } diff --git a/tests/pos-special/stdlib/collection/immutable/Map.scala b/tests/pos-special/stdlib/collection/immutable/Map.scala index 6daad829bf55..1b74883bb612 100644 --- a/tests/pos-special/stdlib/collection/immutable/Map.scala +++ b/tests/pos-special/stdlib/collection/immutable/Map.scala @@ -19,7 +19,6 @@ import scala.collection.generic.DefaultSerializable import scala.collection.immutable.Map.Map4 import scala.collection.mutable.{Builder, ReusableBuilder} import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** Base type of immutable Maps */ trait Map[K, +V] @@ -641,9 +640,9 @@ object Map extends MapFactory[Map] { abstract class AbstractMap[K, +V] extends scala.collection.AbstractMap[K, V] with Map[K, V] private[immutable] final class MapBuilderImpl[K, V] extends ReusableBuilder[(K, V), Map[K, V]] { - private[this] var elems: Map[K, V] @uncheckedCaptures = Map.empty + private[this] var elems: Map[K, V] = Map.empty private[this] var switchedToHashMapBuilder: Boolean = false - private[this] var hashMapBuilder: HashMapBuilder[K, V] @uncheckedCaptures = _ + private[this] var hashMapBuilder: HashMapBuilder[K, V] = _ private[immutable] def getOrElse[V0 >: V](key: K, value: V0): V0 = if (hashMapBuilder ne null) hashMapBuilder.getOrElse(key, value) diff --git a/tests/pos-special/stdlib/collection/immutable/NumericRange.scala b/tests/pos-special/stdlib/collection/immutable/NumericRange.scala index f26d9728e5ad..695083faf27d 100644 --- a/tests/pos-special/stdlib/collection/immutable/NumericRange.scala +++ b/tests/pos-special/stdlib/collection/immutable/NumericRange.scala @@ -15,7 +15,6 @@ package scala.collection.immutable import scala.collection.Stepper.EfficientSplit import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape} import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** `NumericRange` is a more generic version of the * `Range` class which works with arbitrary types. @@ -494,7 +493,7 @@ object NumericRange { import num.mkNumericOps private[this] var _hasNext = !self.isEmpty - private[this] var _next: T @uncheckedCaptures = self.start + private[this] var _next: T = self.start private[this] val lastElement: T = if (_hasNext) self.last else self.start override def knownSize: Int = if (_hasNext) num.toInt((lastElement - _next) / self.step) + 1 else 0 def hasNext: Boolean = _hasNext diff --git a/tests/pos-special/stdlib/collection/immutable/Queue.scala b/tests/pos-special/stdlib/collection/immutable/Queue.scala index 929c79ce588a..785cca4b7c3e 100644 --- a/tests/pos-special/stdlib/collection/immutable/Queue.scala +++ b/tests/pos-special/stdlib/collection/immutable/Queue.scala @@ -201,7 +201,7 @@ sealed class Queue[+A] protected(protected val in: List[A], protected val out: L */ @SerialVersionUID(3L) object Queue extends StrictOptimizedSeqFactory[Queue] { - def newBuilder[sealed A]: Builder[A, Queue[A]] = new ListBuffer[A] mapResult (x => new Queue[A](Nil, x)) + def newBuilder[A]: Builder[A, Queue[A]] = new ListBuffer[A] mapResult (x => new Queue[A](Nil, x)) def from[A](source: IterableOnce[A]^): Queue[A] = source match { case q: Queue[A] => q diff --git a/tests/pos-special/stdlib/collection/immutable/RedBlackTree.scala b/tests/pos-special/stdlib/collection/immutable/RedBlackTree.scala index 5fbc927d7a21..69e93093f60c 100644 --- a/tests/pos-special/stdlib/collection/immutable/RedBlackTree.scala +++ b/tests/pos-special/stdlib/collection/immutable/RedBlackTree.scala @@ -18,7 +18,6 @@ import scala.annotation.meta.{getter, setter} import scala.annotation.tailrec import scala.runtime.Statics.releaseFence import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** An object containing the RedBlack tree implementation used by for `TreeMaps` and `TreeSets`. * @@ -836,10 +835,10 @@ private[collection] object RedBlackTree { * we potentially do so in `startFrom`. */ val maximumHeight = 2 * (32 - Integer.numberOfLeadingZeros(root.count + 2 - 1)) - 2 - new Array[Tree[A, B] @uncheckedCaptures](maximumHeight) + new Array[Tree[A, B]](maximumHeight) } private[this] var index = 0 - protected var lookahead: Tree[A, B] @uncheckedCaptures = + protected var lookahead: Tree[A, B] = if (start.isDefined) startFrom(start.get) else findLeftMostOrPopOnEmpty(root) /** diff --git a/tests/pos-special/stdlib/collection/immutable/SeqMap.scala b/tests/pos-special/stdlib/collection/immutable/SeqMap.scala index 6c955fd52fc2..fdd628f32698 100644 --- a/tests/pos-special/stdlib/collection/immutable/SeqMap.scala +++ b/tests/pos-special/stdlib/collection/immutable/SeqMap.scala @@ -16,7 +16,6 @@ package immutable import scala.collection.mutable.{Builder, ReusableBuilder} import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** A base trait for ordered, immutable maps. * @@ -230,9 +229,9 @@ object SeqMap extends MapFactory[SeqMap] { } private final class SeqMapBuilderImpl[K, V] extends ReusableBuilder[(K, V), SeqMap[K, V]] { - private[this] var elems: SeqMap[K, V] @uncheckedCaptures = SeqMap.empty + private[this] var elems: SeqMap[K, V] = SeqMap.empty private[this] var switchedToVectorMapBuilder: Boolean = false - private[this] var vectorMapBuilder: VectorMapBuilder[K, V] @uncheckedCaptures = _ + private[this] var vectorMapBuilder: VectorMapBuilder[K, V] = _ override def clear(): Unit = { elems = SeqMap.empty diff --git a/tests/pos-special/stdlib/collection/immutable/Set.scala b/tests/pos-special/stdlib/collection/immutable/Set.scala index ac92f81b2013..4632a35f8484 100644 --- a/tests/pos-special/stdlib/collection/immutable/Set.scala +++ b/tests/pos-special/stdlib/collection/immutable/Set.scala @@ -17,7 +17,6 @@ package immutable import scala.collection.immutable.Set.Set4 import scala.collection.mutable.{Builder, ReusableBuilder} import language.experimental.captureChecking -import annotation.unchecked.uncheckedCaptures /** Base trait for immutable set collections */ trait Set[A] extends Iterable[A] @@ -353,9 +352,9 @@ abstract class AbstractSet[A] extends scala.collection.AbstractSet[A] with Set[A * $multipleResults */ private final class SetBuilderImpl[A] extends ReusableBuilder[A, Set[A]] { - private[this] var elems: Set[A @uncheckedCaptures] = Set.empty + private[this] var elems: Set[A] = Set.empty private[this] var switchedToHashSetBuilder: Boolean = false - private[this] var hashSetBuilder: HashSetBuilder[A @uncheckedCaptures] = _ + private[this] var hashSetBuilder: HashSetBuilder[A] = _ override def clear(): Unit = { elems = Set.empty diff --git a/tests/pos-special/stdlib/collection/immutable/StrictOptimizedSeqOps.scala b/tests/pos-special/stdlib/collection/immutable/StrictOptimizedSeqOps.scala index b1e4622971fb..5ceb5435469f 100644 --- a/tests/pos-special/stdlib/collection/immutable/StrictOptimizedSeqOps.scala +++ b/tests/pos-special/stdlib/collection/immutable/StrictOptimizedSeqOps.scala @@ -14,7 +14,6 @@ package scala package collection package immutable import language.experimental.captureChecking -import annotation.unchecked.uncheckedCaptures /** * Trait that overrides operations to take advantage of strict builders. @@ -29,7 +28,7 @@ trait StrictOptimizedSeqOps[+A, +CC[_], +C] if (lengthCompare(1) <= 0) coll else { val builder = newSpecificBuilder - val seen = mutable.HashSet.empty[B @uncheckedCaptures] + val seen = mutable.HashSet.empty[B] val it = this.iterator var different = false while (it.hasNext) { diff --git a/tests/pos-special/stdlib/collection/immutable/TreeMap.scala b/tests/pos-special/stdlib/collection/immutable/TreeMap.scala index ff01ad7806ec..8da2f189a985 100644 --- a/tests/pos-special/stdlib/collection/immutable/TreeMap.scala +++ b/tests/pos-special/stdlib/collection/immutable/TreeMap.scala @@ -21,7 +21,6 @@ import scala.collection.immutable.{RedBlackTree => RB} import scala.collection.mutable.ReusableBuilder import scala.runtime.AbstractFunction2 import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** An immutable SortedMap whose values are stored in a red-black tree. * @@ -271,7 +270,7 @@ final class TreeMap[K, +V] private (private val tree: RB.Tree[K, V])(implicit va private final class Adder[B1 >: V] extends RB.MapHelper[K, B1] with Function1[(K, B1), Unit] { - private var currentMutableTree: RB.Tree[K,B1] @uncheckedCaptures = tree0 + private var currentMutableTree: RB.Tree[K,B1] = tree0 def finalTree = beforePublish(currentMutableTree) override def apply(kv: (K, B1)): Unit = { currentMutableTree = mutableUpd(currentMutableTree, kv._1, kv._2) @@ -322,7 +321,7 @@ object TreeMap extends SortedMapFactory[TreeMap] { extends RB.MapHelper[K, V] with ReusableBuilder[(K, V), TreeMap[K, V]] { type Tree = RB.Tree[K, V] - private var tree:Tree @uncheckedCaptures = null + private var tree:Tree = null def addOne(elem: (K, V)): this.type = { tree = mutableUpd(tree, elem._1, elem._2) @@ -331,7 +330,7 @@ object TreeMap extends SortedMapFactory[TreeMap] { private object adder extends AbstractFunction2[K, V, Unit] { // we cache tree to avoid the outer access to tree // in the hot path (apply) - private[this] var accumulator: Tree @uncheckedCaptures = null + private[this] var accumulator: Tree = null def addForEach(hasForEach: collection.Map[K, V]): Unit = { accumulator = tree hasForEach.foreachEntry(this) diff --git a/tests/pos-special/stdlib/collection/immutable/TreeSeqMap.scala b/tests/pos-special/stdlib/collection/immutable/TreeSeqMap.scala index 91233669e5ca..fe194fa9de5a 100644 --- a/tests/pos-special/stdlib/collection/immutable/TreeSeqMap.scala +++ b/tests/pos-special/stdlib/collection/immutable/TreeSeqMap.scala @@ -16,7 +16,6 @@ package immutable import scala.annotation.tailrec import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** This class implements an immutable map that preserves order using * a hash map for the key to value mapping to provide efficient lookup, @@ -206,7 +205,7 @@ final class TreeSeqMap[K, +V] private ( new TreeSeqMap(ong, mng, ordinal, orderedBy) } else { // Populate with builder otherwise - val bdr = newBuilder[K @uncheckedCaptures, V @uncheckedCaptures](orderedBy) + val bdr = newBuilder[K, V](orderedBy) val iter = ordering.iterator var i = 0 while (i < f) { @@ -224,7 +223,7 @@ final class TreeSeqMap[K, +V] private ( } override def map[K2, V2](f: ((K, V)) => (K2, V2)): TreeSeqMap[K2, V2] = { - val bdr = newBuilder[K2 @uncheckedCaptures, V2 @uncheckedCaptures](orderedBy) + val bdr = newBuilder[K2, V2](orderedBy) val iter = ordering.iterator while (iter.hasNext) { val k = iter.next() @@ -236,7 +235,7 @@ final class TreeSeqMap[K, +V] private ( } override def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^): TreeSeqMap[K2, V2] = { - val bdr = newBuilder[K2 @uncheckedCaptures, V2 @uncheckedCaptures](orderedBy) + val bdr = newBuilder[K2, V2](orderedBy) val iter = ordering.iterator while (iter.hasNext) { val k = iter.next() @@ -251,7 +250,7 @@ final class TreeSeqMap[K, +V] private ( } override def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)]): TreeSeqMap[K2, V2] = { - val bdr = newBuilder[K2 @uncheckedCaptures, V2 @uncheckedCaptures](orderedBy) + val bdr = newBuilder[K2, V2](orderedBy) val iter = ordering.iterator while (iter.hasNext) { val k = iter.next() @@ -304,7 +303,7 @@ object TreeSeqMap extends MapFactory[TreeSeqMap] { else EmptyByInsertion }.asInstanceOf[TreeSeqMap[K, V]] - def from[sealed K, sealed V](it: collection.IterableOnce[(K, V)]^): TreeSeqMap[K, V] = + def from[K, V](it: collection.IterableOnce[(K, V)]^): TreeSeqMap[K, V] = it match { case om: TreeSeqMap[K, V] => om case _ => (newBuilder[K, V] ++= it).result() @@ -312,10 +311,10 @@ object TreeSeqMap extends MapFactory[TreeSeqMap] { @inline private def increment(ord: Int) = if (ord == Int.MaxValue) Int.MinValue else ord + 1 - def newBuilder[sealed K, sealed V]: mutable.Builder[(K, V), TreeSeqMap[K, V]] = newBuilder(OrderBy.Insertion) - def newBuilder[sealed K, sealed V](orderedBy: OrderBy): mutable.Builder[(K, V), TreeSeqMap[K, V]] = new Builder[K, V](orderedBy) + def newBuilder[K, V]: mutable.Builder[(K, V), TreeSeqMap[K, V]] = newBuilder(OrderBy.Insertion) + def newBuilder[K, V](orderedBy: OrderBy): mutable.Builder[(K, V), TreeSeqMap[K, V]] = new Builder[K, V](orderedBy) - final class Builder[sealed K, sealed V](orderedBy: OrderBy) extends mutable.Builder[(K, V), TreeSeqMap[K, V]] { + final class Builder[K, V](orderedBy: OrderBy) extends mutable.Builder[(K, V), TreeSeqMap[K, V]] { private[this] val bdr = new MapBuilderImpl[K, (Int, V)] private[this] var ong = Ordering.empty[K] private[this] var ord = 0 @@ -437,7 +436,7 @@ object TreeSeqMap extends MapFactory[TreeSeqMap] { protected def format(sb: StringBuilder, prefix: String, subPrefix: String): Unit = sb ++= s"${prefix}Tip(${toBinaryString(ord)} -> $value)\n" } - final case class Bin[+T](prefix: Int, mask: Int, left: Ordering[T], var right: Ordering[T @uncheckedCaptures] @scala.annotation.unchecked.uncheckedVariance) extends Ordering[T] { + final case class Bin[+T](prefix: Int, mask: Int, left: Ordering[T], var right: Ordering[T] @scala.annotation.unchecked.uncheckedVariance) extends Ordering[T] { def bin[S](left: Ordering[S], right: Ordering[S]): Ordering[S] = { if ((this.left eq left) && (this.right eq right)) this.asInstanceOf[Bin[S]] else Bin[S](prefix, mask, left, right) @@ -609,7 +608,7 @@ object TreeSeqMap extends MapFactory[TreeSeqMap] { } final def splitAt(n: Int): (Ordering[T], Ordering[T]) = { - var rear: Ordering[T @uncheckedCaptures] = Ordering.empty[T] + var rear: Ordering[T] = Ordering.empty[T] var i = n (modifyOrRemove { (o, v) => i -= 1 diff --git a/tests/pos-special/stdlib/collection/immutable/TreeSet.scala b/tests/pos-special/stdlib/collection/immutable/TreeSet.scala index c4241b818c38..097341283719 100644 --- a/tests/pos-special/stdlib/collection/immutable/TreeSet.scala +++ b/tests/pos-special/stdlib/collection/immutable/TreeSet.scala @@ -20,7 +20,6 @@ import scala.collection.mutable.ReusableBuilder import scala.collection.immutable.{RedBlackTree => RB} import scala.runtime.AbstractFunction1 import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** This class implements immutable sorted sets using a tree. * @@ -263,7 +262,7 @@ object TreeSet extends SortedIterableFactory[TreeSet] { extends RB.SetHelper[A] with ReusableBuilder[A, TreeSet[A]] { type Tree = RB.Tree[A, Any] - private [this] var tree:RB.Tree[A @uncheckedCaptures, Any] = null + private [this] var tree:RB.Tree[A, Any] = null override def addOne(elem: A): this.type = { tree = mutableUpd(tree, elem) diff --git a/tests/pos-special/stdlib/collection/immutable/Vector.scala b/tests/pos-special/stdlib/collection/immutable/Vector.scala index d9d33add512d..d584d4a446af 100644 --- a/tests/pos-special/stdlib/collection/immutable/Vector.scala +++ b/tests/pos-special/stdlib/collection/immutable/Vector.scala @@ -25,7 +25,6 @@ import scala.collection.immutable.VectorInline._ import scala.collection.immutable.VectorStatics._ import scala.collection.mutable.ReusableBuilder import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** $factoryInfo @@ -229,7 +228,7 @@ sealed abstract class Vector[+A] private[immutable] (private[immutable] final va // k >= 0, k = suffix.knownSize val tinyAppendLimit = 4 + vectorSliceCount if (k < tinyAppendLimit) { - var v: Vector[B @uncheckedCaptures] = this + var v: Vector[B] = this suffix match { case it: Iterable[_] => it.asInstanceOf[Iterable[B]].foreach(x => v = v.appended(x)) case _ => suffix.iterator.foreach(x => v = v.appended(x)) @@ -265,7 +264,7 @@ sealed abstract class Vector[+A] private[immutable] (private[immutable] final va /** Length of all slices up to and including index */ protected[immutable] def vectorSlicePrefixLength(idx: Int): Int - override def copyToArray[sealed B >: A](xs: Array[B], start: Int, len: Int): Int = iterator.copyToArray(xs, start, len) + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = iterator.copyToArray(xs, start, len) override def toVector: Vector[A] = this @@ -2393,7 +2392,7 @@ private final class NewVectorIterator[A](v: Vector[A], private[this] var totalLe take(_until) } - override def copyToArray[sealed B >: A](xs: Array[B], start: Int, len: Int): Int = { + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = { val xsLen = xs.length val total = IterableOnce.elemsToCopyToArray(knownSize, xsLen, start, len) var copied = 0 @@ -2468,7 +2467,7 @@ private class LongVectorStepper(it: NewVectorIterator[Long]) // The following definitions are needed for binary compatibility with ParVector private[collection] class VectorIterator[+A](_startIndex: Int, private[this] var endIndex: Int) extends AbstractIterator[A] { - private[immutable] var it: NewVectorIterator[A @uncheckedVariance @uncheckedCaptures] = _ + private[immutable] var it: NewVectorIterator[A @uncheckedVariance] = _ def hasNext: Boolean = it.hasNext def next(): A = it.next() private[collection] def remainingElementCount: Int = it.size diff --git a/tests/pos-special/stdlib/collection/immutable/VectorMap.scala b/tests/pos-special/stdlib/collection/immutable/VectorMap.scala index 0860a0b47f28..2bbcf429e01d 100644 --- a/tests/pos-special/stdlib/collection/immutable/VectorMap.scala +++ b/tests/pos-special/stdlib/collection/immutable/VectorMap.scala @@ -16,7 +16,6 @@ package immutable import scala.annotation.tailrec import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** This class implements immutable maps using a vector/map-based data structure, which preserves insertion order. * @@ -243,7 +242,7 @@ object VectorMap extends MapFactory[VectorMap] { private[immutable] final class VectorMapBuilder[K, V] extends mutable.Builder[(K, V), VectorMap[K, V]] { private[this] val vectorBuilder = new VectorBuilder[K] private[this] val mapBuilder = new MapBuilderImpl[K, (Int, V)] - private[this] var aliased: VectorMap[K, V] @uncheckedCaptures = _ // OK since VectorMapBuilder is private + private[this] var aliased: VectorMap[K, V] = _ // OK since VectorMapBuilder is private override def clear(): Unit = { vectorBuilder.clear() diff --git a/tests/pos-special/stdlib/collection/immutable/WrappedString.scala b/tests/pos-special/stdlib/collection/immutable/WrappedString.scala index 47fe769c81ef..446bdceb3ace 100644 --- a/tests/pos-special/stdlib/collection/immutable/WrappedString.scala +++ b/tests/pos-special/stdlib/collection/immutable/WrappedString.scala @@ -90,7 +90,7 @@ final class WrappedString(private val self: String) extends AbstractSeq[Char] wi case _ => super.lastIndexOf(elem, end) } - override def copyToArray[sealed B >: Char](xs: Array[B], start: Int, len: Int): Int = + override def copyToArray[B >: Char](xs: Array[B], start: Int, len: Int): Int = (xs: Any) match { case chs: Array[Char] => val copied = IterableOnce.elemsToCopyToArray(length, chs.length, start, len) diff --git a/tests/pos-special/stdlib/collection/mutable/AnyRefMap.scala b/tests/pos-special/stdlib/collection/mutable/AnyRefMap.scala index a6413649e219..8f1ac07e725e 100644 --- a/tests/pos-special/stdlib/collection/mutable/AnyRefMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/AnyRefMap.scala @@ -43,7 +43,7 @@ import language.experimental.captureChecking * rapidly as 2^30^ is approached. * */ -class AnyRefMap[K <: AnyRef, sealed V] private[collection] (defaultEntry: K -> V, initialBufferSize: Int, initBlank: Boolean) +class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K -> V, initialBufferSize: Int, initBlank: Boolean) extends AbstractMap[K, V] with MapOps[K, V, Map, AnyRefMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, AnyRefMap[K, V]] @@ -395,24 +395,24 @@ class AnyRefMap[K <: AnyRef, sealed V] private[collection] (defaultEntry: K -> V } @deprecated("Consider requiring an immutable Map or fall back to Map.concat", "2.13.0") - override def + [sealed V1 >: V](kv: (K, V1)): AnyRefMap[K, V1] = AnyRefMap.from(new View.Appended(this, kv)) + override def + [V1 >: V](kv: (K, V1)): AnyRefMap[K, V1] = AnyRefMap.from(new View.Appended(this, kv)) @deprecated("Use ++ with an explicit collection argument instead of + with varargs", "2.13.0") - override def + [sealed V1 >: V](elem1: (K, V1), elem2: (K, V1), elems: (K, V1)*): AnyRefMap[K, V1] = { + override def + [V1 >: V](elem1: (K, V1), elem2: (K, V1), elems: (K, V1)*): AnyRefMap[K, V1] = { val m = this + elem1 + elem2 if(elems.isEmpty) m else m.concat(elems) } - override def concat[sealed V2 >: V](xs: scala.collection.IterableOnce[(K, V2)]^): AnyRefMap[K, V2] = { + override def concat[V2 >: V](xs: scala.collection.IterableOnce[(K, V2)]^): AnyRefMap[K, V2] = { val arm = clone().asInstanceOf[AnyRefMap[K, V2]] xs.iterator.foreach(kv => arm += kv) arm } - override def ++[sealed V2 >: V](xs: scala.collection.IterableOnce[(K, V2)]^): AnyRefMap[K, V2] = concat(xs) + override def ++[V2 >: V](xs: scala.collection.IterableOnce[(K, V2)]^): AnyRefMap[K, V2] = concat(xs) @deprecated("Use m.clone().addOne(k,v) instead of m.updated(k, v)", "2.13.0") - override def updated[sealed V1 >: V](key: K, value: V1): AnyRefMap[K, V1] = + override def updated[V1 >: V](key: K, value: V1): AnyRefMap[K, V1] = clone().asInstanceOf[AnyRefMap[K, V1]].addOne(key, value) private[this] def foreachElement[A,B](elems: Array[AnyRef], f: A => B): Unit = { @@ -437,7 +437,7 @@ class AnyRefMap[K <: AnyRef, sealed V] private[collection] (defaultEntry: K -> V * Unlike `mapValues`, this method generates a new * collection immediately. */ - def mapValuesNow[sealed V1](f: V => V1): AnyRefMap[K, V1] = { + def mapValuesNow[V1](f: V => V1): AnyRefMap[K, V1] = { val arm = new AnyRefMap[K,V1](AnyRefMap.exceptionDefault, 1, false) val hz = java.util.Arrays.copyOf(_hashes, _hashes.length) val kz = java.util.Arrays.copyOf(_keys, _keys.length) @@ -478,11 +478,11 @@ class AnyRefMap[K <: AnyRef, sealed V] private[collection] (defaultEntry: K -> V } // The implicit dummy parameter is necessary to distinguish these methods from the base methods they overload (not override) - def map[K2 <: AnyRef, sealed V2](f: ((K, V)) => (K2, V2))(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = + def map[K2 <: AnyRef, V2](f: ((K, V)) => (K2, V2))(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = AnyRefMap.from(new View.Map(this, f)) - def flatMap[K2 <: AnyRef, sealed V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = + def flatMap[K2 <: AnyRef, V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = AnyRefMap.from(new View.FlatMap(this, f)) - def collect[K2 <: AnyRef, sealed V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = + def collect[K2 <: AnyRef, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = strictOptimizedCollect(AnyRefMap.newBuilder[K2, V2], pf) override def clear(): Unit = { @@ -515,7 +515,7 @@ object AnyRefMap { * * This builder can be reused to create multiple instances. */ - final class AnyRefMapBuilder[K <: AnyRef, sealed V] extends ReusableBuilder[(K, V), AnyRefMap[K, V]] { + final class AnyRefMapBuilder[K <: AnyRef, V] extends ReusableBuilder[(K, V), AnyRefMap[K, V]] { private[collection] var elems: AnyRefMap[K, V] = new AnyRefMap[K, V] def addOne(entry: (K, V)): this.type = { elems += entry @@ -527,11 +527,11 @@ object AnyRefMap { } /** Creates a new `AnyRefMap` with zero or more key/value pairs. */ - def apply[K <: AnyRef, sealed V](elems: (K, V)*): AnyRefMap[K, V] = buildFromIterableOnce(elems) + def apply[K <: AnyRef, V](elems: (K, V)*): AnyRefMap[K, V] = buildFromIterableOnce(elems) - def newBuilder[K <: AnyRef, sealed V]: ReusableBuilder[(K, V), AnyRefMap[K, V]] = new AnyRefMapBuilder[K, V] + def newBuilder[K <: AnyRef, V]: ReusableBuilder[(K, V), AnyRefMap[K, V]] = new AnyRefMapBuilder[K, V] - private def buildFromIterableOnce[K <: AnyRef, sealed V](elems: IterableOnce[(K, V)]^): AnyRefMap[K, V] = { + private def buildFromIterableOnce[K <: AnyRef, V](elems: IterableOnce[(K, V)]^): AnyRefMap[K, V] = { var sz = elems.knownSize if(sz < 0) sz = 4 val arm = new AnyRefMap[K, V](sz * 2) @@ -541,10 +541,10 @@ object AnyRefMap { } /** Creates a new empty `AnyRefMap`. */ - def empty[K <: AnyRef, sealed V]: AnyRefMap[K, V] = new AnyRefMap[K, V] + def empty[K <: AnyRef, V]: AnyRefMap[K, V] = new AnyRefMap[K, V] /** Creates a new empty `AnyRefMap` with the supplied default */ - def withDefault[K <: AnyRef, sealed V](default: K -> V): AnyRefMap[K, V] = new AnyRefMap[K, V](default) + def withDefault[K <: AnyRef, V](default: K -> V): AnyRefMap[K, V] = new AnyRefMap[K, V](default) /** Creates a new `AnyRefMap` from an existing source collection. A source collection * which is already an `AnyRefMap` gets cloned. @@ -554,7 +554,7 @@ object AnyRefMap { * @tparam V the type of the values * @return a new `AnyRefMap` with the elements of `source` */ - def from[K <: AnyRef, sealed V](source: IterableOnce[(K, V)]^): AnyRefMap[K, V] = source match { + def from[K <: AnyRef, V](source: IterableOnce[(K, V)]^): AnyRefMap[K, V] = source match { case source: AnyRefMap[_, _] => source.clone().asInstanceOf[AnyRefMap[K, V]] case _ => buildFromIterableOnce(source) } @@ -562,7 +562,7 @@ object AnyRefMap { /** Creates a new `AnyRefMap` from arrays of keys and values. * Equivalent to but more efficient than `AnyRefMap((keys zip values): _*)`. */ - def fromZip[K <: AnyRef, sealed V](keys: Array[K], values: Array[V]): AnyRefMap[K, V] = { + def fromZip[K <: AnyRef, V](keys: Array[K], values: Array[V]): AnyRefMap[K, V] = { val sz = math.min(keys.length, values.length) val arm = new AnyRefMap[K, V](sz * 2) var i = 0 @@ -574,7 +574,7 @@ object AnyRefMap { /** Creates a new `AnyRefMap` from keys and values. * Equivalent to but more efficient than `AnyRefMap((keys zip values): _*)`. */ - def fromZip[K <: AnyRef, sealed V](keys: Iterable[K]^, values: Iterable[V]^): AnyRefMap[K, V] = { + def fromZip[K <: AnyRef, V](keys: Iterable[K]^, values: Iterable[V]^): AnyRefMap[K, V] = { val sz = math.min(keys.size, values.size) val arm = new AnyRefMap[K, V](sz * 2) val ki = keys.iterator @@ -584,7 +584,7 @@ object AnyRefMap { arm } - implicit def toFactory[K <: AnyRef, sealed V](dummy: AnyRefMap.type): Factory[(K, V), AnyRefMap[K, V]] = ToFactory.asInstanceOf[Factory[(K, V), AnyRefMap[K, V]]] + implicit def toFactory[K <: AnyRef, V](dummy: AnyRefMap.type): Factory[(K, V), AnyRefMap[K, V]] = ToFactory.asInstanceOf[Factory[(K, V), AnyRefMap[K, V]]] @SerialVersionUID(3L) private[this] object ToFactory extends Factory[(AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] with Serializable { @@ -592,12 +592,12 @@ object AnyRefMap { def newBuilder: Builder[(AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] = AnyRefMap.newBuilder[AnyRef, AnyRef] } - implicit def toBuildFrom[K <: AnyRef, sealed V](factory: AnyRefMap.type): BuildFrom[Any, (K, V), AnyRefMap[K, V]] = ToBuildFrom.asInstanceOf[BuildFrom[Any, (K, V), AnyRefMap[K, V]]] + implicit def toBuildFrom[K <: AnyRef, V](factory: AnyRefMap.type): BuildFrom[Any, (K, V), AnyRefMap[K, V]] = ToBuildFrom.asInstanceOf[BuildFrom[Any, (K, V), AnyRefMap[K, V]]] private[this] object ToBuildFrom extends BuildFrom[Any, (AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] { def fromSpecific(from: Any)(it: IterableOnce[(AnyRef, AnyRef)]^) = AnyRefMap.from(it) def newBuilder(from: Any) = AnyRefMap.newBuilder[AnyRef, AnyRef] } - implicit def iterableFactory[K <: AnyRef, sealed V]: Factory[(K, V), AnyRefMap[K, V]] = toFactory[K, V](this) - implicit def buildFromAnyRefMap[K <: AnyRef, sealed V]: BuildFrom[AnyRefMap[_, _], (K, V), AnyRefMap[K, V]] = toBuildFrom(this) + implicit def iterableFactory[K <: AnyRef, V]: Factory[(K, V), AnyRefMap[K, V]] = toFactory[K, V](this) + implicit def buildFromAnyRefMap[K <: AnyRef, V]: BuildFrom[AnyRefMap[_, _], (K, V), AnyRefMap[K, V]] = toBuildFrom(this) } diff --git a/tests/pos-special/stdlib/collection/mutable/ArrayBuffer.scala b/tests/pos-special/stdlib/collection/mutable/ArrayBuffer.scala index 8fa1e6edd566..85a045c34423 100644 --- a/tests/pos-special/stdlib/collection/mutable/ArrayBuffer.scala +++ b/tests/pos-special/stdlib/collection/mutable/ArrayBuffer.scala @@ -21,7 +21,6 @@ import scala.annotation.tailrec import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** An implementation of the `Buffer` class using an array to * represent the assembled sequence internally. Append, update and random @@ -42,7 +41,7 @@ import scala.annotation.unchecked.uncheckedCaptures * @define willNotTerminateInf */ @SerialVersionUID(-1582447879429021880L) -class ArrayBuffer[sealed A] private (initialElements: Array[AnyRef], initialSize: Int) +class ArrayBuffer[A] private (initialElements: Array[AnyRef], initialSize: Int) extends AbstractBuffer[A] with IndexedBuffer[A] with IndexedSeqOps[A, ArrayBuffer, ArrayBuffer[A]] @@ -241,7 +240,7 @@ class ArrayBuffer[sealed A] private (initialElements: Array[AnyRef], initialSize @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") override protected[this] def stringPrefix = "ArrayBuffer" - override def copyToArray[sealed B >: A](xs: Array[B], start: Int, len: Int): Int = { + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = { val copied = IterableOnce.elemsToCopyToArray(length, xs.length, start, len) if(copied > 0) { Array.copy(array, 0, xs, start, copied) @@ -258,7 +257,7 @@ class ArrayBuffer[sealed A] private (initialElements: Array[AnyRef], initialSize override def sortInPlace[B >: A]()(implicit ord: Ordering[B]): this.type = { if (length > 1) { mutationCount += 1 - scala.util.Sorting.stableSort(array.asInstanceOf[Array[B @uncheckedCaptures]], 0, length) + scala.util.Sorting.stableSort(array.asInstanceOf[Array[B]], 0, length) } this } @@ -293,7 +292,7 @@ object ArrayBuffer extends StrictOptimizedSeqFactory[ArrayBuffer] { final val DefaultInitialSize = 16 private[this] val emptyArray = new Array[AnyRef](0) - def from[sealed B](coll: collection.IterableOnce[B]^): ArrayBuffer[B] = { + def from[B](coll: collection.IterableOnce[B]^): ArrayBuffer[B] = { val k = coll.knownSize if (k >= 0) { // Avoid reallocation of buffer if length is known @@ -305,12 +304,12 @@ object ArrayBuffer extends StrictOptimizedSeqFactory[ArrayBuffer] { else new ArrayBuffer[B] ++= coll } - def newBuilder[sealed A]: Builder[A, ArrayBuffer[A]] = + def newBuilder[A]: Builder[A, ArrayBuffer[A]] = new GrowableBuilder[A, ArrayBuffer[A]](empty) { override def sizeHint(size: Int): Unit = elems.ensureSize(size) } - def empty[sealed A]: ArrayBuffer[A] = new ArrayBuffer[A]() + def empty[A]: ArrayBuffer[A] = new ArrayBuffer[A]() /** * @param arrayLen the length of the backing array @@ -359,7 +358,7 @@ object ArrayBuffer extends StrictOptimizedSeqFactory[ArrayBuffer] { } // TODO: use `CheckedIndexedSeqView.Id` once we can change the return type of `ArrayBuffer#view` -final class ArrayBufferView[sealed A] private[mutable](underlying: ArrayBuffer[A], mutationCount: () -> Int) +final class ArrayBufferView[A] private[mutable](underlying: ArrayBuffer[A], mutationCount: () -> Int) extends AbstractIndexedSeqView[A], Pure { /* Removed since it poses problems for capture checking @deprecated("never intended to be public; call ArrayBuffer#view instead", since = "2.13.7") diff --git a/tests/pos-special/stdlib/collection/mutable/ArrayBuilder.scala b/tests/pos-special/stdlib/collection/mutable/ArrayBuilder.scala index 0620d3d23061..be7367c7f021 100644 --- a/tests/pos-special/stdlib/collection/mutable/ArrayBuilder.scala +++ b/tests/pos-special/stdlib/collection/mutable/ArrayBuilder.scala @@ -21,7 +21,7 @@ import scala.reflect.ClassTag * @tparam T the type of the elements for the builder. */ @SerialVersionUID(3L) -sealed abstract class ArrayBuilder[sealed T] +sealed abstract class ArrayBuilder[T] extends ReusableBuilder[T, Array[T]] with Serializable { protected[this] var capacity: Int = 0 diff --git a/tests/pos-special/stdlib/collection/mutable/ArrayDeque.scala b/tests/pos-special/stdlib/collection/mutable/ArrayDeque.scala index f22aacec65c5..d72e483a7f60 100644 --- a/tests/pos-special/stdlib/collection/mutable/ArrayDeque.scala +++ b/tests/pos-special/stdlib/collection/mutable/ArrayDeque.scala @@ -37,7 +37,7 @@ import language.experimental.captureChecking * @define mayNotTerminateInf * @define willNotTerminateInf */ -class ArrayDeque[sealed A] protected ( +class ArrayDeque[A] protected ( protected var array: Array[AnyRef], private[ArrayDeque] var start: Int, private[ArrayDeque] var end: Int @@ -463,7 +463,7 @@ class ArrayDeque[sealed A] protected ( protected def ofArray(array: Array[AnyRef], end: Int): ArrayDeque[A] = new ArrayDeque[A](array, start = 0, end) - override def copyToArray[sealed B >: A](dest: Array[B], destStart: Int, len: Int): Int = { + override def copyToArray[B >: A](dest: Array[B], destStart: Int, len: Int): Int = { val copied = IterableOnce.elemsToCopyToArray(length, dest.length, destStart, len) if (copied > 0) { copySliceToArray(srcStart = 0, dest = dest, destStart = destStart, maxItems = len) @@ -471,7 +471,7 @@ class ArrayDeque[sealed A] protected ( copied } - override def toArray[sealed B >: A: ClassTag]: Array[B] = + override def toArray[B >: A: ClassTag]: Array[B] = copySliceToArray(srcStart = 0, dest = new Array[B](length), destStart = 0, maxItems = length) /** @@ -526,7 +526,7 @@ class ArrayDeque[sealed A] protected ( @SerialVersionUID(3L) object ArrayDeque extends StrictOptimizedSeqFactory[ArrayDeque] { - def from[sealed B](coll: collection.IterableOnce[B]^): ArrayDeque[B] = { + def from[B](coll: collection.IterableOnce[B]^): ArrayDeque[B] = { val s = coll.knownSize if (s >= 0) { val array = alloc(s) @@ -536,14 +536,14 @@ object ArrayDeque extends StrictOptimizedSeqFactory[ArrayDeque] { } else new ArrayDeque[B]() ++= coll } - def newBuilder[sealed A]: Builder[A, ArrayDeque[A]] = + def newBuilder[A]: Builder[A, ArrayDeque[A]] = new GrowableBuilder[A, ArrayDeque[A]](empty) { override def sizeHint(size: Int): Unit = { elems.ensureSize(size) } } - def empty[sealed A]: ArrayDeque[A] = new ArrayDeque[A]() + def empty[A]: ArrayDeque[A] = new ArrayDeque[A]() final val DefaultInitialSize = 16 diff --git a/tests/pos-special/stdlib/collection/mutable/ArraySeq.scala b/tests/pos-special/stdlib/collection/mutable/ArraySeq.scala index bd3a208a94c0..70762e5b340d 100644 --- a/tests/pos-special/stdlib/collection/mutable/ArraySeq.scala +++ b/tests/pos-special/stdlib/collection/mutable/ArraySeq.scala @@ -20,7 +20,6 @@ import scala.collection.convert.impl._ import scala.reflect.ClassTag import scala.util.hashing.MurmurHash3 import language.experimental.captureChecking -import annotation.unchecked.uncheckedCaptures /** * A collection representing `Array[T]`. Unlike `ArrayBuffer` it is always backed by the same @@ -36,7 +35,7 @@ import annotation.unchecked.uncheckedCaptures * @define willNotTerminateInf */ @SerialVersionUID(3L) -sealed abstract class ArraySeq[sealed T] +sealed abstract class ArraySeq[T] extends AbstractSeq[T] with IndexedSeq[T] with IndexedSeqOps[T, ArraySeq, ArraySeq[T]] @@ -77,7 +76,7 @@ sealed abstract class ArraySeq[sealed T] /** Clones this object, including the underlying Array. */ override def clone(): ArraySeq[T] = ArraySeq.make[T](array.clone().asInstanceOf[Array[T]]) - override def copyToArray[sealed B >: T](xs: Array[B], start: Int, len: Int): Int = { + override def copyToArray[B >: T](xs: Array[B], start: Int, len: Int): Int = { val copied = IterableOnce.elemsToCopyToArray(length, xs.length, start, len) if(copied > 0) { Array.copy(array, 0, xs, start, copied) @@ -96,7 +95,7 @@ sealed abstract class ArraySeq[sealed T] ArraySeq.make(array.asInstanceOf[Array[T]].sorted(ord.asInstanceOf[Ordering[Any]])).asInstanceOf[ArraySeq[T]] override def sortInPlace[B >: T]()(implicit ord: Ordering[B]): this.type = { - if (length > 1) scala.util.Sorting.stableSort(array.asInstanceOf[Array[B @uncheckedCaptures]]) + if (length > 1) scala.util.Sorting.stableSort(array.asInstanceOf[Array[B]]) this } } @@ -111,9 +110,9 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => private[this] val EmptyArraySeq = new ofRef[AnyRef](new Array[AnyRef](0)) def empty[T : ClassTag]: ArraySeq[T] = EmptyArraySeq.asInstanceOf[ArraySeq[T]] - def from[sealed A : ClassTag](it: scala.collection.IterableOnce[A]^): ArraySeq[A] = make(Array.from[A](it)) + def from[A : ClassTag](it: scala.collection.IterableOnce[A]^): ArraySeq[A] = make(Array.from[A](it)) - def newBuilder[sealed A : ClassTag]: Builder[A, ArraySeq[A]] = ArrayBuilder.make[A].mapResult(make) + def newBuilder[A : ClassTag]: Builder[A, ArraySeq[A]] = ArrayBuilder.make[A].mapResult(make) /** * Wrap an existing `Array` into a `ArraySeq` of the proper primitive specialization type @@ -127,7 +126,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => * `ArraySeq.make(a.asInstanceOf[Array[Int]])` does not work, it throws a `ClassCastException` * at runtime. */ - def make[sealed T](x: Array[T]): ArraySeq[T] = ((x.asInstanceOf[Array[_]]: @unchecked) match { + def make[T](x: Array[T]): ArraySeq[T] = ((x.asInstanceOf[Array[_]]: @unchecked) match { case null => null case x: Array[AnyRef] => new ofRef[AnyRef](x) case x: Array[Int] => new ofInt(x) diff --git a/tests/pos-special/stdlib/collection/mutable/Buffer.scala b/tests/pos-special/stdlib/collection/mutable/Buffer.scala index 0f472dc9ac82..1f7fc76972a2 100644 --- a/tests/pos-special/stdlib/collection/mutable/Buffer.scala +++ b/tests/pos-special/stdlib/collection/mutable/Buffer.scala @@ -15,11 +15,10 @@ package mutable import scala.annotation.nowarn import language.experimental.captureChecking -import scala.annotation.unchecked.uncheckedCaptures /** A `Buffer` is a growable and shrinkable `Seq`. */ -trait Buffer[sealed A] +trait Buffer[A] extends Seq[A] with SeqOps[A, Buffer, Buffer[A]] with Growable[A] @@ -186,7 +185,7 @@ trait IndexedBuffer[A] extends IndexedSeq[A] // There's scope for a better implementation which copies elements in place. var i = 0 val s = size - val newElems = new Array[(IterableOnce[A]^) @uncheckedCaptures](s) + val newElems = new Array[(IterableOnce[A]^{f*})](s) while (i < s) { newElems(i) = f(this(i)); i += 1 } clear() i = 0 diff --git a/tests/pos-special/stdlib/collection/mutable/CollisionProofHashMap.scala b/tests/pos-special/stdlib/collection/mutable/CollisionProofHashMap.scala index 2b27efb6eac1..0679ab7be201 100644 --- a/tests/pos-special/stdlib/collection/mutable/CollisionProofHashMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/CollisionProofHashMap.scala @@ -33,7 +33,7 @@ import language.experimental.captureChecking * @define mayNotTerminateInf * @define willNotTerminateInf */ -final class CollisionProofHashMap[sealed K, sealed V](initialCapacity: Int, loadFactor: Double)(implicit ordering: Ordering[K]) +final class CollisionProofHashMap[K, V](initialCapacity: Int, loadFactor: Double)(implicit ordering: Ordering[K]) extends AbstractMap[K, V] with MapOps[K, V, Map, CollisionProofHashMap[K, V]] //-- with StrictOptimizedIterableOps[(K, V), Iterable, CollisionProofHashMap[K, V]] @@ -744,17 +744,17 @@ final class CollisionProofHashMap[sealed K, sealed V](initialCapacity: Int, load object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { private[collection] final val ordMsg = "No implicit Ordering[${K2}] found to build a CollisionProofHashMap[${K2}, ${V2}]. You may want to upcast to a Map[${K}, ${V}] first by calling `unsorted`." - def from[sealed K : Ordering, sealed V](it: scala.collection.IterableOnce[(K, V)]^): CollisionProofHashMap[K, V] = { + def from[K : Ordering, V](it: scala.collection.IterableOnce[(K, V)]^): CollisionProofHashMap[K, V] = { val k = it.knownSize val cap = if(k > 0) ((k + 1).toDouble / defaultLoadFactor).toInt else defaultInitialCapacity new CollisionProofHashMap[K, V](cap, defaultLoadFactor) ++= it } - def empty[sealed K : Ordering, sealed V]: CollisionProofHashMap[K, V] = new CollisionProofHashMap[K, V] + def empty[K : Ordering, V]: CollisionProofHashMap[K, V] = new CollisionProofHashMap[K, V] - def newBuilder[sealed K : Ordering, sealed V]: Builder[(K, V), CollisionProofHashMap[K, V]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) + def newBuilder[K : Ordering, V]: Builder[(K, V), CollisionProofHashMap[K, V]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) - def newBuilder[sealed K : Ordering, sealed V](initialCapacity: Int, loadFactor: Double): Builder[(K, V), CollisionProofHashMap[K, V]] = + def newBuilder[K : Ordering, V](initialCapacity: Int, loadFactor: Double): Builder[(K, V), CollisionProofHashMap[K, V]] = new GrowableBuilder[(K, V), CollisionProofHashMap[K, V]](new CollisionProofHashMap[K, V](initialCapacity, loadFactor)) { override def sizeHint(size: Int) = elems.sizeHint(size) } @@ -766,7 +766,7 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { final def defaultInitialCapacity: Int = 16 @SerialVersionUID(3L) - private final class DeserializationFactory[sealed K, sealed V](val tableLength: Int, val loadFactor: Double, val ordering: Ordering[K]) extends Factory[(K, V), CollisionProofHashMap[K, V]] with Serializable { + private final class DeserializationFactory[K, V](val tableLength: Int, val loadFactor: Double, val ordering: Ordering[K]) extends Factory[(K, V), CollisionProofHashMap[K, V]] with Serializable { def fromSpecific(it: IterableOnce[(K, V)]^): CollisionProofHashMap[K, V] = new CollisionProofHashMap[K, V](tableLength, loadFactor)(ordering) ++= it def newBuilder: Builder[(K, V), CollisionProofHashMap[K, V]] = CollisionProofHashMap.newBuilder(tableLength, loadFactor)(ordering) } @@ -789,7 +789,7 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { /////////////////////////// Red-Black Tree Node - final class RBNode[sealed K, sealed V](var key: K, var hash: Int, var value: V, var red: Boolean, var left: RBNode[K, V], var right: RBNode[K, V], var parent: RBNode[K, V]) extends Node { + final class RBNode[K, V](var key: K, var hash: Int, var value: V, var red: Boolean, var left: RBNode[K, V], var right: RBNode[K, V], var parent: RBNode[K, V]) extends Node { override def toString: String = "RBNode(" + key + ", " + hash + ", " + value + ", " + red + ", " + left + ", " + right + ")" @tailrec def getNode(k: K, h: Int)(implicit ord: Ordering[K]): RBNode[K, V] = { @@ -820,17 +820,17 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { } } - @`inline` private def leaf[sealed A, sealed B](key: A, hash: Int, value: B, red: Boolean, parent: RBNode[A, B]): RBNode[A, B] = + @`inline` private def leaf[A, B](key: A, hash: Int, value: B, red: Boolean, parent: RBNode[A, B]): RBNode[A, B] = new RBNode(key, hash, value, red, null, null, parent) - @tailrec private def minNodeNonNull[sealed A, sealed B](node: RBNode[A, B]): RBNode[A, B] = + @tailrec private def minNodeNonNull[A, B](node: RBNode[A, B]): RBNode[A, B] = if (node.left eq null) node else minNodeNonNull(node.left) /** * Returns the node that follows `node` in an in-order tree traversal. If `node` has the maximum key (and is, * therefore, the last node), this method returns `null`. */ - private def successor[sealed A, sealed B](node: RBNode[A, B]): RBNode[A, B] = { + private def successor[A, B](node: RBNode[A, B]): RBNode[A, B] = { if (node.right ne null) minNodeNonNull(node.right) else { var x = node @@ -843,7 +843,7 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { } } - private final class RBNodesIterator[sealed A, sealed B](tree: RBNode[A, B])(implicit @unused ord: Ordering[A]) extends AbstractIterator[RBNode[A, B]] { + private final class RBNodesIterator[A, B](tree: RBNode[A, B])(implicit @unused ord: Ordering[A]) extends AbstractIterator[RBNode[A, B]] { private[this] var nextNode: RBNode[A, B] = if(tree eq null) null else minNodeNonNull(tree) def hasNext: Boolean = nextNode ne null @@ -859,7 +859,7 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { /////////////////////////// Linked List Node - private final class LLNode[sealed K, sealed V](var key: K, var hash: Int, var value: V, var next: LLNode[K, V]) extends Node { + private final class LLNode[K, V](var key: K, var hash: Int, var value: V, var next: LLNode[K, V]) extends Node { override def toString = s"LLNode($key, $value, $hash) -> $next" private[this] def eq(a: Any, b: Any): Boolean = diff --git a/tests/pos-special/stdlib/collection/mutable/HashMap.scala b/tests/pos-special/stdlib/collection/mutable/HashMap.scala index ab45e7ffc73d..1ba651b47819 100644 --- a/tests/pos-special/stdlib/collection/mutable/HashMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/HashMap.scala @@ -33,7 +33,7 @@ import language.experimental.captureChecking * @define willNotTerminateInf */ @deprecatedInheritance("HashMap will be made final; use .withDefault for the common use case of computing a default value", "2.13.0") -class HashMap[sealed K, sealed V](initialCapacity: Int, loadFactor: Double) +class HashMap[K, V](initialCapacity: Int, loadFactor: Double) extends AbstractMap[K, V] with MapOps[K, V, HashMap, HashMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, HashMap[K, V]] @@ -597,17 +597,17 @@ class HashMap[sealed K, sealed V](initialCapacity: Int, loadFactor: Double) @SerialVersionUID(3L) object HashMap extends MapFactory[HashMap] { - def empty[sealed K, sealed V]: HashMap[K, V] = new HashMap[K, V] + def empty[K, V]: HashMap[K, V] = new HashMap[K, V] - def from[sealed K, sealed V](it: collection.IterableOnce[(K, V)]^): HashMap[K, V] = { + def from[K, V](it: collection.IterableOnce[(K, V)]^): HashMap[K, V] = { val k = it.knownSize val cap = if(k > 0) ((k + 1).toDouble / defaultLoadFactor).toInt else defaultInitialCapacity new HashMap[K, V](cap, defaultLoadFactor).addAll(it) } - def newBuilder[sealed K, sealed V]: Builder[(K, V), HashMap[K, V]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) + def newBuilder[K, V]: Builder[(K, V), HashMap[K, V]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) - def newBuilder[sealed K, sealed V](initialCapacity: Int, loadFactor: Double): Builder[(K, V), HashMap[K, V]] = + def newBuilder[K, V](initialCapacity: Int, loadFactor: Double): Builder[(K, V), HashMap[K, V]] = new GrowableBuilder[(K, V), HashMap[K, V]](new HashMap[K, V](initialCapacity, loadFactor)) { override def sizeHint(size: Int) = elems.sizeHint(size) } @@ -619,7 +619,7 @@ object HashMap extends MapFactory[HashMap] { final def defaultInitialCapacity: Int = 16 @SerialVersionUID(3L) - private final class DeserializationFactory[sealed K, sealed V](val tableLength: Int, val loadFactor: Double) extends Factory[(K, V), HashMap[K, V]] with Serializable { + private final class DeserializationFactory[K, V](val tableLength: Int, val loadFactor: Double) extends Factory[(K, V), HashMap[K, V]] with Serializable { def fromSpecific(it: IterableOnce[(K, V)]^): HashMap[K, V] = new HashMap[K, V](tableLength, loadFactor).addAll(it) def newBuilder: Builder[(K, V), HashMap[K, V]] = HashMap.newBuilder(tableLength, loadFactor) } diff --git a/tests/pos-special/stdlib/collection/mutable/HashSet.scala b/tests/pos-special/stdlib/collection/mutable/HashSet.scala index e8c055ff15ef..487abc74bb82 100644 --- a/tests/pos-special/stdlib/collection/mutable/HashSet.scala +++ b/tests/pos-special/stdlib/collection/mutable/HashSet.scala @@ -29,7 +29,7 @@ import language.experimental.captureChecking * @define mayNotTerminateInf * @define willNotTerminateInf */ -final class HashSet[sealed A](initialCapacity: Int, loadFactor: Double) +final class HashSet[A](initialCapacity: Int, loadFactor: Double) extends AbstractSet[A] with SetOps[A, HashSet, HashSet[A]] with StrictOptimizedIterableOps[A, HashSet, HashSet[A]] @@ -407,17 +407,17 @@ final class HashSet[sealed A](initialCapacity: Int, loadFactor: Double) @SerialVersionUID(3L) object HashSet extends IterableFactory[HashSet] { - def from[sealed B](it: scala.collection.IterableOnce[B]^): HashSet[B] = { + def from[B](it: scala.collection.IterableOnce[B]^): HashSet[B] = { val k = it.knownSize val cap = if(k > 0) ((k + 1).toDouble / defaultLoadFactor).toInt else defaultInitialCapacity new HashSet[B](cap, defaultLoadFactor) ++= it } - def empty[sealed A]: HashSet[A] = new HashSet[A] + def empty[A]: HashSet[A] = new HashSet[A] - def newBuilder[sealed A]: Builder[A, HashSet[A]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) + def newBuilder[A]: Builder[A, HashSet[A]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) - def newBuilder[sealed A](initialCapacity: Int, loadFactor: Double): Builder[A, HashSet[A]] = + def newBuilder[A](initialCapacity: Int, loadFactor: Double): Builder[A, HashSet[A]] = new GrowableBuilder[A, HashSet[A]](new HashSet[A](initialCapacity, loadFactor)) { override def sizeHint(size: Int) = elems.sizeHint(size) } @@ -429,7 +429,7 @@ object HashSet extends IterableFactory[HashSet] { final def defaultInitialCapacity: Int = 16 @SerialVersionUID(3L) - private final class DeserializationFactory[sealed A](val tableLength: Int, val loadFactor: Double) extends Factory[A, HashSet[A]] with Serializable { + private final class DeserializationFactory[A](val tableLength: Int, val loadFactor: Double) extends Factory[A, HashSet[A]] with Serializable { def fromSpecific(it: IterableOnce[A]^): HashSet[A] = new HashSet[A](tableLength, loadFactor) ++= it def newBuilder: Builder[A, HashSet[A]] = HashSet.newBuilder(tableLength, loadFactor) } diff --git a/tests/pos-special/stdlib/collection/mutable/HashTable.scala b/tests/pos-special/stdlib/collection/mutable/HashTable.scala index a3534e322cf3..64af941eac1f 100644 --- a/tests/pos-special/stdlib/collection/mutable/HashTable.scala +++ b/tests/pos-special/stdlib/collection/mutable/HashTable.scala @@ -37,7 +37,7 @@ import language.experimental.captureChecking * @tparam A type of the elements contained in this hash table. */ // Not used in the standard library, but used in scala-parallel-collections -private[collection] trait HashTable[sealed A, B, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashUtils[A] { +private[collection] trait HashTable[A, B, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashUtils[A] { // Replacing Entry type parameter by abstract type member here allows to not expose to public // implementation-specific entry classes such as `DefaultEntry` or `LinkedEntry`. // However, I'm afraid it's too late now for such breaking change. @@ -412,7 +412,7 @@ private[collection] object HashTable { /** Class used internally. */ -private[collection] trait HashEntry[A, sealed E <: HashEntry[A, E]] { +private[collection] trait HashEntry[A, E <: HashEntry[A, E]] { val key: A var next: E = _ } diff --git a/tests/pos-special/stdlib/collection/mutable/LinkedHashMap.scala b/tests/pos-special/stdlib/collection/mutable/LinkedHashMap.scala index a253e8738b26..528c39e49bdf 100644 --- a/tests/pos-special/stdlib/collection/mutable/LinkedHashMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/LinkedHashMap.scala @@ -34,7 +34,7 @@ import language.experimental.captureChecking * @define orderDependentFold */ @deprecatedInheritance("LinkedHashMap will be made final; use .withDefault for the common use case of computing a default value", "2.13.11") -class LinkedHashMap[sealed K, sealed V] +class LinkedHashMap[K, V] extends AbstractMap[K, V] with SeqMap[K, V] with MapOps[K, V, LinkedHashMap, LinkedHashMap[K, V]] @@ -477,20 +477,20 @@ class LinkedHashMap[sealed K, sealed V] @SerialVersionUID(3L) object LinkedHashMap extends MapFactory[LinkedHashMap] { - def empty[sealed K, sealed V] = new LinkedHashMap[K, V] + def empty[K, V] = new LinkedHashMap[K, V] - def from[sealed K, sealed V](it: collection.IterableOnce[(K, V)]^) = { + def from[K, V](it: collection.IterableOnce[(K, V)]^) = { val newlhm = empty[K, V] newlhm.sizeHint(it.knownSize) newlhm.addAll(it) newlhm } - def newBuilder[sealed K, sealed V] = new GrowableBuilder(empty[K, V]) + def newBuilder[K, V] = new GrowableBuilder(empty[K, V]) /** Class for the linked hash map entry, used internally. */ - private[mutable] final class LinkedEntry[sealed K, sealed V](val key: K, val hash: Int, var value: V) { + private[mutable] final class LinkedEntry[K, V](val key: K, val hash: Int, var value: V) { var earlier: LinkedEntry[K, V] = null var later: LinkedEntry[K, V] = null var next: LinkedEntry[K, V] = null diff --git a/tests/pos-special/stdlib/collection/mutable/LinkedHashSet.scala b/tests/pos-special/stdlib/collection/mutable/LinkedHashSet.scala index a895034a852c..b9db31651ede 100644 --- a/tests/pos-special/stdlib/collection/mutable/LinkedHashSet.scala +++ b/tests/pos-special/stdlib/collection/mutable/LinkedHashSet.scala @@ -32,7 +32,7 @@ import language.experimental.captureChecking * @define orderDependentFold */ @deprecatedInheritance("LinkedHashSet will be made final", "2.13.11") -class LinkedHashSet[sealed A] +class LinkedHashSet[A] extends AbstractSet[A] with SetOps[A, LinkedHashSet, LinkedHashSet[A]] with StrictOptimizedIterableOps[A, LinkedHashSet, LinkedHashSet[A]] @@ -315,20 +315,20 @@ class LinkedHashSet[sealed A] @SerialVersionUID(3L) object LinkedHashSet extends IterableFactory[LinkedHashSet] { - override def empty[sealed A]: LinkedHashSet[A] = new LinkedHashSet[A] + override def empty[A]: LinkedHashSet[A] = new LinkedHashSet[A] - def from[sealed E](it: collection.IterableOnce[E]^) = { + def from[E](it: collection.IterableOnce[E]^) = { val newlhs = empty[E] newlhs.sizeHint(it.knownSize) newlhs.addAll(it) newlhs } - def newBuilder[sealed A] = new GrowableBuilder(empty[A]) + def newBuilder[A] = new GrowableBuilder(empty[A]) /** Class for the linked hash set entry, used internally. */ - private[mutable] final class Entry[sealed A](val key: A, val hash: Int) { + private[mutable] final class Entry[A](val key: A, val hash: Int) { var earlier: Entry[A] = null var later: Entry[A] = null var next: Entry[A] = null diff --git a/tests/pos-special/stdlib/collection/mutable/ListBuffer.scala b/tests/pos-special/stdlib/collection/mutable/ListBuffer.scala index 4f607c770130..570c815644ee 100644 --- a/tests/pos-special/stdlib/collection/mutable/ListBuffer.scala +++ b/tests/pos-special/stdlib/collection/mutable/ListBuffer.scala @@ -19,7 +19,6 @@ import java.lang.{IllegalArgumentException, IndexOutOfBoundsException} import scala.collection.generic.DefaultSerializable import scala.runtime.Statics.releaseFence -import scala.annotation.unchecked.uncheckedCaptures import language.experimental.captureChecking /** A `Buffer` implementation backed by a list. It provides constant time @@ -38,7 +37,7 @@ import language.experimental.captureChecking * @define willNotTerminateInf */ @SerialVersionUID(-8428291952499836345L) -class ListBuffer[sealed A] +class ListBuffer[A] extends AbstractBuffer[A] with SeqOps[A, ListBuffer, ListBuffer[A]] with StrictOptimizedSeqOps[A, ListBuffer, ListBuffer[A]] @@ -397,9 +396,9 @@ class ListBuffer[sealed A] @SerialVersionUID(3L) object ListBuffer extends StrictOptimizedSeqFactory[ListBuffer] { - def from[sealed A](coll: collection.IterableOnce[A]^): ListBuffer[A] = new ListBuffer[A].freshFrom(coll) + def from[A](coll: collection.IterableOnce[A]^): ListBuffer[A] = new ListBuffer[A].freshFrom(coll) - def newBuilder[sealed A]: Builder[A, ListBuffer[A]] = new GrowableBuilder(empty[A]) + def newBuilder[A]: Builder[A, ListBuffer[A]] = new GrowableBuilder(empty[A]) - def empty[A]: ListBuffer[A] = new ListBuffer[A @uncheckedCaptures] + def empty[A]: ListBuffer[A] = new ListBuffer[A] } diff --git a/tests/pos-special/stdlib/collection/mutable/ListMap.scala b/tests/pos-special/stdlib/collection/mutable/ListMap.scala index 8ddbc264e47b..e4f9322050d5 100644 --- a/tests/pos-special/stdlib/collection/mutable/ListMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/ListMap.scala @@ -31,7 +31,7 @@ import language.experimental.captureChecking * @define orderDependentFold */ @deprecated("Use an immutable.ListMap assigned to a var instead of mutable.ListMap", "2.13.0") -class ListMap[sealed K, sealed V] +class ListMap[K, V] extends AbstractMap[K, V] with MapOps[K, V, ListMap, ListMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, ListMap[K, V]] @@ -77,7 +77,7 @@ class ListMap[sealed K, sealed V] @SerialVersionUID(3L) @deprecated("Use an immutable.ListMap assigned to a var instead of mutable.ListMap", "2.13.0") object ListMap extends MapFactory[ListMap] { - def empty[sealed K, sealed V]: ListMap[K, V] = new ListMap[K, V] - def from[sealed K, sealed V](it: IterableOnce[(K, V)]^): ListMap[K,V] = Growable.from(empty[K, V], it) - def newBuilder[sealed K, sealed V]: Builder[(K, V), ListMap[K,V]] = new GrowableBuilder(empty[K, V]) + def empty[K, V]: ListMap[K, V] = new ListMap[K, V] + def from[K, V](it: IterableOnce[(K, V)]^): ListMap[K,V] = Growable.from(empty[K, V], it) + def newBuilder[K, V]: Builder[(K, V), ListMap[K,V]] = new GrowableBuilder(empty[K, V]) } diff --git a/tests/pos-special/stdlib/collection/mutable/LongMap.scala b/tests/pos-special/stdlib/collection/mutable/LongMap.scala index 2c757160ec77..5ac4757a42eb 100644 --- a/tests/pos-special/stdlib/collection/mutable/LongMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/LongMap.scala @@ -37,7 +37,7 @@ import language.experimental.captureChecking * rapidly as 2^30 is approached. * */ -final class LongMap[sealed V] private[collection] (defaultEntry: Long -> V, initialBufferSize: Int, initBlank: Boolean) +final class LongMap[V] private[collection] (defaultEntry: Long -> V, initialBufferSize: Int, initBlank: Boolean) extends AbstractMap[Long, V] with MapOps[Long, V, Map, LongMap[V]] with StrictOptimizedIterableOps[(Long, V), Iterable, LongMap[V]] @@ -469,18 +469,18 @@ final class LongMap[sealed V] private[collection] (defaultEntry: Long -> V, init } @deprecated("Use ++ with an explicit collection argument instead of + with varargs", "2.13.0") - override def + [sealed V1 >: V](elem1: (Long, V1), elem2: (Long, V1), elems: (Long, V1)*): LongMap[V1] = { + override def + [V1 >: V](elem1: (Long, V1), elem2: (Long, V1), elems: (Long, V1)*): LongMap[V1] = { val m = this + elem1 + elem2 if(elems.isEmpty) m else m.concat(elems) } - override def concat[sealed V1 >: V](xs: scala.collection.IterableOnce[(Long, V1)]^): LongMap[V1] = { + override def concat[V1 >: V](xs: scala.collection.IterableOnce[(Long, V1)]^): LongMap[V1] = { val lm = clone().asInstanceOf[LongMap[V1]] xs.iterator.foreach(kv => lm += kv) lm } - override def ++ [sealed V1 >: V](xs: scala.collection.IterableOnce[(Long, V1)]^): LongMap[V1] = concat(xs) + override def ++ [V1 >: V](xs: scala.collection.IterableOnce[(Long, V1)]^): LongMap[V1] = concat(xs) @deprecated("Use m.clone().addOne(k,v) instead of m.updated(k, v)", "2.13.0") override def updated[V1 >: V](key: Long, value: V1): LongMap[V1] = @@ -520,7 +520,7 @@ final class LongMap[sealed V] private[collection] (defaultEntry: Long -> V, init * Unlike `mapValues`, this method generates a new * collection immediately. */ - def mapValuesNow[sealed V1](f: V => V1): LongMap[V1] = { + def mapValuesNow[V1](f: V => V1): LongMap[V1] = { val zv = if ((extraKeys & 1) == 1) f(zeroValue.asInstanceOf[V]).asInstanceOf[AnyRef] else null val mv = if ((extraKeys & 2) == 2) f(minValue.asInstanceOf[V]).asInstanceOf[AnyRef] else null val lm = new LongMap[V1](LongMap.exceptionDefault, 1, false) @@ -563,11 +563,11 @@ final class LongMap[sealed V] private[collection] (defaultEntry: Long -> V, init this } - def map[sealed V2](f: ((Long, V)) => (Long, V2)): LongMap[V2] = LongMap.from(new View.Map(coll, f)) + def map[V2](f: ((Long, V)) => (Long, V2)): LongMap[V2] = LongMap.from(new View.Map(coll, f)) - def flatMap[sealed V2](f: ((Long, V)) => IterableOnce[(Long, V2)]): LongMap[V2] = LongMap.from(new View.FlatMap(coll, f)) + def flatMap[V2](f: ((Long, V)) => IterableOnce[(Long, V2)]): LongMap[V2] = LongMap.from(new View.FlatMap(coll, f)) - def collect[sealed V2](pf: PartialFunction[(Long, V), (Long, V2)]): LongMap[V2] = + def collect[V2](pf: PartialFunction[(Long, V), (Long, V2)]): LongMap[V2] = strictOptimizedCollect(LongMap.newBuilder[V2], pf) protected[this] def writeReplace(): AnyRef = new DefaultSerializationProxy(LongMap.toFactory[V](LongMap), this) @@ -587,7 +587,7 @@ object LongMap { * * This builder can be reused to create multiple instances. */ - final class LongMapBuilder[sealed V] extends ReusableBuilder[(Long, V), LongMap[V]] { + final class LongMapBuilder[V] extends ReusableBuilder[(Long, V), LongMap[V]] { private[collection] var elems: LongMap[V] = new LongMap[V] override def addOne(entry: (Long, V)): this.type = { elems += entry @@ -599,9 +599,9 @@ object LongMap { } /** Creates a new `LongMap` with zero or more key/value pairs. */ - def apply[sealed V](elems: (Long, V)*): LongMap[V] = buildFromIterableOnce(elems) + def apply[V](elems: (Long, V)*): LongMap[V] = buildFromIterableOnce(elems) - private def buildFromIterableOnce[sealed V](elems: IterableOnce[(Long, V)]^): LongMap[V] = { + private def buildFromIterableOnce[V](elems: IterableOnce[(Long, V)]^): LongMap[V] = { var sz = elems.knownSize if(sz < 0) sz = 4 val lm = new LongMap[V](sz * 2) @@ -611,10 +611,10 @@ object LongMap { } /** Creates a new empty `LongMap`. */ - def empty[sealed V]: LongMap[V] = new LongMap[V] + def empty[V]: LongMap[V] = new LongMap[V] /** Creates a new empty `LongMap` with the supplied default */ - def withDefault[sealed V](default: Long -> V): LongMap[V] = new LongMap[V](default) + def withDefault[V](default: Long -> V): LongMap[V] = new LongMap[V](default) /** Creates a new `LongMap` from an existing source collection. A source collection * which is already a `LongMap` gets cloned. @@ -623,17 +623,17 @@ object LongMap { * @tparam A the type of the collection’s elements * @return a new `LongMap` with the elements of `source` */ - def from[sealed V](source: IterableOnce[(Long, V)]^): LongMap[V] = source match { + def from[V](source: IterableOnce[(Long, V)]^): LongMap[V] = source match { case source: LongMap[_] => source.clone().asInstanceOf[LongMap[V]] case _ => buildFromIterableOnce(source) } - def newBuilder[sealed V]: ReusableBuilder[(Long, V), LongMap[V]] = new LongMapBuilder[V] + def newBuilder[V]: ReusableBuilder[(Long, V), LongMap[V]] = new LongMapBuilder[V] /** Creates a new `LongMap` from arrays of keys and values. * Equivalent to but more efficient than `LongMap((keys zip values): _*)`. */ - def fromZip[sealed V](keys: Array[Long], values: Array[V]): LongMap[V] = { + def fromZip[V](keys: Array[Long], values: Array[V]): LongMap[V] = { val sz = math.min(keys.length, values.length) val lm = new LongMap[V](sz * 2) var i = 0 @@ -645,7 +645,7 @@ object LongMap { /** Creates a new `LongMap` from keys and values. * Equivalent to but more efficient than `LongMap((keys zip values): _*)`. */ - def fromZip[sealed V](keys: scala.collection.Iterable[Long], values: scala.collection.Iterable[V]): LongMap[V] = { + def fromZip[V](keys: scala.collection.Iterable[Long], values: scala.collection.Iterable[V]): LongMap[V] = { val sz = math.min(keys.size, values.size) val lm = new LongMap[V](sz * 2) val ki = keys.iterator @@ -655,7 +655,7 @@ object LongMap { lm } - implicit def toFactory[sealed V](dummy: LongMap.type): Factory[(Long, V), LongMap[V]] = ToFactory.asInstanceOf[Factory[(Long, V), LongMap[V]]] + implicit def toFactory[V](dummy: LongMap.type): Factory[(Long, V), LongMap[V]] = ToFactory.asInstanceOf[Factory[(Long, V), LongMap[V]]] @SerialVersionUID(3L) private[this] object ToFactory extends Factory[(Long, AnyRef), LongMap[AnyRef]] with Serializable { @@ -669,6 +669,6 @@ object LongMap { def newBuilder(from: Any) = LongMap.newBuilder[AnyRef] } - implicit def iterableFactory[sealed V]: Factory[(Long, V), LongMap[V]] = toFactory(this) + implicit def iterableFactory[V]: Factory[(Long, V), LongMap[V]] = toFactory(this) implicit def buildFromLongMap[V]: BuildFrom[LongMap[_], (Long, V), LongMap[V]] = toBuildFrom(this) } diff --git a/tests/pos-special/stdlib/collection/mutable/MultiMap.scala b/tests/pos-special/stdlib/collection/mutable/MultiMap.scala index 281631c92298..93b0d6ae4d73 100644 --- a/tests/pos-special/stdlib/collection/mutable/MultiMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/MultiMap.scala @@ -52,7 +52,7 @@ import language.experimental.captureChecking * @define Coll `MultiMap` */ @deprecated("Use a scala.collection.mutable.MultiDict in the scala-collection-contrib module", "2.13.0") -trait MultiMap[K, sealed V] extends Map[K, Set[V]] { +trait MultiMap[K, V] extends Map[K, Set[V]] { /** Creates a new set. * * Classes that use this trait as a mixin can override this method diff --git a/tests/pos-special/stdlib/collection/mutable/OpenHashMap.scala b/tests/pos-special/stdlib/collection/mutable/OpenHashMap.scala index f1deb25b6a8a..978245d5bffb 100644 --- a/tests/pos-special/stdlib/collection/mutable/OpenHashMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/OpenHashMap.scala @@ -26,10 +26,10 @@ import language.experimental.captureChecking @SerialVersionUID(3L) object OpenHashMap extends MapFactory[OpenHashMap] { - def empty[sealed K, sealed V] = new OpenHashMap[K, V] - def from[sealed K, sealed V](it: IterableOnce[(K, V)]^): OpenHashMap[K,V] = empty ++= it + def empty[K, V] = new OpenHashMap[K, V] + def from[K, V](it: IterableOnce[(K, V)]^): OpenHashMap[K,V] = empty ++= it - def newBuilder[sealed K, sealed V]: Builder[(K, V), OpenHashMap[K,V]] = + def newBuilder[K, V]: Builder[(K, V), OpenHashMap[K,V]] = new GrowableBuilder[(K, V), OpenHashMap[K, V]](empty) /** A hash table entry. @@ -39,7 +39,7 @@ object OpenHashMap extends MapFactory[OpenHashMap] { * If its `key` is not the default value of type `Key`, the entry is occupied. * If the entry is occupied, `hash` contains the hash value of `key`. */ - final private class OpenEntry[sealed Key, sealed Value](var key: Key, + final private class OpenEntry[Key, Value](var key: Key, var hash: Int, var value: Option[Value]) @@ -62,7 +62,7 @@ object OpenHashMap extends MapFactory[OpenHashMap] { * @define willNotTerminateInf */ @deprecated("Use HashMap or one of the specialized versions (LongMap, AnyRefMap) instead of OpenHashMap", "2.13.0") -class OpenHashMap[sealed Key, sealed Value](initialSize : Int) +class OpenHashMap[Key, Value](initialSize : Int) extends AbstractMap[Key, Value] with MapOps[Key, Value, OpenHashMap, OpenHashMap[Key, Value]] with StrictOptimizedIterableOps[(Key, Value), Iterable, OpenHashMap[Key, Value]] diff --git a/tests/pos-special/stdlib/collection/mutable/PriorityQueue.scala b/tests/pos-special/stdlib/collection/mutable/PriorityQueue.scala index a395fac4a44a..ec923b641a71 100644 --- a/tests/pos-special/stdlib/collection/mutable/PriorityQueue.scala +++ b/tests/pos-special/stdlib/collection/mutable/PriorityQueue.scala @@ -67,7 +67,7 @@ import language.experimental.captureChecking * @define mayNotTerminateInf * @define willNotTerminateInf */ -sealed class PriorityQueue[sealed A](implicit val ord: Ordering[A]) +sealed class PriorityQueue[A](implicit val ord: Ordering[A]) extends AbstractIterable[A] with Iterable[A] with IterableOps[A, Iterable, PriorityQueue[A]] @@ -78,7 +78,7 @@ sealed class PriorityQueue[sealed A](implicit val ord: Ordering[A]) with Serializable { - private class ResizableArrayAccess[sealed A0] extends ArrayBuffer[A0] { + private class ResizableArrayAccess[A0] extends ArrayBuffer[A0] { override def mapInPlace(f: A0 => A0): this.type = { var i = 1 // see "we do not use array(0)" comment below (???) val siz = this.size @@ -365,7 +365,7 @@ sealed class PriorityQueue[sealed A](implicit val ord: Ordering[A]) pq } - override def copyToArray[sealed B >: A](xs: Array[B], start: Int, len: Int): Int = { + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = { val copied = IterableOnce.elemsToCopyToArray(length, xs.length, start, len) if (copied > 0) { Array.copy(resarr.p_array, 1, xs, start, copied) @@ -384,7 +384,7 @@ sealed class PriorityQueue[sealed A](implicit val ord: Ordering[A]) @SerialVersionUID(3L) object PriorityQueue extends SortedIterableFactory[PriorityQueue] { - def newBuilder[sealed A : Ordering]: Builder[A, PriorityQueue[A]] = { + def newBuilder[A : Ordering]: Builder[A, PriorityQueue[A]] = { new Builder[A, PriorityQueue[A]] { val pq = new PriorityQueue[A] def addOne(elem: A): this.type = { pq.unsafeAdd(elem); this } @@ -393,9 +393,9 @@ object PriorityQueue extends SortedIterableFactory[PriorityQueue] { } } - def empty[sealed A : Ordering]: PriorityQueue[A] = new PriorityQueue[A] + def empty[A : Ordering]: PriorityQueue[A] = new PriorityQueue[A] - def from[sealed E : Ordering](it: IterableOnce[E]^): PriorityQueue[E] = { + def from[E : Ordering](it: IterableOnce[E]^): PriorityQueue[E] = { val b = newBuilder[E] b ++= it b.result() diff --git a/tests/pos-special/stdlib/collection/mutable/Queue.scala b/tests/pos-special/stdlib/collection/mutable/Queue.scala index a578b0742009..884fbab798a5 100644 --- a/tests/pos-special/stdlib/collection/mutable/Queue.scala +++ b/tests/pos-special/stdlib/collection/mutable/Queue.scala @@ -28,7 +28,7 @@ import language.experimental.captureChecking * @define mayNotTerminateInf * @define willNotTerminateInf */ -class Queue[sealed A] protected (array: Array[AnyRef], start: Int, end: Int) +class Queue[A] protected (array: Array[AnyRef], start: Int, end: Int) extends ArrayDeque[A](array, start, end) with IndexedSeqOps[A, Queue, Queue[A]] with StrictOptimizedSeqOps[A, Queue, Queue[A]] @@ -130,10 +130,10 @@ class Queue[sealed A] protected (array: Array[AnyRef], start: Int, end: Int) @SerialVersionUID(3L) object Queue extends StrictOptimizedSeqFactory[Queue] { - def from[sealed A](source: IterableOnce[A]^): Queue[A] = empty ++= source + def from[A](source: IterableOnce[A]^): Queue[A] = empty ++= source - def empty[sealed A]: Queue[A] = new Queue + def empty[A]: Queue[A] = new Queue - def newBuilder[sealed A]: Builder[A, Queue[A]] = new GrowableBuilder[A, Queue[A]](empty) + def newBuilder[A]: Builder[A, Queue[A]] = new GrowableBuilder[A, Queue[A]](empty) } diff --git a/tests/pos-special/stdlib/collection/mutable/RedBlackTree.scala b/tests/pos-special/stdlib/collection/mutable/RedBlackTree.scala index 1f320f832cdf..4e079bca3245 100644 --- a/tests/pos-special/stdlib/collection/mutable/RedBlackTree.scala +++ b/tests/pos-special/stdlib/collection/mutable/RedBlackTree.scala @@ -32,25 +32,25 @@ private[collection] object RedBlackTree { // Therefore, while obtaining the size of the whole tree is O(1), knowing the number of entries inside a range is O(n) // on the size of the range. - final class Tree[sealed A, sealed B](var root: Node[A, B], var size: Int) { + final class Tree[A, B](var root: Node[A, B], var size: Int) { def treeCopy(): Tree[A, B] = new Tree(copyTree(root), size) } - final class Node[sealed A, sealed B](var key: A, var value: B, var red: Boolean, var left: Node[A, B], var right: Node[A, B], var parent: Node[A, B]) { + final class Node[A, B](var key: A, var value: B, var red: Boolean, var left: Node[A, B], var right: Node[A, B], var parent: Node[A, B]) { override def toString: String = "Node(" + key + ", " + value + ", " + red + ", " + left + ", " + right + ")" } object Tree { - def empty[sealed A, sealed B]: Tree[A, B] = new Tree(null, 0) + def empty[A, B]: Tree[A, B] = new Tree(null, 0) } object Node { - @`inline` def apply[sealed A, sealed B](key: A, value: B, red: Boolean, + @`inline` def apply[A, B](key: A, value: B, red: Boolean, left: Node[A, B], right: Node[A, B], parent: Node[A, B]): Node[A, B] = new Node(key, value, red, left, right, parent) - @`inline` def leaf[sealed A, sealed B](key: A, value: B, red: Boolean, parent: Node[A, B]): Node[A, B] = + @`inline` def leaf[A, B](key: A, value: B, red: Boolean, parent: Node[A, B]): Node[A, B] = new Node(key, value, red, null, null, parent) def unapply[A, B](t: Node[A, B]) = Some((t.key, t.value, t.left, t.right, t.parent)) @@ -181,7 +181,7 @@ private[collection] object RedBlackTree { // ---- insertion ---- - def insert[sealed A, sealed B](tree: Tree[A, B], key: A, value: B)(implicit ord: Ordering[A]): Unit = { + def insert[A, B](tree: Tree[A, B], key: A, value: B)(implicit ord: Ordering[A]): Unit = { var y: Node[A, B] = null var x = tree.root var cmp = 1 @@ -477,16 +477,16 @@ private[collection] object RedBlackTree { if (node.right ne null) transformNodeNonNull(node.right, f) } - def iterator[sealed A: Ordering, sealed B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[(A, B)] = + def iterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[(A, B)] = new EntriesIterator(tree, start, end) - def keysIterator[sealed A: Ordering](tree: Tree[A, _], start: Option[A] = None, end: Option[A] = None): Iterator[A] = + def keysIterator[A: Ordering](tree: Tree[A, _], start: Option[A] = None, end: Option[A] = None): Iterator[A] = new KeysIterator(tree, start, end) - def valuesIterator[sealed A: Ordering, sealed B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[B] = + def valuesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[B] = new ValuesIterator(tree, start, end) - private[this] abstract class TreeIterator[sealed A, sealed B, R](tree: Tree[A, B], start: Option[A], end: Option[A]) + private[this] abstract class TreeIterator[A, B, R](tree: Tree[A, B], start: Option[A], end: Option[A]) (implicit ord: Ordering[A]) extends AbstractIterator[R] { protected def nextResult(node: Node[A, B]): R @@ -514,19 +514,19 @@ private[collection] object RedBlackTree { setNullIfAfterEnd() } - private[this] final class EntriesIterator[sealed A: Ordering, sealed B](tree: Tree[A, B], start: Option[A], end: Option[A]) + private[this] final class EntriesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A]) extends TreeIterator[A, B, (A, B)](tree, start, end) { def nextResult(node: Node[A, B]) = (node.key, node.value) } - private[this] final class KeysIterator[sealed A: Ordering, sealed B](tree: Tree[A, B], start: Option[A], end: Option[A]) + private[this] final class KeysIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A]) extends TreeIterator[A, B, A](tree, start, end) { def nextResult(node: Node[A, B]) = node.key } - private[this] final class ValuesIterator[sealed A: Ordering, sealed B](tree: Tree[A, B], start: Option[A], end: Option[A]) + private[this] final class ValuesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A]) extends TreeIterator[A, B, B](tree, start, end) { def nextResult(node: Node[A, B]) = node.value @@ -604,7 +604,7 @@ private[collection] object RedBlackTree { // building /** Build a Tree suitable for a TreeSet from an ordered sequence of keys */ - def fromOrderedKeys[sealed A](xs: Iterator[A], size: Int): Tree[A, Null] = { + def fromOrderedKeys[A](xs: Iterator[A], size: Int): Tree[A, Null] = { val maxUsedDepth = 32 - Integer.numberOfLeadingZeros(size) // maximum depth of non-leaf nodes def f(level: Int, size: Int): Node[A, Null] = size match { case 0 => null @@ -623,7 +623,7 @@ private[collection] object RedBlackTree { } /** Build a Tree suitable for a TreeMap from an ordered sequence of key/value pairs */ - def fromOrderedEntries[sealed A, sealed B](xs: Iterator[(A, B)], size: Int): Tree[A, B] = { + def fromOrderedEntries[A, B](xs: Iterator[(A, B)], size: Int): Tree[A, B] = { val maxUsedDepth = 32 - Integer.numberOfLeadingZeros(size) // maximum depth of non-leaf nodes def f(level: Int, size: Int): Node[A, B] = size match { case 0 => null @@ -643,7 +643,7 @@ private[collection] object RedBlackTree { new Tree(f(1, size), size) } - def copyTree[sealed A, sealed B](n: Node[A, B]): Node[A, B] = + def copyTree[A, B](n: Node[A, B]): Node[A, B] = if(n eq null) null else { val c = new Node(n.key, n.value, n.red, copyTree(n.left), copyTree(n.right), null) if(c.left != null) c.left.parent = c diff --git a/tests/pos-special/stdlib/collection/mutable/Stack.scala b/tests/pos-special/stdlib/collection/mutable/Stack.scala index 4efa9621f374..0292811d2020 100644 --- a/tests/pos-special/stdlib/collection/mutable/Stack.scala +++ b/tests/pos-special/stdlib/collection/mutable/Stack.scala @@ -35,7 +35,7 @@ import language.experimental.captureChecking * @define willNotTerminateInf */ @migration("Stack is now based on an ArrayDeque instead of a linked list", "2.13.0") -class Stack[sealed A] protected (array: Array[AnyRef], start: Int, end: Int) +class Stack[A] protected (array: Array[AnyRef], start: Int, end: Int) extends ArrayDeque[A](array, start, end) with IndexedSeqOps[A, Stack, Stack[A]] with StrictOptimizedSeqOps[A, Stack, Stack[A]] @@ -135,10 +135,10 @@ class Stack[sealed A] protected (array: Array[AnyRef], start: Int, end: Int) @SerialVersionUID(3L) object Stack extends StrictOptimizedSeqFactory[Stack] { - def from[sealed A](source: IterableOnce[A]^): Stack[A] = empty ++= source + def from[A](source: IterableOnce[A]^): Stack[A] = empty ++= source - def empty[sealed A]: Stack[A] = new Stack + def empty[A]: Stack[A] = new Stack - def newBuilder[sealed A]: Builder[A, Stack[A]] = new GrowableBuilder[A, Stack[A]](empty) + def newBuilder[A]: Builder[A, Stack[A]] = new GrowableBuilder[A, Stack[A]](empty) } diff --git a/tests/pos-special/stdlib/collection/mutable/StringBuilder.scala b/tests/pos-special/stdlib/collection/mutable/StringBuilder.scala index 5320fa1dabb0..c7859214821d 100644 --- a/tests/pos-special/stdlib/collection/mutable/StringBuilder.scala +++ b/tests/pos-special/stdlib/collection/mutable/StringBuilder.scala @@ -110,7 +110,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr override def toString: String = result() - override def toArray[sealed B >: Char](implicit ct: scala.reflect.ClassTag[B]) = + override def toArray[B >: Char](implicit ct: scala.reflect.ClassTag[B]) = ct.runtimeClass match { case java.lang.Character.TYPE => toCharArray.asInstanceOf[Array[B]] case _ => super.toArray diff --git a/tests/pos-special/stdlib/collection/mutable/TreeMap.scala b/tests/pos-special/stdlib/collection/mutable/TreeMap.scala index f714a9ed46c2..dbb87a950d74 100644 --- a/tests/pos-special/stdlib/collection/mutable/TreeMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/TreeMap.scala @@ -29,7 +29,7 @@ import language.experimental.captureChecking * @define Coll mutable.TreeMap * @define coll mutable tree map */ -sealed class TreeMap[sealed K, sealed V] private (tree: RB.Tree[K, V])(implicit val ordering: Ordering[K]) +sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: Ordering[K]) extends AbstractMap[K, V] with SortedMap[K, V] with SortedMapOps[K, V, TreeMap, TreeMap[K, V]] @@ -248,11 +248,11 @@ sealed class TreeMap[sealed K, sealed V] private (tree: RB.Tree[K, V])(implicit @SerialVersionUID(3L) object TreeMap extends SortedMapFactory[TreeMap] { - def from[sealed K : Ordering, sealed V](it: IterableOnce[(K, V)]^): TreeMap[K, V] = + def from[K : Ordering, V](it: IterableOnce[(K, V)]^): TreeMap[K, V] = Growable.from(empty[K, V], it) - def empty[sealed K : Ordering, sealed V]: TreeMap[K, V] = new TreeMap[K, V]() + def empty[K : Ordering, V]: TreeMap[K, V] = new TreeMap[K, V]() - def newBuilder[sealed K: Ordering, sealed V]: Builder[(K, V), TreeMap[K, V]] = new GrowableBuilder(empty[K, V]) + def newBuilder[K: Ordering, V]: Builder[(K, V), TreeMap[K, V]] = new GrowableBuilder(empty[K, V]) } diff --git a/tests/pos-special/stdlib/collection/mutable/TreeSet.scala b/tests/pos-special/stdlib/collection/mutable/TreeSet.scala index 9ba439bea041..59c68a768351 100644 --- a/tests/pos-special/stdlib/collection/mutable/TreeSet.scala +++ b/tests/pos-special/stdlib/collection/mutable/TreeSet.scala @@ -29,7 +29,7 @@ import language.experimental.captureChecking * @define coll mutable tree set */ // Original API designed in part by Lucien Pereira -sealed class TreeSet[sealed A] private (private val tree: RB.Tree[A, Null])(implicit val ordering: Ordering[A]) +sealed class TreeSet[A] private (private val tree: RB.Tree[A, Null])(implicit val ordering: Ordering[A]) extends AbstractSet[A] with SortedSet[A] with SortedSetOps[A, TreeSet, TreeSet[A]] @@ -192,9 +192,9 @@ sealed class TreeSet[sealed A] private (private val tree: RB.Tree[A, Null])(impl @SerialVersionUID(3L) object TreeSet extends SortedIterableFactory[TreeSet] { - def empty[sealed A : Ordering]: TreeSet[A] = new TreeSet[A]() + def empty[A : Ordering]: TreeSet[A] = new TreeSet[A]() - def from[sealed E](it: IterableOnce[E]^)(implicit ordering: Ordering[E]): TreeSet[E] = + def from[E](it: IterableOnce[E]^)(implicit ordering: Ordering[E]): TreeSet[E] = it match { case ts: TreeSet[E] if ordering == ts.ordering => new TreeSet[E](ts.tree.treeCopy()) @@ -210,7 +210,7 @@ object TreeSet extends SortedIterableFactory[TreeSet] { new TreeSet[E](t) } - def newBuilder[sealed A](implicit ordering: Ordering[A]): Builder[A, TreeSet[A]] = new ReusableBuilder[A, TreeSet[A]] { + def newBuilder[A](implicit ordering: Ordering[A]): Builder[A, TreeSet[A]] = new ReusableBuilder[A, TreeSet[A]] { private[this] var tree: RB.Tree[A, Null] = RB.Tree.empty def addOne(elem: A): this.type = { RB.insert(tree, elem, null); this } def result(): TreeSet[A] = new TreeSet[A](tree) diff --git a/tests/pos-special/stdlib/collection/mutable/UnrolledBuffer.scala b/tests/pos-special/stdlib/collection/mutable/UnrolledBuffer.scala index 2015b76a31b8..cfb6d014ae9d 100644 --- a/tests/pos-special/stdlib/collection/mutable/UnrolledBuffer.scala +++ b/tests/pos-special/stdlib/collection/mutable/UnrolledBuffer.scala @@ -46,7 +46,7 @@ import language.experimental.captureChecking * */ @SerialVersionUID(3L) -sealed class UnrolledBuffer[sealed T](implicit val tag: ClassTag[T]) +sealed class UnrolledBuffer[T](implicit val tag: ClassTag[T]) extends AbstractBuffer[T] with Buffer[T] with Seq[T] @@ -73,7 +73,7 @@ sealed class UnrolledBuffer[sealed T](implicit val tag: ClassTag[T]) override def iterableFactory: SeqFactory[UnrolledBuffer] = UnrolledBuffer.untagged - protected def newUnrolled = new Unrolled[T](this) + protected def newUnrolled: Unrolled[T] = new Unrolled[T](this) // The below would allow more flexible behavior without requiring inheritance // that is risky because all the important internals are private. @@ -241,11 +241,11 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] val untagged: SeqFactory[UnrolledBuffer] = new ClassTagSeqFactory.AnySeqDelegate(self) - def empty[sealed A : ClassTag]: UnrolledBuffer[A] = new UnrolledBuffer[A] + def empty[A : ClassTag]: UnrolledBuffer[A] = new UnrolledBuffer[A] - def from[sealed A : ClassTag](source: scala.collection.IterableOnce[A]^): UnrolledBuffer[A] = newBuilder[A].addAll(source) + def from[A : ClassTag](source: scala.collection.IterableOnce[A]^): UnrolledBuffer[A] = newBuilder[A].addAll(source) - def newBuilder[sealed A : ClassTag]: UnrolledBuffer[A] = new UnrolledBuffer[A] + def newBuilder[A : ClassTag]: UnrolledBuffer[A] = new UnrolledBuffer[A] final val waterline: Int = 50 @@ -258,7 +258,7 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] /** Unrolled buffer node. */ - class Unrolled[sealed T: ClassTag] private[collection] (var size: Int, var array: Array[T], var next: Unrolled[T], val buff: UnrolledBuffer[T] = null) { + class Unrolled[T: ClassTag] private[collection] (var size: Int, var array: Array[T], var next: Unrolled[T], val buff: UnrolledBuffer[T] = null) { private[collection] def this() = this(0, new Array[T](unrolledlength), null, null) private[collection] def this(b: UnrolledBuffer[T]) = this(0, new Array[T](unrolledlength), null, b) @@ -437,7 +437,7 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] // This is used by scala.collection.parallel.mutable.UnrolledParArrayCombiner: // Todo -- revisit whether inheritance is the best way to achieve this functionality -private[collection] class DoublingUnrolledBuffer[sealed T](implicit t: ClassTag[T]) extends UnrolledBuffer[T]()(t) { +private[collection] class DoublingUnrolledBuffer[T](implicit t: ClassTag[T]) extends UnrolledBuffer[T]()(t) { override def calcNextLength(sz: Int) = if (sz < 10000) sz * 2 else sz override protected def newUnrolled = new UnrolledBuffer.Unrolled[T](0, new Array[T](4), null, this) } diff --git a/tests/pos-special/stdlib/collection/mutable/WeakHashMap.scala b/tests/pos-special/stdlib/collection/mutable/WeakHashMap.scala index a9498b7fc69b..1f94281a0b59 100644 --- a/tests/pos-special/stdlib/collection/mutable/WeakHashMap.scala +++ b/tests/pos-special/stdlib/collection/mutable/WeakHashMap.scala @@ -34,7 +34,7 @@ import language.experimental.captureChecking * @define willNotTerminateInf */ @SerialVersionUID(3L) -class WeakHashMap[sealed K, sealed V] extends JMapWrapper[K, V](new java.util.WeakHashMap) +class WeakHashMap[K, V] extends JMapWrapper[K, V](new java.util.WeakHashMap) with JMapWrapperLike[K, V, WeakHashMap, WeakHashMap[K, V]] with MapFactoryDefaults[K, V, WeakHashMap, Iterable] { override def empty = new WeakHashMap[K, V] @@ -49,8 +49,8 @@ class WeakHashMap[sealed K, sealed V] extends JMapWrapper[K, V](new java.util.We */ @SerialVersionUID(3L) object WeakHashMap extends MapFactory[WeakHashMap] { - def empty[sealed K, sealed V]: WeakHashMap[K,V] = new WeakHashMap[K, V] - def from[sealed K, sealed V](it: collection.IterableOnce[(K, V)]^): WeakHashMap[K,V] = Growable.from(empty[K, V], it) - def newBuilder[sealed K, sealed V]: Builder[(K, V), WeakHashMap[K,V]] = new GrowableBuilder(WeakHashMap.empty[K, V]) + def empty[K, V]: WeakHashMap[K,V] = new WeakHashMap[K, V] + def from[K, V](it: collection.IterableOnce[(K, V)]^): WeakHashMap[K,V] = Growable.from(empty[K, V], it) + def newBuilder[K, V]: Builder[(K, V), WeakHashMap[K,V]] = new GrowableBuilder(WeakHashMap.empty[K, V]) } diff --git a/tests/pos/boxmap-paper.scala b/tests/pos/boxmap-paper.scala index 7c2c005e6a61..aa983114ed8a 100644 --- a/tests/pos/boxmap-paper.scala +++ b/tests/pos/boxmap-paper.scala @@ -19,7 +19,7 @@ def lazyMap[A, B](c: Cell[A])(f: A => B): () ->{f} Cell[B] trait IO: def print(s: String): Unit -def test(io: IO^{cap}) = +def test(io: IO^) = val loggedOne: () ->{io} Int = () => { io.print("1"); 1 } diff --git a/tests/pos/i18699.scala b/tests/pos/i18699.scala index 61b21b0d3ad4..4bd3fbaad890 100644 --- a/tests/pos/i18699.scala +++ b/tests/pos/i18699.scala @@ -3,5 +3,5 @@ trait Cap: def use: Int = 42 def test2(cs: List[Cap^]): Unit = - val t0: Cap^{cap[test2]} = cs.head // error - var t1: Cap^{cap[test2]} = cs.head // error \ No newline at end of file + val t0: Cap^{cs*} = cs.head // error + var t1: Cap^{cs*} = cs.head // error \ No newline at end of file diff --git a/tests/run-custom-args/captures/colltest5/CollectionStrawManCC5_1.scala b/tests/run-custom-args/captures/colltest5/CollectionStrawManCC5_1.scala index efd331604fbe..20a6a33d3e02 100644 --- a/tests/run-custom-args/captures/colltest5/CollectionStrawManCC5_1.scala +++ b/tests/run-custom-args/captures/colltest5/CollectionStrawManCC5_1.scala @@ -249,12 +249,12 @@ object CollectionStrawMan5 { } /** Concrete collection type: ListBuffer */ - class ListBuffer[sealed A] extends Seq[A] with SeqLike[A] with Builder[A, List[A]] { + class ListBuffer[A] extends Seq[A] with SeqLike[A] with Builder[A, List[A]] { type C[X] = ListBuffer[X] private var first, last: List[A] = Nil private var aliased = false def iterator = first.iterator - def fromIterable[sealed B](coll: Iterable[B]^): ListBuffer[B] = ListBuffer.fromIterable(coll) + def fromIterable[B](coll: Iterable[B]^): ListBuffer[B] = ListBuffer.fromIterable(coll) def apply(i: Int) = first.apply(i) def length = first.length @@ -288,7 +288,7 @@ object CollectionStrawMan5 { object ListBuffer extends SeqFactory { type C[X] = ListBuffer[X] - def fromIterable[sealed B](coll: Iterable[B]^): ListBuffer[B] = new ListBuffer[B] ++= coll + def fromIterable[B](coll: Iterable[B]^): ListBuffer[B] = new ListBuffer[B] ++= coll } /** Concrete collection type: ArrayBuffer */ diff --git a/tests/run-custom-args/captures/colltest5/Test_2.scala b/tests/run-custom-args/captures/colltest5/Test_2.scala index 5ea259b965ed..f6f47b536541 100644 --- a/tests/run-custom-args/captures/colltest5/Test_2.scala +++ b/tests/run-custom-args/captures/colltest5/Test_2.scala @@ -61,10 +61,10 @@ object Test { println(xs16) } - def viewOps(xs: View[Int]^{cap}) = { + def viewOps(xs: View[Int]^) = { val strPlusInt: (String, Int) => String = _ + _ val intPlusStr: (Int, String) => String = _ + _ - val isEven: Int ->{cap[viewOps]} Boolean = _ % 2 == 0 + val isEven: Int => Boolean = _ % 2 == 0 val isNonNeg: Int => Boolean = _ > 0 val flips: Int => List[Int] = x => Cons(x, Cons(-x, Nil)) val x1 = xs.foldLeft("")(strPlusInt)