Skip to content

Commit

Permalink
Immutable readonly 2
Browse files Browse the repository at this point in the history
  • Loading branch information
danog committed Oct 3, 2022
1 parent 5984ccd commit 45452c7
Show file tree
Hide file tree
Showing 30 changed files with 294 additions and 253 deletions.
6 changes: 2 additions & 4 deletions src/Psalm/Internal/Analyzer/ClassAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,7 @@ public function analyze(
$mixins = array_merge($storage->templatedMixins, $storage->namedMixins);
$union = new Union($mixins);

$static_self = new TNamedObject($storage->name);
$static_self->is_static = true;
$static_self = new TNamedObject($storage->name, true);

$union = TypeExpander::expandUnion(
$codebase,
Expand Down Expand Up @@ -1223,8 +1222,7 @@ static function (FunctionLikeParameter $param): PhpParser\Node\Arg {
$method_context->collect_nonprivate_initializations = !$uninitialized_private_properties;
$method_context->self = $fq_class_name;

$this_atomic_object_type = new TNamedObject($fq_class_name);
$this_atomic_object_type->is_static = !$storage->final;
$this_atomic_object_type = new TNamedObject($fq_class_name, !$storage->final);

$method_context->vars_in_scope['$this'] = new Union([$this_atomic_object_type]);
$method_context->vars_possibly_in_scope['$this'] = true;
Expand Down
3 changes: 1 addition & 2 deletions src/Psalm/Internal/Analyzer/ClosureAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ public static function analyzeExpression(
/** @psalm-suppress PossiblyUndefinedStringArrayOffset */
$use_context->vars_in_scope['$this'] = clone $context->vars_in_scope['$this'];
} elseif ($context->self) {
$this_atomic = new TNamedObject($context->self);
$this_atomic->is_static = true;
$this_atomic = new TNamedObject($context->self, true);

$use_context->vars_in_scope['$this'] = new Union([$this_atomic]);
}
Expand Down
20 changes: 10 additions & 10 deletions src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -1826,14 +1826,17 @@ private function getFunctionInformation(

$this_object_type = new TGenericObject(
$context->self,
$template_params
$template_params,
false,
!$storage->final
);
} else {
$this_object_type = new TNamedObject($context->self);
$this_object_type = new TNamedObject(
$context->self,
!$storage->final
);
}

$this_object_type->is_static = !$storage->final;

if ($this->storage instanceof MethodStorage && $this->storage->if_this_is_type) {
$template_result = new TemplateResult($this->getTemplateTypeMap() ?? [], []);

Expand Down Expand Up @@ -1984,14 +1987,11 @@ private function getFunctionInformation(
$closure_type = new TClosure(
'Closure',
$storage->params,
$closure_return_type
$closure_return_type,
$storage instanceof FunctionStorage ? $storage->pure : null,
$storage instanceof FunctionStorage ? $storage->byref_uses : [],
);

if ($storage instanceof FunctionStorage) {
$closure_type->byref_uses = $storage->byref_uses;
$closure_type->is_pure = $storage->pure;
}

$type_provider->setType(
$this->function,
new Union([
Expand Down
13 changes: 5 additions & 8 deletions src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -550,11 +550,8 @@ public static function checkIteratorType(
}
} elseif ($iterator_atomic_type instanceof TIterable) {
if ($iterator_atomic_type->extra_types) {
$iterator_atomic_type_copy = clone $iterator_atomic_type;
$iterator_atomic_type_copy->extra_types = [];
$iterator_atomic_types = [$iterator_atomic_type_copy];
$iterator_atomic_types = array_merge(
$iterator_atomic_types,
[$iterator_atomic_type->setIntersectionTypes([])],
$iterator_atomic_type->extra_types
);
} else {
Expand Down Expand Up @@ -736,10 +733,10 @@ public static function handleIterable(
bool &$has_valid_iterator
): void {
if ($iterator_atomic_type->extra_types) {
$iterator_atomic_type_copy = clone $iterator_atomic_type;
$iterator_atomic_type_copy->extra_types = [];
$iterator_atomic_types = [$iterator_atomic_type_copy];
$iterator_atomic_types = array_merge($iterator_atomic_types, $iterator_atomic_type->extra_types);
$iterator_atomic_types = array_merge(
[$iterator_atomic_type->setIntersectionTypes([])],
$iterator_atomic_type->extra_types
);
} else {
$iterator_atomic_types = [$iterator_atomic_type];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,14 @@ public static function analyze(

// if this array looks like an object-like array, let's return that instead
if (count($array_creation_info->property_types) !== 0) {
$atomic_type = new TKeyedArray($array_creation_info->property_types, $array_creation_info->class_strings);
if ($array_creation_info->can_create_objectlike) {
$atomic_type->sealed = true;
} else {
$atomic_type->previous_key_type = $item_key_type ?? Type::getArrayKey();
$atomic_type->previous_value_type = $item_value_type ?? Type::getMixed();
}
$atomic_type->is_list = $array_creation_info->all_list;
$atomic_type = new TKeyedArray(
$array_creation_info->property_types,
$array_creation_info->class_strings,
$array_creation_info->can_create_objectlike,
$array_creation_info->can_create_objectlike ? null : ($item_key_type ?? Type::getArrayKey()),
$array_creation_info->can_create_objectlike ? null : ($item_value_type ?? Type::getMixed()),
$array_creation_info->all_list
);

$stmt_type = new Union([$atomic_type]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,11 @@ private static function updateTypeWithKeyValues(
&& $key_value instanceof TLiteralInt
&& count($key_values) === 1
) {
$count = ($type->count ?? $type->min_count) ?? 1;
if ($key_value->value >= $count) {
continue;
}

$has_matching_objectlike_property = true;

$type->type_param = Type::combineUnionTypes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,11 @@ private static function analyzeOperands(
}
}

$new_keyed_array = new TKeyedArray($properties);
$new_keyed_array->sealed = $left_type_part->sealed && $right_type_part->sealed;
$new_keyed_array = new TKeyedArray(
$properties,
null,
$left_type_part->sealed && $right_type_part->sealed
);
$result_type_member = new Union([$new_keyed_array]);
} else {
$result_type_member = TypeCombiner::combine(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ public static function analyze(
foreach ($stmt_expr_type->getAtomicTypes() as $type_string => $type_part) {
if ($type_part instanceof TInt || $type_part instanceof TString) {
if ($type_part instanceof TLiteralInt) {
$type_part->value = ~$type_part->value;
$type_part = new TLiteralInt(~$type_part->value);
} elseif ($type_part instanceof TLiteralString) {
$type_part->value = ~$type_part->value;
$type_part = new TLiteralString(~$type_part->value);
}

$acceptable_types[] = $type_part;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
use Psalm\Type\Atomic\TList;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Atomic\TNamedObject;
use Psalm\Type\Atomic\TNonEmptyList;
use Psalm\Type\Union;

use function count;
Expand Down Expand Up @@ -1351,21 +1352,30 @@ private static function coerceValueAfterGatekeeperArgument(
}

if (!$input_type_changed && $param_type->from_docblock && !$input_type->hasMixed()) {
$input_type = clone $input_type;

$types = $input_type->getAtomicTypes();
foreach ($param_type->getAtomicTypes() as $param_atomic_type) {
if ($param_atomic_type instanceof TGenericObject) {
foreach ($input_type->getAtomicTypes() as $input_atomic_type) {
foreach ($types as &$input_atomic_type) {
if ($input_atomic_type instanceof TGenericObject
&& $input_atomic_type->value === $param_atomic_type->value
) {
$new_type_params = [];
foreach ($input_atomic_type->type_params as $i => $type_param) {
if ($type_param->isNever() && isset($param_atomic_type->type_params[$i])) {
$input_type_changed = true;

$input_atomic_type->type_params[$i] = clone $param_atomic_type->type_params[$i];
$new_type_params[$i] = $param_atomic_type->type_params[$i];
}
}
if ($new_type_params) {
$input_atomic_type = new TGenericObject(
$input_atomic_type->value,
[...$input_atomic_type->type_params, ...$new_type_params],
$input_atomic_type->remapped_params,
false,
$input_atomic_type->extra_types
);
}
}
}
}
Expand All @@ -1374,6 +1384,8 @@ private static function coerceValueAfterGatekeeperArgument(
if (!$input_type_changed) {
return;
}

$input_type = new Union($types);
}

$var_id = ExpressionIdentifier::getVarId(
Expand Down Expand Up @@ -1429,20 +1441,24 @@ private static function coerceValueAfterGatekeeperArgument(

if ($unpack) {
if ($unpacked_atomic_array instanceof TList) {
$unpacked_atomic_array = clone $unpacked_atomic_array;
$unpacked_atomic_array->type_param = $input_type;
$unpacked_atomic_array = $unpacked_atomic_array->replaceTypeParam($input_type);

$context->vars_in_scope[$var_id] = new Union([$unpacked_atomic_array]);
} elseif ($unpacked_atomic_array instanceof TArray) {
$unpacked_atomic_array = clone $unpacked_atomic_array;
$unpacked_atomic_array->type_params[1] = $input_type;
$unpacked_atomic_array = $unpacked_atomic_array->replaceTypeParams([
$unpacked_atomic_array->type_params[0],
$input_type
]);

$context->vars_in_scope[$var_id] = new Union([$unpacked_atomic_array]);
} elseif ($unpacked_atomic_array instanceof TKeyedArray
&& $unpacked_atomic_array->is_list
) {
$unpacked_atomic_array = $unpacked_atomic_array->getList();
$unpacked_atomic_array->type_param = $input_type;
if ($unpacked_atomic_array->isNonEmpty()) {
$unpacked_atomic_array = new TNonEmptyList($input_type);
} else {
$unpacked_atomic_array = new TList($input_type);
}

$context->vars_in_scope[$var_id] = new Union([$unpacked_atomic_array]);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@

use function array_filter;
use function array_shift;
use function array_unshift;
use function assert;
use function count;
use function explode;
Expand Down Expand Up @@ -300,9 +299,10 @@ public static function handleAddition(
);
} else {
if ($objectlike_list) {
array_unshift($objectlike_list->properties, $arg_value_type);
$properties = $objectlike_list->properties;
array_unshift($properties, $arg_value_type);

$by_ref_type = new Union([$objectlike_list]);
$by_ref_type = new Union([$objectlike_list->setProperties($properties)]);
} elseif ($array_type instanceof TList) {
$by_ref_type = Type::combineUnionTypes(
$by_ref_type,
Expand Down Expand Up @@ -844,9 +844,6 @@ private static function checkClosureTypeArgs(
&& $closure_type->return_type
&& $closure_param_type->hasTemplate()
) {
$closure_param_type = clone $closure_param_type;
$closure_type->return_type = clone $closure_type->return_type;

$template_result = new TemplateResult(
[],
[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,7 @@ private static function getReturnTypeFromCallMapWithArgs(
$keyed_array = new TKeyedArray([
Type::getInt(),
Type::getInt()
]);
$keyed_array->sealed = true;
$keyed_array->is_list = true;
], null, true, null, null, true);
return new Union([$keyed_array]);

case 'get_called_class':
Expand Down Expand Up @@ -441,9 +439,7 @@ private static function getReturnTypeFromCallMapWithArgs(
$keyed_array = new TKeyedArray([
Type::getInt(),
Type::getInt()
]);
$keyed_array->sealed = true;
$keyed_array->is_list = true;
], null, true, null, null, true);

if ((string) $first_arg_type === 'false') {
return new Union([$keyed_array]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ public static function analyze(
$lhs_type_part->from_docblock = true;

if ($lhs_type_part instanceof TNamedObject) {
$lhs_type_part->extra_types = $extra_types;
$lhs_type_part = $lhs_type_part->setIntersectionTypes($extra_types);
} elseif ($lhs_type_part instanceof TObject && $extra_types) {
$lhs_type_part = array_shift($extra_types);
if ($extra_types) {
$lhs_type_part->extra_types = $extra_types;
$lhs_type_part = $lhs_type_part->setIntersectionTypes($extra_types);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -525,11 +525,11 @@ private static function analyzeNamedConstructor(
if ($generic_param_types) {
$result_atomic_type = new TGenericObject(
$fq_class_name,
$generic_param_types
$generic_param_types,
false,
$from_static
);

$result_atomic_type->is_static = $from_static;

$statements_analyzer->node_data->setType(
$stmt,
new Union([$result_atomic_type])
Expand All @@ -552,11 +552,11 @@ private static function analyzeNamedConstructor(
static fn($map) => clone reset($map),
$storage->template_types
)
)
),
false,
$from_static
);

$result_atomic_type->is_static = $from_static;

$statements_analyzer->node_data->setType(
$stmt,
new Union([$result_atomic_type])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,7 @@ public static function analyze(

foreach ($stmt_expr_type->getAtomicTypes() as $type) {
if ($type instanceof Scalar) {
$keyed_array = new TKeyedArray([new Union([$type])]);
$keyed_array->is_list = true;
$keyed_array->sealed = true;
$keyed_array = new TKeyedArray([new Union([$type])], null, true, null, null, true);
$permissible_atomic_types[] = $keyed_array;
} elseif ($type instanceof TNull) {
$permissible_atomic_types[] = new TArray([Type::getNever(), Type::getNever()]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,7 @@ public static function analyzeFetch(
}

if ($first_part_lc === 'static') {
$static_named_object = new TNamedObject($fq_class_name);
$static_named_object->is_static = true;
$static_named_object = new TNamedObject($fq_class_name, true);

$statements_analyzer->node_data->setType(
$stmt,
Expand Down

0 comments on commit 45452c7

Please sign in to comment.