coding-standard icon indicating copy to clipboard operation
coding-standard copied to clipboard

Drop MissingTraversable* typehint sniffs

Open simPod opened this issue 3 years ago • 15 comments

Remove CS checks for missing traversable type hints

I propose to disable these sniffs as we have and already adopted tools that are more capable to check for such issues (PHPStan/Psalm).

WDYT? If we agree, I'll go and adopt related tests.


Basic example

PHPStan complains about not getting a type spec: https://phpstan.org/r/9a2a974a-d647-4c95-99d1-e87ef7fc9207

function food(iterable $i): void
{
	return;
}

Implementing a method

❌ Missing type hint is complained about https://phpstan.org/r/cebc3f17-4c08-4e6f-a6d8-cfae8ebc4338

interface I {
	public function foo(): iterable;
}

final class C implements I {
	public function foo(): iterable {
		return [];
	}
}

✅ Adding a type hint on the interface fixes the error without having a need to also provide @inheritDoc to all implementations. Implementations inherit that from interface by default so @inheritDoc becomes redundant in most cases we use it nowadays.
Phpstan is not limited to single file evaluation like phpcs but can evaluate the whole context.

https://phpstan.org/r/6c748d83-62b3-4c94-b22b-4d852696050e

interface I {
	/** @return iterable<mixed> */
	public function foo(): iterable;
}

final class C implements I {
	public function foo(): iterable {
		return [];
	}
}

simPod avatar Aug 09 '21 06:08 simPod

PHPStan or Psalm check for these better.

They check them once the spec is written no? It's up to CS to enforce specifying what's inside a traversable. Unless I'm missing knowledge about some features in those tools :)

malarzm avatar Aug 09 '21 08:08 malarzm

What spec do you mean? 🤔

I should've added a playground link though: https://phpstan.org/r/198b1899-3695-4bf6-b158-0c3f3445095d

simPod avatar Aug 09 '21 08:08 simPod

Does psalm already report on missing iterable types?

Ocramius avatar Aug 30 '21 16:08 Ocramius

I guess:

❌ https://psalm.dev/r/6189d0e1e3 without type
✅ https://psalm.dev/r/dacb0340d2 with type

simPod avatar Aug 30 '21 16:08 simPod

Yeh, but that still allows passing on an iterable<mixed> to somebody else (when not consuming it directly, or when declaring a return type).

In practice, this iterable rule has been one of the biggest drivers in type safety a couple years ago, and dropping it still allows for declaring untyped iterables in abstract types 🤔

Before calling it "done", it would be best to have this also in psalm mixed rules, IMO.

Ocramius avatar Aug 30 '21 16:08 Ocramius

The point here was to drop the phpcs check as we have a smarter and more bulletproof alternative in PHPStan. So even though Psalm does no have the feature parity in this matter now, it does not seem like an obstacle to me.
Not having to spam inheritDoc in every implementation is a nice bonus.

TBH I think we all have to use both psalm and phpstan simultaneously to be safe.

simPod avatar Aug 30 '21 16:08 simPod

Not really: I stopped using phpstan for my own work (also OSS), and will likely pick it up again in a few years, if things change 🤷‍♀️

Ocramius avatar Aug 30 '21 16:08 Ocramius

We still tend to use both PHPStan and Psalm in all major Doctrine repositories so there's no need for an additional CS rule

malarzm avatar Aug 30 '21 18:08 malarzm

@doctrine/coding-standard-approvers I'm not sure if this can be merged as a patch release so I'm deferring clicking merge button to somebody more informed :)

malarzm avatar Aug 30 '21 18:08 malarzm

Though in my opinion we can drop features here that are superseded by other tools if those tools are not newborn or experimental or w.e. and other repositories should too. That was the point of this PR.
Other repositories can eventually reenable those.

simPod avatar Aug 30 '21 19:08 simPod

I have been always thinking of the coding standard requiring type annotations as a way to enable static analysis tools, not as a solution on its own. As long as PHPStan no longer needs it, I'd say we could disable this requirement in the coding standard. Those meaningless {@inheritDoc}s alone would be a good reason to do that.

Eventually, I'd like to see this tool focusing on code formatting which it's originally designed for, not on static analysis.

morozov avatar Aug 31 '21 00:08 morozov

Today, I found that using a type alias to replace occurrences of array<int, int|string|Type|null>|array<string, int|string|Type|null> with ArrayOfTypes results in phpcs erroring out with @param annotation of method \Doctrine\DBAL\Query\QueryBuilder::setParameters() does not specify type hint for items of its traversable parameter $types.

So now I'd say this rule is making the maintenance harder: after that refactoring I was planning to narrow down int to Connection::PARAM_*|ParameterType::*, but now it's going to be verbose and impractical.

@Ocramius can you please reconsider?

As for the target branch, I think it's ok to target 9.0.x since it's unlikely to make build fail.

greg0ire avatar Feb 11 '22 19:02 greg0ire

using a type alias to replace occurrences ... results in phpcs erroring out

Sounds like a bug, rather than related to this RFC (which proposes dropping the rule overall).

@Ocramius can you please reconsider?

No, not really - it's something that helped me on countless projects to get type declarations in, even when phpstan/phpstan or vimeo/psalm were installed. It has and is a huge driver for increasing type safety inside codebases.

Ocramius avatar Feb 11 '22 19:02 Ocramius

I reported the bug here FTR: https://github.com/slevomat/coding-standard/issues/1334, hopefully it's fixable. If not, we might consider disabling it on a per-project basis.

greg0ire avatar Feb 11 '22 21:02 greg0ire

It should be fixable :)

kukulich avatar Feb 11 '22 21:02 kukulich

Ping me if this is wished for in the future.

simPod avatar Sep 06 '22 09:09 simPod