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.
Allow context bounds in type declarations
Expand them to deferred givens
- Loading branch information
Showing
20 changed files
with
1,355 additions
and
34 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
//> using options -language:experimental.modularity -source future | ||
trait A[X]: | ||
type Self = X | ||
|
||
object Test2: | ||
def foo[X: A as x](a: x.Self) = ??? | ||
|
||
def bar[X: A as x](a: Int) = ??? | ||
|
||
def baz[X: A as x](a: Int)(using String) = ??? |
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,18 @@ | ||
//> using options -language:experimental.modularity -source future | ||
package hylotest | ||
import compiletime.deferred | ||
|
||
trait Value[Self] | ||
|
||
/** A collection of elements accessible by their position. */ | ||
trait Collection[Self]: | ||
|
||
/** The type of the elements in the collection. */ | ||
type Element: Value | ||
|
||
class BitArray | ||
|
||
given Value[Boolean] {} | ||
|
||
given Collection[BitArray] with | ||
type Element = Boolean |
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,66 @@ | ||
package hylo | ||
|
||
/** A type-erased collection. | ||
* | ||
* A `AnyCollection` forwards its operations to a wrapped value, hiding its implementation. | ||
*/ | ||
final class AnyCollection[Element] private ( | ||
val _start: () => AnyValue, | ||
val _end: () => AnyValue, | ||
val _after: (AnyValue) => AnyValue, | ||
val _at: (AnyValue) => Element | ||
) | ||
|
||
object AnyCollection { | ||
|
||
/** Creates an instance forwarding its operations to `base`. */ | ||
def apply[Base](using b: Collection[Base])(base: Base): AnyCollection[b.Element] = | ||
// NOTE: This evidence is redefined so the compiler won't report ambiguity between `intIsValue` | ||
// and `anyValueIsValue` when the method is called on a collection of `Int`s. None of these | ||
// choices is even correct! Note also that the ambiguity is suppressed if the constructor of | ||
// `AnyValue` is declared with a context bound rather than an implicit parameter. | ||
given Value[b.Position] = b.positionIsValue | ||
|
||
def start(): AnyValue = | ||
AnyValue(base.startPosition) | ||
|
||
def end(): AnyValue = | ||
AnyValue(base.endPosition) | ||
|
||
def after(p: AnyValue): AnyValue = | ||
AnyValue(base.positionAfter(p.unsafelyUnwrappedAs[b.Position])) | ||
|
||
def at(p: AnyValue): b.Element = | ||
base.at(p.unsafelyUnwrappedAs[b.Position]) | ||
|
||
new AnyCollection[b.Element]( | ||
_start = start, | ||
_end = end, | ||
_after = after, | ||
_at = at | ||
) | ||
|
||
} | ||
|
||
given anyCollectionIsCollection[T](using tIsValue: Value[T]): Collection[AnyCollection[T]] with { | ||
|
||
type Element = T | ||
type Position = AnyValue | ||
|
||
extension (self: AnyCollection[T]) { | ||
|
||
def startPosition = | ||
self._start() | ||
|
||
def endPosition = | ||
self._end() | ||
|
||
def positionAfter(p: Position) = | ||
self._after(p) | ||
|
||
def at(p: Position) = | ||
self._at(p) | ||
|
||
} | ||
|
||
} |
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,76 @@ | ||
package hylo | ||
|
||
/** A wrapper around an object providing a reference API. */ | ||
private final class Ref[T](val value: T) { | ||
|
||
override def toString: String = | ||
s"Ref($value)" | ||
|
||
} | ||
|
||
/** A type-erased value. | ||
* | ||
* An `AnyValue` forwards its operations to a wrapped value, hiding its implementation. | ||
*/ | ||
final class AnyValue private ( | ||
private val wrapped: AnyRef, | ||
private val _copy: (AnyRef) => AnyValue, | ||
private val _eq: (AnyRef, AnyRef) => Boolean, | ||
private val _hashInto: (AnyRef, Hasher) => Hasher | ||
) { | ||
|
||
/** Returns a copy of `this`. */ | ||
def copy(): AnyValue = | ||
_copy(this.wrapped) | ||
|
||
/** Returns `true` iff `this` and `other` have an equivalent value. */ | ||
def eq(other: AnyValue): Boolean = | ||
_eq(this.wrapped, other.wrapped) | ||
|
||
/** Hashes the salient parts of `this` into `hasher`. */ | ||
def hashInto(hasher: Hasher): Hasher = | ||
_hashInto(this.wrapped, hasher) | ||
|
||
/** Returns the value wrapped in `this` as an instance of `T`. */ | ||
def unsafelyUnwrappedAs[T]: T = | ||
wrapped.asInstanceOf[Ref[T]].value | ||
|
||
/** Returns a textual description of `this`. */ | ||
override def toString: String = | ||
wrapped.toString | ||
|
||
} | ||
|
||
object AnyValue { | ||
|
||
/** Creates an instance wrapping `wrapped`. */ | ||
def apply[T](using Value[T])(wrapped: T): AnyValue = | ||
def copy(a: AnyRef): AnyValue = | ||
AnyValue(a.asInstanceOf[Ref[T]].value.copy()) | ||
|
||
def eq(a: AnyRef, b: AnyRef): Boolean = | ||
a.asInstanceOf[Ref[T]].value `eq` b.asInstanceOf[Ref[T]].value | ||
|
||
def hashInto(a: AnyRef, hasher: Hasher): Hasher = | ||
a.asInstanceOf[Ref[T]].value.hashInto(hasher) | ||
|
||
new AnyValue(Ref(wrapped), copy, eq, hashInto) | ||
|
||
} | ||
|
||
given anyValueIsValue: Value[AnyValue] with { | ||
|
||
extension (self: AnyValue) { | ||
|
||
def copy(): AnyValue = | ||
self.copy() | ||
|
||
def eq(other: AnyValue): Boolean = | ||
self `eq` other | ||
|
||
def hashInto(hasher: Hasher): Hasher = | ||
self.hashInto(hasher) | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.