@@ -230,62 +230,22 @@ where
230
230
let interner = self . db . interner ( ) ;
231
231
let impl_datum = self . db . impl_datum ( impl_id) ;
232
232
233
- if !impl_datum. is_positive ( ) {
234
- return Ok ( ( ) ) ;
235
- }
236
-
237
- let impl_fields = impl_datum
238
- . binders
239
- . map_ref ( |v| ( & v. trait_ref , & v. where_clauses ) ) ;
240
-
241
- let mut gb = GoalBuilder :: new ( self . db ) ;
242
- // forall<P0...Pn> {...}
243
- let goal = gb. forall (
244
- & impl_fields,
245
- & impl_datum. associated_ty_value_ids ,
246
- |gb, impl_substitution, ( trait_ref, where_clauses) , associated_ty_value_ids| {
247
- let interner = gb. interner ( ) ;
248
-
249
- // if (WC && input types are well formed) { ... }
250
- let impl_wf = Self :: impl_wf_environment ( interner, & where_clauses, & trait_ref) ;
251
- gb. implies ( impl_wf, |gb| {
252
- let db = gb. db ( ) ;
253
-
254
- let assoc_ty_goals = associated_ty_value_ids
255
- . iter ( )
256
- . filter_map ( |& id| Self :: compute_assoc_ty_goal ( db, & impl_substitution, id) ) ;
257
-
258
- // We retrieve all the input types of the where clauses appearing on the trait impl,
259
- // e.g. in:
260
- // ```
261
- // impl<T, K> Foo for (T, K) where T: Iterator<Item = (HashSet<K>, Vec<Box<T>>)> { ... }
262
- // ```
263
- // we would retrieve `HashSet<K>`, `Box<T>`, `Vec<Box<T>>`, `(HashSet<K>, Vec<Box<T>>)`.
264
- // We will have to prove that these types are well-formed (e.g. an additional `K: Hash`
265
- // bound would be needed here).
266
- let mut input_types = Vec :: new ( ) ;
267
- where_clauses. fold ( interner, & mut input_types) ;
268
-
269
- // Things to prove well-formed: input types of the where-clauses, projection types
270
- // appearing in the header, associated type values, and of course the trait ref.
271
- debug ! ( "verify_trait_impl: input_types={:?}" , input_types) ;
272
- let goals = input_types
273
- . into_iter ( )
274
- . map ( |ty| ty. well_formed ( ) . cast ( interner) )
275
- . chain ( assoc_ty_goals)
276
- . chain ( Some ( trait_ref. clone ( ) . well_formed ( ) . cast ( interner) ) ) ;
277
-
278
- gb. all ( goals)
279
- } )
280
- } ,
233
+ let impl_goal = Goal :: all (
234
+ interner,
235
+ impl_header_wf_goal ( self . db , impl_id) . into_iter ( ) . chain (
236
+ impl_datum
237
+ . associated_ty_value_ids
238
+ . iter ( )
239
+ . filter_map ( |& id| compute_assoc_ty_goal ( self . db , id) ) ,
240
+ ) ,
281
241
) ;
282
242
283
- debug ! ( "WF trait goal: {:?}" , goal ) ;
243
+ debug ! ( "WF trait goal: {:?}" , impl_goal ) ;
284
244
285
245
let is_legal = match self
286
246
. solver_choice
287
247
. into_solver ( )
288
- . solve ( self . db , & goal . into_closed_goal ( interner) )
248
+ . solve ( self . db , & impl_goal . into_closed_goal ( interner) )
289
249
{
290
250
Some ( sol) => sol. is_unique ( ) ,
291
251
None => false ,
@@ -298,99 +258,157 @@ where
298
258
Err ( WfError :: IllFormedTraitImpl ( trait_ref. trait_id ) )
299
259
}
300
260
}
261
+ }
301
262
302
- /// Creates the conditions that an impl (and its contents of an impl)
303
- /// can assume to be true when proving that it is well-formed.
304
- fn impl_wf_environment < ' i > (
305
- interner : & ' i I ,
306
- where_clauses : & ' i [ QuantifiedWhereClause < I > ] ,
307
- trait_ref : & ' i TraitRef < I > ,
308
- ) -> impl Iterator < Item = ProgramClause < I > > + ' i {
309
- // if (WC) { ... }
310
- let wc = where_clauses
311
- . iter ( )
312
- . cloned ( )
313
- . map ( move |qwc| qwc. into_from_env_goal ( interner) . cast ( interner) ) ;
314
-
315
- // We retrieve all the input types of the type on which we implement the trait: we will
316
- // *assume* that these types are well-formed, e.g. we will be able to derive that
317
- // `K: Hash` holds without writing any where clause.
318
- //
319
- // Example:
320
- // ```
321
- // struct HashSet<K> where K: Hash { ... }
322
- //
323
- // impl<K> Foo for HashSet<K> {
324
- // // Inside here, we can rely on the fact that `K: Hash` holds
325
- // }
326
- // ```
327
- let mut header_input_types = Vec :: new ( ) ;
328
- trait_ref. fold ( interner, & mut header_input_types) ;
329
-
330
- let types_wf = header_input_types
331
- . into_iter ( )
332
- . map ( move |ty| ty. into_from_env_goal ( interner) . cast ( interner) ) ;
263
+ fn impl_header_wf_goal < I : Interner > (
264
+ db : & dyn RustIrDatabase < I > ,
265
+ impl_id : ImplId < I > ,
266
+ ) -> Option < Goal < I > > {
267
+ let impl_datum = db. impl_datum ( impl_id) ;
333
268
334
- wc. chain ( types_wf)
269
+ if !impl_datum. is_positive ( ) {
270
+ return None ;
335
271
}
336
272
337
- /// Associated type values are special because they can be parametric (independently of
338
- /// the impl), so we issue a special goal which is quantified using the binders of the
339
- /// associated type value, for example in:
340
- ///
341
- /// ```ignore
342
- /// trait Foo {
343
- /// type Item<'a>: Clone where Self: 'a
344
- /// }
345
- ///
346
- /// impl<T> Foo for Box<T> {
347
- /// type Item<'a> = Box<&'a T>;
348
- /// }
349
- /// ```
350
- ///
351
- /// we would issue the following subgoal: `forall<'a> { WellFormed(Box<&'a T>) }`.
352
- ///
353
- /// Note that there is no binder for `T` in the above: the goal we
354
- /// generate is expected to be exected in the context of the
355
- /// larger WF goal for the impl, which already has such a
356
- /// binder. So the entire goal for the impl might be:
357
- ///
358
- /// ```ignore
359
- /// forall<T> {
360
- /// WellFormed(Box<T>) /* this comes from the impl, not this routine */,
361
- /// forall<'a> { WellFormed(Box<&'a T>) },
362
- /// }
363
- /// ```
364
- fn compute_assoc_ty_goal (
365
- db : & dyn RustIrDatabase < I > ,
366
- impl_substitution : & Substitution < I > ,
367
- assoc_ty_id : AssociatedTyValueId < I > ,
368
- ) -> Option < Goal < I > > {
369
- let mut gb = GoalBuilder :: new ( db) ;
370
- let assoc_ty = & db. associated_ty_value ( assoc_ty_id) ;
371
-
372
- // Create `forall<'a> { .. }`
373
- Some ( gb. partially_forall (
374
- & assoc_ty. value . map_ref ( |v| & v. ty ) ,
375
- impl_substitution,
376
- assoc_ty_id,
377
- |gb, assoc_ty_substitution, value_ty, assoc_ty_id| {
378
- let interner = gb. interner ( ) ;
379
- let db = gb. db ( ) ;
380
-
381
- // Hmm, because `Arc<AssociatedTyValue>` does not implement `Fold`, we can't pass this value through,
382
- // just the id, so we have to fetch `assoc_ty` from the database again.
383
- // Implementing `Fold` for `AssociatedTyValue` doesn't *quite* seem right though, as that
384
- // would result in a deep clone, and the value is inert. We could do some more refatoring
385
- // (move the `Arc` behind a newtype, for example) to fix this, but for now doesn't
386
- // seem worth it.
387
- let assoc_ty = & db. associated_ty_value ( assoc_ty_id) ;
388
-
389
- let ( _, projection) = db. impl_parameters_and_projection_from_associated_ty_value (
273
+ let impl_fields = impl_datum
274
+ . binders
275
+ . map_ref ( |v| ( & v. trait_ref , & v. where_clauses ) ) ;
276
+
277
+ let mut gb = GoalBuilder :: new ( db) ;
278
+ // forall<P0...Pn> {...}
279
+ Some (
280
+ gb. forall ( & impl_fields, ( ) , |gb, _, ( trait_ref, where_clauses) , ( ) | {
281
+ let interner = gb. interner ( ) ;
282
+
283
+ // if (WC && input types are well formed) { ... }
284
+ let impl_wf = impl_wf_environment ( interner, & where_clauses, & trait_ref) ;
285
+ gb. implies ( impl_wf, |gb| {
286
+ // We retrieve all the input types of the where clauses appearing on the trait impl,
287
+ // e.g. in:
288
+ // ```
289
+ // impl<T, K> Foo for (T, K) where T: Iterator<Item = (HashSet<K>, Vec<Box<T>>)> { ... }
290
+ // ```
291
+ // we would retrieve `HashSet<K>`, `Box<T>`, `Vec<Box<T>>`, `(HashSet<K>, Vec<Box<T>>)`.
292
+ // We will have to prove that these types are well-formed (e.g. an additional `K: Hash`
293
+ // bound would be needed here).
294
+ let mut input_types = Vec :: new ( ) ;
295
+ where_clauses. fold ( interner, & mut input_types) ;
296
+
297
+ // Things to prove well-formed: input types of the where-clauses, projection types
298
+ // appearing in the header, associated type values, and of course the trait ref.
299
+ debug ! ( "verify_trait_impl: input_types={:?}" , input_types) ;
300
+ let goals = input_types
301
+ . into_iter ( )
302
+ . map ( |ty| ty. well_formed ( ) . cast ( interner) )
303
+ . chain ( Some ( trait_ref. clone ( ) . well_formed ( ) . cast ( interner) ) ) ;
304
+
305
+ gb. all :: < _ , Goal < I > > ( goals)
306
+ } )
307
+ } ) ,
308
+ )
309
+ }
310
+
311
+ /// Creates the conditions that an impl (and its contents of an impl)
312
+ /// can assume to be true when proving that it is well-formed.
313
+ fn impl_wf_environment < ' i , I : Interner > (
314
+ interner : & ' i I ,
315
+ where_clauses : & ' i [ QuantifiedWhereClause < I > ] ,
316
+ trait_ref : & ' i TraitRef < I > ,
317
+ ) -> impl Iterator < Item = ProgramClause < I > > + ' i {
318
+ // if (WC) { ... }
319
+ let wc = where_clauses
320
+ . iter ( )
321
+ . cloned ( )
322
+ . map ( move |qwc| qwc. into_from_env_goal ( interner) . cast ( interner) ) ;
323
+
324
+ // We retrieve all the input types of the type on which we implement the trait: we will
325
+ // *assume* that these types are well-formed, e.g. we will be able to derive that
326
+ // `K: Hash` holds without writing any where clause.
327
+ //
328
+ // Example:
329
+ // ```
330
+ // struct HashSet<K> where K: Hash { ... }
331
+ //
332
+ // impl<K> Foo for HashSet<K> {
333
+ // // Inside here, we can rely on the fact that `K: Hash` holds
334
+ // }
335
+ // ```
336
+ let mut header_input_types = Vec :: new ( ) ;
337
+ trait_ref. fold ( interner, & mut header_input_types) ;
338
+
339
+ let types_wf = header_input_types
340
+ . into_iter ( )
341
+ . map ( move |ty| ty. into_from_env_goal ( interner) . cast ( interner) ) ;
342
+
343
+ wc. chain ( types_wf)
344
+ }
345
+
346
+ /// Associated type values are special because they can be parametric (independently of
347
+ /// the impl), so we issue a special goal which is quantified using the binders of the
348
+ /// associated type value, for example in:
349
+ ///
350
+ /// ```ignore
351
+ /// trait Foo {
352
+ /// type Item<'a>: Clone where Self: 'a
353
+ /// }
354
+ ///
355
+ /// impl<T> Foo for Box<T> {
356
+ /// type Item<'a> = Box<&'a T>;
357
+ /// }
358
+ /// ```
359
+ ///
360
+ /// we would issue the following subgoal: `forall<'a> { WellFormed(Box<&'a T>) }`.
361
+ ///
362
+ /// Note that there is no binder for `T` in the above: the goal we
363
+ /// generate is expected to be exected in the context of the
364
+ /// larger WF goal for the impl, which already has such a
365
+ /// binder. So the entire goal for the impl might be:
366
+ ///
367
+ /// ```ignore
368
+ /// forall<T> {
369
+ /// WellFormed(Box<T>) /* this comes from the impl, not this routine */,
370
+ /// forall<'a> { WellFormed(Box<&'a T>) },
371
+ /// }
372
+ /// ```
373
+ fn compute_assoc_ty_goal < I : Interner > (
374
+ db : & dyn RustIrDatabase < I > ,
375
+ assoc_ty_id : AssociatedTyValueId < I > ,
376
+ ) -> Option < Goal < I > > {
377
+ let mut gb = GoalBuilder :: new ( db) ;
378
+ let assoc_ty = & db. associated_ty_value ( assoc_ty_id) ;
379
+
380
+ // Create `forall<T, 'a> { .. }`
381
+ Some ( gb. forall (
382
+ & assoc_ty. value . map_ref ( |v| & v. ty ) ,
383
+ assoc_ty_id,
384
+ |gb, assoc_ty_substitution, value_ty, assoc_ty_id| {
385
+ let interner = gb. interner ( ) ;
386
+ let db = gb. db ( ) ;
387
+
388
+ // Hmm, because `Arc<AssociatedTyValue>` does not implement `Fold`, we can't pass this value through,
389
+ // just the id, so we have to fetch `assoc_ty` from the database again.
390
+ // Implementing `Fold` for `AssociatedTyValue` doesn't *quite* seem right though, as that
391
+ // would result in a deep clone, and the value is inert. We could do some more refatoring
392
+ // (move the `Arc` behind a newtype, for example) to fix this, but for now doesn't
393
+ // seem worth it.
394
+ let assoc_ty = & db. associated_ty_value ( assoc_ty_id) ;
395
+
396
+ let ( impl_parameters, projection) = db
397
+ . impl_parameters_and_projection_from_associated_ty_value (
390
398
& assoc_ty_substitution. parameters ( interner) ,
391
399
assoc_ty,
392
400
) ;
393
401
402
+ // If (/* impl WF environment */) { ... }
403
+ let impl_id = assoc_ty. impl_id ;
404
+ let impl_datum = & db. impl_datum ( impl_id) ;
405
+ let ImplDatumBound {
406
+ trait_ref : impl_trait_ref,
407
+ where_clauses : impl_where_clauses,
408
+ } = impl_datum. binders . substitute ( interner, impl_parameters) ;
409
+ let impl_wf_clauses =
410
+ impl_wf_environment ( interner, & impl_where_clauses, & impl_trait_ref) ;
411
+ gb. implies ( impl_wf_clauses, |gb| {
394
412
// Get the bounds and where clauses from the trait
395
413
// declaration, substituted appropriately.
396
414
//
@@ -446,7 +464,7 @@ where
446
464
gb. all :: < _ , Goal < I > > ( wf_goals. chain ( bound_goals) )
447
465
} ,
448
466
)
449
- } ,
450
- ) )
451
- }
467
+ } )
468
+ } ,
469
+ ) )
452
470
}
0 commit comments