@@ -113,6 +113,7 @@ use std::rc::Rc;
113
113
use std:: collections:: hash_map:: Entry ;
114
114
use std:: cmp;
115
115
use std:: fmt:: Display ;
116
+ use std:: iter:: FromIterator ;
116
117
use std:: mem:: replace;
117
118
use std:: ops:: { self , Deref } ;
118
119
use syntax:: abi:: Abi ;
@@ -2001,6 +2002,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2001
2002
value)
2002
2003
}
2003
2004
2005
+ fn eager_normalize_in < T > ( & self , span : Span , value : & T ) -> Option < T >
2006
+ where T : TypeFoldable < ' tcx >
2007
+ {
2008
+ let infer_ok = self . inh . partially_normalize_associated_types_in ( span,
2009
+ self . body_id ,
2010
+ self . param_env ,
2011
+ value) ;
2012
+ if infer_ok. obligations . is_empty ( ) {
2013
+ Some ( infer_ok. value )
2014
+ } else {
2015
+ self . inh . register_predicates ( infer_ok. obligations ) ;
2016
+ self . select_obligations_where_possible ( ) ;
2017
+ let resolved = self . resolve_type_vars_if_possible ( & infer_ok. value ) ;
2018
+ if !resolved. needs_infer ( ) {
2019
+ Some ( resolved)
2020
+ } else {
2021
+ None
2022
+ }
2023
+ }
2024
+ }
2025
+
2004
2026
pub fn require_type_meets ( & self ,
2005
2027
ty : Ty < ' tcx > ,
2006
2028
span : Span ,
@@ -2210,67 +2232,76 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2210
2232
bags. entry ( root) . or_insert ( Vec :: new ( ) ) . push ( vid) ;
2211
2233
}
2212
2234
}
2213
-
2235
+ // Discard key, bags is a sequence of pairs (bag, done).
2236
+ let mut bags = Vec :: from_iter ( bags. into_iter ( ) . map ( |b| b. 1 ) . map ( |b| ( b, false ) ) ) ;
2214
2237
// Attempt to find a fallback for each bag.
2215
- for ( _, bag) in bags {
2216
- // Partition the bag by the origin of the type param.
2217
- let ( fn_or_impl, ty_def) = bag. into_iter ( ) . partition ( |& v| {
2218
- match self . infcx . type_variables . borrow ( ) . var_origin ( v) {
2219
- TypeParameterDefinition ( _, _, OriginOfTyParam :: Fn ) |
2220
- TypeParameterDefinition ( _, _, OriginOfTyParam :: Impl ) => true ,
2221
- TypeParameterDefinition ( _, _, OriginOfTyParam :: TyDef ) => false ,
2222
- _ => bug ! ( "type var does not support fallback" )
2223
- }
2224
- } ) ;
2225
- // Params from fns or impls have higher priority than those from type definitions.
2226
- // We consider the priority levels in order and stop at the first success or failure:
2227
- // We succeed if all defaults exist and agree.
2228
- // We fail if existing defaults agree but there are missing defaults.
2229
- // We continue if the priority level is empty or if there are any disagreements.
2230
- let priority_levels: Vec < Vec < ty:: TyVid > > = vec ! [ fn_or_impl, ty_def] ;
2231
- ' priority_levels: for priority_level in priority_levels {
2232
- if priority_level. is_empty ( ) {
2233
- continue ;
2234
- }
2235
- let normalized_default = |& vid| {
2236
- let default = self . infcx . type_variables . borrow ( ) . default ( vid) . get_user ( ) ;
2237
- default. map ( |d| self . normalize_associated_types_in ( d. origin_span , & d. ty ) )
2238
- } ;
2239
- let mut existing_defaults = priority_level. iter ( ) . filter_map ( & normalized_default) ;
2240
- let equivalent_default = match existing_defaults. next ( ) {
2241
- Some ( default) => default,
2242
- None => break , // Failed, no params have defaults at this level.
2243
- } ;
2244
-
2245
- // If there are conflicting defaults, skip this level.
2246
- // FIXME(leodasvacas): In a case like `impl<X: Default=u32, Y = <X as Id>::This>`,
2247
- // as found in the test "dependent_associated_type.rs",
2248
- // if `Y` is normalized before the default of `X` is applied,
2249
- // then it's normalized to `TyInfer`, so we use a fragile workaround here.
2250
- // If it is `Y = Vec<<X as Id>::This>` we are in trouble again.
2251
- // Type equality that considers all inference variables equal is a correct fix.
2252
- if existing_defaults. any ( |default| match ( & default. sty , & equivalent_default. sty ) {
2253
- ( & ty:: TyInfer ( _) , & ty:: TyInfer ( _) ) => false ,
2254
- ( ref a, ref b) => * * a != * * b
2255
- } )
2256
- {
2257
- debug ! ( "apply_user_type_parameter_fallback: skipping priority level" ) ;
2258
- continue ;
2259
- }
2260
- // All existing defaults agree, but for future-proofing
2261
- // we must fail if there is a param with no default.
2262
- if priority_level. iter ( ) . any ( |vid| normalized_default ( vid) == None ) {
2263
- break ;
2264
- }
2265
- // All defaults exist and agree, apply the default and succeed.
2266
- for & vid in & priority_level {
2267
- let ty = self . tcx . mk_var ( vid) ;
2268
- debug ! ( "apply_user_type_parameter_fallback: applying fallback to var: {:?} \
2269
- with ty: {:?} with default: {:?}", vid, ty, equivalent_default) ;
2270
- self . demand_eqtype ( syntax_pos:: DUMMY_SP , & ty, equivalent_default) ;
2271
- break ' priority_levels;
2238
+ loop {
2239
+ // For dependent defaults, solving a bag
2240
+ // might allow us to normalize an associated type in another bag.
2241
+ // For example in `impl<X = u32, Y = <X as Trait>::Type>`.
2242
+ // Therefore we loop over the bags until we are at a fixed point.
2243
+ let mut fixed_point = true ;
2244
+ // Loop over bags that are not done.
2245
+ ' bags: for & mut ( ref bag, ref mut done) in bags. iter_mut ( ) . filter ( |bag| !bag. 1 ) {
2246
+ // Partition the bag by the origin of the type param.
2247
+ let ( fn_or_impl, ty_def) = bag. iter ( ) . partition ( |& & v| {
2248
+ match self . infcx . type_variables . borrow ( ) . var_origin ( v) {
2249
+ TypeParameterDefinition ( _, _, OriginOfTyParam :: Fn ) |
2250
+ TypeParameterDefinition ( _, _, OriginOfTyParam :: Impl ) => true ,
2251
+ TypeParameterDefinition ( _, _, OriginOfTyParam :: TyDef ) => false ,
2252
+ _ => bug ! ( "type var does not support fallback" )
2253
+ }
2254
+ } ) ;
2255
+ // Params from fns or impls have higher priority than those from type definitions.
2256
+ // Consider the priority levels in order:
2257
+ // Try again later if a default can't be normalized.
2258
+ // Succeed if all defaults exist and agree.
2259
+ // Fail if existing defaults agree but there are missing defaults.
2260
+ // Skip the priority level if it's empty or there are disagreements.
2261
+ let priority_levels: Vec < Vec < ty:: TyVid > > = vec ! [ fn_or_impl, ty_def] ;
2262
+ ' priority_levels: for priority_level in priority_levels {
2263
+ if priority_level. is_empty ( ) {
2264
+ continue ;
2265
+ }
2266
+ let get_default = |& v| self . infcx . type_variables . borrow ( ) . default ( v) . as_user ( ) ;
2267
+ let mut existing_defaults = Vec :: new ( ) ;
2268
+ for default in priority_level. iter ( ) . filter_map ( & get_default) {
2269
+ match self . eager_normalize_in ( default. origin_span , & default. ty ) {
2270
+ Some ( def) => existing_defaults. push ( def) ,
2271
+ None => continue ' bags, // Try again later.
2272
+ }
2273
+ }
2274
+ let mut existing_defaults = existing_defaults. iter ( ) ;
2275
+ let equivalent_default = match existing_defaults. next ( ) {
2276
+ Some ( default) => default,
2277
+ None => break , // Failed, no params have defaults at this level.
2278
+ } ;
2279
+ // On conflicting defaults, skip this level.
2280
+ if existing_defaults. any ( |& default| default. sty != equivalent_default. sty ) {
2281
+ debug ! ( "apply_user_type_parameter_fallback: skipping priority level" ) ;
2282
+ continue ;
2283
+ }
2284
+ // All existing defaults agree, but for future-proofing
2285
+ // we must fail if there is a param with no default.
2286
+ if priority_level. iter ( ) . any ( |vid| get_default ( vid) == None ) {
2287
+ break ;
2288
+ }
2289
+ // All defaults exist and agree, apply the default and succeed.
2290
+ for & vid in & priority_level {
2291
+ let ty = self . tcx . mk_var ( vid) ;
2292
+ self . demand_eqtype ( syntax_pos:: DUMMY_SP , & ty, equivalent_default) ;
2293
+ debug ! ( "apply_user_type_parameter_fallback: applied fallback to var: {:?} \
2294
+ with ty: {:?} with default: {:?}", vid, ty, equivalent_default) ;
2295
+ // Progress was made.
2296
+ fixed_point = false ;
2297
+ * done = true ;
2298
+ break ' priority_levels;
2299
+ }
2272
2300
}
2273
2301
}
2302
+ if fixed_point {
2303
+ break ;
2304
+ }
2274
2305
}
2275
2306
}
2276
2307
0 commit comments