Skip to content

Commit c023a79

Browse files
committed
fix(analyzer): fix type flags propagation in iterables
closes #784 Signed-off-by: azjezz <[email protected]>
1 parent 619b225 commit c023a79

File tree

4 files changed

+34
-23
lines changed

4 files changed

+34
-23
lines changed

crates/analyzer/src/resolver/method.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ pub fn resolve_method_targets<'ctx, 'ast, 'arena>(
121121

122122
if object_atomic.is_null() {
123123
result.encountered_null = true;
124-
if !is_null_safe && !block_context.inside_nullsafe_chain {
124+
if !object_type.ignore_nullable_issues() && !is_null_safe && !block_context.inside_nullsafe_chain {
125125
result.has_invalid_target = true;
126126

127127
context.collector.report_with_code(

crates/analyzer/src/statement/loop/mod.rs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ use mago_atom::atom;
1515

1616
use mago_codex::ttype;
1717
use mago_codex::ttype::TType;
18+
use mago_codex::ttype::add_optional_union_type;
1819
use mago_codex::ttype::atomic::TAtomic;
1920
use mago_codex::ttype::atomic::object::TObject;
2021
use mago_codex::ttype::atomic::scalar::TScalar;
2122
use mago_codex::ttype::atomic::scalar::bool::TBool;
2223
use mago_codex::ttype::combine_union_types;
23-
use mago_codex::ttype::combiner::combine;
2424
use mago_codex::ttype::get_array_parameters;
2525
use mago_codex::ttype::get_arraykey;
2626
use mago_codex::ttype::get_iterable_parameters;
@@ -1014,8 +1014,8 @@ fn analyze_iterator<'ctx, 'ast, 'arena>(
10141014
}
10151015

10161016
let mut has_at_least_one_entry = false;
1017-
let mut collected_key_atomics: Vec<TAtomic> = vec![];
1018-
let mut collected_value_atomics: Vec<TAtomic> = vec![];
1017+
let mut key_type = None;
1018+
let mut value_type = None;
10191019
let mut has_valid_iterable_type = false;
10201020
let mut invalid_atomic_ids = Vec::with_capacity(iterator_type.types.len());
10211021

@@ -1035,15 +1035,25 @@ fn analyze_iterator<'ctx, 'ast, 'arena>(
10351035
}
10361036

10371037
let (k, v) = get_array_parameters(array, context.codebase);
1038-
collected_key_atomics.extend(k.types.into_owned());
1039-
collected_value_atomics.extend(v.types.into_owned());
1038+
1039+
key_type = Some(add_optional_union_type(k, key_type.as_ref(), context.codebase));
1040+
value_type = Some(add_optional_union_type(v, value_type.as_ref(), context.codebase));
10401041
}
10411042
TAtomic::Iterable(iterable) => {
10421043
has_valid_iterable_type = true;
10431044
has_at_least_one_entry = false;
10441045

1045-
collected_key_atomics.extend(iterable.key_type.types.iter().cloned());
1046-
collected_value_atomics.extend(iterable.value_type.types.iter().cloned());
1046+
key_type = Some(add_optional_union_type(
1047+
iterable.key_type.as_ref().clone(),
1048+
key_type.as_ref(),
1049+
context.codebase,
1050+
));
1051+
1052+
value_type = Some(add_optional_union_type(
1053+
iterable.value_type.as_ref().clone(),
1054+
value_type.as_ref(),
1055+
context.codebase,
1056+
));
10471057
}
10481058
TAtomic::Object(object) => {
10491059
let (obj_key_type, obj_value_type) = match object {
@@ -1127,8 +1137,8 @@ fn analyze_iterator<'ctx, 'ast, 'arena>(
11271137

11281138
has_valid_iterable_type = true;
11291139

1130-
collected_key_atomics.extend(obj_key_type.types.into_owned());
1131-
collected_value_atomics.extend(obj_value_type.types.into_owned());
1140+
key_type = Some(add_optional_union_type(obj_key_type, key_type.as_ref(), context.codebase));
1141+
value_type = Some(add_optional_union_type(obj_value_type, value_type.as_ref(), context.codebase));
11321142
}
11331143
_ => {
11341144
let iterator_atomic_id = iterator_atomic.get_id();
@@ -1196,19 +1206,7 @@ fn analyze_iterator<'ctx, 'ast, 'arena>(
11961206
return Ok((false, get_mixed(), get_mixed()));
11971207
}
11981208

1199-
let final_key_type = if collected_key_atomics.is_empty() {
1200-
get_mixed()
1201-
} else {
1202-
TUnion::from_vec(combine(collected_key_atomics, context.codebase, false))
1203-
};
1204-
1205-
let final_value_type = if collected_value_atomics.is_empty() {
1206-
get_mixed()
1207-
} else {
1208-
TUnion::from_vec(combine(collected_value_atomics, context.codebase, false))
1209-
};
1210-
1211-
Ok((has_at_least_one_entry, final_key_type, final_value_type))
1209+
Ok((has_at_least_one_entry, key_type.unwrap_or_else(get_mixed), value_type.unwrap_or_else(get_mixed)))
12121210
}
12131211

12141212
/// Scrapes all direct variable names from an expression and indicates if a reference operator (`&`)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
$dir = new DirectoryIterator(__DIR__);
6+
foreach ($dir as $file) {
7+
if ($file->isDot()) {
8+
continue;
9+
}
10+
11+
echo $file->getFilename() . "\n";
12+
}

crates/analyzer/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ test_case!(issue_765);
505505
test_case!(issue_766);
506506
test_case!(issue_776);
507507
test_case!(issue_782);
508+
test_case!(issue_784);
508509
test_case!(issue_785);
509510
test_case!(issue_789);
510511

0 commit comments

Comments
 (0)