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