1
1
use rustc_data_structures:: svh:: Svh ;
2
2
use rustc_hir as hir;
3
+ use rustc_hir:: def:: DefKind ;
3
4
use rustc_hir:: def_id:: { CrateNum , DefId , LocalDefId , LOCAL_CRATE } ;
5
+ use rustc_infer:: traits:: util;
4
6
use rustc_middle:: hir:: map as hir_map;
5
- use rustc_middle:: ty:: subst:: Subst ;
7
+ use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
6
8
use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt , WithConstness } ;
7
9
use rustc_session:: CrateDisambiguator ;
8
10
use rustc_span:: symbol:: Symbol ;
@@ -367,6 +369,103 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
367
369
fn_like. asyncness ( )
368
370
}
369
371
372
+ /// For associated types we allow bounds written on the associated type
373
+ /// (`type X: Trait`) to be used as candidates. We also allow the same bounds
374
+ /// when desugared as bounds on the trait `where Self::X: Trait`.
375
+ ///
376
+ /// Note that this filtering is done with the trait's identity substs to
377
+ /// simplify checking that these bounds are met in impls. This means that
378
+ /// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
379
+ /// `hr-associated-type-bound-1.rs`.
380
+ fn associated_type_projection_predicates (
381
+ tcx : TyCtxt < ' _ > ,
382
+ def_id : DefId ,
383
+ ) -> & ' _ ty:: List < ty:: Predicate < ' _ > > {
384
+ let trait_id = tcx. associated_item ( def_id) . container . id ( ) ;
385
+ let trait_substs = InternalSubsts :: identity_for_item ( tcx, trait_id) ;
386
+
387
+ let generic_trait_bounds = tcx. predicates_of ( trait_id) ;
388
+ let trait_bounds = generic_trait_bounds. instantiate_identity ( tcx) ;
389
+ let trait_predicates = util:: elaborate_predicates ( tcx, trait_bounds. predicates . into_iter ( ) ) ;
390
+
391
+ let predicates = trait_predicates. filter_map ( |obligation| {
392
+ let pred = obligation. predicate ;
393
+ match pred. kind ( ) {
394
+ ty:: PredicateKind :: Trait ( tr, _) => {
395
+ if let ty:: Projection ( p) = tr. skip_binder ( ) . self_ty ( ) . kind {
396
+ if p. item_def_id == def_id && p. substs . starts_with ( trait_substs) {
397
+ return Some ( pred) ;
398
+ }
399
+ }
400
+ }
401
+ ty:: PredicateKind :: Projection ( proj) => {
402
+ if let ty:: Projection ( p) = proj. skip_binder ( ) . projection_ty . self_ty ( ) . kind {
403
+ if p. item_def_id == def_id && p. substs . starts_with ( trait_substs) {
404
+ return Some ( pred) ;
405
+ }
406
+ }
407
+ }
408
+ _ => { }
409
+ }
410
+ None
411
+ } ) ;
412
+
413
+ let result = tcx. mk_predicates ( predicates) ;
414
+ debug ! ( "associated_type_projection_predicates({}) = {:?}" , tcx. def_path_str( def_id) , result) ;
415
+ result
416
+ }
417
+
418
+ /// Opaque types might not have the same issues as associated types, but we use a
419
+ /// similar filtering for consistency.
420
+ fn opaque_type_projection_predicates (
421
+ tcx : TyCtxt < ' _ > ,
422
+ def_id : DefId ,
423
+ ) -> & ' _ ty:: List < ty:: Predicate < ' _ > > {
424
+ let substs = InternalSubsts :: identity_for_item ( tcx, def_id) ;
425
+
426
+ let generics_bounds = tcx. predicates_of ( def_id) ;
427
+ let bounds = generics_bounds. instantiate_identity ( tcx) ;
428
+ let predicates = util:: elaborate_predicates ( tcx, bounds. predicates . into_iter ( ) ) ;
429
+
430
+ let filtered_predicates = predicates. filter_map ( |obligation| {
431
+ let pred = obligation. predicate ;
432
+ match pred. kind ( ) {
433
+ ty:: PredicateKind :: Trait ( tr, _) => {
434
+ if let ty:: Opaque ( opaque_def_id, opaque_substs) = tr. skip_binder ( ) . self_ty ( ) . kind {
435
+ if opaque_def_id == def_id && opaque_substs == substs {
436
+ return Some ( pred) ;
437
+ }
438
+ }
439
+ }
440
+ ty:: PredicateKind :: Projection ( proj) => {
441
+ if let ty:: Opaque ( opaque_def_id, opaque_substs) =
442
+ proj. skip_binder ( ) . projection_ty . self_ty ( ) . kind
443
+ {
444
+ if opaque_def_id == def_id && opaque_substs == substs {
445
+ return Some ( pred) ;
446
+ }
447
+ }
448
+ }
449
+ _ => { }
450
+ }
451
+ None
452
+ } ) ;
453
+
454
+ let result = tcx. mk_predicates ( filtered_predicates) ;
455
+ debug ! ( "opaque_type_projection_predicates({}) = {:?}" , tcx. def_path_str( def_id) , result) ;
456
+ result
457
+ }
458
+
459
+ fn projection_predicates ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> & ' _ ty:: List < ty:: Predicate < ' _ > > {
460
+ match tcx. def_kind ( def_id) {
461
+ DefKind :: AssocTy => associated_type_projection_predicates ( tcx, def_id) ,
462
+ DefKind :: OpaqueTy | DefKind :: AssocOpaqueTy => {
463
+ opaque_type_projection_predicates ( tcx, def_id)
464
+ }
465
+ k => bug ! ( "projection_predicates called on {}" , k. descr( def_id) ) ,
466
+ }
467
+ }
468
+
370
469
pub fn provide ( providers : & mut ty:: query:: Providers < ' _ > ) {
371
470
* providers = ty:: query:: Providers {
372
471
asyncness,
@@ -383,6 +482,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
383
482
instance_def_size_estimate,
384
483
issue33140_self_ty,
385
484
impl_defaultness,
485
+ projection_predicates,
386
486
..* providers
387
487
} ;
388
488
}
0 commit comments