diff --git a/config.xsd b/config.xsd
index 99e0fde33..4d4f377f8 100644
--- a/config.xsd
+++ b/config.xsd
@@ -482,6 +482,7 @@
+
diff --git a/docs/running_psalm/issues.md b/docs/running_psalm/issues.md
index d0e745b38..d9b3b4f16 100644
--- a/docs/running_psalm/issues.md
+++ b/docs/running_psalm/issues.md
@@ -285,6 +285,7 @@
- [UnresolvableInclude](issues/UnresolvableInclude.md)
- [UnsafeGenericInstantiation](issues/UnsafeGenericInstantiation.md)
- [UnsafeInstantiation](issues/UnsafeInstantiation.md)
+ - [UnsupportedPropertyReferenceUsage](issues/UnsupportedPropertyReferenceUsage.md)
- [UnsupportedReferenceUsage](issues/UnsupportedReferenceUsage.md)
- [UnusedBaselineEntry](issues/UnusedBaselineEntry.md)
- [UnusedClass](issues/UnusedClass.md)
diff --git a/docs/running_psalm/issues/UnsupportedPropertyReferenceUsage.md b/docs/running_psalm/issues/UnsupportedPropertyReferenceUsage.md
new file mode 100644
index 000000000..60da066d5
--- /dev/null
+++ b/docs/running_psalm/issues/UnsupportedPropertyReferenceUsage.md
@@ -0,0 +1,40 @@
+# UnsupportedPropertyReferenceUsage
+
+Psalm cannot guarantee the soundness of code that uses references to properties.
+
+### Examples of Uncaught Errors
+
+* Instance property assigned wrong type:
+```php
+b;
+$b = ''; // Fatal error
+```
+
+* Static property assigned wrong type:
+```php
+b;
+$b = 1; // Fatal error
+```
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 70c788cbd..69c518581 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -1,5 +1,5 @@
-
+
tags['variablesfrom'][0]]]>
@@ -114,6 +114,11 @@
$new_property_name
+
+
+ vars_in_scope[$lhs_var_id] = &$context->vars_in_scope[$rhs_var_id]]]>
+
+
$invalid_left_messages[0]
diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php
index 6f0053468..509acb41a 100644
--- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php
+++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php
@@ -56,6 +56,7 @@ use Psalm\Issue\PossiblyUndefinedIntArrayOffset;
use Psalm\Issue\ReferenceConstraintViolation;
use Psalm\Issue\ReferenceReusedFromConfusingScope;
use Psalm\Issue\UnnecessaryVarAnnotation;
+use Psalm\Issue\UnsupportedPropertyReferenceUsage;
use Psalm\IssueBuffer;
use Psalm\Node\Expr\BinaryOp\VirtualBitwiseAnd;
use Psalm\Node\Expr\BinaryOp\VirtualBitwiseOr;
@@ -980,10 +981,18 @@ class AssignmentAnalyzer
$context->references_to_external_scope[$lhs_var_id] = true;
}
if (strpos($rhs_var_id, '->') !== false) {
+ IssueBuffer::maybeAdd(new UnsupportedPropertyReferenceUsage(
+ new CodeLocation($statements_analyzer->getSource(), $stmt),
+ ));
// Reference to object property, we always consider object properties to be an external scope for references
// TODO handle differently so it's detected as unused if the object is unused?
$context->references_to_external_scope[$lhs_var_id] = true;
}
+ if (strpos($rhs_var_id, '::') !== false) {
+ IssueBuffer::maybeAdd(new UnsupportedPropertyReferenceUsage(
+ new CodeLocation($statements_analyzer->getSource(), $stmt),
+ ));
+ }
$lhs_location = new CodeLocation($statements_analyzer->getSource(), $stmt->var);
if (!$stmt->var instanceof ArrayDimFetch && !$stmt->var instanceof PropertyFetch) {
diff --git a/src/Psalm/Issue/UnsupportedPropertyReferenceUsage.php b/src/Psalm/Issue/UnsupportedPropertyReferenceUsage.php
new file mode 100644
index 000000000..a0b0e9d80
--- /dev/null
+++ b/src/Psalm/Issue/UnsupportedPropertyReferenceUsage.php
@@ -0,0 +1,21 @@
+ 'NullArgument',
+ 'ignored_issues' => ['UnsupportedPropertyReferenceUsage'],
],
'assertionOnMagicPropertyWithoutMutationFreeGet' => [
'code' => ' [
'$bar===' => "'bar'",
],
+ 'ignored_issues' => ['UnsupportedPropertyReferenceUsage'],
],
'referenceReassignedInLoop' => [
'code' => ' [
+ 'code' => <<<'PHP'
+ b;
+ $b = ''; // Fatal error
+ PHP,
+ 'error_message' => 'UnsupportedPropertyReferenceUsage',
+ ],
+ 'static property' => [
+ 'code' => <<<'PHP'
+ 'UnsupportedPropertyReferenceUsage',
+ ],
+ 'readonly property' => [
+ 'code' => <<<'PHP'
+ b;
+ $b = 1; // Fatal error
+ PHP,
+ 'error_message' => 'UnsupportedPropertyReferenceUsage',
+ 'error_levels' => [],
+ 'php_version' => '8.1',
+ ],
+ ];
+ }
+}
diff --git a/tests/UnusedVariableTest.php b/tests/UnusedVariableTest.php
index 028dfc6b2..57f1a425d 100644
--- a/tests/UnusedVariableTest.php
+++ b/tests/UnusedVariableTest.php
@@ -1325,6 +1325,8 @@ class UnusedVariableTest extends TestCase
$update = $value;
}
}',
+ 'assertions' => [],
+ 'ignored_issues' => ['UnsupportedPropertyReferenceUsage'],
],
'createdAndUsedInCondition' => [
'code' => '