|
| 1 | +// ignore-tidy-filelength |
1 | 2 | //! "Collection" is the process of determining the type and other external
|
2 | 3 | //! details of each item in Rust. Collection is specifically concerned
|
3 | 4 | //! with *inter-procedural* things -- for example, for a function
|
@@ -79,6 +80,7 @@ pub fn provide(providers: &mut Providers) {
|
79 | 80 | projection_ty_from_predicates,
|
80 | 81 | explicit_predicates_of,
|
81 | 82 | super_predicates_of,
|
| 83 | + super_predicates_that_define_assoc_type, |
82 | 84 | trait_explicit_predicates_and_bounds,
|
83 | 85 | type_param_predicates,
|
84 | 86 | trait_def,
|
@@ -651,17 +653,10 @@ impl ItemCtxt<'tcx> {
|
651 | 653 | hir::GenericBound::Trait(poly_trait_ref, _) => {
|
652 | 654 | let trait_ref = &poly_trait_ref.trait_ref;
|
653 | 655 | let trait_did = trait_ref.trait_def_id().unwrap();
|
654 |
| - let traits_did = super_traits_of(self.tcx, trait_did); |
655 |
| - |
656 |
| - traits_did.iter().any(|trait_did| { |
| 656 | + super_traits_of(self.tcx, trait_did).any(|trait_did| { |
657 | 657 | self.tcx
|
658 |
| - .associated_items(*trait_did) |
659 |
| - .find_by_name_and_kind( |
660 |
| - self.tcx, |
661 |
| - assoc_name, |
662 |
| - ty::AssocKind::Type, |
663 |
| - *trait_did, |
664 |
| - ) |
| 658 | + .associated_items(trait_did) |
| 659 | + .find_by_name_and_kind(self.tcx, assoc_name, ty::AssocKind::Type, trait_did) |
665 | 660 | .is_some()
|
666 | 661 | })
|
667 | 662 | }
|
@@ -1035,55 +1030,91 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
|
1035 | 1030 | /// the transitive super-predicates are converted.
|
1036 | 1031 | fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> {
|
1037 | 1032 | debug!("super_predicates(trait_def_id={:?})", trait_def_id);
|
1038 |
| - let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local()); |
| 1033 | + tcx.super_predicates_that_define_assoc_type((trait_def_id, None)) |
| 1034 | +} |
1039 | 1035 |
|
1040 |
| - let item = match tcx.hir().get(trait_hir_id) { |
1041 |
| - Node::Item(item) => item, |
1042 |
| - _ => bug!("trait_node_id {} is not an item", trait_hir_id), |
1043 |
| - }; |
| 1036 | +/// Ensures that the super-predicates of the trait with a `DefId` |
| 1037 | +/// of `trait_def_id` are converted and stored. This also ensures that |
| 1038 | +/// the transitive super-predicates are converted. |
| 1039 | +fn super_predicates_that_define_assoc_type( |
| 1040 | + tcx: TyCtxt<'_>, |
| 1041 | + (trait_def_id, assoc_name): (DefId, Option<Ident>), |
| 1042 | +) -> ty::GenericPredicates<'_> { |
| 1043 | + debug!( |
| 1044 | + "super_predicates_that_define_assoc_type(trait_def_id={:?}, assoc_name={:?})", |
| 1045 | + trait_def_id, assoc_name |
| 1046 | + ); |
| 1047 | + if trait_def_id.is_local() { |
| 1048 | + debug!("super_predicates_that_define_assoc_type: local trait_def_id={:?}", trait_def_id); |
| 1049 | + let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local()); |
1044 | 1050 |
|
1045 |
| - let (generics, bounds) = match item.kind { |
1046 |
| - hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits), |
1047 |
| - hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), |
1048 |
| - _ => span_bug!(item.span, "super_predicates invoked on non-trait"), |
1049 |
| - }; |
| 1051 | + let item = match tcx.hir().get(trait_hir_id) { |
| 1052 | + Node::Item(item) => item, |
| 1053 | + _ => bug!("trait_node_id {} is not an item", trait_hir_id), |
| 1054 | + }; |
1050 | 1055 |
|
1051 |
| - let icx = ItemCtxt::new(tcx, trait_def_id); |
1052 |
| - |
1053 |
| - // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. |
1054 |
| - let self_param_ty = tcx.types.self_param; |
1055 |
| - let superbounds1 = |
1056 |
| - AstConv::compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span); |
1057 |
| - |
1058 |
| - let superbounds1 = superbounds1.predicates(tcx, self_param_ty); |
1059 |
| - |
1060 |
| - // Convert any explicit superbounds in the where-clause, |
1061 |
| - // e.g., `trait Foo where Self: Bar`. |
1062 |
| - // In the case of trait aliases, however, we include all bounds in the where-clause, |
1063 |
| - // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>` |
1064 |
| - // as one of its "superpredicates". |
1065 |
| - let is_trait_alias = tcx.is_trait_alias(trait_def_id); |
1066 |
| - let superbounds2 = icx.type_parameter_bounds_in_generics( |
1067 |
| - generics, |
1068 |
| - item.hir_id, |
1069 |
| - self_param_ty, |
1070 |
| - OnlySelfBounds(!is_trait_alias), |
1071 |
| - None, |
1072 |
| - ); |
| 1056 | + let (generics, bounds) = match item.kind { |
| 1057 | + hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits), |
| 1058 | + hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), |
| 1059 | + _ => span_bug!(item.span, "super_predicates invoked on non-trait"), |
| 1060 | + }; |
1073 | 1061 |
|
1074 |
| - // Combine the two lists to form the complete set of superbounds: |
1075 |
| - let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); |
| 1062 | + let icx = ItemCtxt::new(tcx, trait_def_id); |
1076 | 1063 |
|
1077 |
| - // Now require that immediate supertraits are converted, |
1078 |
| - // which will, in turn, reach indirect supertraits. |
1079 |
| - for &(pred, span) in superbounds { |
1080 |
| - debug!("superbound: {:?}", pred); |
1081 |
| - if let ty::PredicateAtom::Trait(bound, _) = pred.skip_binders() { |
1082 |
| - tcx.at(span).super_predicates_of(bound.def_id()); |
| 1064 | + // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. |
| 1065 | + let self_param_ty = tcx.types.self_param; |
| 1066 | + let superbounds1 = if let Some(assoc_name) = assoc_name { |
| 1067 | + AstConv::compute_bounds_that_match_assoc_type( |
| 1068 | + &icx, |
| 1069 | + self_param_ty, |
| 1070 | + &bounds, |
| 1071 | + SizedByDefault::No, |
| 1072 | + item.span, |
| 1073 | + assoc_name, |
| 1074 | + ) |
| 1075 | + } else { |
| 1076 | + let bounds: Vec<_> = bounds.iter().collect(); |
| 1077 | + AstConv::compute_bounds(&icx, self_param_ty, &bounds, SizedByDefault::No, item.span) |
| 1078 | + }; |
| 1079 | + |
| 1080 | + let superbounds1 = superbounds1.predicates(tcx, self_param_ty); |
| 1081 | + |
| 1082 | + // Convert any explicit superbounds in the where-clause, |
| 1083 | + // e.g., `trait Foo where Self: Bar`. |
| 1084 | + // In the case of trait aliases, however, we include all bounds in the where-clause, |
| 1085 | + // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>` |
| 1086 | + // as one of its "superpredicates". |
| 1087 | + let is_trait_alias = tcx.is_trait_alias(trait_def_id); |
| 1088 | + let superbounds2 = icx.type_parameter_bounds_in_generics( |
| 1089 | + generics, |
| 1090 | + item.hir_id, |
| 1091 | + self_param_ty, |
| 1092 | + OnlySelfBounds(!is_trait_alias), |
| 1093 | + assoc_name, |
| 1094 | + ); |
| 1095 | + |
| 1096 | + // Combine the two lists to form the complete set of superbounds: |
| 1097 | + let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); |
| 1098 | + |
| 1099 | + // Now require that immediate supertraits are converted, |
| 1100 | + // which will, in turn, reach indirect supertraits. |
| 1101 | + if assoc_name.is_none() { |
| 1102 | + // FIXME: move this into the `super_predicates_of` query |
| 1103 | + for &(pred, span) in superbounds { |
| 1104 | + debug!("superbound: {:?}", pred); |
| 1105 | + if let ty::PredicateAtom::Trait(bound, _) = pred.skip_binders() { |
| 1106 | + tcx.at(span).super_predicates_of(bound.def_id()); |
| 1107 | + } |
| 1108 | + } |
1083 | 1109 | }
|
1084 |
| - } |
1085 | 1110 |
|
1086 |
| - ty::GenericPredicates { parent: None, predicates: superbounds } |
| 1111 | + ty::GenericPredicates { parent: None, predicates: superbounds } |
| 1112 | + } else { |
| 1113 | + // if `assoc_name` is None, then the query should've been redirected to an |
| 1114 | + // external provider |
| 1115 | + assert!(assoc_name.is_some()); |
| 1116 | + tcx.super_predicates_of(trait_def_id) |
| 1117 | + } |
1087 | 1118 | }
|
1088 | 1119 |
|
1089 | 1120 | pub fn super_traits_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> impl Iterator<Item = DefId> {
|
@@ -1123,6 +1154,8 @@ pub fn super_traits_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> impl Iterator<It
|
1123 | 1154 | }
|
1124 | 1155 | }
|
1125 | 1156 | }
|
| 1157 | + |
| 1158 | + set.into_iter() |
1126 | 1159 | }
|
1127 | 1160 |
|
1128 | 1161 | fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
|
@@ -1976,8 +2009,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
1976 | 2009 | index += 1;
|
1977 | 2010 |
|
1978 | 2011 | let sized = SizedByDefault::Yes;
|
1979 |
| - let bounds = |
1980 |
| - AstConv::compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span); |
| 2012 | + let bounds: Vec<_> = param.bounds.iter().collect(); |
| 2013 | + let bounds = AstConv::compute_bounds(&icx, param_ty, &bounds, sized, param.span); |
1981 | 2014 | predicates.extend(bounds.predicates(tcx, param_ty));
|
1982 | 2015 | }
|
1983 | 2016 | GenericParamKind::Const { .. } => {
|
|
0 commit comments