]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_hir_analysis/src/collect/item_bounds.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / compiler / rustc_hir_analysis / src / collect / item_bounds.rs
CommitLineData
29967ef6 1use super::ItemCtxt;
c295e0f8 2use crate::astconv::AstConv;
29967ef6
XL
3use rustc_hir as hir;
4use rustc_infer::traits::util;
5use rustc_middle::ty::subst::InternalSubsts;
064997fb 6use rustc_middle::ty::{self, DefIdTree, TyCtxt};
29967ef6
XL
7use rustc_span::def_id::DefId;
8use rustc_span::Span;
9
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`.
12///
13/// Note that this filtering is done with the items identity substs 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`.
17fn associated_type_bounds<'tcx>(
18 tcx: TyCtxt<'tcx>,
19 assoc_item_def_id: DefId,
c295e0f8 20 ast_bounds: &'tcx [hir::GenericBound<'tcx>],
29967ef6
XL
21 span: Span,
22) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
23 let item_ty = tcx.mk_projection(
24 assoc_item_def_id,
25 InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
26 );
27
c295e0f8
XL
28 let icx = ItemCtxt::new(tcx, assoc_item_def_id);
29 let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
30 // Associated types are implicitly sized unless a `?Sized` bound is found
31 <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
29967ef6 32
064997fb 33 let trait_def_id = tcx.parent(assoc_item_def_id);
29967ef6
XL
34 let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
35
5869c6ff
XL
36 let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
37 match pred.kind().skip_binder() {
94222f64 38 ty::PredicateKind::Trait(tr) => tr.self_ty() == item_ty,
5869c6ff
XL
39 ty::PredicateKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
40 ty::PredicateKind::TypeOutlives(outlives) => outlives.0 == item_ty,
29967ef6 41 _ => false,
5869c6ff
XL
42 }
43 });
29967ef6
XL
44
45 let all_bounds = tcx
46 .arena
47 .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent));
48 debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds);
49 all_bounds
50}
51
52/// Opaque types don't inherit bounds from their parent: for return position
53/// impl trait it isn't possible to write a suitable predicate on the
54/// containing function and for type-alias impl trait we don't have a backwards
55/// compatibility issue.
f2b60f7d 56#[instrument(level = "trace", skip(tcx), ret)]
29967ef6
XL
57fn opaque_type_bounds<'tcx>(
58 tcx: TyCtxt<'tcx>,
59 opaque_def_id: DefId,
c295e0f8 60 ast_bounds: &'tcx [hir::GenericBound<'tcx>],
29967ef6 61 span: Span,
f2b60f7d 62 in_trait: bool,
29967ef6 63) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
5e7ed085 64 ty::print::with_no_queries!({
f2b60f7d
FG
65 let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id);
66 let item_ty = if in_trait {
67 tcx.mk_projection(opaque_def_id, substs)
68 } else {
69 tcx.mk_opaque(opaque_def_id, substs)
70 };
29967ef6 71
c295e0f8
XL
72 let icx = ItemCtxt::new(tcx, opaque_def_id);
73 let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
74 // Opaque types are implicitly sized unless a `?Sized` bound is found
75 <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
f2b60f7d
FG
76 debug!(?bounds);
77
5099ac24 78 tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty))
29967ef6
XL
79 })
80}
81
82pub(super) fn explicit_item_bounds(
83 tcx: TyCtxt<'_>,
84 def_id: DefId,
85) -> &'_ [(ty::Predicate<'_>, Span)] {
86 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
87 match tcx.hir().get(hir_id) {
88 hir::Node::TraitItem(hir::TraitItem {
89 kind: hir::TraitItemKind::Type(bounds, _),
90 span,
91 ..
92 }) => associated_type_bounds(tcx, def_id, bounds, *span),
93 hir::Node::Item(hir::Item {
f2b60f7d 94 kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
29967ef6
XL
95 span,
96 ..
f2b60f7d 97 }) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait),
29967ef6
XL
98 _ => bug!("item_bounds called on {:?}", def_id),
99 }
100}
101
102pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
103 tcx.mk_predicates(
104 util::elaborate_predicates(
105 tcx,
106 tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
107 )
108 .map(|obligation| obligation.predicate),
109 )
110}