Skip to content
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

chalkify: Implement lowering rule Implied-Bound-From-Trait #49435

Merged
merged 1 commit into from
Apr 10, 2018

Conversation

tmandry
Copy link
Member

@tmandry tmandry commented Mar 28, 2018

For #49177.

TODO:

  • Implement where clauses besides trait and projection predicates
  • Is the output of the lower_trait_higher_rank test correct?
  • Remove Self::Trait from the query tcx.predicates_of(<trait_id>).predicates
  • Consider moving tests to compile-fail to make them more manageable

@tmandry
Copy link
Member Author

tmandry commented Mar 28, 2018

r? @nikomatsakis

@@ -58,6 +58,8 @@ impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
}
}

/// Lowers a trait or projection predicate to a `FromEnv(...)` clause.
Copy link
Member

Choose a reason for hiding this comment

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

What does this comment refer to actually?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nothing, I added it by accident!

@@ -99,6 +101,38 @@ impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
}
}

/// For a given `where_clause`, returns a clause `FromEnv(WC) :- Implemented(Self: Trait<P1..Pn>)`.
Copy link
Member

Choose a reason for hiding this comment

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

So actually the rule we want is FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>). But there is a slight subtlety: the FromEnv in the left hand side is not exactly a real FromEnv predicate, it's rather some notation (maybe not very appropriate, I agree):

  • if WC == TraitRef, then indeed it means FromEnv(TraitRef)
  • if WC == ProjectionPredicate, then again it means FromEnv(ProjectionPredicate)
  • in any other case, WC is left unchanged, e.g. in the above FromEnv(T: 'a) just means T: 'a
    see this section in the book.

As an example, given this trait:

trait Foo<'a, T> where T: Copy, T: 'a, T: Iterator<Item = i32> { }

we would like the following clauses:

forall<'a, Self, T> {
    FromEnv(T: Copy) :- FromEnv(Self: Foo<'a, T>).
    FromEnv(T: Iterator<Item = i32>) :- FromEnv(Self: Foo<'a, T>).
    (T: 'a) :- FromEnv(Self: Foo<'a, T>).
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, I really don't know how I mixed that up >.>

Doing the rest in a match clause really ought to be a matter of using Lower IMO, but right now it eagerly lowers straight to a Goal when DomainGoal is needed. I want to play around with this when I get some time.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I think I'm going to issue a fix for the eager lowering soon, it should benefit the ergonomics of your PR

@@ -99,6 +101,38 @@ impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
}
}

/// For a given `where_clause`, returns a clause `FromEnv(WC) :- Implemented(Self: Trait<P1..Pn>)`.
Copy link
Member

Choose a reason for hiding this comment

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

As an aside, to avoid writing again code about binders, I'd rather see something like:

impl<'tcx> DomainGoal<'tcx> {
    fn into_from_env_goal(self) -> DomainGoal<'tcx> {
        match self {
            DomainGoal::Holds(wca) => DomainGoal::FromEnv(wca),
            other => other // unchanged
        }
    }
}

then the same thing recursively for Goal:

impl<'tcx> Goal<'tcx> {
    fn into_from_env_goal(self) -> Goal<'tcx> {
        match self {
            Goal::DomainGoal(dg) => Goal::DomainGoal(dg.into_from_env_goal()),
            Goal::Quantified(q, g) => Goal::Quantified(q, g.into_from_env_goal()),
            /* ... */
        }
    }
}

and then you can just do something like:

let predicates = tcx.predicates_of(def_id).predicates.lower();

/* do appropriate things to remove the `Self: Trait` predicate */

let predicates = predicates.into_iter().map(|p| p.into_from_env_goal());

Copy link
Member

Choose a reason for hiding this comment

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

Actually I was mistaken this would not quite work since we only can have DomainGoal as a consequence. Ok so do as you want 😀

// forall<Self, P1..Pn> {
// FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn)
// }

Copy link
Member

Choose a reason for hiding this comment

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

You might want to keep this comment just above your code which generates the clauses just below.

#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
//~| ERROR FromEnv
//~| ERROR forall
//~| ERROR forall
Copy link
Member

Choose a reason for hiding this comment

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

The output looks good, just need to change to FromEnv(...) :- FromEnv(Self: Foo<F>) instead of FromEnv(...) :- Implemented(Self: Foo<F>) 😃

@shepmaster shepmaster added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 30, 2018
@tmandry tmandry added WG-traits Working group: Traits, https://internals.rust-lang.org/t/announcing-traits-working-group/6804 A-traits Area: Trait system labels Mar 30, 2018
@tmandry tmandry force-pushed the rule-implied-bound-from-trait branch from 5c67da7 to 287a1ac Compare March 31, 2018 05:49
@tmandry
Copy link
Member Author

tmandry commented Mar 31, 2018

Rebased on #49497 and it definitely makes things nicer! 🏂

Note that the test output for HRTBs changed.

@tmandry tmandry force-pushed the rule-implied-bound-from-trait branch from 287a1ac to 4ef87c6 Compare March 31, 2018 15:50
@nikomatsakis nikomatsakis added S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 4, 2018
@nikomatsakis
Copy link
Contributor

Blocked on #49497

@scalexm
Copy link
Member

scalexm commented Apr 4, 2018

I’d like to review one more time once #49497 lands.

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.

Few nits -- seems roughly right? I've been doing reviews all day though so my "attention to detail" is starting to flag. I'll try and take another look tomorrow.

where_clause: &ty::Predicate<'tcx>,
) -> Clause<'tcx> {
// We can't use the full `Lower` chain here, as it'll wrap our where clause in `Holds` instead
// of `FromEnv`. We also handle ty::Binder similarly to `Lower`, but at the Clause level.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand this comment actually

Copy link
Member Author

Choose a reason for hiding this comment

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

Neither do I, honestly. I was tired when I wrote this.

Trait(binder) => binder.lower_from_env(),
Projection(binder) => binder.lower_from_env(),
RegionOutlives(p) => p.lower(),
TypeOutlives(p) => p.lower(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make where_clause implement LowerFromEnv? So we can just do where_clause.lower_from_env()?

Copy link
Member

@scalexm scalexm Apr 4, 2018

Choose a reason for hiding this comment

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

I was going to suggest, instead of the LowerFromEnv machinery:

trait IntoFromEnvGoal {
    fn into_from_env_goal(self) -> Self;
}

impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> {
    fn into_from_env_goal(self) -> DomainGoal<'tcx> { /* ... */ }
}

and then a straightforward:

ProgramClause::ForAll(
    // we might map a dummy binder here, ok for now
    where_clause.lower().map_bound(|goal| ProgramClause {
        goal: goal.into_from_env_goal(),
        hypotheses
    })
)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, IntoFromEnvGoal turns out to be much simpler. Thanks!

@tmandry tmandry force-pushed the rule-implied-bound-from-trait branch from 4ef87c6 to 7ac35ea Compare April 6, 2018 18:22
@tmandry tmandry changed the title [WIP] chalkify: Implement lowering rule Implied-Bound-From-Trait chalkify: Implement lowering rule Implied-Bound-From-Trait Apr 6, 2018
@tmandry
Copy link
Member Author

tmandry commented Apr 6, 2018

Changed implementation to use IntoFromEnvGoal as suggested by @scalexm, rebased, and squashed. Also, added some Outlives predicates to the test.

This should be ready, modulo the predicates_of query, which I can do as part of this PR or separately. I'll be working on that this afternoon.

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Apr 9, 2018

📌 Commit 7ac35ea has been approved by nikomatsakis

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. labels Apr 9, 2018
@bors
Copy link
Contributor

bors commented Apr 10, 2018

⌛ Testing commit 7ac35ea with merge a8a8d6b...

bors added a commit that referenced this pull request Apr 10, 2018
…atsakis

chalkify: Implement lowering rule Implied-Bound-From-Trait

For #49177.

TODO:
- [x] Implement where clauses besides trait and projection predicates
- [x] Is the output of the `lower_trait_higher_rank` test correct?
- [ ] Remove `Self::Trait` from the query `tcx.predicates_of(<trait_id>).predicates`
- [ ] Consider moving tests to compile-fail to make them more manageable
@bors
Copy link
Contributor

bors commented Apr 10, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: nikomatsakis
Pushing a8a8d6b to master...

@bors bors merged commit 7ac35ea into rust-lang:master Apr 10, 2018
@tmandry tmandry deleted the rule-implied-bound-from-trait branch April 14, 2018 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-traits Area: Trait system S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. WG-traits Working group: Traits, https://internals.rust-lang.org/t/announcing-traits-working-group/6804
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants