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.
fix scala#9482: implement manifest algorithm
- Loading branch information
1 parent
cf6fa97
commit bc8bb02
Showing
7 changed files
with
274 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
val `Array[Nothing]` = manifest[Array[Nothing]] // error | ||
val `Array[Null]` = manifest[Array[Null]] // error | ||
val m_Nothing = manifest[Nothing] // error | ||
val m_Null = manifest[Null] // error | ||
|
||
val `Array[? <: Nothing]` = manifest[Array[? <: Nothing]] // error | ||
val `Array[? <: Null]` = manifest[Array[? <: Null]] // error | ||
|
||
val `Int @unchecked` = manifest[Int @unchecked] // error | ||
|
||
val `0 | 1` = manifest[0 | 1] // error |
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,11 @@ | ||
import scala.reflect.OptManifest | ||
|
||
object Ref { | ||
def make[A: OptManifest]: Ref[A] = ??? | ||
} | ||
trait Ref[A] | ||
|
||
trait Foo[A] { | ||
val bar = Ref.make[Int] | ||
val baz: Ref[A] = Ref.make | ||
} |
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,29 @@ | ||
object Foo { | ||
|
||
object opaques { | ||
opaque type Inner = String | ||
val i: Inner = "i" | ||
} | ||
|
||
val singleton: opaques.Inner = opaques.i | ||
|
||
val m_Inner = manifest[opaques.Inner] // we can see the erasure of the opaque type | ||
val m_singleton = manifest[singleton.type] | ||
val om_Inner = optManifest[opaques.Inner] | ||
val om_singleton = optManifest[singleton.type] | ||
val ct_Inner = reflect.classTag[opaques.Inner] | ||
val ct_singleton = reflect.classTag[singleton.type] | ||
} | ||
|
||
object Bar { | ||
type F[T] <: T | ||
manifest[Array[F[Int]]] // would not work in Scala 2 | ||
} | ||
|
||
val `List[Nothing]` = manifest[List[Nothing]] | ||
val `List[Array[Nothing]]` = manifest[List[Array[Nothing]]] | ||
|
||
val `Array[Array[List[Int]]]` = manifest[Array[Array[List[Int]]]] | ||
|
||
trait Mixin[T <: Mixin[T]] { type Self = T } | ||
class Baz extends Mixin[Baz] { val m = manifest[Self] } |
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,101 @@ | ||
import scala.reflect.{classTag, ClassTag, NoManifest} | ||
|
||
@main def Test: Unit = | ||
|
||
/* ====== no manifest available ====== */ | ||
|
||
locally { | ||
noManifest[Array[? <: Int]] // available as a manifest | ||
noManifest[Array[? <: String]] // available as a manifest | ||
noManifest[Array[Nothing]] | ||
noManifest[Array[Null]] | ||
noManifest[Nothing] | ||
noManifest[Null] | ||
} | ||
|
||
/* ====== ClassTag and OptManifest have the same runtime class and same equality ======= */ | ||
|
||
locally { | ||
interopOpt[List[Int]] | ||
interopOpt[List[? <: Int]] | ||
} | ||
|
||
/* ====== Test some OptManifest have the same runtime class and are equal ======= */ | ||
|
||
locally { | ||
sameClassEqualOpt[List[Int], List[? <: Int]] // not equal for full manifests | ||
sameClassEqualOpt[List[Int], List[String]] // not equal for full manifests | ||
} | ||
|
||
/* ============================================================================= */ | ||
// The following tests rely on <:< being correct, i.e. `equals` on Manifest // | ||
// uses `<:<` underneath. // | ||
/* ============================================================================= */ | ||
|
||
/* ====== Test some Manifest have the same runtime class and are equal ======= */ | ||
|
||
locally { | ||
trait A | ||
trait B {def b: Int} | ||
trait C {def c: Int} | ||
trait D {def d: Int} | ||
class fooAnnot extends scala.annotation.StaticAnnotation | ||
|
||
type SomeRefinedType = | ||
((B {def b: 0} & C) & ((A @fooAnnot) & D {def d: 2})) {def c: 1} | ||
|
||
sameClassEqualMan[Array[? <: String], Array[String]] | ||
sameClassEqualMan[SomeRefinedType, A] | ||
} | ||
|
||
|
||
/* ====== Test some Manifest have the same runtime class but are not equal ======= */ | ||
|
||
locally { | ||
sameClassNonEqualMan[List[Int], List[? <: Int]] | ||
sameClassNonEqualMan[List[Int], List[String]] | ||
} | ||
|
||
/* ====== Test that some Manifest have the same runtime class, are not equal, but are `<:<` ======= */ | ||
|
||
locally { | ||
class A | ||
class B extends A | ||
|
||
sameClassSub[List[Int], List[AnyVal]] | ||
sameClassSub[List[Unit], List[AnyVal]] | ||
sameClassSub[List[B], List[A]] | ||
sameClassSub[Array[List[B]], Array[List[A]]] | ||
} | ||
|
||
end Test | ||
|
||
def noManifest[A: OptManifest] = | ||
assert(optManifest[A] eq NoManifest) | ||
|
||
def interopOpt[A: ClassTag: OptManifest] = | ||
assert(classTag[A] == optManifest[A]) | ||
optManifest[A] match | ||
case optA: ClassTag[_] => | ||
assert(classTag[A].runtimeClass == optA.runtimeClass) | ||
|
||
def sameClassEqualOpt[A: OptManifest, B: OptManifest] = | ||
assert(optManifest[A] == optManifest[B]) | ||
(optManifest[A], optManifest[B]) match | ||
case (a: ClassTag[_], b: ClassTag[_]) => | ||
assert(a.runtimeClass == b.runtimeClass) | ||
|
||
def sameClassMan[A: Manifest, B: Manifest] = | ||
assert(manifest[A].runtimeClass == manifest[B].runtimeClass) | ||
|
||
def sameClassEqualMan[A: Manifest, B: Manifest] = | ||
sameClassMan[A, B] | ||
assert(manifest[A] == manifest[B]) | ||
|
||
def sameClassNonEqualMan[A: Manifest, B: Manifest] = | ||
sameClassMan[A, B] | ||
assert(manifest[A] != manifest[B]) | ||
|
||
def sameClassSub[A: Manifest, B: Manifest] = | ||
sameClassNonEqualMan[A, B] | ||
assert(manifest[A] <:< manifest[B]) |