Skip to content

Semantic equality to syntactic equality #401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

basil-cow
Copy link
Contributor

No description provided.

@basil-cow basil-cow force-pushed the sem_eq branch 2 times, most recently from 8d371a2 to 011cbd3 Compare April 17, 2020 13:32
@basil-cow basil-cow force-pushed the sem_eq branch 2 times, most recently from eea51d7 to ccce5d0 Compare May 3, 2020 19:20
Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some old comments, perhaps no longer relevant

.intern(interner)
};

self.clauses.push(syn_eq_lower(interner, &clause));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I was considering in doing this was making ClauseBuilder generic over two Interner values, one of which represented "Semantically equal" predicates and one of which represented "syntactically equal". This helps ensure we are not failing to do the conversion. I'm not sure how much value it really adds, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought about making syn_eq_lower to return a SynLowered<Fold::Result>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I follow -- what is SynLowered, just a newtype?

@@ -735,6 +735,7 @@ impl<I: Interner> ToProgramClauses<I> for AssociatedTyDatum<I> {

// add new type parameter U
builder.push_bound_ty(|builder, ty| {
let alias = AliasTy::Projection(projection.clone());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a random refactoring?

@basil-cow
Copy link
Contributor Author

Woah you can push to my branch

@bjorn3
Copy link
Member

bjorn3 commented May 5, 2020

@Areredify There is a checkbox "Allow edits and access to secrets by maintainers" both when opening a PR and when you opened it at the bottom of the sidebar. It is checked by default.

clause: &ProgramClause<I>,
outer_binder: DebruijnIndex,
) -> Fallible<ProgramClause<I>> {
let interner = self.interner;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should either

  • save the old values of new_params/new_goals, and restore before we return
  • or assert that they are empty (if that is known to be true)

I don't see why they would be known to be empty, though, so I think we should save the values of the vector. The alternative would be to rewrite the code to not touch pre-existing things and just save the lengths.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably we need to save binders_len too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We know them to be empty because only domain goals and program clauses contain types (and EqGoal, but it is unique), and when folding domain goals we are guaranteed to not encounter another goal or clause. If we restrict input types of syn_lower to only be ProgramClause and Goal, then the lowering should be correct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, then add assertions -- I guess it's true that we only have to worry about domain goal, and it cannot contain clauses. Right. I was thinking about how goals can contain clauses in general (and vice versa, of course).

let ((binders, implication), in_binders) = match clause.data(interner) {
ProgramClauseData::ForAll(for_all) => (for_all.clone().into(), true),
// introduce a dummy binder and shift implication through it
ProgramClauseData::Implies(implication) => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I keep meaning to factor away ProgramClauseData::Implies, and just always have a binder.

};
let mut binders: Vec<_> = binders.as_slice(interner).clone().into();

let outer_binder = outer_binder.shifted_in();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment:

// Adjust the outer binder to account for the binder in the program clause


let outer_binder = outer_binder.shifted_in();

self.binders_len = binders.len();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment here, referencing the function comment:

// First lower the "consequence" -- in our example that is 
//
// ```
// Implemented(<X as Iterator>::Item: Debug)
// ```
//
// then save out the `new_params` and `new_goals` vectors to store any new variables created as a result. In this case, that would be the `Y` parameter and `AliasEq(<X as Iterator>::Item, Y)` goals. 
//
// Note that these new parameters will have indices that come after the existing parameters, so any references to existing parameters like `X` in the "conditions" are still valid even if we insert new parameters.

self.binders_len = binders.len();
let consequence = implication.consequence.fold_with(self, outer_binder)?;
// Immediately move `new_params` out of of the folder struct so it's safe
// to call `.fold_with` again
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(then I think you can remove this comment, it's explained more usefully above)


let outer_binder = outer_binder.shifted_in();

self.binders_len = binders.len();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment:

Set binders_len to binders.len since new parameters will be added into the existing forall<...> binder on the program clause.


struct SynEqFolder<'i, I: Interner> {
interner: &'i I,
new_params: Vec<ParameterKind<()>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments on these fields -- what do they store?

My suggestions:

Store the kinds of any new parameters that are introduced during folding. These parameters will either be added to an enclosing exists binder (when lowering a goal) or an enclosing forall binder (when lowering a program clause).

struct SynEqFolder<'i, I: Interner> {
interner: &'i I,
new_params: Vec<ParameterKind<()>>,
new_goals: Vec<Goal<I>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For each new parameter X, introduces an AliasEq goal that defines it, like AliasEq(<T as Iterator>::Item, X)

interner: &'i I,
new_params: Vec<ParameterKind<()>>,
new_goals: Vec<Goal<I>>,
binders_len: usize,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stores the number of variables in the binder that we are adding parameters into thus far. Incremented for each new variable we add.

TyData,
};

pub fn syn_eq_lower<I: Interner, T: Fold<I>>(interner: &I, clause: &T) -> <T as Fold<I>>::Result {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a comment. Also, I wonder if it's worth adding some other trait since you only really want to fold program clauses and goals here..? Nah, probably not, but we should add a comment about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think making it into syn_lower_clause and syn_lower_goal should be enough

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, two separate functions would be fine

@jackh726
Copy link
Member

Closing in favor of #589

@jackh726 jackh726 closed this Oct 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants