forked from scala/scala3
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request scala#15877 from dotty-staging/cc-experiment
Add experimental capture checking
- Loading branch information
Showing
213 changed files
with
8,214 additions
and
526 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package dotty.tools | ||
package dotc | ||
package cc | ||
|
||
import core.* | ||
import Types.*, Symbols.*, Contexts.* | ||
|
||
/** A one-element cache for the boxed version of an unboxed capturing type */ | ||
class BoxedTypeCache: | ||
private var boxed: Type = compiletime.uninitialized | ||
private var unboxed: Type = NoType | ||
|
||
def apply(tp: AnnotatedType)(using Context): Type = | ||
if tp ne unboxed then | ||
unboxed = tp | ||
val CapturingType(parent, refs) = tp: @unchecked | ||
boxed = CapturingType(parent, refs, boxed = true) | ||
boxed | ||
end BoxedTypeCache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package dotty.tools | ||
package dotc | ||
package cc | ||
|
||
import core.* | ||
import Types.*, Symbols.*, Contexts.*, Annotations.* | ||
import ast.Trees.* | ||
import ast.{tpd, untpd} | ||
import Decorators.* | ||
import config.Printers.capt | ||
import printing.Printer | ||
import printing.Texts.Text | ||
|
||
/** An annotation representing a capture set and whether it is boxed. | ||
* It simulates a normal @retains annotation except that it is more efficient, | ||
* supports variables as capture sets, and adds a `boxed` flag. | ||
* These annotations are created during capture checking. Before that | ||
* there are only regular @retains and @retainsByName annotations. | ||
* @param refs the capture set | ||
* @param boxed whether the type carrying the annotation is boxed | ||
* @param cls the underlying class (either annotation.retains or annotation.retainsByName) | ||
*/ | ||
case class CaptureAnnotation(refs: CaptureSet, boxed: Boolean)(cls: Symbol) extends Annotation: | ||
import CaptureAnnotation.* | ||
import tpd.* | ||
|
||
/** A cache for boxed version of a capturing type with this annotation */ | ||
val boxedType = BoxedTypeCache() | ||
|
||
/** Reconstitute annotation tree from capture set */ | ||
override def tree(using Context) = | ||
val elems = refs.elems.toList.map { | ||
case cr: TermRef => ref(cr) | ||
case cr: TermParamRef => untpd.Ident(cr.paramName).withType(cr) | ||
case cr: ThisType => This(cr.cls) | ||
} | ||
val arg = repeated(elems, TypeTree(defn.AnyType)) | ||
New(symbol.typeRef, arg :: Nil) | ||
|
||
override def symbol(using Context) = cls | ||
|
||
override def derivedAnnotation(tree: Tree)(using Context): Annotation = | ||
unsupported(i"derivedAnnotation(Tree), $tree, $refs") | ||
|
||
def derivedAnnotation(refs: CaptureSet, boxed: Boolean)(using Context): Annotation = | ||
if (this.refs eq refs) && (this.boxed == boxed) then this | ||
else CaptureAnnotation(refs, boxed)(cls) | ||
|
||
override def sameAnnotation(that: Annotation)(using Context): Boolean = that match | ||
case CaptureAnnotation(refs, boxed) => | ||
this.refs == refs && this.boxed == boxed && this.symbol == that.symbol | ||
case _ => false | ||
|
||
override def mapWith(tm: TypeMap)(using Context) = | ||
val elems = refs.elems.toList | ||
val elems1 = elems.mapConserve(tm) | ||
if elems1 eq elems then this | ||
else if elems1.forall(_.isInstanceOf[CaptureRef]) | ||
then derivedAnnotation(CaptureSet(elems1.asInstanceOf[List[CaptureRef]]*), boxed) | ||
else EmptyAnnotation | ||
|
||
override def refersToParamOf(tl: TermLambda)(using Context): Boolean = | ||
refs.elems.exists { | ||
case TermParamRef(tl1, _) => tl eq tl1 | ||
case _ => false | ||
} | ||
|
||
override def toText(printer: Printer): Text = refs.toText(printer) | ||
|
||
override def hash: Int = | ||
(refs.hashCode << 1) | (if boxed then 1 else 0) | ||
|
||
override def eql(that: Annotation) = that match | ||
case that: CaptureAnnotation => (this.refs eq that.refs) && (this.boxed == that.boxed) | ||
case _ => false | ||
|
||
end CaptureAnnotation |
Oops, something went wrong.