@@ -49,6 +49,8 @@ pub enum ImplExprAtom<'tcx> {
49
49
Concrete {
50
50
def_id : DefId ,
51
51
generics : GenericArgsRef < ' tcx > ,
52
+ /// The impl exprs that prove the clauses on the impl.
53
+ impl_exprs : Vec < ImplExpr < ' tcx > > ,
52
54
} ,
53
55
/// A context-bound clause like `where T: Trait`.
54
56
LocalBound {
@@ -71,8 +73,18 @@ pub enum ImplExprAtom<'tcx> {
71
73
/// `dyn Trait` implements `Trait` using a built-in implementation; this refers to that
72
74
/// built-in implementation.
73
75
Dyn ,
74
- /// A built-in trait whose implementation is computed by the compiler, such as `Sync`.
75
- Builtin { r#trait : PolyTraitRef < ' tcx > } ,
76
+ /// A built-in trait whose implementation is computed by the compiler, such as `FnMut`. This
77
+ /// morally points to an invisible `impl` block; as such it contains the information we may
78
+ /// need from one.
79
+ Builtin {
80
+ r#trait : PolyTraitRef < ' tcx > ,
81
+ /// The `ImplExpr`s required to satisfy the implied predicates on the trait declaration.
82
+ /// E.g. since `FnMut: FnOnce`, a built-in `T: FnMut` impl would have an `ImplExpr` for `T:
83
+ /// FnOnce`.
84
+ impl_exprs : Vec < ImplExpr < ' tcx > > ,
85
+ /// The values of the associated types for this trait.
86
+ types : Vec < ( DefId , Ty < ' tcx > ) > ,
87
+ } ,
76
88
/// An error happened while resolving traits.
77
89
Error ( String ) ,
78
90
}
@@ -83,8 +95,6 @@ pub struct ImplExpr<'tcx> {
83
95
pub r#trait : PolyTraitRef < ' tcx > ,
84
96
/// The kind of implemention of the root of the tree.
85
97
pub r#impl : ImplExprAtom < ' tcx > ,
86
- /// A list of `ImplExpr`s required to fully specify the trait references in `impl`.
87
- pub args : Vec < Self > ,
88
98
}
89
99
90
100
/// Items have various predicates in scope. `path_to` uses them as a starting point for trait
@@ -290,7 +300,7 @@ impl<'tcx> PredicateSearcher<'tcx> {
290
300
291
301
// Resolve predicates required to mention the item.
292
302
let nested_impl_exprs =
293
- self . resolve_item_predicates ( alias_ty. def_id , alias_ty. args , warn) ?;
303
+ self . resolve_item_required_predicates ( alias_ty. def_id , alias_ty. args , warn) ?;
294
304
295
305
// Add all the bounds on the corresponding associated item.
296
306
self . extend ( item_bounds. map ( |( index, pred) | {
@@ -360,23 +370,22 @@ impl<'tcx> PredicateSearcher<'tcx> {
360
370
361
371
let tcx = self . tcx ;
362
372
let impl_source = shallow_resolve_trait_ref ( tcx, self . param_env , erased_tref) ;
363
- let nested;
364
373
let atom = match impl_source {
365
374
Ok ( ImplSource :: UserDefined ( ImplSourceUserDefinedData {
366
375
impl_def_id,
367
376
args : generics,
368
377
..
369
378
} ) ) => {
370
379
// Resolve the predicates required by the impl.
371
- nested = self . resolve_item_predicates ( impl_def_id, generics, warn) ?;
380
+ let impl_exprs =
381
+ self . resolve_item_required_predicates ( impl_def_id, generics, warn) ?;
372
382
ImplExprAtom :: Concrete {
373
383
def_id : impl_def_id,
374
384
generics,
385
+ impl_exprs,
375
386
}
376
387
}
377
388
Ok ( ImplSource :: Param ( _) ) => {
378
- // Mentioning a local clause requires no extra predicates to hold.
379
- nested = vec ! [ ] ;
380
389
match self . resolve_local ( erased_tref. upcast ( self . tcx ) , warn) ? {
381
390
Some ( candidate) => {
382
391
let path = candidate. path ;
@@ -402,17 +411,45 @@ impl<'tcx> PredicateSearcher<'tcx> {
402
411
}
403
412
}
404
413
}
405
- Ok ( ImplSource :: Builtin ( BuiltinImplSource :: Object { .. } , _) ) => {
406
- nested = vec ! [ ] ;
407
- ImplExprAtom :: Dyn
408
- }
414
+ Ok ( ImplSource :: Builtin ( BuiltinImplSource :: Object { .. } , _) ) => ImplExprAtom :: Dyn ,
409
415
Ok ( ImplSource :: Builtin ( _, _) ) => {
410
- // Builtin impls currently don't need nested predicates.
411
- nested = vec ! [ ] ;
412
- ImplExprAtom :: Builtin { r#trait : * tref }
416
+ // Resolve the predicates implied by the trait.
417
+ let trait_def_id = erased_tref. skip_binder ( ) . def_id ;
418
+ // If we wanted to not skip this binder, we'd have to instantiate the bound
419
+ // regions, solve, then wrap the result in a binder. And track higher-kinded
420
+ // clauses better all over.
421
+ let impl_exprs = self . resolve_item_implied_predicates (
422
+ trait_def_id,
423
+ erased_tref. skip_binder ( ) . args ,
424
+ warn,
425
+ ) ?;
426
+ let types = tcx
427
+ . associated_items ( trait_def_id)
428
+ . in_definition_order ( )
429
+ . filter ( |assoc| matches ! ( assoc. kind, AssocKind :: Type ) )
430
+ . filter_map ( |assoc| {
431
+ let ty = AliasTy :: new ( tcx, assoc. def_id , erased_tref. skip_binder ( ) . args )
432
+ . to_ty ( tcx) ;
433
+ let ty = erase_and_norm ( tcx, self . param_env , ty) ;
434
+ if let TyKind :: Alias ( _, alias_ty) = ty. kind ( ) {
435
+ if alias_ty. def_id == assoc. def_id {
436
+ warn ( & format ! ( "Failed to compute associated type {ty}" ) ) ;
437
+ // We can't return the unnormalized associated type as that would
438
+ // make the trait ref contain itself, which would make hax's
439
+ // `sinto` infrastructure loop.
440
+ return None ;
441
+ }
442
+ }
443
+ Some ( ( assoc. def_id , ty) )
444
+ } )
445
+ . collect ( ) ;
446
+ ImplExprAtom :: Builtin {
447
+ r#trait : * tref,
448
+ impl_exprs,
449
+ types,
450
+ }
413
451
}
414
452
Err ( e) => {
415
- nested = vec ! [ ] ;
416
453
let msg = format ! (
417
454
"Could not find a clause for `{tref:?}` in the current context: `{e:?}`"
418
455
) ;
@@ -423,21 +460,45 @@ impl<'tcx> PredicateSearcher<'tcx> {
423
460
424
461
Ok ( ImplExpr {
425
462
r#impl : atom,
426
- args : nested,
427
463
r#trait : * tref,
428
464
} )
429
465
}
430
466
431
467
/// Resolve the predicates required by the given item.
432
- pub fn resolve_item_predicates (
468
+ pub fn resolve_item_required_predicates (
469
+ & mut self ,
470
+ def_id : DefId ,
471
+ generics : GenericArgsRef < ' tcx > ,
472
+ // Call back into hax-related code to display a nice warning.
473
+ warn : & impl Fn ( & str ) ,
474
+ ) -> Result < Vec < ImplExpr < ' tcx > > , String > {
475
+ let tcx = self . tcx ;
476
+ self . resolve_predicates ( generics, required_predicates ( tcx, def_id) , warn)
477
+ }
478
+
479
+ /// Resolve the predicates implied by the given item.
480
+ pub fn resolve_item_implied_predicates (
433
481
& mut self ,
434
482
def_id : DefId ,
435
483
generics : GenericArgsRef < ' tcx > ,
436
484
// Call back into hax-related code to display a nice warning.
437
485
warn : & impl Fn ( & str ) ,
438
486
) -> Result < Vec < ImplExpr < ' tcx > > , String > {
439
487
let tcx = self . tcx ;
440
- required_predicates ( tcx, def_id)
488
+ self . resolve_predicates ( generics, implied_predicates ( tcx, def_id) , warn)
489
+ }
490
+
491
+ /// Apply the given generics to the provided clauses and resolve the trait references in the
492
+ /// current context.
493
+ pub fn resolve_predicates (
494
+ & mut self ,
495
+ generics : GenericArgsRef < ' tcx > ,
496
+ predicates : GenericPredicates < ' tcx > ,
497
+ // Call back into hax-related code to display a nice warning.
498
+ warn : & impl Fn ( & str ) ,
499
+ ) -> Result < Vec < ImplExpr < ' tcx > > , String > {
500
+ let tcx = self . tcx ;
501
+ predicates
441
502
. predicates
442
503
. iter ( )
443
504
. map ( |( clause, _span) | * clause)
0 commit comments