mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 13:51:54 +01:00
Merge pull request #7106 from orklah/7098
fix reconciliation between positive-int and inferior/superior assertions
This commit is contained in:
commit
604f47d52a
@ -1638,8 +1638,7 @@ class SimpleAssertionReconciler extends Reconciler
|
|||||||
}
|
}
|
||||||
$existing_var_type->addType($atomic_type);
|
$existing_var_type->addType($atomic_type);
|
||||||
} elseif ($atomic_type instanceof Atomic\TLiteralInt) {
|
} elseif ($atomic_type instanceof Atomic\TLiteralInt) {
|
||||||
$new_range = new Atomic\TIntRange($assertion_value, null);
|
if ($atomic_type->value < $assertion_value) {
|
||||||
if (!$new_range->contains($atomic_type->value)) {
|
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
} /*elseif ($inside_loop) {
|
} /*elseif ($inside_loop) {
|
||||||
//when inside a loop, allow the range to extends the type
|
//when inside a loop, allow the range to extends the type
|
||||||
@ -1651,11 +1650,10 @@ class SimpleAssertionReconciler extends Reconciler
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
} elseif ($atomic_type instanceof Atomic\TPositiveInt) {
|
} elseif ($atomic_type instanceof Atomic\TPositiveInt) {
|
||||||
if ($assertion_value <= 0) {
|
if ($assertion_value > 1) {
|
||||||
//emit an issue here in the future about incompatible type
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
|
$existing_var_type->addType(new Atomic\TIntRange($assertion_value, null));
|
||||||
}
|
}
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
|
||||||
$existing_var_type->addType(new Atomic\TIntRange($assertion_value, null));
|
|
||||||
} elseif ($atomic_type instanceof TInt) {
|
} elseif ($atomic_type instanceof TInt) {
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
$existing_var_type->addType(new Atomic\TIntRange($assertion_value, null));
|
$existing_var_type->addType(new Atomic\TIntRange($assertion_value, null));
|
||||||
@ -1685,10 +1683,9 @@ class SimpleAssertionReconciler extends Reconciler
|
|||||||
}
|
}
|
||||||
$existing_var_type->addType($atomic_type);
|
$existing_var_type->addType($atomic_type);
|
||||||
} elseif ($atomic_type instanceof Atomic\TLiteralInt) {
|
} elseif ($atomic_type instanceof Atomic\TLiteralInt) {
|
||||||
$new_range = new Atomic\TIntRange(null, $assertion_value);
|
if ($atomic_type->value > $assertion_value) {
|
||||||
if (!$new_range->contains($atomic_type->value)) {
|
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
}/* elseif ($inside_loop) {
|
} /* elseif ($inside_loop) {
|
||||||
//when inside a loop, allow the range to extends the type
|
//when inside a loop, allow the range to extends the type
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
if ($atomic_type->value < $assertion_value) {
|
if ($atomic_type->value < $assertion_value) {
|
||||||
@ -1698,11 +1695,10 @@ class SimpleAssertionReconciler extends Reconciler
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
} elseif ($atomic_type instanceof Atomic\TPositiveInt) {
|
} elseif ($atomic_type instanceof Atomic\TPositiveInt) {
|
||||||
if ($assertion_value <= 0) {
|
|
||||||
//emit an issue here in the future about incompatible type
|
|
||||||
}
|
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
$existing_var_type->addType(new Atomic\TIntRange(1, $assertion_value));
|
if ($assertion_value >= 1) {
|
||||||
|
$existing_var_type->addType(new Atomic\TIntRange(1, $assertion_value));
|
||||||
|
}
|
||||||
} elseif ($atomic_type instanceof TInt) {
|
} elseif ($atomic_type instanceof TInt) {
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
$existing_var_type->addType(new Atomic\TIntRange(null, $assertion_value));
|
$existing_var_type->addType(new Atomic\TIntRange(null, $assertion_value));
|
||||||
|
@ -1519,9 +1519,7 @@ class SimpleNegatedAssertionReconciler extends Reconciler
|
|||||||
}
|
}
|
||||||
$existing_var_type->addType($atomic_type);
|
$existing_var_type->addType($atomic_type);
|
||||||
} elseif ($atomic_type instanceof Atomic\TLiteralInt) {
|
} elseif ($atomic_type instanceof Atomic\TLiteralInt) {
|
||||||
$new_range = new Atomic\TIntRange(null, $assertion_value);
|
if ($atomic_type->value > $assertion_value) {
|
||||||
if (!$new_range->contains($atomic_type->value)) {
|
|
||||||
//emit an issue here in the future about incompatible type
|
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
} /*elseif ($inside_loop) {
|
} /*elseif ($inside_loop) {
|
||||||
//when inside a loop, allow the range to extends the type
|
//when inside a loop, allow the range to extends the type
|
||||||
@ -1533,11 +1531,10 @@ class SimpleNegatedAssertionReconciler extends Reconciler
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
} elseif ($atomic_type instanceof Atomic\TPositiveInt) {
|
} elseif ($atomic_type instanceof Atomic\TPositiveInt) {
|
||||||
if ($assertion_value > 0) {
|
|
||||||
//emit an issue here in the future about incompatible type
|
|
||||||
}
|
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
$existing_var_type->addType(new Atomic\TIntRange(null, $assertion_value));
|
if ($assertion_value >= 1) {
|
||||||
|
$existing_var_type->addType(new Atomic\TIntRange(1, $assertion_value));
|
||||||
|
}
|
||||||
} elseif ($atomic_type instanceof TInt) {
|
} elseif ($atomic_type instanceof TInt) {
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
$existing_var_type->addType(new Atomic\TIntRange(null, $assertion_value));
|
$existing_var_type->addType(new Atomic\TIntRange(null, $assertion_value));
|
||||||
@ -1564,11 +1561,9 @@ class SimpleNegatedAssertionReconciler extends Reconciler
|
|||||||
}
|
}
|
||||||
$existing_var_type->addType($atomic_type);
|
$existing_var_type->addType($atomic_type);
|
||||||
} elseif ($atomic_type instanceof Atomic\TLiteralInt) {
|
} elseif ($atomic_type instanceof Atomic\TLiteralInt) {
|
||||||
$new_range = new Atomic\TIntRange($assertion_value, null);
|
if ($atomic_type->value < $assertion_value) {
|
||||||
if (!$new_range->contains($atomic_type->value)) {
|
|
||||||
//emit an issue here in the future about incompatible type
|
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
}/* elseif ($inside_loop) {
|
} /* elseif ($inside_loop) {
|
||||||
//when inside a loop, allow the range to extends the type
|
//when inside a loop, allow the range to extends the type
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
if ($atomic_type->value < $assertion_value) {
|
if ($atomic_type->value < $assertion_value) {
|
||||||
@ -1578,11 +1573,10 @@ class SimpleNegatedAssertionReconciler extends Reconciler
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
} elseif ($atomic_type instanceof Atomic\TPositiveInt) {
|
} elseif ($atomic_type instanceof Atomic\TPositiveInt) {
|
||||||
if ($assertion_value > 0) {
|
if ($assertion_value > 1) {
|
||||||
//emit an issue here in the future about incompatible type
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
|
$existing_var_type->addType(new Atomic\TIntRange($assertion_value, null));
|
||||||
}
|
}
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
|
||||||
$existing_var_type->addType(new Atomic\TIntRange($assertion_value, 1));
|
|
||||||
} elseif ($atomic_type instanceof TInt) {
|
} elseif ($atomic_type instanceof TInt) {
|
||||||
$existing_var_type->removeType($atomic_type->getKey());
|
$existing_var_type->removeType($atomic_type->getKey());
|
||||||
$existing_var_type->addType(new Atomic\TIntRange($assertion_value, null));
|
$existing_var_type->addType(new Atomic\TIntRange($assertion_value, null));
|
||||||
|
@ -106,6 +106,10 @@ class TIntRange extends TInt
|
|||||||
*/
|
*/
|
||||||
public static function convertToIntRange(TInt $int_atomic): TIntRange
|
public static function convertToIntRange(TInt $int_atomic): TIntRange
|
||||||
{
|
{
|
||||||
|
if ($int_atomic instanceof TIntRange) {
|
||||||
|
return $int_atomic;
|
||||||
|
}
|
||||||
|
|
||||||
if ($int_atomic instanceof TPositiveInt) {
|
if ($int_atomic instanceof TPositiveInt) {
|
||||||
return new TIntRange(1, null);
|
return new TIntRange(1, null);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ use Psalm\Storage\FileStorage;
|
|||||||
use Psalm\Type;
|
use Psalm\Type;
|
||||||
use Psalm\Type\Atomic\TFloat;
|
use Psalm\Type\Atomic\TFloat;
|
||||||
use Psalm\Type\Atomic\TInt;
|
use Psalm\Type\Atomic\TInt;
|
||||||
|
use Psalm\Type\Atomic\TIntRange;
|
||||||
use Psalm\Type\Atomic\TLiteralFloat;
|
use Psalm\Type\Atomic\TLiteralFloat;
|
||||||
use Psalm\Type\Atomic\TLiteralInt;
|
use Psalm\Type\Atomic\TLiteralInt;
|
||||||
use Psalm\Type\Atomic\TLiteralString;
|
use Psalm\Type\Atomic\TLiteralString;
|
||||||
@ -280,8 +281,12 @@ class Union implements TypeNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($type instanceof TInt && $this->literal_int_types) {
|
} elseif ($type instanceof TInt && $this->literal_int_types) {
|
||||||
foreach ($this->literal_int_types as $key => $_) {
|
//we remove any literal that is already included in a wider type
|
||||||
unset($this->literal_int_types[$key], $this->types[$key]);
|
$int_type_in_range = TIntRange::convertToIntRange($type);
|
||||||
|
foreach ($this->literal_int_types as $key => $literal_int_type) {
|
||||||
|
if ($int_type_in_range->contains($literal_int_type->value)) {
|
||||||
|
unset($this->literal_int_types[$key], $this->types[$key]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} elseif ($type instanceof TFloat && $this->literal_float_types) {
|
} elseif ($type instanceof TFloat && $this->literal_float_types) {
|
||||||
foreach ($this->literal_float_types as $key => $_) {
|
foreach ($this->literal_float_types as $key => $_) {
|
||||||
|
@ -644,6 +644,30 @@ class IntRangeTest extends TestCase
|
|||||||
}
|
}
|
||||||
}',
|
}',
|
||||||
],
|
],
|
||||||
|
'positiveIntToRangeWithInferior' => [
|
||||||
|
'<?php
|
||||||
|
/** @var positive-int $length */
|
||||||
|
$length = 0;
|
||||||
|
|
||||||
|
if ($length < 8) {
|
||||||
|
throw new \RuntimeException();
|
||||||
|
}',
|
||||||
|
'assertions' => [
|
||||||
|
'$length===' => 'int<8, max>',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'positiveIntToRangeWithSuperiorOrEqual' => [
|
||||||
|
'<?php
|
||||||
|
/** @var positive-int $length */
|
||||||
|
$length = 0;
|
||||||
|
|
||||||
|
if ($length >= 8) {
|
||||||
|
throw new \RuntimeException();
|
||||||
|
}',
|
||||||
|
'assertions' => [
|
||||||
|
'$length===' => 'int<1, 7>',
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user