1 use super::program_clauses
::ToProgramClauses
;
2 use crate::clauses
::builder
::ClauseBuilder
;
3 use crate::clauses
::{match_alias_ty, match_type_name}
;
6 use crate::ProgramClause
;
7 use crate::RustIrDatabase
;
10 use chalk_ir
::interner
::Interner
;
11 use chalk_ir
::visit
::{Visit, Visitor}
;
12 use chalk_ir
::DebruijnIndex
;
13 use rustc_hash
::FxHashSet
;
16 /// When proving a `FromEnv` goal, we elaborate all `FromEnv` goals
17 /// found in the environment.
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
>>,
27 let mut this_round
= vec
![];
28 in_clauses
.visit_with(
29 &mut EnvElaborator
::new(db
, &mut this_round
),
30 DebruijnIndex
::INNERMOST
,
32 out
.extend(this_round
);
35 struct EnvElaborator
<'me
, I
: Interner
> {
36 db
: &'me
dyn RustIrDatabase
<I
>,
37 builder
: ClauseBuilder
<'me
, I
>,
40 impl<'me
, I
: Interner
> EnvElaborator
<'me
, I
> {
41 fn new(db
: &'me
dyn RustIrDatabase
<I
>, out
: &'me
mut Vec
<ProgramClause
<I
>>) -> Self {
44 builder
: ClauseBuilder
::new(db
, out
),
49 impl<'me
, I
: Interner
> Visitor
<'me
, I
> for EnvElaborator
<'me
, I
> {
52 fn as_dyn(&mut self) -> &mut dyn Visitor
<'me
, I
, Result
= Self::Result
> {
56 fn interner(&self) -> &'me I
{
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
)
67 TyData
::Alias(alias_ty
) => match_alias_ty(&mut self.builder
, alias_ty
),
68 TyData
::Placeholder(_
) => {}
70 // FIXME(#203) -- We haven't fully figured out the implied
71 // bounds story around `dyn Trait` types.
74 TyData
::Function(_
) | TyData
::BoundVar(_
) | TyData
::InferenceVar(_
, _
) => (),
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
);
82 FromEnv
::Trait(trait_ref
) => {
83 let trait_datum
= self.db
.trait_datum(trait_ref
.trait_id
);
85 trait_datum
.to_program_clauses(&mut self.builder
);
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
{
92 .associated_ty_data(associated_ty_id
)
93 .to_program_clauses(&mut self.builder
);
96 FromEnv
::Ty(ty
) => ty
.visit_with(self, outer_binder
),