Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upImplied bounds, second take #82
Conversation
nikomatsakis
reviewed
Feb 6, 2018
|
First round of comments. Will read in more depth tomorrow, especially the accumulator stuff. This is nice! |
| @@ -29,17 +29,12 @@ pub Goal: Box<Goal> = { | |||
| Goal1: Box<Goal> = { | |||
| "forall" "<" <p:Comma<ParameterKind>> ">" "{" <g:Goal> "}" => Box::new(Goal::ForAll(p, g)), | |||
| "exists" "<" <p:Comma<ParameterKind>> ">" "{" <g:Goal> "}" => Box::new(Goal::Exists(p, g)), | |||
| <i:IfKeyword> "(" <w:Comma<WhereClause>> ")" "{" <g:Goal> "}" => Box::new(Goal::Implies(w, g, i)), | |||
| "if" "(" <w:Comma<WhereClause>> ")" "{" <g:Goal> "}" => Box::new(Goal::Implies(w, g)), | |||
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
I am happy to see if_raw gone, I have to say. That always felt "yucky".
| fn parse_and_lower_program(text: &str, solver_choice: SolverChoice, skip_coherence: bool) | ||
| -> Result<ir::Program> | ||
| { | ||
| if skip_coherence { |
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
It seems like this parameter is just always false? Can we just plain remove this?
| @@ -108,6 +109,7 @@ fn cycley_recursive_cached(b: &mut Bencher) { | |||
| CYCLEY_GOAL, | |||
| b, | |||
| "Unique", | |||
| true | |||
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
well I guess it's true here, but not (I take it) for the reasons stated? (why is it true here?)
This comment has been minimized.
This comment has been minimized.
scalexm
Feb 6, 2018
•
Author
Member
The recursive solver fails to answer uniquely goals of the form <Bar as Foo>::Assoc: SomeTrait (or WellFormed(<Bar as Foo>::Assoc: SomeTrait)). So this is a temporary hack (de-activing checking WF requirements) so that the benchmark tests pass, but I should add a FIXME or something because this is really not ought to stay.
| @@ -747,13 +790,19 @@ impl<T> UCanonical<T> { | |||
| } | |||
|
|
|||
| impl UCanonical<InEnvironment<Goal>> { | |||
| /// A goal has coinductive semantics if it is of the form `T: AutoTrait`. | |||
| /// A goal has coinductive semantics if it is of the form `T: AutoTrait`, or if it is of the | |||
| /// form `WellFormed(T: Trait)` where `Trait` is any trait. The latter is needed for dealing | |||
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
I am mildly surprised that we don't want to just make all WellFormed goals coinductive. But I guess it's only needed for traits...
This comment has been minimized.
This comment has been minimized.
scalexm
Feb 6, 2018
Author
Member
Well types only have where clauses of the form T: Trait, there are no WF(Type) where clauses so you never have the kinds of cycles encountered with traits.
| @@ -445,6 +447,10 @@ impl LowerWhereClause<ir::DomainGoal> for WhereClause { | |||
| WhereClause::TraitRefWellFormed { ref trait_ref } => { | |||
| ir::WellFormed::TraitRef(trait_ref.lower(env)?).cast() | |||
| } | |||
| WhereClause::TyFromEnv { ref ty } => ir::FromEnv::Ty(ty.lower(env)?).cast(), | |||
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
I am torn on the question of what this should mean:
if (T: Trait) { .. }
I am thinking maybe we should make that equivalent to if (FromEnv(T: Trait)) { .. } and then have an explicit form if (Implemented(T: Trait)) { .. }. Basically T: Trait would parse to an AST form whose expansion depends on whether it appears in a "clause" (in which case it is FromEnv) or a Goal (in which case it is "Implemented").
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
(That said, I'm not really sure when we would want to say if (Implemented(T: Trait)) { ... }.. but maybe it's useful when crafting unit tests or something.)
This comment has been minimized.
This comment has been minimized.
scalexm
Feb 6, 2018
Author
Member
Yeah not really sure either, but I think converting to FromEnv(T: Trait) in clauses is a good thing, and the explicit goal Implemented would replace the former if_raw statement in a much nicer way.
| // | ||
| // forall<T> { | ||
| // Normalize(<T as Foo>::Assoc -> U) :- FromEnv(T: Foo<Assoc = U>) | ||
| // } |
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
As an aside, and not for this PR, I wonder if we can use macros to make this code less tedious to write.
| impl<T> A for T where T: B {} | ||
| } error_msg { | ||
| "trait impl for \"B\" does not meet well-formedness requirements" | ||
| } |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| type Value; | ||
| } | ||
|
|
||
| impl Bar for i32 { |
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
Maybe add a comment here: this fails because i32: Foo does not hold
| type Value; | ||
| } | ||
|
|
||
| impl<K> Foo for Set<K> { |
This comment has been minimized.
This comment has been minimized.
|
|
||
| // Type parameters and higher-kinded types do not carry any input types (so we can sort | ||
| // of assume they are always WF). | ||
| Ty::Var(..) | Ty::ForAll(..) => (), |
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
Hmm, Ty::ForAll corresponds to for<'a> fn(&'a u32) or some such. I don't know that we can assume they are always WF. I think this accumulator probably doesn't want to accumulate into a vector, but rather to invoke a callback, because in the case of for<'a> we may want to create subuniverses? I have to read this code a bit more carefully I guess.
This comment has been minimized.
This comment has been minimized.
scalexm
Feb 6, 2018
Author
Member
Actually we discussed that and for some reason we decided that higher-kinded types are always WF. This is similar to the fact that if we have this kind of function:
fn foo<T>(arg: HashSet<NotHash<T>>) { ... }we would not issue any error until the function is called. For lifetime parametric function types, again an error would be issued only if a function of this type is ever called. We discussed that in our dropbox paper (see 2017.07.25).
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Feb 6, 2018
Collaborator
Oh, right, I forgot about that. Basically we were assuming that for all types introduce their own implied bounds, right? Makes sense.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@scalexm ok so the changes to make then are:
Do you think you'll have time for that? Do you want me to do it? We should probably make more tests but I'm not inclined to block on that. |
scalexm
added some commits
Jan 25, 2018
scalexm
force-pushed the
scalexm:implied-bounds-ok
branch
from
05f2322
to
acd499f
Feb 6, 2018
scalexm
and others
added some commits
Feb 6, 2018
This comment has been minimized.
This comment has been minimized.
|
I read over the changes more thoroughly. Everything looks great. I looked briefly at the on-demand test was failing; for some reason it is now creating However, I did notice one thing. It seems like you are treating The intention is that "projection eq" is the "normal" rule, with Anyway, I pushed a final commit with a test that fails as a result -- but I think is expected to pass. |
scalexm commentedFeb 5, 2018
•
edited
This is a full implementation of implied bounds as well as enforcing WF requirements on impls and type declarations.
The rules for WF requirements on traits are detailed in #12 (and in the code). The rules for types are much more simple (no need for co-recursion but we still have two predicates,
WellFormedandFromEnv).I was not greatly inspired for the tests, so one can feel free to add some more.
Fixes #11 and incidentally some form of bug related to #70. And eventually #12 will be resolved too.