From 74b9416174e1bc24d1e7d92f13e548b7024070d4 Mon Sep 17 00:00:00 2001 From: z78078 Date: Wed, 17 Aug 2022 17:44:17 +0800 Subject: [PATCH] nac3core: add fields initialization check for parent class --- nac3core/src/toplevel/composer.rs | 39 +++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index 16f508a7..63a213e4 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -1509,6 +1509,7 @@ impl TopLevelComposer { } let mut errors = HashSet::new(); + let mut inited_fields_cache: HashMap> = HashMap::new(); let mut analyze = |i, def: &Arc>, ast: &Option| { let class_def = def.read(); if let TopLevelDef::Class { @@ -1617,12 +1618,42 @@ impl TopLevelComposer { if *name != init_str_id { unreachable!("must be init function here") } - let all_inited = Self::get_all_assigned_field(body.as_slice())?; - for (f, _, _) in fields { - if !all_inited.contains(f) { + + let locally_inited_fields = Self::get_all_assigned_field(body.as_slice())?; + for field in locally_inited_fields.iter() { + inited_fields_cache + .entry(*object_id) + .and_modify(|v| v.push(*field)) + .or_insert(vec![*field]); + } + + let not_locally_inited_fields = fields + .iter() + .filter_map(|(field, _, _)| if !locally_inited_fields.contains(field) { Some(*field) } else { None } ); + + let mut ancestors_id = ancestors + .iter() + .skip(1) + .filter_map(|ancestor| { + match ancestor { + TypeAnnotation::CustomClass { id, .. } => Some(*id), + _ => None + } + }); + + for field in not_locally_inited_fields { + let ancestor_inited = ancestors_id.any(|id| { + if let Some(ancestor_inited_fields) = inited_fields_cache.get(&id) { + ancestor_inited_fields.contains(&field) + } else { + false + } + }); + + if !ancestor_inited { return Err(format!( "fields `{}` of class `{}` not fully initialized in the initializer (at {})", - f, + field, class_name, body[0].location, ));