11use rustc_data_structures:: svh:: Svh ;
22use rustc_hir as hir;
3+ use rustc_hir:: def:: DefKind ;
34use rustc_hir:: def_id:: { CrateNum , DefId , LocalDefId , LOCAL_CRATE } ;
5+ use rustc_infer:: traits:: util;
46use rustc_middle:: hir:: map as hir_map;
5- use rustc_middle:: ty:: subst:: Subst ;
7+ use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
68use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt , WithConstness } ;
79use rustc_session:: CrateDisambiguator ;
810use rustc_span:: symbol:: Symbol ;
@@ -367,6 +369,103 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
367369 fn_like. asyncness ( )
368370}
369371
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+
370469pub fn provide ( providers : & mut ty:: query:: Providers < ' _ > ) {
371470 * providers = ty:: query:: Providers {
372471 asyncness,
@@ -383,6 +482,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
383482 instance_def_size_estimate,
384483 issue33140_self_ty,
385484 impl_defaultness,
485+ projection_predicates,
386486 ..* providers
387487 } ;
388488}
0 commit comments