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

Make native reason-promise covariant, like JS #49

Open
aantron opened this issue Dec 31, 2019 · 0 comments
Open

Make native reason-promise covariant, like JS #49

aantron opened this issue Dec 31, 2019 · 0 comments

Comments

@aantron
Copy link
Owner

aantron commented Dec 31, 2019

c9d8008 marked JS promises covariant. We should do the same in the native version. However, that is a full implementation, and a correct implementation of promises usually prevents the compiler from admitting covariance (the compiler infers invariance). This is because such an implementation requires several helper data structures to defer callbacks and avoid memory leaks, so we need to either:

  • Add casts to fool the compiler (as in Lwt).
  • Search more thoroughly for data structures that don't prevent the compiler from inferring covariance.

The current data structures don't (or shouldn't!!) make the promises invariant, the compiler just can't tell that they don't.

After dealing with this, the covariance tests should be made to run (rather, build) on both JS and native:

promise/test/js/test_ffi.re

Lines 316 to 360 in c9d8008

let covarianceTests = Framework.suite("covariance", [
test("promise", () => {
let p: Promise.t(subtype) = Promise.resolved(`A);
let p: Promise.t(type_) = (p :> Promise.t(type_));
ignore(p);
Promise.resolved(true);
}),
test("ok", () => {
let p: Promise.t(result(subtype, unit)) = Promise.resolved(Ok(`A));
let p: Promise.t(result(type_, unit)) =
(p :> Promise.t(result(type_, unit)));
ignore(p);
Promise.resolved(true);
}),
test("error", () => {
let p: Promise.t(result(unit, subtype)) = Promise.resolved(Error(`A));
let p: Promise.t(result(unit, type_)) =
(p :> Promise.t(result(unit, type_)));
ignore(p);
Promise.resolved(true);
}),
test("option", () => {
let p: Promise.t(option(subtype)) = Promise.resolved(Some(`A));
let p: Promise.t(option(type_)) = (p :> Promise.t(option(type_)));
ignore(p);
Promise.resolved(true);
}),
test("fulfillment", () => {
let p: Promise.Js.t(subtype, unit) = Promise.Js.resolved(`A);
let p: Promise.Js.t(type_, unit) = (p :> Promise.Js.t(type_, unit));
ignore(p);
Promise.resolved(true);
}),
test("rejection", () => {
let p: Promise.Js.t(unit, subtype) = Promise.Js.rejected(`A);
let p: Promise.Js.t(unit, type_) = (p :> Promise.Js.t(unit, type_));
p->Promise.Js.catch(_ => Promise.resolved())->ignore;
Promise.resolved(true);
}),
]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant