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: text/0000-default-type-parameter-fallback-take-two.md
+14-8Lines changed: 14 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -176,7 +176,7 @@ This would currently result in inference failures when trying to do `assert_ne!(
176
176
177
177
# Guide-level explanation
178
178
179
-
When writing Rust code, you may find that you'd like to make a functionality more generic. But that does not always play well with inference, leading to an error like "type annotations needed" or "the type of this value must be known in this context". Say you have the following function that prints the path to a file, if it was provided:
179
+
When writing Rust code, you may find that you'd like to make a functionality more generic. But that does not always play well with inference, leading to an error like "type annotations needed". Say you have the following function that prints the path to a file, if it was provided:
180
180
181
181
```rust
182
182
usestd::path::Path;
@@ -229,7 +229,7 @@ Which tells inference to use `String` as backup choice if dosen't have enough in
229
229
230
230
A big use case for type parameter defaults is to help evolve a library while maintaing backwards compatibility. However there are cases where defaults may break inference.
231
231
232
-
The bad news is that adding a default to an existing type parameter or changing a default may break inference for your users because that may create conflicts among defaults. The good news is that you can add a new type parameter along with a default in the declaration of a type or trait without breaking inference, and the compiler will guide you on how to update your fns, methods and impls through lints and a simple syntax called _default elision_.
232
+
The bad news is that adding a default to an existing type parameter or changing a default may break inference for your users because that may create conflicts among defaults. The good news is that you can add a new type parameter along with a default in the declaration of a type or trait without breaking inference, and the compiler will guide you on how to update your fns, methods and impls through lints and a simple syntax called _default elision_.
233
233
234
234
For an example, let's say an UI library has the following type for text:
235
235
@@ -287,7 +287,17 @@ The behaviour of partially supplied parameter lists is as per RFC 213, omited pa
287
287
288
288
## Defaults as fallbacks for inference
289
289
290
-
A key part of this proposal is that inference is now aware of defaults. When we would otherwise error due to an uninferred type we instead try using the default. This is called inference fallback which is our final attempt at inference.
290
+
A key part of this proposal is that inference is now aware of defaults. When we would otherwise error due to an uninferred type we instead try using the default. This is called inference fallback which is our final attempt at inference. The algorithm for doing this is essentialy the one detailed in RFC 213, with a few considerations:
291
+
292
+
- The interaction with literal fallback may change, see "Unresolved Questions".
293
+
294
+
- The algorithm did not specify what happens in eager type resolution such as the `structurally_resolve_type` method, notably used to resolve method receivers. To prevent being a hazard to a future where no longer need to eagerly resolve types, we specify that eager type resolution will not do fallback.
295
+
296
+
- The algorithm ran obligation selection and fallback in a loop to allow solving edge cases where fallbacks generates new obligations and those obligations generate new fallbacks. This is complex and difficult to reason about, since none of the motivations require this behaviour we propose leaving it as future extension, eliminating the loop and running fallback only once.
297
+
298
+
### Error messages
299
+
300
+
Instead of having specific error messages detailing which defaults are in conflict as RFC 213 proposes, we will instead emit generic "type annotations needed" error messages if fallback fails. Specifying which defaults are conflicting can be complicated because the number of possible conflicts is quadratic in the number of defaults being applied and because it requires doing some sort of ad-hoc type equality which is a fishy thing to try considering that dependent defaults would require full inference to detect conflicts. Most users won't be able to act on this information anyways since conflicts are likely to come from separate crates. Thefore we detect and rollback failed fallbacks so that the error emitted is the same as if there were no fallback at all. This can be revisted later as we gain experience with the feature and learn what information would be most helpful.
291
301
292
302
### Conflicts among defaults
293
303
@@ -546,7 +556,7 @@ There are multiple alternatives of what to do about the interaction of user fall
546
556
547
557
And now a fifth option proposed by this RFC:
548
558
549
-
5. Error on conflicting numericals, whenever DWIM would prefer a user fallback we instead error.
559
+
5. Error on conflicting numericals, whenever DWIM would prefer a user fallback we instead error.
550
560
551
561
The two following examples show the consequences of each alternative, example 1:
552
562
@@ -578,10 +588,6 @@ Option 3 gives the best results, but it may change the behaviour of existing cod
578
588
579
589
Is there a better name for default elision? Default propagation? Default inheritance? Is there a better syntax than `A=_`?
580
590
581
-
### Hazard to improvements to type checking
582
-
583
-
Applying fallback seems natural when it's run at the very end of type checking, where you would get the error "type annotation needed". However type checking sometimes needs eagerly resolve a type, infamously in method calls, leading to the error "type must be known in this context". Applying fallback there maybe a hazard to a future where no longer need to eagerly resolve types.
584
-
585
591
### Interaction with specialization
586
592
587
593
Consider the example that shows the behaviour of the current implemetation:
0 commit comments