From 69e7d0a37820d6f22a03a7005a9b3c07ace745ff Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 15 May 2022 13:12:13 +0200 Subject: [PATCH] use opt var in cycle marks --- compiler/can/src/def.rs | 5 +---- compiler/can/src/effect_module.rs | 4 ++-- compiler/types/src/subs.rs | 32 +++++++++++++++++++------------ 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index f2707eb405..074c71e83d 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -814,10 +814,7 @@ pub(crate) fn sort_can_defs( debug_assert!(!is_specialization, "Self-recursive specializations can only be determined during solving - but it was determined for {:?} now, that's a bug!", def); // this function calls itself, and must be typechecked as a recursive def - Declaration::DeclareRec( - vec![mark_def_recursive(def)], - IllegalCycleMark::new(var_store), - ) + Declaration::DeclareRec(vec![mark_def_recursive(def)], IllegalCycleMark::empty()) } else { Declaration::Declare(def) }; diff --git a/compiler/can/src/effect_module.rs b/compiler/can/src/effect_module.rs index 101f5ea5e2..d6062647b9 100644 --- a/compiler/can/src/effect_module.rs +++ b/compiler/can/src/effect_module.rs @@ -74,7 +74,7 @@ pub(crate) fn build_effect_builtins( let def = helper!(build_effect_forever); declarations.push(Declaration::DeclareRec( vec![def], - IllegalCycleMark::new(var_store), + IllegalCycleMark::empty(), )); } @@ -83,7 +83,7 @@ pub(crate) fn build_effect_builtins( let def = helper!(build_effect_loop); declarations.push(Declaration::DeclareRec( vec![def], - IllegalCycleMark::new(var_store), + IllegalCycleMark::empty(), )); } diff --git a/compiler/types/src/subs.rs b/compiler/types/src/subs.rs index 6c5f28cba1..374b5aa3c9 100644 --- a/compiler/types/src/subs.rs +++ b/compiler/types/src/subs.rs @@ -926,15 +926,15 @@ pub struct OptVariable(u32); impl OptVariable { pub const NONE: OptVariable = OptVariable(Variable::NULL.0); - pub fn is_none(self) -> bool { - self == OptVariable::NONE + pub const fn is_none(self) -> bool { + self.0 == Self::NONE.0 } - pub fn is_some(self) -> bool { - self != OptVariable::NONE + pub const fn is_some(self) -> bool { + self.0 != Self::NONE.0 } - pub fn into_variable(self) -> Option { + pub const fn into_variable(self) -> Option { if self.is_none() { None } else { @@ -944,7 +944,7 @@ impl OptVariable { pub fn unwrap_or_else(self, or_else: F) -> Variable where - F: Fn() -> Variable, + F: FnOnce() -> Variable, { if self.is_none() { or_else() @@ -1039,23 +1039,31 @@ pub fn new_marks(var_store: &mut VarStore) -> (RedundantMark, ExhaustiveMark) { /// Marks whether a recursive let-cycle was determined to be illegal during solving. #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct IllegalCycleMark(Variable); +pub struct IllegalCycleMark(OptVariable); impl IllegalCycleMark { pub fn new(var_store: &mut VarStore) -> Self { - Self(var_store.fresh()) + Self(OptVariable(var_store.fresh().index())) } - pub fn variable_for_introduction(&self) -> Variable { - self.0 + /// used for recursive blocks with just one function; invalid recursion in such blocks is + /// always a type error, so we don't need to generate a custom error message in such cases + pub const fn empty() -> Self { + Self(OptVariable::NONE) } pub fn set_illegal(&self, subs: &mut Subs) { - subs.set_content(self.0, Content::Error); + if let Some(var) = self.0.into_variable() { + subs.set_content(var, Content::Error); + } } pub fn is_illegal(&self, subs: &Subs) -> bool { - matches!(subs.get_content_without_compacting(self.0), Content::Error) + if let Some(var) = self.0.into_variable() { + matches!(subs.get_content_without_compacting(var), Content::Error) + } else { + false + } } }