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

UnevaluatedCode for declare with return #8892

Closed
ElisDN opened this issue Dec 12, 2022 · 6 comments
Closed

UnevaluatedCode for declare with return #8892

ElisDN opened this issue Dec 12, 2022 · 6 comments

Comments

@ElisDN
Copy link
Contributor

ElisDN commented Dec 12, 2022

It works in global namespace:

https://psalm.dev/r/d4d61a5673

but it throws an error with namespace:

https://psalm.dev/r/49ce4900b9

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/d4d61a5673
<?php

declare(strict_types=1);

return [];
Psalm output (using commit ef02ded):

No issues!
https://psalm.dev/r/49ce4900b9
<?php

declare(strict_types=1);

namespace App;

return [];
Psalm output (using commit ef02ded):

ERROR: UnevaluatedCode - 3:1 - Expressions after return/throw/continue

@orklah
Copy link
Collaborator

orklah commented Dec 12, 2022

There's a fault in Psalm handling of statements in and out namespaces

What happens here is:

  • Psalm sees a new file
  • It first process the classes, interfaces, traits, and namespaces
  • For each namespace, it also extracts classes, interfaces and traits
  • It puts every leftover statement in the namespace in a list
  • It analyze the list of leftover statement for each namespace (so here, the return) because return could contain an expression that needs to be analyzed from within the namespace
  • Then Psalm analyze statements that were out of the namespaces (here, it's the declare). However, the return already flagged the whole file as having returned so it fails.

There's a reason to that though, because any statement in the file could use any symbol also declared in the file, no matter the order of the statements.

So I guess, we would need to first extract symbols, collect leftover statement for each namespace and then process statements in the correct context and in order(so declare first, then leftovers by namespace). This may be a big change to support a very unusual pattern though...

What I'm more worried about is the fact that the declare is analyzed at then end (after namespaces) so I'm not sure it's correctly processed when analyzing other statements

@weirdan
Copy link
Collaborator

weirdan commented Dec 12, 2022

What I'm more worried about is the fact that the declare is analyzed at then end (after namespaces) so I'm not sure it's correctly processed when analyzing other statements

Indeed: https://psalm.dev/r/3a0287fa0f

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/3a0287fa0f
<?php declare(strict_types=1);

// namespace NS;

function f(int $_i): void {}

function ff(string|int $a): void {
	atan($a);

	/** @psalm-check-type $a = int */;

	f($a); // expected: no issues here. If $a was a string, there would be an exception thrown on atan() call
}
Psalm output (using commit ef02ded):

ERROR: InvalidArgument - 8:7 - Argument 1 of atan expects float, but int|string provided

ERROR: UnusedFunctionCall - 8:2 - The call to atan is not used

ERROR: CheckType - 10:35 - Checked variable $a = int does not match $a = int|string

ERROR: PossiblyInvalidArgument - 12:4 - Argument 1 of f expects int, but possibly different type int|string provided

@vudaltsov
Copy link
Contributor

This issue can be now closed!

@orklah
Copy link
Collaborator

orklah commented May 4, 2023

Yes, this specific issue has been fixed. For future reference, #8892 (comment) still holds and the way Psalm process this is not optimal (and lead to very marginal edge cases for files that would contain a strict type declaration and namespace that have expressions that need to be evaluated)

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

4 participants