diff --git a/crates/compiler/can/src/annotation.rs b/crates/compiler/can/src/annotation.rs index c3fc13e13a..deb85be333 100644 --- a/crates/compiler/can/src/annotation.rs +++ b/crates/compiler/can/src/annotation.rs @@ -127,7 +127,7 @@ pub struct NamedVariable { pub struct AbleVariable { pub variable: Variable, pub name: Lowercase, - pub abilities: Vec, + pub abilities: VecSet, // NB: there may be multiple occurrences of a variable pub first_seen: Region, } @@ -166,7 +166,7 @@ impl IntroducedVariables { self.named.insert(named_variable); } - pub fn insert_able(&mut self, name: Lowercase, var: Loc, abilities: Vec) { + pub fn insert_able(&mut self, name: Lowercase, var: Loc, abilities: VecSet) { self.debug_assert_not_already_present(var.value); let able_variable = AbleVariable { @@ -539,7 +539,11 @@ fn can_annotation_help( // Generate an variable bound to the ability so we can keep compiling. let var = var_store.fresh(); - introduced_variables.insert_able(fresh_ty_var, Loc::at(region, var), vec![symbol]); + introduced_variables.insert_able( + fresh_ty_var, + Loc::at(region, var), + VecSet::singleton(symbol), + ); return Type::Variable(var); } @@ -930,7 +934,7 @@ fn canonicalize_has_clause( ); let var_name = Lowercase::from(var_name); - let mut can_abilities = Vec::with_capacity(abilities.len()); + let mut can_abilities = VecSet::with_capacity(abilities.len()); for &Loc { region, value: ability, @@ -957,10 +961,10 @@ fn canonicalize_has_clause( }; references.insert(ability); - if can_abilities.contains(&ability) { + let already_seen = can_abilities.insert(ability); + + if already_seen { env.problem(roc_problem::can::Problem::DuplicateHasAbility { ability, region }); - } else { - can_abilities.push(ability); } } diff --git a/crates/compiler/can/src/module.rs b/crates/compiler/can/src/module.rs index 24487cea18..0b8e9b6793 100644 --- a/crates/compiler/can/src/module.rs +++ b/crates/compiler/can/src/module.rs @@ -136,7 +136,7 @@ pub struct Module { #[derive(Debug, Default)] pub struct RigidVariables { pub named: MutMap, - pub able: MutMap)>, + pub able: MutMap)>, pub wildcards: VecSet, } diff --git a/crates/compiler/collections/src/vec_set.rs b/crates/compiler/collections/src/vec_set.rs index d5fd02a63c..492fe7014a 100644 --- a/crates/compiler/collections/src/vec_set.rs +++ b/crates/compiler/collections/src/vec_set.rs @@ -1,6 +1,6 @@ use std::{borrow::Borrow, iter::FromIterator}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct VecSet { elements: Vec, } @@ -26,6 +26,12 @@ impl VecSet { } } + pub fn singleton(element: T) -> Self { + Self { + elements: vec![element], + } + } + pub fn len(&self) -> usize { self.elements.len() } @@ -145,3 +151,11 @@ impl From> for VecSet { Self { elements } } } + +impl std::ops::Deref for VecSet { + type Target = [T]; + + fn deref(&self) -> &Self::Target { + &self.elements + } +}