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

Typestate-oriented programming #3591

Closed
olleharstedt opened this issue Jun 15, 2020 · 7 comments
Closed

Typestate-oriented programming #3591

olleharstedt opened this issue Jun 15, 2020 · 7 comments

Comments

@olleharstedt
Copy link
Contributor

olleharstedt commented Jun 15, 2020

Did you guys discuss typestate-oriented programming anything?

Building on article [1], it would allow you to "tag" types and resources, like so:

/** @var File<Open> */
$handle = fopen("/tmp/inputfile.txt", "r");
/** @var string */
$buffer = fgets($handle, 4096));
// This changes $handle to @var File<Closed>
fclose($handle);
// Type error: $handle must have type File<Open>
fgets($handle, 1);

See [2] for more details about this paradigm. It corresponds loosely to what in functional programming is done with linear (or affine) types.

[1] http://marcosh.github.io/post/2020/05/26/phantom-types-in-php.html

[2] https://www.cs.cmu.edu/%7Ejssunshi/pubs/onward2009-state.pdf

@andyg0808
Copy link

@olleharstedt I'm wondering if [1] was the intended link, because the article there seems to have more to do with marking interpretations of primitive types, rather than marking states.

@olleharstedt
Copy link
Contributor Author

@andyg0808 It was intended, since phantom types can simulate typestate in some settings.

@olleharstedt
Copy link
Contributor Author

olleharstedt commented Jun 16, 2020

Psalm seems to already have typestate related features, as shown here: #1255

Related to array_shift:

/** @var array{string, int} */
$arr = ["foo", 1];
array_shift($arr);  // Modifies the type

Seems like this happens in method handleByRefArrayAdjustment in Psalm? Maybe there's a way to make it possible to define your own functions like this, instead of the hard-coded list?

NB: array_shift is not type-safe if there's a reference to the argument. For that, you'd need borrow pointer logic and all that jazz that Rust uses, or, maybe more inline with Psalm philosophy, just give up if there's a reference detected.

Basically the method AssignmentAnalyzer::assignByRefParam should be programmable by annotations and not depend on any hard-coding nor reference operator (since all objects always are passed as references (no value semantics like arrays)).

@muglug
Copy link
Collaborator

muglug commented Jun 17, 2020

Psalm already handles closing file handlers via the resource-closed type: https://psalm.dev/r/2737e2dc70

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/2737e2dc70
<?php

$fp = tmpfile();

if ($fp) {
    fclose($fp);
	fwrite($fp, "hello");
}
Psalm output (using commit e1cc27f):

ERROR: InvalidArgument - 7:9 - Argument 1 of fwrite expects resource, closed-resource provided

@muglug
Copy link
Collaborator

muglug commented Jun 17, 2020

I don't plan to add any annotations to change state beyond existing @param-out annotations

@muglug muglug closed this as completed Jun 17, 2020
@olleharstedt
Copy link
Contributor Author

I don't plan to add any annotations to change state beyond existing @param-out annotations

@muglug Do you plan to do something with alias tracking? E.g. to fix array_shift in the case where argument has an alias in the same scope.

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

No branches or pull requests

3 participants