@@ -243,7 +243,7 @@ where
243243 let goal = gb. forall (
244244 & impl_fields,
245245 & 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| {
247247 let interner = gb. interner ( ) ;
248248
249249 // if (WC) { ... }
@@ -275,9 +275,10 @@ where
275275 |gb| {
276276 let db = gb. db ( ) ;
277277
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+ } ) ;
281282
282283 // We retrieve all the input types of the where clauses appearing on the trait impl,
283284 // e.g. in:
@@ -355,110 +356,90 @@ where
355356 /// ```
356357 fn compute_assoc_ty_goal (
357358 db : & dyn RustIrDatabase < I > ,
359+ impl_substitution : & Substitution < I > ,
358360 assoc_ty_id : AssociatedTyValueId < I > ,
359361 ) -> Option < Goal < I > > {
360- let interner = db . interner ( ) ;
362+ let mut gb = GoalBuilder :: new ( db ) ;
361363 let assoc_ty = & db. associated_ty_value ( assoc_ty_id) ;
362364
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) ;
456417
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) ;
458423
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+ ) )
463444 }
464445}
0 commit comments