diff --git a/build/target-repository/docs/rector_rules_overview.md b/build/target-repository/docs/rector_rules_overview.md
index e41ae0f3965..b8550568d8e 100644
--- a/build/target-repository/docs/rector_rules_overview.md
+++ b/build/target-repository/docs/rector_rules_overview.md
@@ -1,4 +1,4 @@
-# 352 Rules Overview
+# 353 Rules Overview
@@ -10,7 +10,7 @@
- [CodingStyle](#codingstyle) (27)
-- [DeadCode](#deadcode) (42)
+- [DeadCode](#deadcode) (43)
- [EarlyReturn](#earlyreturn) (9)
@@ -2509,6 +2509,27 @@ Remove initialization with null value from property declarations
+### RemoveNullTagValueNodeRector
+
+Remove `@var/@param/@return` null docblock
+
+- class: [`Rector\DeadCode\Rector\ClassMethod\RemoveNullTagValueNodeRector`](../rules/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector.php)
+
+```diff
+ class SomeClass
+ {
+- /**
+- * @return null
+- */
+ public function foo()
+ {
+ return null;
+ }
+ }
+```
+
+
+
### RemoveParentCallWithoutParentRector
Remove unused parent call with no parent class
diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_param.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_param.php.inc
new file mode 100644
index 00000000000..ca9d474d56a
--- /dev/null
+++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_param.php.inc
@@ -0,0 +1,30 @@
+
+-----
+
diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_return.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_return.php.inc
new file mode 100644
index 00000000000..5279eb21411
--- /dev/null
+++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_return.php.inc
@@ -0,0 +1,30 @@
+
+-----
+
diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_var.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_var.php.inc
new file mode 100644
index 00000000000..f681f440623
--- /dev/null
+++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_var.php.inc
@@ -0,0 +1,24 @@
+
+-----
+
diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_var2.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_var2.php.inc
new file mode 100644
index 00000000000..b92bfa15a05
--- /dev/null
+++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/remove_null_var2.php.inc
@@ -0,0 +1,28 @@
+
+-----
+
diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/skip_different_tag_value.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/skip_different_tag_value.php.inc
new file mode 100644
index 00000000000..1c3e49073c8
--- /dev/null
+++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/Fixture/skip_different_tag_value.php.inc
@@ -0,0 +1,14 @@
+doTestFile($filePath);
+ }
+
+ /**
+ * @return Iterator
+ */
+ public static function provideData(): Iterator
+ {
+ return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
+ }
+
+ public function provideConfigFilePath(): string
+ {
+ return __DIR__ . '/config/configured_rule.php';
+ }
+}
diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/config/configured_rule.php b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/config/configured_rule.php
new file mode 100644
index 00000000000..9f0870d9adc
--- /dev/null
+++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector/config/configured_rule.php
@@ -0,0 +1,10 @@
+rule(RemoveNullTagValueNodeRector::class);
+};
diff --git a/rules/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector.php b/rules/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector.php
new file mode 100644
index 00000000000..242a68f5a5b
--- /dev/null
+++ b/rules/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector.php
@@ -0,0 +1,170 @@
+>
+ */
+ public function getNodeTypes(): array
+ {
+ return [ClassMethod::class, Function_::class, Expression::class, Property::class];
+ }
+
+ private function isNull(VarTagValueNode|ParamTagValueNode|ReturnTagValueNode $tag): bool
+ {
+ return $tag->type instanceof IdentifierTypeNode
+ && $tag->type->__toString() === 'null'
+ && $tag->description === '';
+ }
+
+ /**
+ * @param string[] $paramNames
+ */
+ private function removeParamNullTag(PhpDocInfo $phpDocInfo, array $paramNames): void
+ {
+ $phpDocNodeTraverser = new PhpDocNodeTraverser();
+ $phpDocNodeTraverser->traverseWithCallable(
+ $phpDocInfo->getPhpDocNode(),
+ '',
+ static function (AstNode $astNode) use ($paramNames) : ?int {
+ if (! $astNode instanceof PhpDocTagNode) {
+ return null;
+ }
+
+ if (! $astNode->value instanceof ParamTagValueNode) {
+ return null;
+ }
+
+ if (in_array($astNode->value->parameterName , $paramNames, true)) {
+ return PhpDocNodeTraverser::NODE_REMOVE;
+ }
+
+ return null;
+ });
+ }
+
+ private function processVarTagNull(Expression|Property $node): ?Node
+ {
+ $phpdocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
+ $varTagValueNode = $phpdocInfo->getVarTagValueNode();
+
+ if ($varTagValueNode instanceof VarTagValueNode && $this->isNull($varTagValueNode)) {
+
+ $phpdocInfo->removeByType(VarTagValueNode::class);
+ $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node);
+
+ return $node;
+ }
+
+ return null;
+ }
+
+ /**
+ * @param ClassMethod|Function_|Expression|Property $node
+ */
+ public function refactor(Node $node): ?Node
+ {
+ if ($node instanceof Expression || $node instanceof Property) {
+ return $this->processVarTagNull($node);
+ }
+
+ $phpdocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
+ $removedParamNames = [];
+
+ foreach ($node->params as $param) {
+ $paramName = $this->getName($param);
+ $paramTagValueNode = $phpdocInfo->getParamTagValueByName($paramName);
+
+ if ($paramTagValueNode instanceof ParamTagValueNode && $this->isNull($paramTagValueNode)) {
+ $removedParamNames[] = $paramTagValueNode->parameterName;
+ }
+ }
+
+ $hasRemoved = false;
+ if ($removedParamNames !== []) {
+ $this->removeParamNullTag($phpdocInfo, $removedParamNames);
+ $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node);
+
+ $hasRemoved = true;
+ }
+
+ $returnTagValueNode = $phpdocInfo->getReturnTagValue();
+ if ($returnTagValueNode instanceof ReturnTagValueNode && $this->isNull($returnTagValueNode)) {
+ $phpdocInfo->removeByType(ReturnTagValueNode::class);
+ $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node);
+
+ $hasRemoved = true;
+ }
+
+ if (! $hasRemoved) {
+ return null;
+ }
+
+ return $node;
+ }
+}
diff --git a/utils/Command/MissingInSetCommand.php b/utils/Command/MissingInSetCommand.php
index 659e5ed2ecb..5be75d5d8d7 100644
--- a/utils/Command/MissingInSetCommand.php
+++ b/utils/Command/MissingInSetCommand.php
@@ -6,6 +6,7 @@
use Nette\Utils\Strings;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
+use Rector\DeadCode\Rector\ClassMethod\RemoveNullTagValueNodeRector;
use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector;
use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenCollectorRector;
use Rector\TypeDeclaration\Rector\BooleanAnd\BinaryOpNullableToInstanceofRector;
@@ -34,6 +35,8 @@ final class MissingInSetCommand extends Command
FinalizeClassesWithoutChildrenCollectorRector::class,
// changes behavior, should be applied on purpose regardless PHP 7.3 level
JsonThrowOnErrorRector::class,
+ // in confront with sub type safe belt detection on RemoveUseless*TagRector
+ RemoveNullTagValueNodeRector::class,
];
public function __construct(