]> git.proxmox.com Git - rustc.git/blob - src/librustc_traits/chalk_context/program_clauses.rs
New upstream version 1.33.0+dfsg1
[rustc.git] / src / librustc_traits / chalk_context / program_clauses.rs
1 use rustc::traits::{
2 WellFormed,
3 FromEnv,
4 DomainGoal,
5 GoalKind,
6 Clause,
7 Clauses,
8 ProgramClause,
9 ProgramClauseCategory,
10 Environment,
11 };
12 use rustc::ty;
13 use rustc::ty::subst::{Substs, Subst};
14 use rustc::hir;
15 use rustc::hir::def_id::DefId;
16 use rustc_target::spec::abi;
17 use super::ChalkInferenceContext;
18 use crate::lowering::Lower;
19 use crate::generic_types;
20 use std::iter;
21
22 fn assemble_clauses_from_impls<'tcx>(
23 tcx: ty::TyCtxt<'_, '_, 'tcx>,
24 trait_def_id: DefId,
25 clauses: &mut Vec<Clause<'tcx>>
26 ) {
27 tcx.for_each_impl(trait_def_id, |impl_def_id| {
28 clauses.extend(
29 tcx.program_clauses_for(impl_def_id)
30 .into_iter()
31 .cloned()
32 );
33 });
34 }
35
36 fn assemble_clauses_from_assoc_ty_values<'tcx>(
37 tcx: ty::TyCtxt<'_, '_, 'tcx>,
38 trait_def_id: DefId,
39 clauses: &mut Vec<Clause<'tcx>>
40 ) {
41 tcx.for_each_impl(trait_def_id, |impl_def_id| {
42 for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
43 clauses.extend(
44 tcx.program_clauses_for(*def_id)
45 .into_iter()
46 .cloned()
47 );
48 }
49 });
50 }
51
52 fn assemble_builtin_sized_impls<'tcx>(
53 tcx: ty::TyCtxt<'_, '_, 'tcx>,
54 sized_def_id: DefId,
55 ty: ty::Ty<'tcx>,
56 clauses: &mut Vec<Clause<'tcx>>
57 ) {
58 let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
59 let clause = ProgramClause {
60 goal: ty::TraitPredicate {
61 trait_ref: ty::TraitRef {
62 def_id: sized_def_id,
63 substs: tcx.mk_substs_trait(ty, &[]),
64 },
65 }.lower(),
66 hypotheses: tcx.mk_goals(
67 nested.iter()
68 .cloned()
69 .map(|nested_ty| ty::TraitRef {
70 def_id: sized_def_id,
71 substs: tcx.mk_substs_trait(nested_ty, &[]),
72 })
73 .map(|trait_ref| ty::TraitPredicate { trait_ref })
74 .map(|pred| GoalKind::DomainGoal(pred.lower()))
75 .map(|goal_kind| tcx.mk_goal(goal_kind))
76 ),
77 category: ProgramClauseCategory::Other,
78 };
79 // Bind innermost bound vars that may exist in `ty` and `nested`.
80 clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
81 };
82
83 match &ty.sty {
84 // Non parametric primitive types.
85 ty::Bool |
86 ty::Char |
87 ty::Int(..) |
88 ty::Uint(..) |
89 ty::Float(..) |
90 ty::Error |
91 ty::Never => push_builtin_impl(ty, &[]),
92
93 // These ones are always `Sized`.
94 &ty::Array(_, length) => {
95 push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
96 }
97 ty::RawPtr(ptr) => {
98 push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
99 }
100 &ty::Ref(_, _, mutbl) => {
101 push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
102 }
103 ty::FnPtr(fn_ptr) => {
104 let fn_ptr = fn_ptr.skip_binder();
105 let fn_ptr = generic_types::fn_ptr(
106 tcx,
107 fn_ptr.inputs_and_output.len(),
108 fn_ptr.variadic,
109 fn_ptr.unsafety,
110 fn_ptr.abi
111 );
112 push_builtin_impl(fn_ptr, &[]);
113 }
114 &ty::FnDef(def_id, ..) => {
115 push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
116 }
117 &ty::Closure(def_id, ..) => {
118 push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
119 }
120 &ty::Generator(def_id, ..) => {
121 push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
122 }
123
124 // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
125 &ty::Tuple(type_list) => {
126 let type_list = generic_types::type_list(tcx, type_list.len());
127 push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
128 }
129
130 // Struct def
131 ty::Adt(adt_def, _) => {
132 let substs = Substs::bound_vars_for_item(tcx, adt_def.did);
133 let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
134 let sized_constraint = adt_def.sized_constraint(tcx)
135 .iter()
136 .map(|ty| ty.subst(tcx, substs))
137 .collect::<Vec<_>>();
138 push_builtin_impl(adt, &sized_constraint);
139 }
140
141 // Artificially trigger an ambiguity.
142 ty::Infer(..) => {
143 // Everybody can find at least two types to unify against:
144 // general ty vars, int vars and float vars.
145 push_builtin_impl(tcx.types.i32, &[]);
146 push_builtin_impl(tcx.types.u32, &[]);
147 push_builtin_impl(tcx.types.f32, &[]);
148 push_builtin_impl(tcx.types.f64, &[]);
149 }
150
151 ty::Projection(_projection_ty) => {
152 // FIXME: add builtin impls from the associated type values found in
153 // trait impls of `projection_ty.trait_ref(tcx)`.
154 }
155
156 // The `Sized` bound can only come from the environment.
157 ty::Param(..) |
158 ty::Placeholder(..) |
159 ty::UnnormalizedProjection(..) => (),
160
161 // Definitely not `Sized`.
162 ty::Foreign(..) |
163 ty::Str |
164 ty::Slice(..) |
165 ty::Dynamic(..) |
166 ty::Opaque(..) => (),
167
168 ty::Bound(..) |
169 ty::GeneratorWitness(..) => bug!("unexpected type {:?}", ty),
170 }
171 }
172
173 fn wf_clause_for_raw_ptr<'tcx>(
174 tcx: ty::TyCtxt<'_, '_, 'tcx>,
175 mutbl: hir::Mutability
176 ) -> Clauses<'tcx> {
177 let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
178
179 let wf_clause = ProgramClause {
180 goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
181 hypotheses: ty::List::empty(),
182 category: ProgramClauseCategory::WellFormed,
183 };
184 let wf_clause = Clause::Implies(wf_clause);
185
186 // `forall<T> { WellFormed(*const T). }`
187 tcx.mk_clauses(iter::once(wf_clause))
188 }
189
190 fn wf_clause_for_fn_ptr<'tcx>(
191 tcx: ty::TyCtxt<'_, '_, 'tcx>,
192 arity_and_output: usize,
193 variadic: bool,
194 unsafety: hir::Unsafety,
195 abi: abi::Abi
196 ) -> Clauses<'tcx> {
197 let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
198
199 let wf_clause = ProgramClause {
200 goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
201 hypotheses: ty::List::empty(),
202 category: ProgramClauseCategory::WellFormed,
203 };
204 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
205
206 // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
207 // where `n + 1` == `arity_and_output`
208 tcx.mk_clauses(iter::once(wf_clause))
209 }
210
211 fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
212 let ty = generic_types::bound(tcx, 0);
213 let slice_ty = tcx.mk_slice(ty);
214
215 let sized_trait = match tcx.lang_items().sized_trait() {
216 Some(def_id) => def_id,
217 None => return ty::List::empty(),
218 };
219 let sized_implemented = ty::TraitRef {
220 def_id: sized_trait,
221 substs: tcx.mk_substs_trait(ty, ty::List::empty()),
222 };
223 let sized_implemented: DomainGoal = ty::TraitPredicate {
224 trait_ref: sized_implemented
225 }.lower();
226
227 let wf_clause = ProgramClause {
228 goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
229 hypotheses: tcx.mk_goals(
230 iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
231 ),
232 category: ProgramClauseCategory::WellFormed,
233 };
234 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
235
236 // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
237 tcx.mk_clauses(iter::once(wf_clause))
238 }
239
240 fn wf_clause_for_array<'tcx>(
241 tcx: ty::TyCtxt<'_, '_, 'tcx>,
242 length: &'tcx ty::LazyConst<'tcx>
243 ) -> Clauses<'tcx> {
244 let ty = generic_types::bound(tcx, 0);
245 let array_ty = tcx.mk_ty(ty::Array(ty, length));
246
247 let sized_trait = match tcx.lang_items().sized_trait() {
248 Some(def_id) => def_id,
249 None => return ty::List::empty(),
250 };
251 let sized_implemented = ty::TraitRef {
252 def_id: sized_trait,
253 substs: tcx.mk_substs_trait(ty, ty::List::empty()),
254 };
255 let sized_implemented: DomainGoal = ty::TraitPredicate {
256 trait_ref: sized_implemented
257 }.lower();
258
259 let wf_clause = ProgramClause {
260 goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
261 hypotheses: tcx.mk_goals(
262 iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
263 ),
264 category: ProgramClauseCategory::WellFormed,
265 };
266 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
267
268 // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
269 tcx.mk_clauses(iter::once(wf_clause))
270 }
271
272 fn wf_clause_for_tuple<'tcx>(
273 tcx: ty::TyCtxt<'_, '_, 'tcx>,
274 arity: usize
275 ) -> Clauses<'tcx> {
276 let type_list = generic_types::type_list(tcx, arity);
277 let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
278
279 let sized_trait = match tcx.lang_items().sized_trait() {
280 Some(def_id) => def_id,
281 None => return ty::List::empty(),
282 };
283
284 // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of
285 // hypotheses is actually empty.
286 let sized_implemented = type_list[0 .. std::cmp::max(arity, 1) - 1].iter()
287 .map(|ty| ty::TraitRef {
288 def_id: sized_trait,
289 substs: tcx.mk_substs_trait(*ty, ty::List::empty()),
290 })
291 .map(|trait_ref| ty::TraitPredicate { trait_ref })
292 .map(|predicate| predicate.lower());
293
294 let wf_clause = ProgramClause {
295 goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
296 hypotheses: tcx.mk_goals(
297 sized_implemented.map(|domain_goal| {
298 tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
299 })
300 ),
301 category: ProgramClauseCategory::WellFormed,
302 };
303 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
304
305 // ```
306 // forall<T1, ..., Tn-1, Tn> {
307 // WellFormed((T1, ..., Tn)) :-
308 // Implemented(T1: Sized),
309 // ...
310 // Implemented(Tn-1: Sized).
311 // }
312 // ```
313 tcx.mk_clauses(iter::once(wf_clause))
314 }
315
316 fn wf_clause_for_ref<'tcx>(
317 tcx: ty::TyCtxt<'_, '_, 'tcx>,
318 mutbl: hir::Mutability
319 ) -> Clauses<'tcx> {
320 let region = tcx.mk_region(
321 ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
322 );
323 let ty = generic_types::bound(tcx, 1);
324 let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
325 ty,
326 mutbl,
327 });
328
329 let _outlives: DomainGoal = ty::OutlivesPredicate(ty, region).lower();
330 let wf_clause = ProgramClause {
331 goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
332 hypotheses: ty::List::empty(),
333
334 // FIXME: restore this later once we get better at handling regions
335 // hypotheses: tcx.mk_goals(
336 // iter::once(tcx.mk_goal(outlives.into_goal()))
337 // ),
338 category: ProgramClauseCategory::WellFormed,
339 };
340 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
341
342 // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
343 tcx.mk_clauses(iter::once(wf_clause))
344 }
345
346 fn wf_clause_for_fn_def<'tcx>(
347 tcx: ty::TyCtxt<'_, '_, 'tcx>,
348 def_id: DefId
349 ) -> Clauses<'tcx> {
350 let fn_def = generic_types::fn_def(tcx, def_id);
351
352 let wf_clause = ProgramClause {
353 goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)),
354 hypotheses: ty::List::empty(),
355 category: ProgramClauseCategory::WellFormed,
356 };
357 let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
358
359 // `forall <T1, ..., Tn+1> { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }`
360 // where `def_id` maps to the `some_fn` function definition
361 tcx.mk_clauses(iter::once(wf_clause))
362 }
363
364 impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
365 pub(super) fn program_clauses_impl(
366 &self,
367 environment: &Environment<'tcx>,
368 goal: &DomainGoal<'tcx>,
369 ) -> Vec<Clause<'tcx>> {
370 use rustc::traits::WhereClause::*;
371 use rustc::infer::canonical::OriginalQueryValues;
372
373 let goal = self.infcx.resolve_type_vars_if_possible(goal);
374
375 debug!("program_clauses(goal = {:?})", goal);
376
377 let mut clauses = match goal {
378 DomainGoal::Holds(Implemented(trait_predicate)) => {
379 // These come from:
380 // * implementations of the trait itself (rule `Implemented-From-Impl`)
381 // * the trait decl (rule `Implemented-From-Env`)
382
383 let mut clauses = vec![];
384
385 assemble_clauses_from_impls(
386 self.infcx.tcx,
387 trait_predicate.def_id(),
388 &mut clauses
389 );
390
391 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
392 assemble_builtin_sized_impls(
393 self.infcx.tcx,
394 trait_predicate.def_id(),
395 trait_predicate.self_ty(),
396 &mut clauses
397 );
398 }
399
400 // FIXME: we need to add special rules for builtin impls:
401 // * `Copy` / `Clone`
402 // * `Sized`
403 // * `Unsize`
404 // * `Generator`
405 // * `FnOnce` / `FnMut` / `Fn`
406 // * trait objects
407 // * auto traits
408
409 // Rule `Implemented-From-Env` will be computed from the environment.
410 clauses
411 }
412
413 DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
414 // These come from:
415 // * the assoc type definition (rule `ProjectionEq-Placeholder`)
416 // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
417 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
418 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
419
420 let clauses = self.infcx.tcx.program_clauses_for(
421 projection_predicate.projection_ty.item_def_id
422 ).into_iter()
423
424 // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
425 .filter(|clause| clause.category() == ProgramClauseCategory::Other)
426
427 .cloned()
428 .collect::<Vec<_>>();
429
430 // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
431 // from the environment.
432 clauses
433 }
434
435 DomainGoal::Holds(RegionOutlives(..)) => {
436 // These come from:
437 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
438 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
439
440 // All of these rules are computed in the environment.
441 vec![]
442 }
443
444 DomainGoal::Holds(TypeOutlives(..)) => {
445 // These come from:
446 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
447 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
448
449 // All of these rules are computed in the environment.
450 vec![]
451 }
452
453 DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
454 // These come from -- the trait decl (rule `WellFormed-TraitRef`).
455 self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
456 .into_iter()
457
458 // only select `WellFormed-TraitRef`
459 .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
460
461 .cloned()
462 .collect()
463 }
464
465 DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
466 // These come from:
467 // * the associated type definition if `ty` refers to an unnormalized
468 // associated type (rule `WellFormed-AssocTy`)
469 // * custom rules for built-in types
470 // * the type definition otherwise (rule `WellFormed-Type`)
471 let clauses = match ty.sty {
472 ty::Projection(data) => {
473 self.infcx.tcx.program_clauses_for(data.item_def_id)
474 }
475
476 // These types are always WF.
477 ty::Bool |
478 ty::Char |
479 ty::Int(..) |
480 ty::Uint(..) |
481 ty::Float(..) |
482 ty::Str |
483 ty::Param(..) |
484 ty::Placeholder(..) |
485 ty::Error |
486 ty::Never => {
487 let wf_clause = ProgramClause {
488 goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
489 hypotheses: ty::List::empty(),
490 category: ProgramClauseCategory::WellFormed,
491 };
492 let wf_clause = Clause::Implies(wf_clause);
493
494 self.infcx.tcx.mk_clauses(iter::once(wf_clause))
495 }
496
497 // Always WF (recall that we do not check for parameters to be WF).
498 ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
499
500 // Always WF (recall that we do not check for parameters to be WF).
501 ty::FnPtr(fn_ptr) => {
502 let fn_ptr = fn_ptr.skip_binder();
503 wf_clause_for_fn_ptr(
504 self.infcx.tcx,
505 fn_ptr.inputs_and_output.len(),
506 fn_ptr.variadic,
507 fn_ptr.unsafety,
508 fn_ptr.abi
509 )
510 }
511
512 // WF if inner type is `Sized`.
513 ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx),
514
515 // WF if inner type is `Sized`.
516 ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length),
517
518 // WF if all types but the last one are `Sized`.
519 ty::Tuple(types) => wf_clause_for_tuple(
520 self.infcx.tcx,
521 types.len()
522 ),
523
524 // WF if `sub_ty` outlives `region`.
525 ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl),
526
527 ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id),
528
529 ty::Dynamic(..) => {
530 // FIXME: no rules yet for trait objects
531 ty::List::empty()
532 }
533
534 ty::Adt(def, ..) => {
535 self.infcx.tcx.program_clauses_for(def.did)
536 }
537
538 // FIXME: these are probably wrong
539 ty::Foreign(def_id) |
540 ty::Closure(def_id, ..) |
541 ty::Generator(def_id, ..) |
542 ty::Opaque(def_id, ..) => {
543 self.infcx.tcx.program_clauses_for(def_id)
544 }
545
546 // Artificially trigger an ambiguity.
547 ty::Infer(..) => {
548 let tcx = self.infcx.tcx;
549 let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64];
550 let clauses = types.iter()
551 .cloned()
552 .map(|ty| ProgramClause {
553 goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
554 hypotheses: ty::List::empty(),
555 category: ProgramClauseCategory::WellFormed,
556 })
557 .map(|clause| Clause::Implies(clause));
558 tcx.mk_clauses(clauses)
559 }
560
561 ty::GeneratorWitness(..) |
562 ty::UnnormalizedProjection(..) |
563 ty::Bound(..) => {
564 bug!("unexpected type {:?}", ty)
565 }
566 };
567
568 clauses.into_iter()
569 .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
570 .cloned()
571 .collect()
572 }
573
574 DomainGoal::FromEnv(FromEnv::Trait(..)) => {
575 // These come from:
576 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
577 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
578 // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
579 // `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
580
581 // All of these rules are computed in the environment.
582 vec![]
583 }
584
585 DomainGoal::FromEnv(FromEnv::Ty(..)) => {
586 // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
587 // comes from the environment).
588 vec![]
589 }
590
591 DomainGoal::Normalize(projection_predicate) => {
592 // These come from -- assoc ty values (rule `Normalize-From-Impl`).
593 let mut clauses = vec![];
594
595 assemble_clauses_from_assoc_ty_values(
596 self.infcx.tcx,
597 projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
598 &mut clauses
599 );
600
601 clauses
602 }
603 };
604
605 debug!("program_clauses: clauses = {:?}", clauses);
606 debug!("program_clauses: adding clauses from environment = {:?}", environment);
607
608 let mut _orig_query_values = OriginalQueryValues::default();
609 let canonical_environment = self.infcx.canonicalize_query(
610 environment,
611 &mut _orig_query_values
612 ).value;
613 let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment);
614
615 debug!("program_clauses: env_clauses = {:?}", env_clauses);
616
617 clauses.extend(env_clauses.into_iter().cloned());
618 clauses.extend(environment.clauses.iter().cloned());
619 clauses
620 }
621 }