]> git.proxmox.com Git - rustc.git/blob - src/librustc_traits/chalk_context/program_clauses/builtin.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc_traits / chalk_context / program_clauses / builtin.rs
1 use rustc::traits::{
2 GoalKind,
3 Clause,
4 ProgramClause,
5 ProgramClauseCategory,
6 };
7 use rustc::ty::{self, Ty, TyCtxt};
8 use rustc::ty::subst::{GenericArg, InternalSubsts, Subst};
9 use rustc::hir;
10 use rustc::hir::def_id::DefId;
11 use crate::lowering::Lower;
12 use crate::generic_types;
13
14 /// Returns a predicate of the form
15 /// `Implemented(ty: Trait) :- Implemented(nested: Trait)...`
16 /// where `Trait` is specified by `trait_def_id`.
17 fn builtin_impl_clause(
18 tcx: TyCtxt<'tcx>,
19 ty: Ty<'tcx>,
20 nested: &[GenericArg<'tcx>],
21 trait_def_id: DefId,
22 ) -> ProgramClause<'tcx> {
23 ProgramClause {
24 goal: ty::TraitPredicate {
25 trait_ref: ty::TraitRef {
26 def_id: trait_def_id,
27 substs: tcx.mk_substs_trait(ty, &[]),
28 },
29 }.lower(),
30 hypotheses: tcx.mk_goals(
31 nested.iter()
32 .cloned()
33 .map(|nested_ty| ty::TraitRef {
34 def_id: trait_def_id,
35 substs: tcx.mk_substs_trait(nested_ty.expect_ty(), &[]),
36 })
37 .map(|trait_ref| ty::TraitPredicate { trait_ref })
38 .map(|pred| GoalKind::DomainGoal(pred.lower()))
39 .map(|goal_kind| tcx.mk_goal(goal_kind))
40 ),
41 category: ProgramClauseCategory::Other,
42 }
43 }
44
45 crate fn assemble_builtin_unsize_impls<'tcx>(
46 tcx: TyCtxt<'tcx>,
47 unsize_def_id: DefId,
48 source: Ty<'tcx>,
49 target: Ty<'tcx>,
50 clauses: &mut Vec<Clause<'tcx>>,
51 ) {
52 match (&source.kind, &target.kind) {
53 (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {
54 if data_a.principal_def_id() != data_b.principal_def_id()
55 || data_b.auto_traits().any(|b| data_a.auto_traits().all(|a| a != b))
56 {
57 return;
58 }
59
60 // FIXME: rules for trait upcast
61 }
62
63 (_, &ty::Dynamic(..)) => {
64 // FIXME: basically, we should have something like:
65 // ```
66 // forall<T> {
67 // Implemented(T: Unsize< for<...> dyn Trait<...> >) :-
68 // for<...> Implemented(T: Trait<...>).
69 // }
70 // ```
71 // The question is: how to correctly handle the higher-ranked
72 // `for<...>` binder in order to have a generic rule?
73 // (Having generic rules is useful for caching, as we may be able
74 // to turn this function and others into tcx queries later on).
75 }
76
77 (ty::Array(_, length), ty::Slice(_)) => {
78 let ty_param = generic_types::bound(tcx, 0);
79 let array_ty = tcx.mk_ty(ty::Array(ty_param, length));
80 let slice_ty = tcx.mk_ty(ty::Slice(ty_param));
81
82 // `forall<T> { Implemented([T; N]: Unsize<[T]>). }`
83 let clause = ProgramClause {
84 goal: ty::TraitPredicate {
85 trait_ref: ty::TraitRef {
86 def_id: unsize_def_id,
87 substs: tcx.mk_substs_trait(array_ty, &[slice_ty.into()])
88 },
89 }.lower(),
90 hypotheses: ty::List::empty(),
91 category: ProgramClauseCategory::Other,
92 };
93
94 clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
95 }
96
97 (ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => {
98 // FIXME: ambiguous
99 }
100
101 (ty::Adt(def_id_a, ..), ty::Adt(def_id_b, ..)) => {
102 if def_id_a != def_id_b {
103 return;
104 }
105
106 // FIXME: rules for struct unsizing
107 }
108
109 (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
110 if tys_a.len() != tys_b.len() {
111 return;
112 }
113
114 // FIXME: rules for tuple unsizing
115 }
116
117 _ => (),
118 }
119 }
120
121 crate fn assemble_builtin_sized_impls<'tcx>(
122 tcx: TyCtxt<'tcx>,
123 sized_def_id: DefId,
124 ty: Ty<'tcx>,
125 clauses: &mut Vec<Clause<'tcx>>,
126 ) {
127 let mut push_builtin_impl = |ty: Ty<'tcx>, nested: &[GenericArg<'tcx>]| {
128 let clause = builtin_impl_clause(tcx, ty, nested, sized_def_id);
129 // Bind innermost bound vars that may exist in `ty` and `nested`.
130 clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
131 };
132
133 match &ty.kind {
134 // Non parametric primitive types.
135 ty::Bool |
136 ty::Char |
137 ty::Int(..) |
138 ty::Uint(..) |
139 ty::Float(..) |
140 ty::Infer(ty::IntVar(_)) |
141 ty::Infer(ty::FloatVar(_)) |
142 ty::Error |
143 ty::Never => push_builtin_impl(ty, &[]),
144
145 // These ones are always `Sized`.
146 &ty::Array(_, length) => {
147 push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
148 }
149 ty::RawPtr(ptr) => {
150 push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
151 }
152 &ty::Ref(_, _, mutbl) => {
153 push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
154 }
155 ty::FnPtr(fn_ptr) => {
156 let fn_ptr = fn_ptr.skip_binder();
157 let fn_ptr = generic_types::fn_ptr(
158 tcx,
159 fn_ptr.inputs_and_output.len(),
160 fn_ptr.c_variadic,
161 fn_ptr.unsafety,
162 fn_ptr.abi
163 );
164 push_builtin_impl(fn_ptr, &[]);
165 }
166 &ty::FnDef(def_id, ..) => {
167 push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
168 }
169 &ty::Closure(def_id, ..) => {
170 push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
171 }
172 &ty::Generator(def_id, ..) => {
173 push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
174 }
175
176 // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
177 &ty::Tuple(type_list) => {
178 let type_list = generic_types::type_list(tcx, type_list.len());
179 push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &type_list);
180 }
181
182 // Struct def
183 ty::Adt(adt_def, _) => {
184 let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did);
185 let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
186 let sized_constraint = adt_def.sized_constraint(tcx)
187 .iter()
188 .map(|ty| GenericArg::from(ty.subst(tcx, substs)))
189 .collect::<Vec<_>>();
190 push_builtin_impl(adt, &sized_constraint);
191 }
192
193 // Artificially trigger an ambiguity by adding two possible types to
194 // unify against.
195 ty::Infer(ty::TyVar(_)) => {
196 push_builtin_impl(tcx.types.i32, &[]);
197 push_builtin_impl(tcx.types.f32, &[]);
198 }
199
200 ty::Projection(_projection_ty) => {
201 // FIXME: add builtin impls from the associated type values found in
202 // trait impls of `projection_ty.trait_ref(tcx)`.
203 }
204
205 // The `Sized` bound can only come from the environment.
206 ty::Param(..) |
207 ty::Placeholder(..) |
208 ty::UnnormalizedProjection(..) => (),
209
210 // Definitely not `Sized`.
211 ty::Foreign(..) |
212 ty::Str |
213 ty::Slice(..) |
214 ty::Dynamic(..) |
215 ty::Opaque(..) => (),
216
217 ty::Bound(..) |
218 ty::GeneratorWitness(..) |
219 ty::Infer(ty::FreshTy(_)) |
220 ty::Infer(ty::FreshIntTy(_)) |
221 ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty),
222 }
223 }
224
225 crate fn assemble_builtin_copy_clone_impls<'tcx>(
226 tcx: TyCtxt<'tcx>,
227 trait_def_id: DefId,
228 ty: Ty<'tcx>,
229 clauses: &mut Vec<Clause<'tcx>>,
230 ) {
231 let mut push_builtin_impl = |ty: Ty<'tcx>, nested: &[GenericArg<'tcx>]| {
232 let clause = builtin_impl_clause(tcx, ty, nested, trait_def_id);
233 // Bind innermost bound vars that may exist in `ty` and `nested`.
234 clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
235 };
236
237 match &ty.kind {
238 // Implementations provided in libcore.
239 ty::Bool |
240 ty::Char |
241 ty::Int(..) |
242 ty::Uint(..) |
243 ty::Float(..) |
244 ty::RawPtr(..) |
245 ty::Never |
246 ty::Ref(_, _, hir::Mutability::Immutable) => (),
247
248 // Non parametric primitive types.
249 ty::Infer(ty::IntVar(_)) |
250 ty::Infer(ty::FloatVar(_)) |
251 ty::Error => push_builtin_impl(ty, &[]),
252
253 // These implement `Copy`/`Clone` if their element types do.
254 &ty::Array(_, length) => {
255 let element_ty = generic_types::bound(tcx, 0);
256 push_builtin_impl(
257 tcx.mk_ty(ty::Array(element_ty, length)),
258 &[GenericArg::from(element_ty)],
259 );
260 }
261 &ty::Tuple(type_list) => {
262 let type_list = generic_types::type_list(tcx, type_list.len());
263 push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
264 }
265 &ty::Closure(def_id, ..) => {
266 let closure_ty = generic_types::closure(tcx, def_id);
267 let upvar_tys: Vec<_> = match &closure_ty.kind {
268 ty::Closure(_, substs) => {
269 substs.as_closure()
270 .upvar_tys(def_id, tcx)
271 .map(|ty| GenericArg::from(ty))
272 .collect()
273 },
274 _ => bug!(),
275 };
276 push_builtin_impl(closure_ty, &upvar_tys);
277 }
278
279 // These ones are always `Clone`.
280 ty::FnPtr(fn_ptr) => {
281 let fn_ptr = fn_ptr.skip_binder();
282 let fn_ptr = generic_types::fn_ptr(
283 tcx,
284 fn_ptr.inputs_and_output.len(),
285 fn_ptr.c_variadic,
286 fn_ptr.unsafety,
287 fn_ptr.abi
288 );
289 push_builtin_impl(fn_ptr, &[]);
290 }
291 &ty::FnDef(def_id, ..) => {
292 push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
293 }
294
295 // These depend on whatever user-defined impls might exist.
296 ty::Adt(_, _) => (),
297
298 // Artificially trigger an ambiguity by adding two possible types to
299 // unify against.
300 ty::Infer(ty::TyVar(_)) => {
301 push_builtin_impl(tcx.types.i32, &[]);
302 push_builtin_impl(tcx.types.f32, &[]);
303 }
304
305 ty::Projection(_projection_ty) => {
306 // FIXME: add builtin impls from the associated type values found in
307 // trait impls of `projection_ty.trait_ref(tcx)`.
308 }
309
310 // The `Copy`/`Clone` bound can only come from the environment.
311 ty::Param(..) |
312 ty::Placeholder(..) |
313 ty::UnnormalizedProjection(..) |
314 ty::Opaque(..) => (),
315
316 // Definitely not `Copy`/`Clone`.
317 ty::Dynamic(..) |
318 ty::Foreign(..) |
319 ty::Generator(..) |
320 ty::Str |
321 ty::Slice(..) |
322 ty::Ref(_, _, hir::Mutability::Mutable) => (),
323
324 ty::Bound(..) |
325 ty::GeneratorWitness(..) |
326 ty::Infer(ty::FreshTy(_)) |
327 ty::Infer(ty::FreshIntTy(_)) |
328 ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty),
329 }
330 }