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

Forbidding injectivity of inductive types with parameters that are too large #1649

Merged
merged 21 commits into from
Feb 25, 2019

Conversation

nikswamy
Copy link
Collaborator

See the discussion in issue #349

@nikswamy nikswamy requested a review from mtzguido February 13, 2019 06:35
@mtzguido
Copy link
Member

Left some minor remarks, here a few higher-level ones.

First, note that this now fails

let isMkInj (x:_) (w:i x) : Lemma (w == Mkinj #x) = ()

I believe since w is Mkinj (Mkinj?.f w) (if one could write that), and we do not know if Mkinj?.f w is x. I feel this could be made work soundly if we didn't have that Mkinj is injective internally. But maybe that is just what Kenji suggested in #349, which caused many regressions? In any case, not sure having this is useful.

Also note some types are not getting injectivity due to how universes are resolved. This one from FStar.Algebra.Monoid, for instance, ends up with a U_name as the universe for a and Type0 as the universe for the type.

type monoid_morphism (#a #b:Type) (f:a -> b) (ma:monoid a) (mb:monoid b) =
  | MonoidMorphism :
    unit:squash (monoid_morphism_unit_lemma f ma mb) ->
    mult:squash (monoid_morphism_mult_lemma f ma mb) ->
    monoid_morphism f ma mb

It can be fixed like this

type monoid_morphism (#a : Type u#aa) (#b : Type u#bb) (f:a -> b) (ma:monoid a) (mb:monoid b) : Type u#(max aa bb) =

Seems to be the only one in ulib/ so this might no be a big deal.

Otherwise looks good to me, the universe check does seem sound. I would also rebase the PR so we have a cleaner history. I could do that if you want.

@nikswamy
Copy link
Collaborator Author

Thanks for the comments, Guido.

FWIW, I don't see the "minor remarks" you refer to.

I'm still a bit unsatisfied with the restriction imposed by this patch. It's rather specific in that it excludes injectivity of type formers when they contain function-typed parameters with domain in universes that are too large. That excludes this particular paradox, which is good, and so I'm in favor of this being merged.

OTOH, if the check is really to be justified on cardinality grounds, then a type with any parameter that is in a universe too large (not just those with function-typed parameters with too-large domains) should not be injective. But, that doesn't seem to be feasible at all, since it would exclude many simple parameterized inductive types.

I'm inclined to merge this patch now, so that we forbid at least the paradox we know about.
And then to return to this and provide a more comprehensive solution perhaps in conjunction with a solution to #65. That should also address your example with MkInj #x not being equal to w : i x.

@nikswamy
Copy link
Collaborator Author

Also, not sure about the rebasing. We've generally not being doing that ... so why should this PR require it?

let _, k = U.arrow_formals k in //don't care about indices here
let tps, env_tps, _, us = TcTerm.tc_binders env tps in
let u_k =
match (SS.compress k).n with
Copy link
Member

Choose a reason for hiding this comment

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

Could we call env.universe_of here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not really, that would compute one universe too high.

In this case, we have, for instance, type t : Type u#0 = ... where k = Type u#0 and we want u_k to be u#0 not its successor.

I agree that this code is more syntactic than ideal. But, fwiw, the typechecking rules for inductices in TcInductive really enforce that the result type of an inductive is a Tm_type or eqtype.

Copy link
Member

Choose a reason for hiding this comment

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

True, sorry, I meant TcTerm.level_of_type

| _ -> failwith (BU.format1 "Impossible: Type of inductive is %s" (Print.term_to_string k))
in
//BU.print2 "Universe of tycon: %s : %s\n" (Ident.string_of_lid t) (Print.univ_to_string u_k);
let rec universe_leq u v =
Copy link
Member

Choose a reason for hiding this comment

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

Maybe this function should live somewhere else, such as Syntax.Util

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I didn't want to put this in Syntax.Util since I didn't want it to be used outside of a context (e.g., in the typechecker) where universe unification variables may still be around. This boolean function may give the wrong result when called on universe terms with U_unif terms. The proper way of checking of enforcing universe inequalities in the typechecker would be to call FStar.TypeChecker.Rel to register and solve universe inequality constraints.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Note, within the SMT encoding, we really ought to not have U_unif anymore ... I suppose I could assert that here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OTOH, when this function returns false, the is_injective flag is false ... i.e., erring conservatively.

Copy link
Member

Choose a reason for hiding this comment

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

I indeed interpreted as a conservative leq, where returning false means "I don't know". It might be useful somewhere else, but we could factor it out when the need arises.

@mtzguido
Copy link
Member

Sorry, I missed to hit "submit" on the review again. I also think we should merge this for the time being, even if we're not so certain about it.

I'm fine with not rebasing. I only like it to have a cleaner git history to bisect or find out how something evolved.

@nikswamy nikswamy merged commit 953aa38 into master Feb 25, 2019
@catalin-hritcu catalin-hritcu deleted the nik_attemping_349 branch March 15, 2019 16:15
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.

2 participants