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

Purity inference #7170

Merged
merged 73 commits into from
Nov 7, 2024
Merged

Purity inference #7170

merged 73 commits into from
Nov 7, 2024

Conversation

agu-z
Copy link
Collaborator

@agu-z agu-z commented Oct 17, 2024

Introduces the "Purity Inference" model of effects as described in Richard's talk:

  • All functions are now either pure or effectful
pure : Str -> Str
effectful! : Str => Str
  • Functions are inferred as effectful when they call other effectful functions
printName! = \user ->
    putLine! user.name
  • The "source" effect functions come from the platform.
  • Higher-order functions that are annotated to take pure functions cannot be passed effectful functions
List.map names putLine! 
             # ^^^^^^^^ error
  • However, you can make an effectful higher-order function that takes effectful functions
forEach! : List a, (a => {}) => {}
forEach! = \list, fn! -> ...
  • A warning is produced if effectful functions are not suffixed with ! and viceversa
  • The ! suffix is not only required on defs, but also on record fields, and all pattern matched identifiers (tuple, tags, opaques, etc).
  • Standalone statements are allowed in effectful functions:
main! = \{} ->
    line = getLine! {}
    
    if line == "secret" then
        putLine! "You found the secret"
        putLine! "Congratulations!"
    else
        {}
    
    putLine! "You entered: $(line)"
  • A warning is produced if they don't call any effectful functions, since that means they are dead code
  • Also, an IGNORED RESULT warning is produced if they return anything other than {}
  • If you still want to ignore the result, you can assign it to _:
_ = File.delete! "data.json"
  • ...but you'll still get a warning if what you ignored is pure
  • You can roc run a program with a pure/effectful mismatch, which can be useful while you're debugging
  • Task still works if that's what the platform exposes in its hosted module. This will allow us to migrate platforms incrementally.

Type checking and errors preview:
https://www.youtube.com/watch?v=5a3r88-oEQQ

@ayazhafiz
Copy link
Member

ayazhafiz commented Oct 17, 2024 via email

@agu-z agu-z force-pushed the purity-inference branch 8 times, most recently from 9039954 to c063025 Compare October 25, 2024 00:03
@agu-z agu-z changed the title [WIP] Purity inference Purity inference Oct 25, 2024
@agu-z agu-z marked this pull request as ready for review October 25, 2024 00:19
@agu-z agu-z requested a review from ayazhafiz October 25, 2024 00:19
Copy link
Collaborator

@smores56 smores56 left a comment

Choose a reason for hiding this comment

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

Initial review, only partway through. More comments tomorrow!

crates/compiler/can/src/desugar.rs Outdated Show resolved Hide resolved
crates/compiler/parse/src/ident.rs Outdated Show resolved Hide resolved
crates/compiler/problem/src/can.rs Show resolved Hide resolved
crates/compiler/can/src/constraint.rs Show resolved Hide resolved
crates/compiler/can/src/copy.rs Outdated Show resolved Hide resolved
crates/compiler/can/src/def.rs Outdated Show resolved Hide resolved
crates/compiler/can/src/expr.rs Outdated Show resolved Hide resolved
crates/compiler/can/src/expr.rs Show resolved Hide resolved
crates/compiler/mono/src/layout.rs Outdated Show resolved Hide resolved
crates/compiler/mono/src/layout.rs Outdated Show resolved Hide resolved
examples/cli/effects.roc Show resolved Hide resolved
Copy link
Collaborator

@smores56 smores56 left a comment

Choose a reason for hiding this comment

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

Okay, I've finished reading the whole thing (more or less). It looks good to me! A couple of minor things, and then I think we're good to go. You supporting both Tasks and effectful functions makes this need much less coordination to get right than the built-in Task effort.

crates/compiler/module/src/symbol.rs Show resolved Hide resolved
crates/reporting/src/error/type.rs Outdated Show resolved Hide resolved
crates/reporting/src/error/type.rs Outdated Show resolved Hide resolved
crates/compiler/load/tests/test_reporting.rs Show resolved Hide resolved
crates/compiler/load/tests/test_reporting.rs Outdated Show resolved Hide resolved
@ayazhafiz
Copy link
Member

@agu-z can you ping me for review after rebase?

@agu-z agu-z force-pushed the purity-inference branch 2 times, most recently from dcbff1f to 2b8d9aa Compare October 30, 2024 23:27
Comment on lines +845 to +848
/// Require idents to be accurately suffixed
FxSuffix(Index<FxSuffixConstraint>),
/// Set an fx var as pure if flex (no effectful functions were called)
FlexToPure(Variable),
Copy link
Member

Choose a reason for hiding this comment

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

Is this necessary? Would it be sufficient to add an Eq constraint that the fx var on a function is Pure or Impure depending on the suffix? With an appropriate context.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do you mean FlexToPure or FxSuffix should use Eq?

The former I think wouldn't work because the logic is different than the normal unification of fx vars. However, FxSuffix might work as Eq with a custom Reason.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@ayazhafiz let me know which one you mean when you have a chance

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We decided to merge this, but I'm happy to clean this up in a follow up PR!

@agu-z agu-z force-pushed the purity-inference branch 4 times, most recently from a5aeb82 to d3abe4a Compare November 7, 2024 05:40
Things go wrong when multiple tests depend on the same platform
on Linux. Tried a few workarounds but the problem persisted.
We decided to keep only one test for now.
Copy link
Collaborator

@lukewilliamboswell lukewilliamboswell left a comment

Choose a reason for hiding this comment

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

Massive upgrade, thank you for all the hard work Agus 🎉 😍

@agu-z agu-z merged commit dfb2966 into main Nov 7, 2024
18 checks passed
@agu-z agu-z deleted the purity-inference branch November 8, 2024 00:00
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.

4 participants