You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/_spec/03-types.md
+6-1Lines changed: 6 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -1012,7 +1012,11 @@ We define `memberType(´T´, ´id´, ´p´)` as follows:
1012
1012
- If ´m´ is not defined, the result is undefined.
1013
1013
- If ´m´ is a class declaration, the result is a class result with class ´m´.
1014
1014
- If ´m´ is a term definition in class ´D´ with declared type ´U´, the result is a term result with underlying type [`asSeenFrom`](#as-seen-from)`(´U´, ´D´, ´p´)` and stable flag true if and only if ´m´ is stable.
1015
-
- If ´m´ is a type member definition in class ´D´ with declared type definition ´U´, the result is a type result with underlying type definition [`asSeenFrom`](#as-seen-from)`(´U´, ´D´, ´p´)`.
1015
+
- If ´m´ is a type member definition in class ´D´, the result is a type result with underlying type definition [`asSeenFrom`](#as-seen-from)`(´U´, ´D´, ´p´)` where ´U´ is defined as follows:
1016
+
- If ´m´ is an opaque type alias member definition with declared definition ´>: L <: H = V´, then
1017
+
- ´U´ is ´= V´ if `´p = D.´this` or if we are computing `memberType` in a [_transparent mode_](#type-erasure),
1018
+
- ´U´ is ´>: L <: H´ otherwise.
1019
+
- ´U´ is the declared type definition of ´m´ otherwise.
1016
1020
- If ´T´ is another monomorphic type designator of the form ´q.X´:
1017
1021
- Let ´U´ be `memberType(´q´, ´X´)`
1018
1022
- Let ´H´ be the upper bound of ´U´
@@ -1228,6 +1232,7 @@ A type is called _generic_ if it contains type arguments or type variables.
1228
1232
_Type erasure_ is a mapping from (possibly generic) types to non-generic types.
1229
1233
We write ´|T|´ for the erasure of type ´T´.
1230
1234
The erasure mapping is defined as follows.
1235
+
Internal computations are performed in a _transparent mode_, which has an effect on how [`memberType`](#member-type) behaves for opaque type aliases.
1231
1236
1232
1237
- The erasure of `AnyKind` is `Object`.
1233
1238
- The erasure of a non-class type designator is the erasure of its underlying upper bound.
Copy file name to clipboardExpand all lines: docs/_spec/04-basic-declarations-and-definitions.md
+36-5Lines changed: 36 additions & 5 deletions
Original file line number
Diff line number
Diff line change
@@ -16,6 +16,7 @@ PatVarDef ::= ‘val’ PatDef
16
16
Def ::= PatVarDef
17
17
| ‘def’ FunDef
18
18
| ‘type’ {nl} TypeDef
19
+
| ‘opaque‘ ‘type‘ {nl} OpaqueTypeDef
19
20
| TmplDef
20
21
```
21
22
@@ -218,17 +219,21 @@ A variable definition `var ´x_1, ..., x_n: T´ = ´e´` is a shorthand for the
218
219
## Type Declarations and Type Aliases
219
220
220
221
```ebnf
221
-
Dcl ::= ‘type’ {nl} TypeDcl
222
-
TypeDcl ::= id [TypeParamClause] [‘>:’ Type] [‘<:’ Type]
223
-
Def ::= ‘type’ {nl} TypeDef
224
-
TypeDef ::= id [TypeParamClause] ‘=’ Type
222
+
Dcl ::= ‘type’ {nl} TypeDcl
223
+
TypeDcl ::= id [TypeParamClause] [‘>:’ Type] [‘<:’ Type]
224
+
Def ::= ‘type’ {nl} TypeDef
225
+
| ‘opaque‘ ‘type‘ {nl} OpaqueTypeDef
226
+
TypeDef ::= id [TypeParamClause] ‘=’ Type
227
+
OpaqueTypeDef ::= id [TypeParamClause] [‘>:’ Type] [‘<:’ Type] ‘=’ Type
225
228
```
226
229
227
230
A possibly parameterized _type declaration_`type ´t´[´\mathit{tps}\,´] >: ´L´ <: ´H´` declares ´t´ to be an abstract type.
228
231
If omitted, ´L´ and ´H´ are implied to be `Nothing` and `scala.Any`, respectively.
229
232
230
233
A possibly parameterized _type alias_`type ´t´[´\mathit{tps}\,´] = ´T´` defines ´t´ to be a concrete type member.
231
234
235
+
An _opaque type alias_`type ´t´ >: ´L´ <: ´H´ = ´T´` defines ´t´ to be an opaque type alias with public bounds `>: ´L´ <: ´H´` and a private alias `= ´T´`.
236
+
232
237
If a type parameter clause `[´\mathit{tps}\,´]` is present, it is desugared away according to the rules in the following section.
233
238
234
239
### Desugaring of parameterized type declarations
@@ -248,7 +253,7 @@ A parameterized abstract type
248
253
```scala
249
254
type ´t´[´\mathit{tps}\,´] >: ´L´ <: ´H´
250
255
```
251
-
is desugared into an unparameterized abstract type as follow:
256
+
is desugared into an unparameterized abstract type as follows:
252
257
- If `L` conforms to `Nothing`, then,
253
258
254
259
```scala
@@ -286,6 +291,25 @@ type ´t´ = [´\mathit{tps'}\,´] =>> ´T´
286
291
```
287
292
where ´\mathit{tps'}´ is computed as in the previous case.
288
293
294
+
####OpaqueTypeAlias
295
+
296
+
A parameterized typealias
297
+
```scala
298
+
type ´t´[´\mathit{tps}\,´] >: ´L´ <: ´H´ = ´T´
299
+
```
300
+
is desugared into an unparameterized opaquetypealiasasfollows:
301
+
-If `L` conforms to `Nothing`, then,
302
+
303
+
```scala
304
+
type ´t´ >:Nothing<: [´\mathit{tps'}\,´] =>> ´H´ = [´\mathit{tps'}\,´] =>> ´T´
where ´\mathit{tps'}´ is computed as in the previous cases.
312
+
289
313
###Non-ParameterizedTypeDeclarations and TypeAliases
290
314
291
315
A _type declaration_ `type ´t´ >: ´L´ <: ´H´` declares ´t´ to be an abstracttypewhose [typedefinition](03-types.html#type-definitions) has the lower bound type ´L´ and upper bound type ´H´.
@@ -295,6 +319,13 @@ It is a compile-time error if ´L´ does not conform to ´H´.
295
319
296
320
A _type alias_ `type ´t´ = ´T´` defines ´t´ to be an alias name for the type ´T´.
297
321
322
+
An _opaque typealias_ `type ´t´ >: ´L´ <: ´H´ = ´T´` defines ´t´ to be an opaquetypealiaswith public bounds `>: ´L´ <: ´H´` and a private alias `= ´T´`.
323
+
Anopaquetypealias can only be declared within a [template](./05-classes-and-objects.html#templates).
324
+
´L<:T´ and ´T<:H´ must be truefor the definition to be valid.
325
+
When viewed from within its enclosing template, an opaquetypealias behaves asatypealiaswithtypedefinition `= ´T´`.
326
+
When viewed from anywhere else, it behaves asatypedeclarationwithtypedefinition `>: ´L´ <: ´H´`.
327
+
See [`memberType`](./03-types.html#member-type) for the precise mechanism that governs this dual view.
328
+
298
329
The scope rules for [definitions](#basic-declarations-and-definitions) and [typeparameters](#method-declarations-and-definitions) make it possible that a typename appears in its own bounds or in its right-hand side.
299
330
However, it is a static error if a typealias refers recursively to the defined typeitself.
300
331
That is, the type ´T´ in a typealias `type ´t´[´\mathit{tps}\,´] = ´T´` may not refer directly or indirectly to the name ´t´.
In general, one can think of an opaque type as being only transparent in the scope of `private[this]`.
178
178
179
-
[More details](opaques-details.md)
179
+
## Top-level Opaque Types
180
+
181
+
An opaque type alias on the top-level is transparent in all other top-level definitions in the sourcefile where it appears, but is opaque in nested
182
+
objects and classes and in all other source files. Example:
183
+
```scala
184
+
// in test1.scala
185
+
opaquetypeA=String
186
+
valx:A="abc"
187
+
188
+
objectobj:
189
+
valy:A="abc"// error: found: "abc", required: A
190
+
191
+
// in test2.scala
192
+
defz:String= x // error: found: A, required: String
193
+
```
194
+
This behavior becomes clear if one recalls that top-level definitions are placed in their own synthetic object. For instance, the code in `test1.scala` would expand to
195
+
```scala
196
+
objecttest1$package:
197
+
opaquetypeA=String
198
+
valx:A="abc"
199
+
200
+
objectobj:
201
+
valy:A="abc"// error: cannot assign "abc" to opaque type alias A
202
+
```
203
+
The opaque type alias `A` is transparent in its scope, which includes the definition of `x`, but not the definitions of `obj` and `y`.
0 commit comments