@@ -243,7 +243,7 @@ where
243
243
let goal = gb. forall (
244
244
& impl_fields,
245
245
& impl_datum. associated_ty_value_ids ,
246
- |gb, _ , ( trait_ref, where_clauses) , associated_ty_value_ids| {
246
+ |gb, impl_substitution , ( trait_ref, where_clauses) , associated_ty_value_ids| {
247
247
let interner = gb. interner ( ) ;
248
248
249
249
// if (WC) { ... }
@@ -275,9 +275,10 @@ where
275
275
|gb| {
276
276
let db = gb. db ( ) ;
277
277
278
- let assoc_ty_goals = associated_ty_value_ids
279
- . iter ( )
280
- . filter_map ( |& id| Self :: compute_assoc_ty_goal ( db, id) ) ;
278
+ let assoc_ty_goals =
279
+ associated_ty_value_ids. iter ( ) . filter_map ( |& id| {
280
+ Self :: compute_assoc_ty_goal ( db, & impl_substitution, id)
281
+ } ) ;
281
282
282
283
// We retrieve all the input types of the where clauses appearing on the trait impl,
283
284
// e.g. in:
@@ -355,110 +356,90 @@ where
355
356
/// ```
356
357
fn compute_assoc_ty_goal (
357
358
db : & dyn RustIrDatabase < I > ,
359
+ impl_substitution : & Substitution < I > ,
358
360
assoc_ty_id : AssociatedTyValueId < I > ,
359
361
) -> Option < Goal < I > > {
360
- let interner = db . interner ( ) ;
362
+ let mut gb = GoalBuilder :: new ( db ) ;
361
363
let assoc_ty = & db. associated_ty_value ( assoc_ty_id) ;
362
364
363
- // Split the binders on the assoc. ty value into those
364
- // from the *impl* (in our example, `T`) and those from
365
- // the associated type (in our example, `'a`).
366
- let ( impl_binders, value_binders) =
367
- db. split_associated_ty_value_parameters ( & assoc_ty. value . binders , assoc_ty) ;
368
-
369
- // In our final goal, the binders from the impl will be
370
- // something like `^1.N` -- i.e., a debruijn index of 1 --
371
- // and the binders from the associted type value will be `^0.N`.
372
- let all_parameters: Vec < _ > = {
373
- let value_parameters = value_binders
374
- . iter ( )
375
- . zip ( 0 ..)
376
- . map ( |p| p. to_parameter ( interner) ) ;
377
- let impl_debruin = DebruijnIndex :: INNERMOST . shifted_in ( ) ;
378
- let impl_parameters = impl_binders
379
- . iter ( )
380
- . zip ( 0 ..)
381
- . map ( |p| p. to_parameter_at_depth ( interner, impl_debruin) ) ;
382
- value_parameters. chain ( impl_parameters) . collect ( )
383
- } ;
384
-
385
- // Get the projection for this associated type:
386
- //
387
- // * `projection`: `<Box<!T> as Foo>::Item<'!a>`
388
- let ( _, projection) =
389
- db. impl_parameters_and_projection_from_associated_ty_value ( & all_parameters, assoc_ty) ;
390
-
391
- // Get the ty that the impl is using -- `Box<&'!a !T>`, in our example
392
- let AssociatedTyValueBound { ty : value_ty } =
393
- assoc_ty. value . substitute ( interner, & all_parameters) ;
394
-
395
- let mut input_types = Vec :: new ( ) ;
396
- value_ty. fold ( interner, & mut input_types) ;
397
-
398
- // We require that `WellFormed(T)` for each type that appears in the value
399
- let wf_goals = input_types
400
- . into_iter ( )
401
- . map ( |ty| DomainGoal :: WellFormed ( WellFormed :: Ty ( ty) ) )
402
- . casted ( interner) ;
403
-
404
- // Get the bounds and where clauses from the trait
405
- // declaration, substituted appropriately.
406
- //
407
- // From our example:
408
- //
409
- // * bounds
410
- // * original in trait, `Clone`
411
- // * after substituting impl parameters, `Clone`
412
- // * note that the self-type is not yet supplied for bounds,
413
- // we will do that later
414
- // * where clauses
415
- // * original in trait, `Self: 'a`
416
- // * after substituting impl parameters, `Box<!T>: '!a`
417
- let assoc_ty_datum = db. associated_ty_data ( projection. associated_ty_id ) ;
418
- let AssociatedTyDatumBound {
419
- bounds : defn_bounds,
420
- where_clauses : defn_where_clauses,
421
- } = assoc_ty_datum
422
- . binders
423
- . substitute ( interner, & projection. substitution ) ;
424
-
425
- // Check that the `value_ty` meets the bounds from the trait.
426
- // Here we take the substituted bounds (`defn_bounds`) and we
427
- // supply the self-type `value_ty` to yield the final result.
428
- //
429
- // In our example, the bound was `Clone`, so the combined
430
- // result is `Box<!T>: Clone`. This is then converted to a
431
- // well-formed goal like `WellFormed(Box<!T>: Clone)`.
432
- let bound_goals = defn_bounds
433
- . iter ( )
434
- . cloned ( )
435
- . flat_map ( |qb| qb. into_where_clauses ( interner, value_ty. clone ( ) ) )
436
- . map ( |qwc| qwc. into_well_formed_goal ( interner) )
437
- . casted ( interner) ;
438
-
439
- // Concatenate the WF goals of inner types + the requirements from trait
440
- let goals = wf_goals. chain ( bound_goals) ;
441
- let goal = Goal :: all ( interner, goals) ;
442
- if goal. is_trivially_true ( interner) {
443
- return None ;
444
- }
445
-
446
- // Add where clauses from the associated ty definition. We must
447
- // substitute parameters here, like we did with the bounds above.
448
- let hypotheses = defn_where_clauses
449
- . iter ( )
450
- . cloned ( )
451
- . map ( |qwc| qwc. into_from_env_goal ( interner) )
452
- . casted ( interner)
453
- . collect ( ) ;
454
-
455
- let goal = GoalData :: Implies ( hypotheses, goal) . intern ( interner) ;
365
+ // Create `forall<'a> { .. }`
366
+ Some ( gb. partially_forall (
367
+ & assoc_ty. value . map_ref ( |v| & v. ty ) ,
368
+ impl_substitution,
369
+ assoc_ty_id,
370
+ |gb, assoc_ty_substitution, value_ty, assoc_ty_id| {
371
+ let interner = gb. interner ( ) ;
372
+ let db = gb. db ( ) ;
373
+
374
+ // Hmm, because `Arc<AssociatedTyValue>` does not implement `Fold`, we can't pass this value through,
375
+ // just the id, so we have to fetch `assoc_ty` from the database again.
376
+ // Implementing `Fold` for `AssociatedTyValue` doesn't *quite* seem right though, as that
377
+ // would result in a deep clone, and the value is inert. We could do some more refatoring
378
+ // (move the `Arc` behind a newtype, for example) to fix this, but for now doesn't
379
+ // seem worth it.
380
+ let assoc_ty = & db. associated_ty_value ( assoc_ty_id) ;
381
+
382
+ let ( _, projection) = db. impl_parameters_and_projection_from_associated_ty_value (
383
+ & assoc_ty_substitution. parameters ( interner) ,
384
+ assoc_ty,
385
+ ) ;
386
+
387
+ // Get the bounds and where clauses from the trait
388
+ // declaration, substituted appropriately.
389
+ //
390
+ // From our example:
391
+ //
392
+ // * bounds
393
+ // * original in trait, `Clone`
394
+ // * after substituting impl parameters, `Clone`
395
+ // * note that the self-type is not yet supplied for bounds,
396
+ // we will do that later
397
+ // * where clauses
398
+ // * original in trait, `Self: 'a`
399
+ // * after substituting impl parameters, `Box<!T>: '!a`
400
+ let assoc_ty_datum = db. associated_ty_data ( projection. associated_ty_id ) ;
401
+ let AssociatedTyDatumBound {
402
+ bounds : defn_bounds,
403
+ where_clauses : defn_where_clauses,
404
+ } = assoc_ty_datum
405
+ . binders
406
+ . substitute ( interner, & projection. substitution ) ;
407
+
408
+ // Create `if (/* where clauses on associated type value */) { .. }`
409
+ gb. implies (
410
+ defn_where_clauses
411
+ . iter ( )
412
+ . cloned ( )
413
+ . map ( |qwc| qwc. into_from_env_goal ( interner) ) ,
414
+ |gb| {
415
+ let mut input_types = Vec :: new ( ) ;
416
+ value_ty. fold ( interner, & mut input_types) ;
456
417
457
- debug ! ( "compute_assoc_ty_goal: goal={:?}" , goal) ;
418
+ // We require that `WellFormed(T)` for each type that appears in the value
419
+ let wf_goals = input_types
420
+ . into_iter ( )
421
+ . map ( |ty| DomainGoal :: WellFormed ( WellFormed :: Ty ( ty) ) )
422
+ . casted ( interner) ;
458
423
459
- // Create a composed goal that is universally quantified over
460
- // the parameters from the associated type value (e.g.,
461
- // `forall<'a> { .. }` in our example).
462
- Some ( goal. quantify ( interner, QuantifierKind :: ForAll , value_binders. to_vec ( ) ) )
424
+ // Check that the `value_ty` meets the bounds from the trait.
425
+ // Here we take the substituted bounds (`defn_bounds`) and we
426
+ // supply the self-type `value_ty` to yield the final result.
427
+ //
428
+ // In our example, the bound was `Clone`, so the combined
429
+ // result is `Box<!T>: Clone`. This is then converted to a
430
+ // well-formed goal like `WellFormed(Box<!T>: Clone)`.
431
+ let bound_goals = defn_bounds
432
+ . iter ( )
433
+ . cloned ( )
434
+ . flat_map ( |qb| qb. into_where_clauses ( interner, value_ty. clone ( ) ) )
435
+ . map ( |qwc| qwc. into_well_formed_goal ( interner) )
436
+ . casted ( interner) ;
437
+
438
+ // Concatenate the WF goals of inner types + the requirements from trait
439
+ gb. all :: < _ , Goal < I > > ( wf_goals. chain ( bound_goals) )
440
+ } ,
441
+ )
442
+ } ,
443
+ ) )
463
444
}
464
445
}
0 commit comments