nickel icon indicating copy to clipboard operation
nickel copied to clipboard

Opaque Contract type

Open Radvendii opened this issue 2 years ago • 2 comments

It used to be that contracts were all functions (morally) of type Label -> Dyn -> Dyn Now we also allow special record contracts, and we are discouraged from actually using the contracts as functions. (they should be used with std.contract.apply instead)

It would reduce confusion and mistakes, and allow for better error reporting and more features to have an opaque Contract type, and require calling some std.contract.from_function to convert from a function that used to just implicitly be a Contract.


Is your feature request related to a problem? Please describe.

  • #1460
  • People not using std.contract.apply
  • Can add extra information (e.g. "came from std.contract.from_predicate" means we can freely || or && the contracts)
  • Can require that any term in contract position (i.e. after |) must be of type Contract

Describe the solution you'd like An opaque Contract type, with explicit conversion from a function that would right now just be a contract

Describe alternatives you've considered The way we do it now works, though with the problems mentioned above. We could also add an opaque contract type, but have automatic conversion from functions Label -> Dyn -> Dyn when needed.

Additional context This would be a breaking change, so it could only happen in Nickel 2.0

Radvendii avatar Jul 20 '23 16:07 Radvendii

@yannham I don't see a tag that signifies "breaking change"

Radvendii avatar Jul 20 '23 16:07 Radvendii

This was discussed in the weekly again, because of some reports similar to https://github.com/tweag/nickel/issues/1460 (on a very large codebase). A possible backward-compatible solution would be to add this new contract opaque type, but still allow implicit conversion from a function to the corresponding contract. Now, this would negate some of the benefits, as we can't complain when something in contract position is not a contract, and so we can't really solve #1460 directly.

However, we can issue a deprecation warning in those cases, and at least the users now have the possibility to move to the new way (the modification is likely to just add a call to a hypothetical std.contract.from_function here and there, so nothing major).

yannham avatar May 03 '24 12:05 yannham

This is more or less what's been implemented in #1987. This only concerns functions, but functions are the problematic bit (for the rest, records and static types can't be applied, and they are all valid contracts). We went the backward-compatibility route and still accept naked functions, but document this as legacy and will be deprecated.

yannham avatar Jul 17 '24 09:07 yannham