Skip to content

Commit f5b9572

Browse files
authored
Merge pull request #5331 from dotty-staging/sips-olivier
Add more detail pages for implicit/dependent functions and class Shadowing
2 parents 8610cdb + 1d07a22 commit f5b9572

File tree

6 files changed

+168
-17
lines changed

6 files changed

+168
-17
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
layout: doc-page
3+
title: "Dependent Function Types - More Details"
4+
---
5+
6+
Initial implementation in (#3464)[https://github.com/lampepfl/dotty/pull/3464].
7+
8+
## Syntax
9+
10+
FunArgTypes ::= InfixType
11+
| ‘(’ [ FunArgType {‘,’ FunArgType } ] ‘)’
12+
| '(' TypedFunParam {',' TypedFunParam } ')'
13+
TypedFunParam ::= id ':' Type
14+
15+
Dependent function types associate to the right, e.g.
16+
`(s: S) ⇒ (t: T) ⇒ U` is the same as `(s: S) ⇒ ((t: T) ⇒ U)`.
17+
18+
## Implementation
19+
20+
Dependent function types are shorthands for class types that define `apply`
21+
methods with a dependent result type.Dependent function types desugar to
22+
refinement types of `scala.FunctionN`. A dependent functon type
23+
`(x1: K1, ..., xN: KN) => R` of arity `N` translates to
24+
25+
FunctionN[K1, ..., Kn, R'] {
26+
def apply(x1: K1, ..., xN: KN): R
27+
}
28+
29+
where the result type parameter `R'` is the least upper approximation of the
30+
precise result type `R` without any referance to value parameters `x1, ..., xN`.
31+
32+
The syntax and sementics of anonymous dependent functions is identical to the
33+
one of regular functions. Eta expansion is naturaly generalized to produce
34+
dependent function types for methods with dependent result types.
35+
36+
Dependent functions can be implicit, and generalize to arity `N > 22` in the
37+
same way that other functions do, see [the corresponding
38+
documentation](https://dotty.epfl.ch/docs/reference/dropped/limit22.html).
39+
40+
## Examples
41+
42+
- (depfuntype.scala)[https://github.com/lampepfl/dotty/blob/0.10.x/tests/pos/depfuntype.scala]
43+
44+
- (eff-dependent.scala)[https://github.com/lampepfl/dotty/blob/0.10.x/tests/run/eff-dependent.scala]
45+
46+
### Type Checking
47+
48+
After desugaring no additional typing rules are required for dependent function types.

docs/docs/reference/dependent-function-types.md

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ on the function's parameter values. Example:
1010

1111
def extractKey(e: Entry): e.Key = e.key // a dependent method
1212
val extractor: (e: Entry) => e.Key = extractKey // a dependent function value
13-
// ║ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ║
14-
// ║ Dependent ║
15-
// ║ Function Type ║
13+
// ║ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ║
14+
// ║ Dependent ║
15+
// ║ Function Type ║
1616
// ╚═══════════════════╝
1717
Scala already has _dependent methods_, i.e. methods where the result
1818
type refers to some of the parameters of the method. Method
@@ -40,14 +40,4 @@ refinement. In fact, the dependent function type above is just syntactic sugar f
4040
def apply(e: Entry): e.Key
4141
}
4242

43-
In general, a dependent functon type `(x1: K1, ..., xN: KN) => R` of arity `N`
44-
translates to
45-
46-
FunctionN[K1, ..., Kn, R'] {
47-
def apply(x1: K1, ..., xN: KN): R
48-
}
49-
50-
where the result type parameter `R'` is an upper approximation of the
51-
true result type `R` that does not mention any of the parameters `x1, ..., xN`.
52-
53-
43+
[More details](./dependent-function-types-spec.html)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
layout: doc-page
3+
title: "Dropped: Class Shadowing - More Details"
4+
---
5+
6+
Spec diff: in section [5.1.4 Overriding](https://www.scala-lang.org/files/archive/spec/2.12/05-classes-and-objects.html), add *M' must not be a class*.
7+
8+
> Why do we want to make this change to the language?
9+
10+
Class shadowing is irregular compared to other types of overrides. Indeed, inner classes are not actually overriden but simply shadowed.
11+
12+
13+
> How much existing code is going to be affected?
14+
15+
From all the code compiled so far with Dotty the only instance of this I could find is in the stdlib. Looking at [this commit](https://github.com/lampepfl/scala/commit/68f13bf39979b631ed211ec1751934306ceb5d6c#diff-7aa508b70e055b47c823764e3e5646b8) it seems like the usage of class shadowing was accidental.
16+
17+
18+
> How exactly is existing code going to be affected?
19+
20+
Code that relies on overridden inner classes will stop compiling.
21+
22+
23+
> Is this change going to be migratable automatically?
24+
25+
No.

docs/docs/reference/dropped/class-shadowing.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,4 @@ other, but classes in Scala cannot be overridden. To keep things clean
2424
(and its internal operations consistent) the Dotty compiler forces you
2525
to rename the inner classes so that their names are different.
2626

27-
28-
29-
27+
[More details](./class-shadowing-spec.html)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
layout: doc-page
3+
title: "Implicit Function Types - More Details"
4+
---
5+
6+
Initial implementation in (#1775)[https://github.com/lampepfl/dotty/pull/1775].
7+
8+
## Syntax
9+
10+
Type ::= [`implicit'] FunArgTypes `=>' Type
11+
| HkTypeParamClause `=>' Type
12+
| InfixType
13+
Expr ::= [`implicit'] FunParams `=>' Expr
14+
BlockResult ::= [`implicit'] FunParams `=>' Block
15+
| Expr1
16+
17+
Implicit function types associate to the right, e.g.
18+
`implicit S ⇒ implicit T ⇒ U` is the same as `implicit S ⇒ (implicit T ⇒ U)`.
19+
20+
## Implementation
21+
22+
Implicit function types are shorthands for class types that define `apply`
23+
methods with implicit parameters. Specifically, the `N`-ary function type
24+
`implicit T1, ..., TN ⇒ R` is a shorthand for the class type
25+
`ImplicitFunctionN[T1 , ... , TN, R]`. Such class types are defined in the
26+
Scala library for `N` between 1 and 22 as follows.
27+
28+
package scala
29+
trait ImplicitFunctionN[-T1 , ... , -TN, +R] {
30+
def apply(implicit x1: T1 , ... , xN: TN): R
31+
}
32+
33+
Anonymous implicit functions `implicit (x1: T1, ..., xn: Tn) => e` map
34+
implicit parameters `xi` of types `Ti` to a result given by expression `e`.
35+
The scope of each implicit parameter `xi` is `e`. Implicit parameters must
36+
have pairwise distinct names.
37+
38+
If the expected type of the anonymous implicit function is of the form
39+
`scala.ImplicitFunctionN[S1, ..., Sn, R]`, the expected type of `e` is `R` and
40+
the type `Ti` of any of the parameters `xi` can be omitted, in which case `Ti
41+
= Si` is assumed. If the expected type of the anonymous implicit function is
42+
some other type, all implicit parameter types must be explicitly given, and
43+
the expected type of `e` is undefined. The type of the anonymous implicit
44+
function is `scala.ImplicitFunctionN[S1, ...,Sn, T]`, where `T` is the widened
45+
type of `e`. `T` must be equivalent to a type which does not refer to any of
46+
the implicit parameters `xi`.
47+
48+
The anonymous implicit function is evaluated as the instance creation
49+
expression:
50+
51+
new scala.ImplicitFunctionN[T1, ..., Tn, T] {
52+
def apply(implicit x1: T1, ..., xn: Tn): T = e
53+
}
54+
55+
In the case of a single untyped implicit parameter, `implicit (x) => e` can be
56+
abbreviated to `implicit x => e`. If an anonymous implicit function `implicit
57+
(x: T) => e` with a single typed parameter appears as the result expression of
58+
a block, it can be abbreviated to `implicit x: T => e`
59+
60+
A implicit parameter may also be a wildcard represented by an underscore `_`. In
61+
that case, a fresh name for the parameter is chosen arbitrarily.
62+
63+
Note: The closing paragraph of the [Anonymous Functions section](https://www
64+
.scala-lang.org/files/archive/spec/2.12/06-expressions.html#anonymous-
65+
functions) of the Scala 2.12 is subsumed by implicit function types and should
66+
be removed.
67+
68+
Anonymous implicit functions `implicit (x1: T1, ..., xn: Tn) => e` are
69+
automatically inserted around any expression `e` whose expected type is
70+
`scala.ImplicitFunctionN[T1, ..., Tn, R]`. This is analogous to the automatic
71+
insertion of `scala.Function0` around expression in by-name argument position.
72+
73+
Implicit functions generalize to `N > 22` in the same way that functions do,
74+
see [the corresponding
75+
documentation](https://dotty.epfl.ch/docs/reference/dropped/limit22.html).
76+
77+
## Examples
78+
79+
See the section on Expressiveness from [Simplicitly: foundations and
80+
applications of implicit function
81+
types](https://dl.acm.org/citation.cfm?id=3158130). I've extracted it in [this
82+
Gist](https://gist.github.com/OlivierBlanvillain/234d3927fe9e9c6fba074b53a7bd9
83+
592), it might easier to access than the pdf.
84+
85+
### Type Checking
86+
87+
After desugaring no additional typing rules are required for implicit function
88+
types.

docs/docs/reference/implicit-function-types.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,5 @@ With that setup, the table construction code above compiles and expands to:
101101
### Reference
102102

103103
For more info, see the [blog article](https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html).
104+
105+
[More details](./implicit-function-types-spec.html)

0 commit comments

Comments
 (0)