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
@@ -20,12 +20,13 @@ val x = Set(if condition then Val else Var)
20
20
21
21
Here, the inferred type of `x` is `Set[Kind & Product & Serializable]` whereas one would have hoped it to be `Set[Kind]`. The reasoning for this particular type to be inferred is as follows:
22
22
23
-
- The type of the conditional above is the [union type](../new-types/union-types.md)`Val | Var`.
24
-
- A union type is widened in type inference to the least supertype that is not a union type.
25
-
In the example, this type is `Kind & Product & Serializable` since all three traits are traits of both `Val` and `Var`.
23
+
- The type of the conditional above is the [union type](../new-types/union-types.md)`Val | Var`. This union type is treated as "soft", which means it was not explicitly written in the source program, but came from forming an upper bound of the types of
24
+
some alternatives.
25
+
- A soft union type is widened in type inference to the least product of class or trait types that is a supertype of the union type.
26
+
In the example, this type is `Kind & Product & Serializable` since all three traits are super-traits of both `Val` and `Var`.
26
27
So that type becomes the inferred element type of the set.
27
28
28
-
Scala 3 allows one to mark a mixin trait as `transparent`, which means that it can be suppressed in type inference. Here's an example that follows the lines of the code above, but now with a new transparent trait `S` instead of `Product`:
29
+
Scala 3 allows one to mark a trait or class as `transparent`, which means that it can be suppressed in type inference. Here's an example that follows the lines of the code above, but now with a new transparent trait `S` instead of `Product`:
29
30
30
31
```scala
31
32
transparenttraitS
@@ -38,13 +39,40 @@ val x = Set(if condition then Val else Var)
38
39
Now `x` has inferred type `Set[Kind]`. The common transparent trait `S` does not
39
40
appear in the inferred type.
40
41
41
-
## Transparent Traits
42
+
In the previous example, one could also declare `Kind` as `transparent`:
43
+
```scala
44
+
transparenttraitKind
45
+
```
46
+
The widened union type of `if condition then Val else Var` would then
47
+
_only_ contain the transparent traits `Kind` and `S`. In this case,
48
+
the widening is not performed at all, so `x` would have type `Set[Val | Var]`.
49
+
50
+
The root classes and traits `Any`, `AnyVal`, `Object`, and `Matchable` are
51
+
considered to be transparent. This means that an expression such
52
+
as
53
+
```scala
54
+
if condition then1else"hello"
55
+
```
56
+
will have type `Int | String` instead of the widened type `Any`.
57
+
42
58
43
-
The traits [`scala.Product`](https://scala-lang.org/api/3.x/scala/Product.html), [`java.io.Serializable`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/Serializable.html) and [`java.lang.Comparable`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Comparable.html)
44
-
are treated automatically as transparent. Other traits are turned into transparent traits using the modifier `transparent`. Scala 2 traits can also be made transparent
45
-
by adding a [`@transparentTrait`](https://scala-lang.org/api/3.x/scala/annotation/transparentTrait.html) annotation. This annotation is defined in [`scala.annotation`](https://scala-lang.org/api/3.x/scala/annotation.html). It will be deprecated and phased out once Scala 2/3 interoperability is no longer needed.
46
59
47
-
Typically, transparent traits are traits
60
+
## Which Traits and Classes Are Transparent?
61
+
62
+
Traits and classes are declared transparent by adding the modifier `transparent`. Scala 2 traits and classes can also be declared transparent by adding a [`@transparentTrait`](https://scala-lang.org/api/3.x/scala/annotation/transparentTrait.html) annotation. This annotation is defined in [`scala.annotation`](https://scala-lang.org/api/3.x/scala/annotation.html). It will be deprecated and phased out once Scala 2/3 interoperability is no longer needed.
63
+
64
+
The following classes and traits are automatically treated as transparent:
65
+
```scala
66
+
scala.Any
67
+
scala.AnyVal
68
+
scala.Matchable
69
+
scala.Product
70
+
java.lang.Object
71
+
java.lang.Comparable
72
+
java.io.Serializable
73
+
```
74
+
75
+
Typically, transparent types other than the root classes are traits
48
76
that influence the implementation of inheriting classes and traits that are not usually used as types by themselves. Two examples from the standard collection library are:
49
77
50
78
-[`IterableOps`](https://scala-lang.org/api/3.x/scala/collection/IterableOps.html), which provides method implementations for an [`Iterable`](https://scala-lang.org/api/3.x/scala/collection/Iterable.html).
@@ -55,7 +83,10 @@ declared transparent.
55
83
56
84
## Rules for Inference
57
85
58
-
Transparent traits can be given as explicit types as usual. But they are often elided when types are inferred. Roughly, the rules for type inference say that transparent traits are dropped from intersections where possible.
86
+
Transparent traits and classes can be given as explicit types as usual. But they are often elided when types are inferred. Roughly, the rules for type inference imply the following.
87
+
88
+
- Transparent traits and classes are dropped from intersections where possible.
89
+
- Union types are not widened if widening would result in only transparent supertypes.
59
90
60
91
The precise rules are as follows:
61
92
@@ -65,6 +96,6 @@ The precise rules are as follows:
65
96
- If the type inferred so far is of the form `T1 & ... & Tn` where
66
97
`n >= 1`, replace the maximal number of transparent `Ti`s by `Any`, while ensuring that
67
98
the resulting type is still a subtype of the bound `B`.
68
-
- However, do not perform this widening if all transparent traits`Ti` can get replaced in that way.
99
+
- However, do not perform this widening if all transparent types`Ti` can get replaced in that way. This clause ensures that a single transparent trait instance such as [`Product`](https://scala-lang.org/api/3.x/scala/Product.html) is not widened to [`Any`](https://scala-lang.org/api/3.x/scala/Any.html). Transparent trait instances are only dropped when they appear in conjunction with some other type.
69
100
70
-
The last clause ensures that a single transparent trait instance such as [`Product`](https://scala-lang.org/api/3.x/scala/Product.html) is not widened to [`Any`](https://scala-lang.org/api/3.x/scala/Any.html). Transparent trait instances are only dropped when they appear in conjunction with some other type.
101
+
- If the original type was a is union type that got widened in a previous step to a product consisting only of transparent types, keep the original union type instead of its widened form.
0 commit comments