Skip to content

[Php80] Skip loose false comparison in StrContainsRector and MbStrContainsRector - #8641

Closed
guillaume-sainthillier wants to merge 3 commits into
rectorphp:mainfrom
guillaume-sainthillier:strcontains-skip-loose-comparison
Closed

guillaume-sainthillier wants to merge 3 commits into
rectorphp:mainfrom
guillaume-sainthillier:strcontains-skip-loose-comparison

Conversation

@guillaume-sainthillier

Copy link
Copy Markdown
Contributor

Loose comparisons to false (added in #3246) are not equivalent to str_contains():

var_dump(strpos('abc', 'a') != false);   // false, match at position 0 == false
var_dump(str_contains('abc', 'a'));      // true

var_dump(strstr('a0', '0') != false);    // false, "0" == false
var_dump(str_contains('a0', '0'));       // true

So strpos($haystack, $needle) != false (or == false) is rewritten to code with a different result whenever the needle is at the start. Same for mb_strpos() / mb_strstr() in MbStrContainsRector.

Change: both rules only handle === / !== again. Loose fixtures became skip_loose_*; the offset_*_equal_* fixtures were removed as they now duplicate the skip.

@samsonasik

Copy link
Copy Markdown
Member

Just quick look, it seems it looks like academic use case on loose comparison use on that purpose, which mostly false negative.

Most of the time, the usage is intended as str contains needs I guess.

@guillaume-sainthillier

Copy link
Copy Markdown
Contributor Author

Fair point that the intent is almost always "contains". The strstr() case ("0" == false) is indeed academic. For strpos() != false though, a match at position 0 is common, e.g. strpos($path, '/') != false on an absolute path, and the rewrite flips the result there. I'd rather Rector not silently change runtime behaviour, even towards the likely intent. Happy to narrow this to strpos()/mb_strpos() only and keep the strstr() loose rewrite if you prefer, or close it if you'd rather keep the intent-based behaviour.

…ns-skip-loose-comparison

# Conflicts:
#	rules-tests/Php80/Rector/NotIdentical/MbStrContainsRector/Fixture/offset_variable_zero_equal_strpos.php.inc
#	rules/Php80/Rector/NotIdentical/MbStrContainsRector.php
…ns-skip-loose-comparison

# Conflicts:
#	rules-tests/Php80/Rector/NotIdentical/StrContainsRector/Fixture/offset_variable_zero_equal_strpos.php.inc
@TomasVotruba

Copy link
Copy Markdown
Member

I agree with @samsonasik . Can you revert that part? In real projects the same stucture would be converted manually to one we do here.

@guillaume-sainthillier

Copy link
Copy Markdown
Contributor Author

Makes sense, thanks both. Closing, as reverting the loose-comparison part leaves nothing in this PR.

@guillaume-sainthillier
guillaume-sainthillier deleted the strcontains-skip-loose-comparison branch October 12, 2026 11:50
@TomasVotruba

Copy link
Copy Markdown
Member

Thanks for the ping though! It's always better to have these battle tested.

What legacy project do you work on that you've found these?

@guillaume-sainthillier

Copy link
Copy Markdown
Contributor Author

For this PR it was only "theoretical" :) I will let you know if I find real use cases from some legacy php 5.2 projects

@TomasVotruba

Copy link
Copy Markdown
Member

Ah, I thought you had some troubles :) I prefer real projects over theory, as we try to be practical tool, with as few rules as possible to deliver speed to most projects.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants