2 use crate::astconv
::{AstConv, PredicateFilter}
;
4 use rustc_infer
::traits
::util
;
5 use rustc_middle
::ty
::GenericArgs
;
6 use rustc_middle
::ty
::{self, Ty, TyCtxt, TypeFoldable, TypeFolder}
;
7 use rustc_span
::def_id
::{DefId, LocalDefId}
;
10 /// For associated types we include both bounds written on the type
11 /// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
13 /// Note that this filtering is done with the items identity args to
14 /// simplify checking that these bounds are met in impls. This means that
15 /// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
16 /// `hr-associated-type-bound-1.rs`.
17 fn associated_type_bounds
<'tcx
>(
19 assoc_item_def_id
: LocalDefId
,
20 ast_bounds
: &'tcx
[hir
::GenericBound
<'tcx
>],
22 ) -> &'tcx
[(ty
::Clause
<'tcx
>, Span
)] {
23 let item_ty
= Ty
::new_projection(
25 assoc_item_def_id
.to_def_id(),
26 GenericArgs
::identity_for_item(tcx
, assoc_item_def_id
),
29 let icx
= ItemCtxt
::new(tcx
, assoc_item_def_id
);
30 let mut bounds
= icx
.astconv().compute_bounds(item_ty
, ast_bounds
, PredicateFilter
::All
);
31 // Associated types are implicitly sized unless a `?Sized` bound is found
32 icx
.astconv().add_implicitly_sized(&mut bounds
, item_ty
, ast_bounds
, None
, span
);
34 let trait_def_id
= tcx
.local_parent(assoc_item_def_id
);
35 let trait_predicates
= tcx
.trait_explicit_predicates_and_bounds(trait_def_id
);
37 let bounds_from_parent
= trait_predicates
41 .filter(|(pred
, _
)| match pred
.kind().skip_binder() {
42 ty
::ClauseKind
::Trait(tr
) => tr
.self_ty() == item_ty
,
43 ty
::ClauseKind
::Projection(proj
) => proj
.projection_ty
.self_ty() == item_ty
,
44 ty
::ClauseKind
::TypeOutlives(outlives
) => outlives
.0 == item_ty
,
47 .map(|(clause
, span
)| (clause
, span
));
49 let all_bounds
= tcx
.arena
.alloc_from_iter(bounds
.clauses().chain(bounds_from_parent
));
51 "associated_type_bounds({}) = {:?}",
52 tcx
.def_path_str(assoc_item_def_id
.to_def_id()),
58 /// Opaque types don't inherit bounds from their parent: for return position
59 /// impl trait it isn't possible to write a suitable predicate on the
60 /// containing function and for type-alias impl trait we don't have a backwards
61 /// compatibility issue.
62 #[instrument(level = "trace", skip(tcx), ret)]
63 fn opaque_type_bounds
<'tcx
>(
65 opaque_def_id
: LocalDefId
,
66 ast_bounds
: &'tcx
[hir
::GenericBound
<'tcx
>],
69 ) -> &'tcx
[(ty
::Clause
<'tcx
>, Span
)] {
70 ty
::print
::with_no_queries
!({
71 let icx
= ItemCtxt
::new(tcx
, opaque_def_id
);
72 let mut bounds
= icx
.astconv().compute_bounds(item_ty
, ast_bounds
, PredicateFilter
::All
);
73 // Opaque types are implicitly sized unless a `?Sized` bound is found
74 icx
.astconv().add_implicitly_sized(&mut bounds
, item_ty
, ast_bounds
, None
, span
);
77 tcx
.arena
.alloc_from_iter(bounds
.clauses())
81 pub(super) fn explicit_item_bounds(
84 ) -> ty
::EarlyBinder
<&'_
[(ty
::Clause
<'_
>, Span
)]> {
85 match tcx
.opt_rpitit_info(def_id
.to_def_id()) {
86 // RPITIT's bounds are the same as opaque type bounds, but with
87 // a projection self type.
88 Some(ty
::ImplTraitInTraitData
::Trait { opaque_def_id, .. }
) => {
89 let item
= tcx
.hir().get_by_def_id(opaque_def_id
.expect_local()).expect_item();
90 let opaque_ty
= item
.expect_opaque_ty();
91 return ty
::EarlyBinder
::bind(opaque_type_bounds(
93 opaque_def_id
.expect_local(),
98 ty
::GenericArgs
::identity_for_item(tcx
, def_id
),
103 // These should have been fed!
104 Some(ty
::ImplTraitInTraitData
::Impl { .. }
) => unreachable
!(),
108 let hir_id
= tcx
.hir().local_def_id_to_hir_id(def_id
);
109 let bounds
= match tcx
.hir().get(hir_id
) {
110 hir
::Node
::TraitItem(hir
::TraitItem
{
111 kind
: hir
::TraitItemKind
::Type(bounds
, _
),
114 }) => associated_type_bounds(tcx
, def_id
, bounds
, *span
),
115 hir
::Node
::Item(hir
::Item
{
116 kind
: hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy { bounds, in_trait: false, .. }
),
120 let args
= GenericArgs
::identity_for_item(tcx
, def_id
);
121 let item_ty
= Ty
::new_opaque(tcx
, def_id
.to_def_id(), args
);
122 opaque_type_bounds(tcx
, def_id
, bounds
, item_ty
, *span
)
124 // Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking
125 // for the item bounds of the *opaques* in a trait's default method signature, we
126 // need to map these projections back to opaques.
127 hir
::Node
::Item(hir
::Item
{
128 kind
: hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy { bounds, in_trait: true, origin, .. }
),
132 let (hir
::OpaqueTyOrigin
::FnReturn(fn_def_id
)
133 | hir
::OpaqueTyOrigin
::AsyncFn(fn_def_id
)) = *origin
137 let args
= GenericArgs
::identity_for_item(tcx
, def_id
);
138 let item_ty
= Ty
::new_opaque(tcx
, def_id
.to_def_id(), args
);
139 tcx
.arena
.alloc_slice(
140 &opaque_type_bounds(tcx
, def_id
, bounds
, item_ty
, *span
)
142 .fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }
),
145 hir
::Node
::Item(hir
::Item { kind: hir::ItemKind::TyAlias(..), .. }
) => &[],
146 _
=> bug
!("item_bounds called on {:?}", def_id
),
148 ty
::EarlyBinder
::bind(bounds
)
151 pub(super) fn item_bounds(
154 ) -> ty
::EarlyBinder
<&'_ ty
::List
<ty
::Clause
<'_
>>> {
155 tcx
.explicit_item_bounds(def_id
).map_bound(|bounds
| {
156 tcx
.mk_clauses_from_iter(util
::elaborate(tcx
, bounds
.iter().map(|&(bound
, _span
)| bound
)))
160 struct AssocTyToOpaque
<'tcx
> {
165 impl<'tcx
> TypeFolder
<TyCtxt
<'tcx
>> for AssocTyToOpaque
<'tcx
> {
166 fn interner(&self) -> TyCtxt
<'tcx
> {
170 fn fold_ty(&mut self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
171 if let ty
::Alias(ty
::Projection
, projection_ty
) = ty
.kind()
172 && let Some(ty
::ImplTraitInTraitData
::Trait { fn_def_id, .. }
) =
173 self.tcx
.opt_rpitit_info(projection_ty
.def_id
)
174 && fn_def_id
== self.fn_def_id
176 self.tcx
.type_of(projection_ty
.def_id
).instantiate(self.tcx
, projection_ty
.args
)