Skip to content

Commit ed386f0

Browse files
authored
Merge pull request #11845 from dotty-staging/remove-use-of-erased-from-library
Remove use of `erased` in library
2 parents d15df36 + c8fde08 commit ed386f0

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,6 +2092,13 @@ class Typer extends Namer
20922092
sym.owner.info.decls.openForMutations.unlink(sym)
20932093
return EmptyTree
20942094
}
2095+
// TODO: - Remove this when `scala.language.experimental.erasedDefinitions` is no longer experimental.
2096+
// - Modify signature to `erased def erasedValue[T]: T`
2097+
if sym.eq(defn.Compiletime_erasedValue) then
2098+
// scala.compiletime.erasedValue should be `erased` but we cannot add this in the source.
2099+
// The library cannot use experimental language features,
2100+
// hence we special case it until `erased` is no longer experimental.
2101+
sym.setFlag(Erased)
20952102
val DefDef(name, paramss, tpt, _) = ddef
20962103
completeAnnotations(ddef, sym)
20972104
val paramss1 = paramss.nestedMapConserve(typed(_)).asInstanceOf[List[ParamClause]]
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package scala
2+
package compiletime
3+
4+
import annotation.compileTimeOnly
5+
6+
/** Use this method when you have a type, do not have a value for it but want to
7+
* pattern match on it. For example, given a type `Tup <: Tuple`, one can
8+
* pattern-match on it as follows:
9+
* ```scala
10+
* inline erasedValue[Tup] match {
11+
* case _: EmptyTuple => ...
12+
* case _: h *: t => ...
13+
* }
14+
* ```
15+
* This value can only be used in an inline match and the value cannot be used in
16+
* the branches.
17+
* @syntax markdown
18+
*/
19+
// TODO add `erased` once it is not an experimental feature anymore
20+
def erasedValue[T]: T = ???
21+
22+
/** Used as the initializer of a mutable class or object field, like this:
23+
*
24+
* var x: T = uninitialized
25+
*
26+
* This signifies that the field is not initialized on its own. It is still initialized
27+
* as part of the bulk initialization of the object it belongs to, which assigns zero
28+
* values such as `null`, `0`, `0.0`, `false` to all object fields.
29+
*/
30+
@compileTimeOnly("`uninitialized` can only be used as the right hand side of a mutable field definition")
31+
def uninitialized: Nothing = ???
32+
33+
/** The error method is used to produce user-defined compile errors during inline expansion.
34+
* If an inline expansion results in a call error(msgStr) the compiler produces an error message containing the given msgStr.
35+
*
36+
* ```scala
37+
* error("My error message")
38+
* ```
39+
* or
40+
* ```scala
41+
* inline def errorOnThisCode(inline x: Any) =
42+
* error("My error of this code: " + codeOf(x))
43+
* ```
44+
* @syntax markdown
45+
*/
46+
inline def error(inline msg: String): Nothing = ???
47+
48+
/** Returns the string representation of argument code:
49+
*
50+
* ```scala
51+
* inline def logged(inline p1: Any) =
52+
* ("code: " + codeOf(p1), p1)
53+
*
54+
* logged(identity("foo"))
55+
* // above is equivalent to:
56+
* // ("code: scala.Predef.identity("foo")", identity("foo"))
57+
* ```
58+
*
59+
* The formatting of the code is not stable across version of the compiler.
60+
*
61+
* @note only `inline` arguments will be displayed as "code".
62+
* Other values may display unintutively.
63+
*
64+
* @syntax markdown
65+
*/
66+
transparent inline def codeOf(arg: Any): String =
67+
// implemented in dotty.tools.dotc.typer.Inliner.Intrinsics
68+
error("Compiler bug: `codeOf` was not evaluated by the compiler")
69+
70+
/** Checks at compiletime that the provided values is a constant after
71+
* inlining and constant folding.
72+
*
73+
* Usage:
74+
* ```scala
75+
* inline def twice(inline n: Int): Int =
76+
* requireConst(n) // compile-time assertion that the parameter `n` is a constant
77+
* n + n
78+
*
79+
* twice(1)
80+
* val m: Int = ...
81+
* twice(m) // error: expected a constant value but found: m
82+
* ```
83+
* @syntax markdown
84+
*/
85+
inline def requireConst(inline x: Boolean | Byte | Short | Int | Long | Float | Double | Char | String): Unit =
86+
// implemented in dotty.tools.dotc.typer.Inliner
87+
error("Compiler bug: `requireConst` was not evaluated by the compiler")
88+
89+
/** Same as `constValue` but returns a `None` if a constant value
90+
* cannot be constructed from the provided type. Otherwise returns
91+
* that value wrapped in `Some`.
92+
*/
93+
transparent inline def constValueOpt[T]: Option[T] =
94+
// implemented in dotty.tools.dotc.typer.Inliner
95+
error("Compiler bug: `constValueOpt` was not evaluated by the compiler")
96+
97+
/** Given a constant, singleton type `T`, convert it to a value
98+
* of the same singleton type. For example: `assert(constValue[1] == 1)`.
99+
*/
100+
transparent inline def constValue[T]: T =
101+
// implemented in dotty.tools.dotc.typer.Inliner
102+
error("Compiler bug: `constValue` was not evaluated by the compiler")
103+
104+
/** Given a tuple type `(X1, ..., Xn)`, returns a tuple value
105+
* `(constValue[X1], ..., constValue[Xn])`.
106+
*/
107+
inline def constValueTuple[T <: Tuple]: T =
108+
val res =
109+
inline erasedValue[T] match
110+
case _: EmptyTuple => EmptyTuple
111+
case _: (t *: ts) => constValue[t] *: constValueTuple[ts]
112+
end match
113+
res.asInstanceOf[T]
114+
end constValueTuple
115+
116+
/** Summons first given matching one of the listed cases. E.g. in
117+
*
118+
* ```scala
119+
* given B { ... }
120+
*
121+
* summonFrom {
122+
* case given A => 1
123+
* case given B => 2
124+
* case given C => 3
125+
* case _ => 4
126+
* }
127+
* ```
128+
* the returned value would be `2`.
129+
* @syntax markdown
130+
*/
131+
transparent inline def summonFrom[T](f: Nothing => T): T =
132+
error("Compiler bug: `summonFrom` was not evaluated by the compiler")
133+
134+
/** Summon a given value of type `T`. Usually, the argument is not passed explicitly.
135+
* The summoning is delayed until the call has been fully inlined.
136+
*
137+
* @tparam T the type of the value to be summoned
138+
* @return the given value typed as the provided type parameter
139+
*/
140+
transparent inline def summonInline[T]: T = summonFrom {
141+
case t: T => t
142+
}
143+
144+
/** Given a tuple T, summons each of its member types and returns them in
145+
* a Tuple.
146+
*
147+
* @tparam T the tuple containing the types of the values to be summoned
148+
* @return the given values typed as elements of the tuple
149+
*/
150+
inline def summonAll[T <: Tuple]: T =
151+
val res =
152+
inline erasedValue[T] match
153+
case _: EmptyTuple => EmptyTuple
154+
case _: (t *: ts) => summonInline[t] *: summonAll[ts]
155+
end match
156+
res.asInstanceOf[T]
157+
end summonAll
158+
159+
/** Assertion that an argument is by-name. Used for nullability checking. */
160+
def byName[T](x: => T): T = x

0 commit comments

Comments
 (0)