Closed (fixed)
Project:
Drupal core
Version:
main
Component:
base system
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
30 Nov 2025 at 20:18 UTC
Updated:
18 Aug 2026 at 12:00 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
andypostAs polyfill already added core can use the attribute on earlier versions of PHP
https://github.com/symfony/polyfill-php85
Comment #3
andypostComment #4
joachim commentedI'm not sure what the polyfill serves here, unless elsewhere in Symfony there's magic which detects the #NoDiscard attribute in static code analysis.
Comment #5
longwavePHPStan supports
#[NoDiscard]: https://github.com/phpstan/phpstan/releases/tag/2.1.28Comment #7
joachim commentedWhat else do we need to do here?
Comment #8
andypost@joachim as summary said we need to mark sensitive functions with this attribute so consumers will throw if result is not used
Comment #9
joachim commentedI mean, before we tackle the child issues to actually add the attribute, is there anything else to do here?
Comment #10
andypostMy idea was to apply it to few places like AccessResult, CacheableMetadata, cache merge, validators, query builders, render array builders
I will create MR to give a try asap but let's find more places where it helpful
Comment #12
andypostSomehow PHPStan does not catch it but PHPStorm showing
In
core/modules/media/src/MediaAccessControlHandler.php:130—Comment #13
andypostit works dynamically
Comment #14
andypostPHPStan does not catch because we have
checkThisOnly: trueand I'm not sure it viable to allow it as much more errors appearComment #15
andypostComment #16
andypostSo I think it ready to file child issues and it's enough to add the attribute to interface only
Comment #17
andypostInterface only attribute is not working(
Comment #19
andyposton direct class call PHPStan works https://git.drupalcode.org/issue/drupal-3575572/-/jobs/8642189
Comment #20
andypostFiled few child issues
Comment #22
joachim commentedI'm confused - we're filing child issues, but the MR here seems to be all the changes?
Comment #23
andypostI just tested here different approaches, child issues are to work on
Comment #24
dcam commentedI looked at these issues last night and had a couple of thoughts:
Comment #25
joachim commented> It would be nice for the child issues to include the justification for why the attribute should be applied to the included functions.
Because not using the return of those is probably (or even always!) a mistake. Same reason for all of them really!
Comment #26
dcam commentedI figured that out from reading the docs. But that doesn't mean someone can understand at a glance why that's the case for a particular function or set of functions, especially if they're looking at an API they aren't familiar with.
Comment #27
andypostwould be great to find some better wording then deadcode
Comment #28
andypoststill the most illustrative example is https://git.drupalcode.org/project/drupal/-/merge_requests/14887/diffs?c...
Comment #29
andypostGuideline to reuse result as state got changes after call
Comment #30
longwaveComing from #3575572: Add [#NoDiscard] to Utility classes which added it to multiple classes:
\Drupal\Component\Utility\Color
\Drupal\Component\Utility\Crypt
\Drupal\Component\Utility\Html
\Drupal\Component\Utility\NestedArray
\Drupal\Component\Utility\Tags
To me I don't see the need to add it to Color or Tags, if we go down that route then we could add it to practically any method that doesn't have a void return type, but I'm not sure that's really necessary.
Initially I think this should be only added to security, access control or encryption related methods, where mistakes in API usage can cause critical bugs. However, I'm open to suggestions as to other types of API as well?
Comment #31
joachim commented> Initially I think this should be only added to security, access control or encryption related methods, where mistakes in API usage can cause critical bugs
+1
Though I would add to that, methods on value objects which return a new object instead of altering it.
So: AccessResult and CacheableMetadata, for instance.
Comment #32
penyaskito+1. This is one of the first thoughts I have when thinking about
#[NoDiscard]. E.g.\Drupal\jsonapi\JsonApiResource\LinkCollectionand everywhere there's some kind ofreturn new static(maybe aside of constructors, but maybe we want _also_ constructors).Edit: I added another "non security" example because of AccessResult and CacheableMetadata could (should) even be considered security, access control related methods.
Comment #33
quietone commentedTried to put the when to use this into the proposed resolution
Comment #34
smustgrave commentedBased on the current proposed solution is there consensus those are good guidelines to use this?
Comment #36
smustgrave commentedThe proposed changes makes sense and there's been no follow up since they were added. What would be next?
Comment #37
longwaveWe need to figure out where to document this decision - either in existing documentation somewhere or a new page.
Comment #38
smustgrave commentedMaybe a page under https://www.drupal.org/docs/develop/security ?
Comment #39
quietone commented@smustgrave, that does make sense. But considering we have other Coding Practices I think a more general solution is needed. For a long term solution I think coordination with the coding standards committee is needed.
In the meantime, this issue came up in the committer meeting and catch and I thought the best way to make progress is to make a page in the core policies for this type of topic. The new page is Coding practices.
Comment #40
catchNew page looks great for now, if we find a more permanent place/approach we can move it then. Going to go ahead and mark this fixed.
Comment #42
smustgrave commentedLove the new page and image it has other possibilities!
Comment #43
smustgrave commentedCould it be an announcement?