diff --git a/docs/docs/reference/dependent-function-types-spec.md b/docs/docs/reference/dependent-function-types-spec.md new file mode 100644 index 000000000000..1d7cc23414f3 --- /dev/null +++ b/docs/docs/reference/dependent-function-types-spec.md @@ -0,0 +1,48 @@ +--- +layout: doc-page +title: "Dependent Function Types - More Details" +--- + +Initial implementation in (#3464)[https://github.com/lampepfl/dotty/pull/3464]. + +## Syntax + + FunArgTypes ::= InfixType + | ‘(’ [ FunArgType {‘,’ FunArgType } ] ‘)’ + | '(' TypedFunParam {',' TypedFunParam } ')' + TypedFunParam ::= id ':' Type + +Dependent function types associate to the right, e.g. +`(s: S) ⇒ (t: T) ⇒ U` is the same as `(s: S) ⇒ ((t: T) ⇒ U)`. + +## Implementation + +Dependent function types are shorthands for class types that define `apply` +methods with a dependent result type.Dependent function types desugar to +refinement types of `scala.FunctionN`. A dependent functon type +`(x1: K1, ..., xN: KN) => R` of arity `N` translates to + + FunctionN[K1, ..., Kn, R'] { + def apply(x1: K1, ..., xN: KN): R + } + +where the result type parameter `R'` is the least upper approximation of the +precise result type `R` without any referance to value parameters `x1, ..., xN`. + +The syntax and sementics of anonymous dependent functions is identical to the +one of regular functions. Eta expansion is naturaly generalized to produce +dependent function types for methods with dependent result types. + +Dependent functions can be implicit, and generalize to arity `N > 22` in the +same way that other functions do, see [the corresponding +documentation](https://dotty.epfl.ch/docs/reference/dropped/limit22.html). + +## Examples + +- (depfuntype.scala)[https://github.com/lampepfl/dotty/blob/0.10.x/tests/pos/depfuntype.scala] + +- (eff-dependent.scala)[https://github.com/lampepfl/dotty/blob/0.10.x/tests/run/eff-dependent.scala] + +### Type Checking + +After desugaring no additional typing rules are required for dependent function types. diff --git a/docs/docs/reference/dependent-function-types.md b/docs/docs/reference/dependent-function-types.md index 47530e1c5006..efd8f19f02c7 100644 --- a/docs/docs/reference/dependent-function-types.md +++ b/docs/docs/reference/dependent-function-types.md @@ -10,9 +10,9 @@ on the function's parameter values. Example: def extractKey(e: Entry): e.Key = e.key // a dependent method val extractor: (e: Entry) => e.Key = extractKey // a dependent function value - // ║ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ║ - // ║ Dependent ║ - // ║ Function Type ║ + // ║ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ║ + // ║ Dependent ║ + // ║ Function Type ║ // ╚═══════════════════╝ Scala already has _dependent methods_, i.e. methods where the result 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 def apply(e: Entry): e.Key } -In general, a dependent functon type `(x1: K1, ..., xN: KN) => R` of arity `N` -translates to - - FunctionN[K1, ..., Kn, R'] { - def apply(x1: K1, ..., xN: KN): R - } - -where the result type parameter `R'` is an upper approximation of the -true result type `R` that does not mention any of the parameters `x1, ..., xN`. - - +[More details](./dependent-function-types-spec.html) diff --git a/docs/docs/reference/dropped/class-shadowing-spec.md b/docs/docs/reference/dropped/class-shadowing-spec.md new file mode 100644 index 000000000000..84e4cfdba9ce --- /dev/null +++ b/docs/docs/reference/dropped/class-shadowing-spec.md @@ -0,0 +1,25 @@ +--- +layout: doc-page +title: "Dropped: Class Shadowing - More Details" +--- + +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*. + +> Why do we want to make this change to the language? + +Class shadowing is irregular compared to other types of overrides. Indeed, inner classes are not actually overriden but simply shadowed. + + +> How much existing code is going to be affected? + +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. + + +> How exactly is existing code going to be affected? + +Code that relies on overridden inner classes will stop compiling. + + +> Is this change going to be migratable automatically? + +No. diff --git a/docs/docs/reference/dropped/class-shadowing.md b/docs/docs/reference/dropped/class-shadowing.md index b850f5fab846..f9df14a7b028 100644 --- a/docs/docs/reference/dropped/class-shadowing.md +++ b/docs/docs/reference/dropped/class-shadowing.md @@ -24,6 +24,4 @@ other, but classes in Scala cannot be overridden. To keep things clean (and its internal operations consistent) the Dotty compiler forces you to rename the inner classes so that their names are different. - - - +[More details](./class-shadowing-spec.html) diff --git a/docs/docs/reference/implicit-function-types-spec.md b/docs/docs/reference/implicit-function-types-spec.md new file mode 100644 index 000000000000..0453bcdf1a0c --- /dev/null +++ b/docs/docs/reference/implicit-function-types-spec.md @@ -0,0 +1,88 @@ +--- +layout: doc-page +title: "Implicit Function Types - More Details" +--- + +Initial implementation in (#1775)[https://github.com/lampepfl/dotty/pull/1775]. + +## Syntax + + Type ::= [`implicit'] FunArgTypes `=>' Type + | HkTypeParamClause `=>' Type + | InfixType + Expr ::= [`implicit'] FunParams `=>' Expr + BlockResult ::= [`implicit'] FunParams `=>' Block + | Expr1 + +Implicit function types associate to the right, e.g. +`implicit S ⇒ implicit T ⇒ U` is the same as `implicit S ⇒ (implicit T ⇒ U)`. + +## Implementation + +Implicit function types are shorthands for class types that define `apply` +methods with implicit parameters. Specifically, the `N`-ary function type +`implicit T1, ..., TN ⇒ R` is a shorthand for the class type +`ImplicitFunctionN[T1 , ... , TN, R]`. Such class types are defined in the +Scala library for `N` between 1 and 22 as follows. + + package scala + trait ImplicitFunctionN[-T1 , ... , -TN, +R] { + def apply(implicit x1: T1 , ... , xN: TN): R + } + +Anonymous implicit functions `implicit (x1: T1, ..., xn: Tn) => e` map +implicit parameters `xi` of types `Ti` to a result given by expression `e`. +The scope of each implicit parameter `xi` is `e`. Implicit parameters must +have pairwise distinct names. + +If the expected type of the anonymous implicit function is of the form +`scala.ImplicitFunctionN[S1, ..., Sn, R]`, the expected type of `e` is `R` and +the type `Ti` of any of the parameters `xi` can be omitted, in which case `Ti += Si` is assumed. If the expected type of the anonymous implicit function is +some other type, all implicit parameter types must be explicitly given, and +the expected type of `e` is undefined. The type of the anonymous implicit +function is `scala.ImplicitFunctionN[S1, ...,Sn, T]`, where `T` is the widened +type of `e`. `T` must be equivalent to a type which does not refer to any of +the implicit parameters `xi`. + +The anonymous implicit function is evaluated as the instance creation +expression: + + new scala.ImplicitFunctionN[T1, ..., Tn, T] { + def apply(implicit x1: T1, ..., xn: Tn): T = e + } + +In the case of a single untyped implicit parameter, `implicit (x) => e` can be +abbreviated to `implicit x => e`. If an anonymous implicit function `implicit +(x: T) => e` with a single typed parameter appears as the result expression of +a block, it can be abbreviated to `implicit x: T => e` + +A implicit parameter may also be a wildcard represented by an underscore `_`. In +that case, a fresh name for the parameter is chosen arbitrarily. + +Note: The closing paragraph of the [Anonymous Functions section](https://www +.scala-lang.org/files/archive/spec/2.12/06-expressions.html#anonymous- +functions) of the Scala 2.12 is subsumed by implicit function types and should +be removed. + +Anonymous implicit functions `implicit (x1: T1, ..., xn: Tn) => e` are +automatically inserted around any expression `e` whose expected type is +`scala.ImplicitFunctionN[T1, ..., Tn, R]`. This is analogous to the automatic +insertion of `scala.Function0` around expression in by-name argument position. + +Implicit functions generalize to `N > 22` in the same way that functions do, +see [the corresponding +documentation](https://dotty.epfl.ch/docs/reference/dropped/limit22.html). + +## Examples + +See the section on Expressiveness from [Simplicitly: foundations and +applications of implicit function +types](https://dl.acm.org/citation.cfm?id=3158130). I've extracted it in [this +Gist](https://gist.github.com/OlivierBlanvillain/234d3927fe9e9c6fba074b53a7bd9 +592), it might easier to access than the pdf. + +### Type Checking + +After desugaring no additional typing rules are required for implicit function +types. diff --git a/docs/docs/reference/implicit-function-types.md b/docs/docs/reference/implicit-function-types.md index 6570aeb929c7..e3b956ecbf46 100644 --- a/docs/docs/reference/implicit-function-types.md +++ b/docs/docs/reference/implicit-function-types.md @@ -101,3 +101,5 @@ With that setup, the table construction code above compiles and expands to: ### Reference For more info, see the [blog article](https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html). + +[More details](./implicit-function-types-spec.html)