Skip to content

Commit 88614f6

Browse files
committed
use Visitor in EnvElaborator and change some callbacks
1 parent 5687f89 commit 88614f6

File tree

5 files changed

+95
-74
lines changed

5 files changed

+95
-74
lines changed

chalk-derive/src/lib.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
extern crate proc_macro;
22

33
use proc_macro::TokenStream;
4+
use proc_macro2::Span;
45
use quote::{format_ident, quote};
56
use syn::{parse_macro_input, Data, DeriveInput, GenericParam, Ident, TypeParamBound};
67

@@ -346,6 +347,20 @@ fn bounded_by_trait<'p>(param: &'p GenericParam, name: &str) -> Option<&'p Ident
346347
/// - There is a single parameter `I: Interner` (does not have to be named `I`)
347348
#[proc_macro_derive(Visit, attributes(has_interner))]
348349
pub fn derive_visit(item: TokenStream) -> TokenStream {
350+
let trait_name = Ident::new("Visit", Span::call_site());
351+
let method_name = Ident::new("visit_with", Span::call_site());
352+
derive_any_visit(item, trait_name, method_name)
353+
}
354+
355+
/// Same as Visit, but derives SuperVisit instead
356+
#[proc_macro_derive(SuperVisit, attributes(has_interner))]
357+
pub fn derive_super_visit(item: TokenStream) -> TokenStream {
358+
let trait_name = Ident::new("SuperVisit", Span::call_site());
359+
let method_name = Ident::new("super_visit_with", Span::call_site());
360+
derive_any_visit(item, trait_name, method_name)
361+
}
362+
363+
fn derive_any_visit(item: TokenStream, trait_name: Ident, method_name: Ident) -> TokenStream {
349364
let input = parse_macro_input!(item as DeriveInput);
350365
let (impl_generics, ty_generics, where_clause_ref) = input.generics.split_for_impl();
351366

@@ -363,8 +378,8 @@ pub fn derive_visit(item: TokenStream) -> TokenStream {
363378
.expect("Expected has_interner argument");
364379

365380
return TokenStream::from(quote! {
366-
impl #impl_generics Visit < #arg > for #type_name #ty_generics #where_clause_ref {
367-
fn visit_with<'i, R: VisitResult>(
381+
impl #impl_generics #trait_name < #arg > for #type_name #ty_generics #where_clause_ref {
382+
fn #method_name <'i, R: VisitResult>(
368383
&self,
369384
visitor: &mut dyn Visitor < 'i, #arg, Result = R >,
370385
outer_binder: DebruijnIndex,
@@ -419,10 +434,10 @@ pub fn derive_visit(item: TokenStream) -> TokenStream {
419434
.push(syn::parse2(quote! { #param: Visit<_I> }).unwrap());
420435

421436
return TokenStream::from(quote! {
422-
impl #impl_generics Visit < _I > for #type_name < #param >
437+
impl #impl_generics #trait_name < _I > for #type_name < #param >
423438
#where_clause
424439
{
425-
fn visit_with<'i, R: VisitResult>(
440+
fn #method_name <'i, R: VisitResult>(
426441
&self,
427442
visitor: &mut dyn Visitor < 'i, _I, Result = R >,
428443
outer_binder: DebruijnIndex,
@@ -450,10 +465,10 @@ pub fn derive_visit(item: TokenStream) -> TokenStream {
450465
let impl_generics = &input.generics;
451466

452467
return TokenStream::from(quote! {
453-
impl #impl_generics Visit < #i > for #type_name < #i >
468+
impl #impl_generics #trait_name < #i > for #type_name < #i >
454469
#where_clause_ref
455470
{
456-
fn visit_with<'i, R: VisitResult>(
471+
fn #method_name <'i, R: VisitResult>(
457472
&self,
458473
visitor: &mut dyn Visitor < 'i, #i, Result = R >,
459474
outer_binder: DebruijnIndex,
@@ -467,7 +482,10 @@ pub fn derive_visit(item: TokenStream) -> TokenStream {
467482
});
468483
}
469484

470-
panic!("derive(Visit) requires a parameter that implements HasInterner or Interner");
485+
panic!(
486+
"derive({}) requires a parameter that implements HasInterner or Interner",
487+
trait_name
488+
);
471489
}
472490

473491
/// Generates the body of the Visit impl

chalk-ir/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::cast::{Cast, CastTo};
44
use crate::fold::shift::Shift;
55
use crate::fold::{Fold, Folder, Subst, SuperFold};
66
use crate::visit::{SuperVisit, Visit, VisitExt, VisitResult, Visitor};
7-
use chalk_derive::{Fold, HasInterner, Visit};
7+
use chalk_derive::{Fold, HasInterner, SuperVisit, Visit};
88
use chalk_engine::fallible::*;
99
use std::iter;
1010
use std::marker::PhantomData;
@@ -864,7 +864,7 @@ impl<I: Interner> TraitRef<I> {
864864
}
865865

866866
/// Where clauses that can be written by a Rust programmer.
867-
#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner)]
867+
#[derive(Clone, PartialEq, Eq, Hash, Fold, SuperVisit, HasInterner)]
868868
pub enum WhereClause<I: Interner> {
869869
Implemented(TraitRef<I>),
870870
AliasEq(AliasEq<I>),
@@ -932,7 +932,7 @@ pub enum FromEnv<I: Interner> {
932932
/// A "domain goal" is a goal that is directly about Rust, rather than a pure
933933
/// logical statement. As much as possible, the Chalk solver should avoid
934934
/// decomposing this enum, and instead treat its values opaquely.
935-
#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner)]
935+
#[derive(Clone, PartialEq, Eq, Hash, Fold, SuperVisit, HasInterner)]
936936
pub enum DomainGoal<I: Interner> {
937937
Holds(WhereClause<I>),
938938

@@ -1122,7 +1122,7 @@ pub struct Normalize<I: Interner> {
11221122
/// Proves **equality** between a projection `T::Foo` and a type
11231123
/// `U`. Equality can be proven via normalization, but we can also
11241124
/// prove that `T::Foo = V::Foo` if `T = V` without normalizing.
1125-
#[derive(Clone, PartialEq, Eq, Hash, Fold)]
1125+
#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit)]
11261126
pub struct AliasEq<I: Interner> {
11271127
pub alias: AliasTy<I>,
11281128
pub ty: Ty<I>,

chalk-ir/src/visit.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
use std::fmt::Debug;
33

44
use crate::{
5-
AliasEq, BoundVar, DebruijnIndex, Goal, InferenceVar, Interner, Lifetime, LifetimeData,
6-
PlaceholderIndex, ProgramClause, Ty, TyData,
5+
BoundVar, DebruijnIndex, DomainGoal, Goal, InferenceVar, Interner, Lifetime, LifetimeData,
6+
PlaceholderIndex, ProgramClause, Ty, TyData, WhereClause,
77
};
88

99
mod binder_impls;
@@ -83,6 +83,14 @@ where
8383
goal.super_visit_with(self.as_dyn(), outer_binder)
8484
}
8585

86+
fn visit_domain_goal(
87+
&mut self,
88+
domain_goal: &DomainGoal<I>,
89+
outer_binder: DebruijnIndex,
90+
) -> Self::Result {
91+
domain_goal.super_visit_with(self.as_dyn(), outer_binder)
92+
}
93+
8694
/// If overridden to return true, then visiting will panic if a
8795
/// free variable is encountered. This should be done if free
8896
/// type/lifetime variables are not expected.
@@ -159,12 +167,12 @@ where
159167
}
160168
}
161169

162-
fn visit_alias_eq(
170+
fn visit_where_clause(
163171
&mut self,
164-
alias_eq: &AliasEq<I>,
172+
where_clause: &WhereClause<I>,
165173
outer_binder: DebruijnIndex,
166174
) -> Self::Result {
167-
alias_eq.super_visit_with(self.as_dyn(), outer_binder)
175+
where_clause.super_visit_with(self.as_dyn(), outer_binder)
168176
}
169177

170178
/// As with `visit_free_placeholder_ty`, but for lifetimes.
@@ -375,7 +383,7 @@ impl<I: Interner> Visit<I> for ProgramClause<I> {
375383
}
376384
}
377385

378-
impl<I: Interner> Visit<I> for AliasEq<I> {
386+
impl<I: Interner> Visit<I> for WhereClause<I> {
379387
fn visit_with<'i, R: VisitResult>(
380388
&self,
381389
visitor: &mut dyn Visitor<'i, I, Result = R>,
@@ -384,21 +392,19 @@ impl<I: Interner> Visit<I> for AliasEq<I> {
384392
where
385393
I: 'i,
386394
{
387-
visitor.visit_alias_eq(self, outer_binder)
395+
visitor.visit_where_clause(self, outer_binder)
388396
}
389397
}
390398

391-
impl<I: Interner> SuperVisit<I> for AliasEq<I> {
392-
fn super_visit_with<'i, R: VisitResult>(
399+
impl<I: Interner> Visit<I> for DomainGoal<I> {
400+
fn visit_with<'i, R: VisitResult>(
393401
&self,
394402
visitor: &mut dyn Visitor<'i, I, Result = R>,
395403
outer_binder: DebruijnIndex,
396404
) -> R
397405
where
398406
I: 'i,
399407
{
400-
R::new()
401-
.and_then(|| self.alias.visit_with(visitor, outer_binder))
402-
.and_then(|| self.ty.visit_with(visitor, outer_binder))
408+
visitor.visit_domain_goal(self, outer_binder)
403409
}
404410
}

chalk-solve/src/clauses/env_elaborator.rs

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use crate::RustIrDatabase;
99
use crate::Ty;
1010
use crate::TyData;
1111
use chalk_ir::interner::Interner;
12-
use chalk_ir::AliasTy;
12+
use chalk_ir::visit::{Visit, Visitor};
13+
use chalk_ir::DebruijnIndex;
1314
use rustc_hash::FxHashSet;
1415

1516
/// When proving a `FromEnv` goal, we elaborate all `FromEnv` goals
@@ -24,10 +25,10 @@ pub(super) fn elaborate_env_clauses<I: Interner>(
2425
out: &mut FxHashSet<ProgramClause<I>>,
2526
) {
2627
let mut this_round = vec![];
27-
let mut visitor = EnvElaborator::new(db, &mut this_round);
28-
for clause in in_clauses {
29-
visitor.visit_program_clause(&clause);
30-
}
28+
in_clauses.visit_with(
29+
&mut EnvElaborator::new(db, &mut this_round),
30+
DebruijnIndex::INNERMOST,
31+
);
3132
out.extend(this_round);
3233
}
3334

@@ -43,15 +44,20 @@ impl<'me, I: Interner> EnvElaborator<'me, I> {
4344
builder: ClauseBuilder::new(db, out),
4445
}
4546
}
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+
}
4655

47-
fn visit_alias_ty(&mut self, alias_ty: &AliasTy<I>) {
48-
debug!("EnvElaborator::visit_alias_ty(alias_ty={:?})", alias_ty);
49-
self.db
50-
.associated_ty_data(alias_ty.associated_ty_id)
51-
.to_program_clauses(&mut self.builder);
56+
fn interner(&self) -> &'me I {
57+
self.db.interner()
5258
}
5359

54-
fn visit_ty(&mut self, ty: &Ty<I>) {
60+
fn visit_ty(&mut self, ty: &Ty<I>, _outer_binder: DebruijnIndex) {
5561
debug!("EnvElaborator::visit_ty(ty={:?})", ty);
5662
let interner = self.db.interner();
5763
match ty.data(interner) {
@@ -61,7 +67,9 @@ impl<'me, I: Interner> EnvElaborator<'me, I> {
6167
TyData::Placeholder(_) => {}
6268

6369
TyData::Alias(alias_ty) => {
64-
self.visit_alias_ty(alias_ty);
70+
self.db
71+
.associated_ty_data(alias_ty.associated_ty_id)
72+
.to_program_clauses(&mut self.builder);
6573
}
6674

6775
// FIXME(#203) -- We haven't fully figured out the implied
@@ -72,44 +80,26 @@ impl<'me, I: Interner> EnvElaborator<'me, I> {
7280
}
7381
}
7482

75-
fn visit_from_env(&mut self, from_env: &FromEnv<I>) {
76-
debug!("EnvElaborator::visit_from_env(from_env={:?})", from_env);
77-
match from_env {
78-
FromEnv::Trait(trait_ref) => {
79-
let trait_datum = self.db.trait_datum(trait_ref.trait_id);
83+
fn visit_domain_goal(&mut self, domain_goal: &DomainGoal<I>, outer_binder: DebruijnIndex) {
84+
if let DomainGoal::FromEnv(from_env) = domain_goal {
85+
debug!("EnvElaborator::visit_domain_goal(from_env={:?})", from_env);
86+
match from_env {
87+
FromEnv::Trait(trait_ref) => {
88+
let trait_datum = self.db.trait_datum(trait_ref.trait_id);
8089

81-
trait_datum.to_program_clauses(&mut self.builder);
90+
trait_datum.to_program_clauses(&mut self.builder);
8291

83-
// If we know that `T: Iterator`, then we also know
84-
// things about `<T as Iterator>::Item`, so push those
85-
// implied bounds too:
86-
for &associated_ty_id in &trait_datum.associated_ty_ids {
87-
self.db
88-
.associated_ty_data(associated_ty_id)
89-
.to_program_clauses(&mut self.builder);
92+
// If we know that `T: Iterator`, then we also know
93+
// things about `<T as Iterator>::Item`, so push those
94+
// implied bounds too:
95+
for &associated_ty_id in &trait_datum.associated_ty_ids {
96+
self.db
97+
.associated_ty_data(associated_ty_id)
98+
.to_program_clauses(&mut self.builder);
99+
}
90100
}
101+
FromEnv::Ty(ty) => ty.visit_with(self, outer_binder),
91102
}
92-
FromEnv::Ty(ty) => self.visit_ty(ty),
93-
}
94-
}
95-
96-
fn visit_domain_goal(&mut self, domain_goal: &DomainGoal<I>) {
97-
debug!(
98-
"EnvElaborator::visit_domain_goal(domain_goal={:?})",
99-
domain_goal
100-
);
101-
match domain_goal {
102-
DomainGoal::FromEnv(from_env) => self.visit_from_env(from_env),
103-
_ => {}
104-
}
105-
}
106-
107-
fn visit_program_clause(&mut self, clause: &ProgramClause<I>) {
108-
debug!("visit_program_clause(clause={:?})", clause);
109-
let interner = self.db.interner();
110-
match clause.data(interner) {
111-
ProgramClauseData::Implies(clause) => self.visit_domain_goal(&clause.consequence),
112-
ProgramClauseData::ForAll(clause) => self.visit_domain_goal(&clause.value.consequence),
113103
}
114104
}
115105
}

chalk-solve/src/wf.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,18 @@ impl<'i, 't, I: Interner> Visitor<'i, I> for InputTypeCollector<'i, I> {
6767
self.interner
6868
}
6969

70-
fn visit_alias_eq(&mut self, alias_eq: &AliasEq<I>, outer_binder: DebruijnIndex) {
71-
TyData::Alias(alias_eq.alias.clone())
72-
.intern(self.interner)
73-
.visit_with(self, outer_binder);
74-
alias_eq.ty.visit_with(self, outer_binder);
70+
fn visit_where_clause(&mut self, where_clause: &WhereClause<I>, outer_binder: DebruijnIndex) {
71+
match where_clause {
72+
WhereClause::AliasEq(alias_eq) => {
73+
TyData::Alias(alias_eq.alias.clone())
74+
.intern(self.interner)
75+
.visit_with(self, outer_binder);
76+
alias_eq.ty.visit_with(self, outer_binder);
77+
}
78+
WhereClause::Implemented(trait_ref) => {
79+
trait_ref.visit_with(self, outer_binder);
80+
}
81+
}
7582
}
7683

7784
fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) {

0 commit comments

Comments
 (0)