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 ;
@@ -365,6 +367,106 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
365
367
fn_like. asyncness ( )
366
368
}
367
369
370
+ /// For associated types we allow bounds written on the associated type
371
+ /// (`type X: Trait`) to be used as candidates. We also allow the same bounds
372
+ /// when desugared as bounds on the trait `where Self::X: Trait`.
373
+ ///
374
+ /// Note that this filtering is done with the trait's identity substs to
375
+ /// simplify checking that these bounds are met in impls. This means that
376
+ /// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
377
+ /// `hr-associated-type-bound-1.rs`.
378
+ fn associated_type_projection_predicates (
379
+ tcx : TyCtxt < ' _ > ,
380
+ def_id : DefId ,
381
+ ) -> & ' _ ty:: List < ty:: Predicate < ' _ > > {
382
+ let trait_id = tcx. associated_item ( def_id) . container . id ( ) ;
383
+ let trait_substs = InternalSubsts :: identity_for_item ( tcx, trait_id) ;
384
+
385
+ let generic_trait_bounds = tcx. predicates_of ( trait_id) ;
386
+ let trait_bounds = generic_trait_bounds. instantiate_identity ( tcx) ;
387
+ let trait_predicates = util:: elaborate_predicates ( tcx, trait_bounds. predicates . into_iter ( ) ) ;
388
+
389
+ let predicates = trait_predicates. filter_map ( |obligation| {
390
+ let pred = obligation. predicate ;
391
+ match pred. kind ( ) {
392
+ ty:: PredicateKind :: Trait ( tr, _) => {
393
+ if let ty:: Projection ( p) = tr. skip_binder ( ) . self_ty ( ) . kind {
394
+ if p. item_def_id == def_id && p. substs . starts_with ( trait_substs) {
395
+ return Some ( pred) ;
396
+ }
397
+ }
398
+ }
399
+ ty:: PredicateKind :: Projection ( proj) => {
400
+ if let ty:: Projection ( p) = proj. skip_binder ( ) . projection_ty . self_ty ( ) . kind {
401
+ if p. item_def_id == def_id && p. substs . starts_with ( trait_substs) {
402
+ return Some ( pred) ;
403
+ }
404
+ }
405
+ }
406
+ _ => { }
407
+ }
408
+ None
409
+ } ) ;
410
+
411
+ let result = tcx. mk_predicates ( predicates) ;
412
+ debug ! ( "associated_type_projection_predicates({}) = {:?}" , tcx. def_path_str( def_id) , result) ;
413
+ result
414
+ }
415
+
416
+ /// Opaque types don't have the same issues as associated types: the only
417
+ /// predicates on an opaque type (excluding those it inherits from its parent
418
+ /// item) should be of the form we're expecting.
419
+ fn opaque_type_projection_predicates (
420
+ tcx : TyCtxt < ' _ > ,
421
+ def_id : DefId ,
422
+ ) -> & ' _ ty:: List < ty:: Predicate < ' _ > > {
423
+ let substs = InternalSubsts :: identity_for_item ( tcx, def_id) ;
424
+
425
+ let generics_bounds = tcx. predicates_of ( def_id) ;
426
+ let bounds = generics_bounds. instantiate_identity ( tcx) ;
427
+ let predicates = util:: elaborate_predicates ( tcx, bounds. predicates . into_iter ( ) ) ;
428
+
429
+ let filtered_predicates = predicates. filter_map ( |obligation| {
430
+ let pred = obligation. predicate ;
431
+ match pred. kind ( ) {
432
+ ty:: PredicateKind :: Trait ( tr, _) => {
433
+ if let ty:: Opaque ( opaque_def_id, opaque_substs) = tr. skip_binder ( ) . self_ty ( ) . kind {
434
+ if opaque_def_id == def_id && opaque_substs == substs {
435
+ return Some ( pred) ;
436
+ }
437
+ }
438
+ }
439
+ ty:: PredicateKind :: Projection ( proj) => {
440
+ if let ty:: Opaque ( opaque_def_id, opaque_substs) =
441
+ proj. skip_binder ( ) . projection_ty . self_ty ( ) . kind
442
+ {
443
+ if opaque_def_id == def_id && opaque_substs == substs {
444
+ return Some ( pred) ;
445
+ }
446
+ }
447
+ }
448
+ _ => { }
449
+ }
450
+ tcx. sess . delay_span_bug (
451
+ obligation. cause . span ( tcx) ,
452
+ & format ! ( "unexpected predicate {:?} on opaque type" , pred) ,
453
+ ) ;
454
+ None
455
+ } ) ;
456
+
457
+ let result = tcx. mk_predicates ( filtered_predicates) ;
458
+ debug ! ( "opaque_type_projection_predicates({}) = {:?}" , tcx. def_path_str( def_id) , result) ;
459
+ result
460
+ }
461
+
462
+ fn projection_predicates ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> & ' _ ty:: List < ty:: Predicate < ' _ > > {
463
+ match tcx. def_kind ( def_id) {
464
+ DefKind :: AssocTy => associated_type_projection_predicates ( tcx, def_id) ,
465
+ DefKind :: OpaqueTy => opaque_type_projection_predicates ( tcx, def_id) ,
466
+ k => bug ! ( "projection_predicates called on {}" , k. descr( def_id) ) ,
467
+ }
468
+ }
469
+
368
470
pub fn provide ( providers : & mut ty:: query:: Providers < ' _ > ) {
369
471
* providers = ty:: query:: Providers {
370
472
asyncness,
@@ -381,6 +483,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
381
483
instance_def_size_estimate,
382
484
issue33140_self_ty,
383
485
impl_defaultness,
486
+ projection_predicates,
384
487
..* providers
385
488
} ;
386
489
}
0 commit comments