From d6cb8ee21974bf0544697ed1a5c7d550dc23b9af Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 5 Sep 2020 14:16:26 -0700 Subject: [PATCH] Add lint for attempting to iterate over /datum/foo --- src/dreamchecker/lib.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/dreamchecker/lib.rs b/src/dreamchecker/lib.rs index a6b7517b..3bdaf3a8 100644 --- a/src/dreamchecker/lib.rs +++ b/src/dreamchecker/lib.rs @@ -1312,7 +1312,33 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Statement::ForList { in_list, block, var_type, name, .. } => { let mut scoped_locals = local_vars.clone(); if let Some(in_list) = in_list { - self.visit_expression(location, in_list, None, &mut scoped_locals); + let list = self.visit_expression(location, in_list, None, &mut scoped_locals); + match list.static_ty { + StaticType::None => { + // Occurs extremely often due to DM not complaining about this, with + // over 800 detections on /tg/. Maybe a future lint. + } + StaticType::List { .. } => {/* OK */} + StaticType::Type(ty) => { + if ty != self.objtree.expect("/world") && ty != self.objtree.expect("/list") { + let atom = self.objtree.expect("/atom"); + if ty.is_subtype_of(&atom) { + // Fine. + } else if atom.is_subtype_of(&ty) { + // Iffy conceptually, but the only detections on /tg/ are false positives in the + // component system, where we loop over `var/datum/parent` that is known to be an + // atom in a way that's hard for Dreamchecker to capture. + error(location, "iterating over a /datum which might not be an /atom") + .set_severity(Severity::Hint) + .register(self.context); + } else { + // The type is a /datum/foo subtype that definitely can't be looped over. + error(location, format!("iterating over a {} which cannot be iterated", ty.path)) + .register(self.context); + } + } + } + } } if let Some(var_type) = var_type { self.visit_var(location, var_type, name, None, &mut scoped_locals);