1 use crate::generic_types;
2 use crate::lowering::Lower;
4 Clause, Clauses, DomainGoal, GoalKind, ProgramClause, ProgramClauseCategory, WellFormed,
6 use rustc::ty::{self, TyCtxt};
8 use rustc_hir::def_id::DefId;
9 use rustc_target::spec::abi;
12 crate fn wf_clause_for_raw_ptr(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> {
13 let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
15 let wf_clause = ProgramClause {
16 goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
17 hypotheses: ty::List::empty(),
18 category: ProgramClauseCategory::WellFormed,
20 let wf_clause = Clause::Implies(wf_clause);
22 // `forall<T> { WellFormed(*const T). }`
23 tcx.mk_clauses(iter::once(wf_clause))
26 crate fn wf_clause_for_fn_ptr(
28 arity_and_output: usize,
30 unsafety: hir::Unsafety,
33 let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
35 let wf_clause = ProgramClause {
36 goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
37 hypotheses: ty::List::empty(),
38 category: ProgramClauseCategory::WellFormed,
40 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
42 // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
43 // where `n + 1` == `arity_and_output`
44 tcx.mk_clauses(iter::once(wf_clause))
47 crate fn wf_clause_for_slice(tcx: TyCtxt<'_>) -> Clauses<'_> {
48 let ty = generic_types::bound(tcx, 0);
49 let slice_ty = tcx.mk_slice(ty);
51 let sized_trait = match tcx.lang_items().sized_trait() {
52 Some(def_id) => def_id,
53 None => return ty::List::empty(),
55 let sized_implemented =
56 ty::TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, ty::List::empty()) };
57 let sized_implemented: DomainGoal<'_> =
58 ty::TraitPredicate { trait_ref: sized_implemented }.lower();
60 let wf_clause = ProgramClause {
61 goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
62 hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))),
63 category: ProgramClauseCategory::WellFormed,
65 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
67 // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
68 tcx.mk_clauses(iter::once(wf_clause))
71 crate fn wf_clause_for_array<'tcx>(
73 length: &'tcx ty::Const<'tcx>,
75 let ty = generic_types::bound(tcx, 0);
76 let array_ty = tcx.mk_ty(ty::Array(ty, length));
78 let sized_trait = match tcx.lang_items().sized_trait() {
79 Some(def_id) => def_id,
80 None => return ty::List::empty(),
82 let sized_implemented =
83 ty::TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, ty::List::empty()) };
84 let sized_implemented: DomainGoal<'_> =
85 ty::TraitPredicate { trait_ref: sized_implemented }.lower();
87 let wf_clause = ProgramClause {
88 goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
89 hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))),
90 category: ProgramClauseCategory::WellFormed,
92 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
94 // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
95 tcx.mk_clauses(iter::once(wf_clause))
98 crate fn wf_clause_for_tuple(tcx: TyCtxt<'_>, arity: usize) -> Clauses<'_> {
99 let type_list = generic_types::type_list(tcx, arity);
100 let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
102 let sized_trait = match tcx.lang_items().sized_trait() {
103 Some(def_id) => def_id,
104 None => return ty::List::empty(),
107 // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of
108 // hypotheses is actually empty.
109 let sized_implemented = type_list[0..std::cmp::max(arity, 1) - 1]
111 .map(|ty| ty::TraitRef {
113 substs: tcx.mk_substs_trait(ty.expect_ty(), ty::List::empty()),
115 .map(|trait_ref| ty::TraitPredicate { trait_ref })
116 .map(|predicate| predicate.lower());
118 let wf_clause = ProgramClause {
119 goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
120 hypotheses: tcx.mk_goals(
121 sized_implemented.map(|domain_goal| tcx.mk_goal(GoalKind::DomainGoal(domain_goal))),
123 category: ProgramClauseCategory::WellFormed,
125 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
128 // forall<T1, ..., Tn-1, Tn> {
129 // WellFormed((T1, ..., Tn)) :-
130 // Implemented(T1: Sized),
132 // Implemented(Tn-1: Sized).
135 tcx.mk_clauses(iter::once(wf_clause))
138 crate fn wf_clause_for_ref(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> {
139 let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0)));
140 let ty = generic_types::bound(tcx, 1);
141 let ref_ty = tcx.mk_ref(region, ty::TypeAndMut { ty, mutbl });
143 let outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower();
144 let wf_clause = ProgramClause {
145 goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
146 hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(outlives.into_goal()))),
147 category: ProgramClauseCategory::WellFormed,
149 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
151 // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
152 tcx.mk_clauses(iter::once(wf_clause))
155 crate fn wf_clause_for_fn_def(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
156 let fn_def = generic_types::fn_def(tcx, def_id);
158 let wf_clause = ProgramClause {
159 goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)),
160 hypotheses: ty::List::empty(),
161 category: ProgramClauseCategory::WellFormed,
163 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
165 // `forall <T1, ..., Tn+1> { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }`
166 // where `def_id` maps to the `some_fn` function definition
167 tcx.mk_clauses(iter::once(wf_clause))