From aefcbda194f08682debd3b69948597e9455ca84b Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Wed, 25 Sep 2024 17:42:12 -0700 Subject: [PATCH] Fix invariant(false) handling --- .../expr/call/function_call_analyzer.rs | 6 +--- .../call/function_call_return_type_fetcher.rs | 8 +++++- src/analyzer/stmt/switch_analyzer.rs | 28 ++----------------- .../elseWithInvariantFalse/input.hack | 9 ++++++ 4 files changed, 19 insertions(+), 32 deletions(-) create mode 100644 tests/inference/FunctionCall/elseWithInvariantFalse/input.hack diff --git a/src/analyzer/expr/call/function_call_analyzer.rs b/src/analyzer/expr/call/function_call_analyzer.rs index f06b7c49..b4a0fe43 100644 --- a/src/analyzer/expr/call/function_call_analyzer.rs +++ b/src/analyzer/expr/call/function_call_analyzer.rs @@ -245,6 +245,7 @@ pub(crate) fn analyze( if stmt_type.is_nothing() && !context.inside_loop { context.has_returned = true; context.control_actions.insert(ControlAction::End); + return Ok(()); } match name { @@ -527,11 +528,6 @@ fn process_invariant( statements_analyzer: &StatementsAnalyzer, analysis_data: &mut FunctionAnalysisData, ) { - if first_arg.2 == aast::Expr_::False { - context.has_returned = true; - context.control_actions.insert(ControlAction::End); - return; - } let assertion_context = statements_analyzer.get_assertion_context( context.function_context.calling_class.as_ref(), context.function_context.calling_functionlike_id.as_ref(), diff --git a/src/analyzer/expr/call/function_call_return_type_fetcher.rs b/src/analyzer/expr/call/function_call_return_type_fetcher.rs index c5fcc162..d5d98800 100644 --- a/src/analyzer/expr/call/function_call_return_type_fetcher.rs +++ b/src/analyzer/expr/call/function_call_return_type_fetcher.rs @@ -28,7 +28,6 @@ use std::sync::Arc; use crate::expr::binop::concat_analyzer::{analyze_concat_nodes, get_concat_nodes}; use crate::expr::fetch::array_fetch_analyzer::handle_array_access_on_dict; -use crate::expr::variable_fetch_analyzer; use crate::function_analysis_data::FunctionAnalysisData; use crate::scope::BlockContext; use crate::scope_analyzer::ScopeAnalyzer; @@ -172,6 +171,13 @@ fn handle_special_functions( context: &mut BlockContext, ) -> Option { match name { + &StrId::INVARIANT => { + if let Some((_, aast::Expr(_, _, aast::Expr_::False))) = args.first() { + Some(get_nothing()) + } else { + None + } + } &StrId::TYPE_STRUCTURE_FN => { if let (Some((_, first_arg_expr)), Some((_, second_arg_expr))) = (args.first(), args.get(1)) diff --git a/src/analyzer/stmt/switch_analyzer.rs b/src/analyzer/stmt/switch_analyzer.rs index fd0684d0..f90b0c40 100644 --- a/src/analyzer/stmt/switch_analyzer.rs +++ b/src/analyzer/stmt/switch_analyzer.rs @@ -1,9 +1,7 @@ -use hakana_code_info::codebase_info::CodebaseInfo; use hakana_code_info::ttype::{combine_union_types, get_mixed_any}; -use hakana_str::{Interner, StrId}; + use indexmap::IndexMap; use oxidized::{aast, aast::Pos}; -use rustc_hash::{FxHashMap, FxHashSet}; use std::rc::Rc; use crate::{ @@ -19,11 +17,7 @@ use crate::{ stmt_analyzer::AnalysisError, }; -use super::{ - control_analyzer::{self, BreakContext}, - if_conditional_analyzer::add_branch_dataflow, - switch_case_analyzer::analyze_case, -}; +use super::{if_conditional_analyzer::add_branch_dataflow, switch_case_analyzer::analyze_case}; pub(crate) fn analyze( statements_analyzer: &StatementsAnalyzer, @@ -89,8 +83,6 @@ pub(crate) fn analyze( let original_context = context.clone(); - let mut last_case_exit_type = ControlAction::Break; - let has_default = stmt.2.is_some(); let mut cases = stmt.1.iter().enumerate().collect::>(); @@ -195,19 +187,3 @@ pub(crate) fn analyze( Ok(()) } - -fn get_last_action(case_actions: FxHashSet) -> Option { - if !case_actions.contains(&ControlAction::None) { - if case_actions.len() == 1 && case_actions.contains(&ControlAction::End) { - return Some(ControlAction::Return); - } else if case_actions.len() == 1 && case_actions.contains(&ControlAction::Continue) { - return Some(ControlAction::Continue); - } else if case_actions.contains(&ControlAction::LeaveSwitch) { - return Some(ControlAction::Break); - } - } else if case_actions.len() != 1 { - return Some(ControlAction::Break); - } - - None -} diff --git a/tests/inference/FunctionCall/elseWithInvariantFalse/input.hack b/tests/inference/FunctionCall/elseWithInvariantFalse/input.hack new file mode 100644 index 00000000..6d88cbaa --- /dev/null +++ b/tests/inference/FunctionCall/elseWithInvariantFalse/input.hack @@ -0,0 +1,9 @@ +function foo(): void { + if (rand(0, 1)) { + $a = 5; + } else { + invariant(false, 'bad'); + } + + echo $a; +} \ No newline at end of file