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
@@ -270,9 +262,9 @@ val voly: Int => [T] => T => T = poly
270
262
271
263
As this feature only provides a shortcut to express already definable objects, the only impacted area is the type system.
272
264
273
-
When typing a polymorphic method `m` there are three cases to consider:
265
+
When typing a polymorphic method `m` there are two cases to consider:
274
266
275
-
#### With expected type
267
+
#### Polymorphic expected type
276
268
If the expected type is a polymorphic function taking `[T_1 <: U_1 >: L_1, ..., T_n <: U_n >: L_n]` as type parameters, `(A_1, ..., A_k)` as term parameters and returning `R`, we proceed as follows:
277
269
278
270
Note: Polymorphic functions always take term parameters (but `k` can equal zero if the clause is explicit: `[T] => () => T`).
@@ -297,7 +289,7 @@ Note: Polymorphic functions always take term parameters (but `k` can equal zero
297
289
*1. If it succeeds, the above is the created tree.
298
290
*2. If it fails, go to [Default](#Default).
299
291
300
-
At 3.2. if the cause of the error is such that [Default](#Default) will never succeed, we might return that error directly, this is at the discretion of the implementation, to make errors as clear as possible.
292
+
At 3.ii. if the cause of the error is such that [Non-polymorphic expected type](#non-polymorphic-expected-type) will never succeed, we might return that error directly, this is at the discretion of the implementation, to make errors as clear as possible.
301
293
302
294
Note: Type checking will be in charge of overloading resolution, as well as term inference, so the following will work:
303
295
~~~scala
@@ -327,43 +319,7 @@ val voo: [T] => T => [U] => U => (T, U) = foo
If there is no expected type, let `ms` be all the overloaded variants of `m` which take at least one explicit parameter clause.
335
-
336
-
If `ms` contains no variants, go to [Default](#Default).
337
-
If it contains more than one variant, throw an overloading error.
338
-
339
-
If `ms` contains exactly one variant, then it is expanded as follows:
340
-
-->
341
-
342
-
`m` has to contain at least one explicit term clause before the return type or the next type clause.
343
-
<details>
344
-
<summary>Note</summary>
345
-
Since the only way to create multiple type clause is with extension methods, and since they force an explicit clause, this condition is currently equivalent to "`m` contains explicit term parameters".
346
-
The stricter wording was chosen to already accommodate [SIP-47 - Clause Interleaving](https://github.com/scala/improvement-proposals/pull/47).
347
-
</details>
348
-
349
-
If `m` doesn't satisfy the above condition, go to [Default](#Default), otherwise:
350
-
351
-
Assuming in all generality that `m` takes `[T_1 <: U_1 >: L_1, ..., T_n <: U_n >: L_n]` as type parameters and `(A_1, ..., A_k)` as the first clause of (explicit or implicit) term parameters, then `m` is expanded as follows:
352
-
353
-
1. Copies of `T_i`s are created, and replaced in `U_i`s, `L_i`s, `A_i`s and `R`, noted respectively `T'_i`, `U'_i`, `L'_i` and `A'_i`.
354
-
355
-
2.`m` is replaced by the following:
356
-
~~~scala
357
-
[T'_1<:U'_1>:L'_1, ... , T'_n<:U'_n>:L'_n]
358
-
=> (a_1: A'_1 ..., a_k: A'_k)
359
-
=> m[T'_1, ..., T'_n](a_1, ..., a_k)
360
-
~~~
361
-
362
-
3.`m[T'_1, ..., T'_n](a_1, ..., a_k)` is type-checked (with no expected type).
363
-
364
-
Note: Again, type checking takes care of term inference, and there is no overloading resolution necessary, as there is only one option by assumption.
365
-
366
-
#### Default
322
+
#### Non-polymorphic expected type
367
323
368
324
No polymorphic eta-expansion is performed, this corresponds to the old behaviour, written here as a reminder:
369
325
@@ -394,7 +350,7 @@ As this proposal never generates code that couldn't have been written by hand be
394
350
395
351
#### Source
396
352
397
-
This proposal conserves source compatibility when a non-polymorphic type is present, since by definition the behaviour is the same.
353
+
This proposal conserves source compatibility when a non-polymorphic expected type is present, or when there is no expected type, since by definition the behaviour is the same.
398
354
399
355
In the case the expected type is polymorphic, either the code did not compile before, or there was an implicit conversion from the inferred monomorphic function to the expected polymorphic function. In the latter case, source compatibility is broken, since polymorphic eta-expansion will apply before search for implicit conversions, for example:
400
356
@@ -410,24 +366,11 @@ val function: [T] => T => T = method
410
366
// now: method is eta-expanded to [T] => T => T (conv is not called)
411
367
```
412
368
413
-
When there is no expected type, this proposal breaks source compatibility, in this regard it is essentially a change in type inference, and therefore has all the usual repercussions of changing type inference, for example:
414
-
415
-
```scala
416
-
defmethod[T](x: T):T= x
417
-
valfunction= method // was Any => Any is now [T] => T => T
418
-
valy= function(5) // was Any is now Int
419
-
420
-
deflookFor[T](x: T)(usingu: T):T= u
421
-
lookFor(method) // was searching for Any => Any, is now searching for [T] => T => T
422
-
// This change in search can find different instances, and thus potentially wildly different behaviour !
423
-
```
424
-
425
-
While these examples might seem damming, this is no different than any other change to type inference.
426
-
427
369
### Restrictions
428
370
429
371
Not included in this proposal are:
430
372
373
+
* Applying polymorphic eta-expansion when there is no return type
431
374
* Expanding `[T] => T => T` to `[T] => T => Id[T]` to make `tuple.map(identity)` work (might work out of the box anyways, but not guaranteed)
432
375
* Expanding `x => x` to `[T] => (x: T) => x` if necessary (and generalizations)
433
376
* Expanding `_` to `[T] => (x: T) => x` if necessary (and generalizations)
@@ -447,22 +390,6 @@ If you think of anything else that is worth discussing about the proposal, this
447
390
448
391
<!-- If some design aspects are not settled yet, this section can present the open questions, with possible alternatives. By the time the proposal is accepted, all the open questions will have to be resolved. -->
449
392
450
-
#### Overloaded methods and no expected type
451
-
452
-
In the case where there is no expected type, there is nothing to guide overloading resolution, and it becomes complicated to find a good metric for the "best" variant, for example where we compare signatures in pairs:
453
-
454
-
~~~scala
455
-
(A)(B):R
456
-
(A)(usingC):R// currently more specific
457
-
458
-
(A)(B):R// currently more specific
459
-
(A)[T](T):R
460
-
461
-
(A)(B):R// currently more specific
462
-
(A)[T](usingT):R// intuitively more specific ?
463
-
~~~
464
-
465
-
As we have not yet been able to find a good universal and intuitive heuristic, we propose to let this question be settled on during the implementation phase, as the ease of implementation can help to choose between equivalently good imperfect metrics.
0 commit comments