]> git.proxmox.com Git - rustc.git/blob - vendor/chalk-solve-0.80.0/src/clauses/env_elaborator.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / vendor / chalk-solve-0.80.0 / src / clauses / env_elaborator.rs
1 use super::program_clauses::ToProgramClauses;
2 use crate::clauses::builder::ClauseBuilder;
3 use crate::clauses::{match_alias_ty, match_ty};
4 use crate::DomainGoal;
5 use crate::FromEnv;
6 use crate::ProgramClause;
7 use crate::RustIrDatabase;
8 use crate::Ty;
9 use crate::{debug_span, TyKind};
10 use chalk_ir::interner::Interner;
11 use chalk_ir::visit::{Visit, Visitor};
12 use chalk_ir::{DebruijnIndex, Environment};
13 use rustc_hash::FxHashSet;
14 use std::ops::ControlFlow;
15 use tracing::instrument;
16
17 /// When proving a `FromEnv` goal, we elaborate all `FromEnv` goals
18 /// found in the environment.
19 ///
20 /// For example, when `T: Clone` is in the environment, we can prove
21 /// `T: Copy` by adding the clauses from `trait Clone`, which includes
22 /// the rule `FromEnv(T: Copy) :- FromEnv(T: Clone)
23 pub(super) fn elaborate_env_clauses<I: Interner>(
24 db: &dyn RustIrDatabase<I>,
25 in_clauses: &[ProgramClause<I>],
26 out: &mut FxHashSet<ProgramClause<I>>,
27 environment: &Environment<I>,
28 ) {
29 let mut this_round = vec![];
30 let builder = &mut ClauseBuilder::new(db, &mut this_round);
31 let mut elaborater = EnvElaborator {
32 db,
33 builder,
34 environment,
35 };
36 in_clauses.visit_with(&mut elaborater, DebruijnIndex::INNERMOST);
37 out.extend(this_round);
38 }
39
40 struct EnvElaborator<'me, 'builder, I: Interner> {
41 db: &'me dyn RustIrDatabase<I>,
42 builder: &'builder mut ClauseBuilder<'me, I>,
43 environment: &'me Environment<I>,
44 }
45
46 impl<'me, 'builder, I: Interner> Visitor<I> for EnvElaborator<'me, 'builder, I> {
47 type BreakTy = ();
48
49 fn as_dyn(&mut self) -> &mut dyn Visitor<I, BreakTy = Self::BreakTy> {
50 self
51 }
52
53 fn interner(&self) -> I {
54 self.db.interner()
55 }
56 #[instrument(level = "debug", skip(self, _outer_binder))]
57 fn visit_ty(&mut self, ty: &Ty<I>, _outer_binder: DebruijnIndex) -> ControlFlow<()> {
58 match ty.kind(self.interner()) {
59 TyKind::Alias(alias_ty) => match_alias_ty(self.builder, self.environment, alias_ty),
60 TyKind::Placeholder(_) => {}
61
62 // FIXME(#203) -- We haven't fully figured out the implied
63 // bounds story around `dyn Trait` types.
64 TyKind::Dyn(_) => (),
65
66 TyKind::Function(_) | TyKind::BoundVar(_) | TyKind::InferenceVar(_, _) => (),
67
68 _ => {
69 // This shouldn't fail because of the above clauses
70 match_ty(self.builder, self.environment, ty)
71 .map_err(|_| ())
72 .unwrap()
73 }
74 }
75 ControlFlow::Continue(())
76 }
77
78 fn visit_domain_goal(
79 &mut self,
80 domain_goal: &DomainGoal<I>,
81 outer_binder: DebruijnIndex,
82 ) -> ControlFlow<()> {
83 if let DomainGoal::FromEnv(from_env) = domain_goal {
84 debug_span!("visit_domain_goal", ?from_env);
85 match from_env {
86 FromEnv::Trait(trait_ref) => {
87 let trait_datum = self.db.trait_datum(trait_ref.trait_id);
88
89 trait_datum.to_program_clauses(self.builder, self.environment);
90
91 // If we know that `T: Iterator`, then we also know
92 // things about `<T as Iterator>::Item`, so push those
93 // implied bounds too:
94 for &associated_ty_id in &trait_datum.associated_ty_ids {
95 self.db
96 .associated_ty_data(associated_ty_id)
97 .to_program_clauses(self.builder, self.environment);
98 }
99 ControlFlow::Continue(())
100 }
101 FromEnv::Ty(ty) => ty.visit_with(self, outer_binder),
102 }
103 } else {
104 ControlFlow::Continue(())
105 }
106 }
107 }