@@ -2178,12 +2178,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2178
2178
}
2179
2179
}
2180
2180
2181
+ /// This runs as the last resort of type inference.
2182
+ ///
2183
+ /// It applies user supplied defaults as fallbacks for inference variables,
2184
+ /// for example in `fn foo<T=String>()` an inference variable originated from `T`
2185
+ /// will have `String` as its default.
2186
+ ///
2187
+ /// Adding a default to a type parameter that has none should be backwards compatible.
2188
+ /// However if we get conflicting defaults we do not know how to resolve them.
2189
+ /// Therefore we must future-proof against such a conflict by not allowing
2190
+ /// type variables with defaults to unify with type variables without defaults.
2191
+ ///
2192
+ /// We may come up with rules to prioritize a type parameter over another.
2193
+ /// When unifying type variables, the highest priority parameter involved
2194
+ /// has the final say on what the default should be.
2195
+ /// Currently we prioritize defaults from impls and fns over defaults in types,
2196
+ /// this for example allows `fn foo<T=String>(x: Option<T>)` to work
2197
+ /// even though `Option<T>` has no default for `T`.
2181
2198
fn apply_user_type_parameter_fallback ( & self ) {
2182
2199
use self :: TypeVariableOrigin :: TypeParameterDefinition ;
2183
2200
use ty:: OriginOfTyParam ;
2184
-
2185
2201
// Collect variables that are unsolved and support fallback,
2186
- // grouped by subtyping equivalence.
2202
+ // grouped in bags by subtyping equivalence.
2187
2203
let mut bags = FxHashMap ( ) ;
2188
2204
for vid in self . fulfillment_cx . borrow ( ) . vars_in_unsolved_obligations ( ) {
2189
2205
let mut type_variables = self . infcx . type_variables . borrow_mut ( ) ;
@@ -2199,9 +2215,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2199
2215
bags. entry ( root) . or_insert ( Vec :: new ( ) ) . push ( vid) ;
2200
2216
}
2201
2217
}
2202
-
2218
+ // A bag will successfuly fallback to a default if all of it's variables
2219
+ // have a default, and that default is the same.
2220
+ // Low priority variables will be ignored in the presence of higher priority variables.
2203
2221
' bags: for ( _, mut bag) in bags. into_iter ( ) {
2204
- // Partition the bag by the origin of the default .
2222
+ // Partition the bag by the origin of the type param .
2205
2223
let ( fn_or_impl, ty_def) = bag. into_iter ( ) . partition ( |& v| {
2206
2224
match self . infcx . type_variables . borrow ( ) . var_origin ( v) {
2207
2225
TypeParameterDefinition ( _, _, OriginOfTyParam :: Fn ) |
@@ -2212,7 +2230,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2212
2230
} ) ;
2213
2231
// Params from fns or impls take priority, if they exist ignore the rest of the bag.
2214
2232
bag = fn_or_impl;
2215
- if bag. is_empty ( ) {
2233
+ if bag. is_empty ( ) {
2216
2234
bag = ty_def;
2217
2235
}
2218
2236
// For future-proofing against conflicting defaults,
@@ -2233,7 +2251,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2233
2251
let normalized_default = self . normalize_associated_types_in (
2234
2252
user_default. origin_span ,
2235
2253
& user_default. ty ) ;
2236
- // QUESTION(leodasvacas):
2254
+ // QUESTION(leodasvacas):
2237
2255
// This will emit "expected type mismatch" on conflicting defaults, which is bad.
2238
2256
// I'd be happy to somehow detect or rollback this demand on conflict defaults
2239
2257
// so we would emit "type annotations needed" instead.
0 commit comments