From fa7dec29979094ac9ed88c42b8e1eeebf6a02936 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 4 Apr 2021 21:22:59 +0200 Subject: [PATCH] no more boolean algebra --- compiler/builtins/src/unique.rs | 1413 ------------------------- compiler/can/src/scope.rs | 2 - compiler/mono/src/ir.rs | 4 +- compiler/mono/src/layout.rs | 46 - compiler/reporting/src/error/type.rs | 2 - compiler/solve/src/solve.rs | 53 - compiler/types/src/boolean_algebra.rs | 214 ---- compiler/types/src/lib.rs | 1 - compiler/types/src/pretty_print.rs | 76 -- compiler/types/src/solved_types.rs | 48 - compiler/types/src/subs.rs | 35 +- compiler/types/src/types.rs | 101 +- compiler/unify/src/unify.rs | 74 +- 13 files changed, 10 insertions(+), 2059 deletions(-) delete mode 100644 compiler/builtins/src/unique.rs delete mode 100644 compiler/types/src/boolean_algebra.rs diff --git a/compiler/builtins/src/unique.rs b/compiler/builtins/src/unique.rs deleted file mode 100644 index 38f88de8fb..0000000000 --- a/compiler/builtins/src/unique.rs +++ /dev/null @@ -1,1413 +0,0 @@ -use crate::std::StdLib; -use roc_collections::all::{default_hasher, MutMap}; -use roc_module::ident::TagName; -use roc_module::symbol::Symbol; -use roc_region::all::Region; -use roc_types::builtin_aliases; -use roc_types::solved_types::{SolvedBool, SolvedType}; -use roc_types::subs::VarId; -use std::collections::HashMap; - -/// Example: -/// -/// let_tvars! { a, b, c } -/// -/// This is equivalent to: -/// -/// let a = VarId::from_u32(1); -/// let b = VarId::from_u32(2); -/// let c = VarId::from_u32(3); -/// -/// The idea is that this is less error-prone than assigning hardcoded IDs by hand. -macro_rules! let_tvars { - ($($name:ident,)+) => { let_tvars!($($name),+) }; - ($($name:ident),*) => { - let mut _current_tvar = 0; - - $( - _current_tvar += 1; - - let $name = VarId::from_u32(_current_tvar); - )* - }; -} - -/// Keep this up to date by hand! -/// -const NUM_BUILTIN_IMPORTS: usize = 7; - -/// These can be shared between definitions, they will get instantiated when converted to Type -const FUVAR: VarId = VarId::from_u32(1000); -const TOP_LEVEL_CLOSURE_VAR: VarId = VarId::from_u32(1001); - -fn shared(base: SolvedType) -> SolvedType { - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![SolvedType::Boolean(SolvedBool::SolvedShared), base], - ) -} - -fn boolean(b: VarId) -> SolvedType { - SolvedType::Boolean(SolvedBool::SolvedContainer(b, vec![])) -} - -fn container(cvar: VarId, mvars: Vec) -> SolvedType { - SolvedType::Boolean(SolvedBool::SolvedContainer(cvar, mvars)) -} - -pub fn uniq_stdlib() -> StdLib { - use crate::std::Mode; - - let types = types(); - - /* - debug_assert!({ - let normal_types: MutSet = builtins::types().keys().copied().collect(); - let normal_aliases: MutSet = builtins::aliases().keys().copied().collect(); - - let unique_types = types.keys().copied().collect(); - let unique_aliases = aliases.keys().copied().collect(); - - let missing_unique_types: MutSet = - normal_types.difference(&unique_types).copied().collect(); - let missing_normal_types: MutSet = - unique_types.difference(&normal_types).copied().collect(); - - let missing_unique_aliases: MutSet = normal_aliases - .difference(&unique_aliases) - .copied() - .collect(); - let missing_normal_aliases: MutSet = unique_aliases - .difference(&normal_aliases) - .copied() - .filter(|v| *v != Symbol::ATTR_ATTR) - .collect(); - - let cond = missing_normal_types.is_empty() - && missing_unique_types.is_empty() - && missing_normal_aliases.is_empty() - && missing_unique_aliases.is_empty(); - - if !cond { - println!("Missing hardcoded types for:"); - println!("normal types: {:?}", missing_normal_types); - println!("unique types: {:?}", missing_unique_types); - println!("normal aliases: {:?}", missing_normal_aliases); - println!("unique aliases: {:?}", missing_unique_aliases); - } - - cond - }); - */ - - StdLib { - mode: Mode::Uniqueness, - types, - applies: vec![ - Symbol::ATTR_ATTR, - Symbol::LIST_LIST, - Symbol::SET_SET, - Symbol::DICT_DICT, - Symbol::STR_STR, - ] - .into_iter() - .collect(), - } -} - -pub fn types() -> MutMap { - let mut types = HashMap::with_capacity_and_hasher(NUM_BUILTIN_IMPORTS, default_hasher()); - - let mut add_type = |symbol, typ| { - debug_assert!( - !types.contains_key(&symbol), - "Duplicate type definition for {:?}", - symbol - ); - - // TODO instead of using Region::zero for all of these, - // instead use the Region where they were defined in their - // source .roc files! This can give nicer error messages. - types.insert(symbol, (typ, Region::zero())); - }; - - fn div_by_zero() -> SolvedType { - SolvedType::TagUnion( - vec![(TagName::Global("DivByZero".into()), vec![])], - Box::new(SolvedType::Wildcard), - ) - } - - // Num module - - // add or (+) : Attr u (Num (Attr u num)) - // , Attr v (Num (Attr v num)) - // -> Attr w (Num (Attr w num)) - add_type(Symbol::NUM_ADD, { - let_tvars! { u, v, w, num }; - unique_function(vec![num_type(u, num), num_type(v, num)], num_type(w, num)) - }); - - fn overflow() -> SolvedType { - SolvedType::TagUnion( - vec![(TagName::Global("Overflow".into()), vec![])], - Box::new(SolvedType::Wildcard), - ) - } - - // addChecked : Num a, Num a -> Result (Num a) [ Overflow ]* - add_type(Symbol::NUM_ADD_CHECKED, { - let_tvars! { u, v, w, num, result, star }; - unique_function( - vec![num_type(u, num), num_type(v, num)], - result_type(result, num_type(w, num), lift(star, overflow())), - ) - }); - - // addWrap : Int, Int -> Int - add_type(Symbol::NUM_ADD_WRAP, { - let_tvars! { u, v, w, int }; - unique_function(vec![int_type(u, int), int_type(v, int)], int_type(w, int)) - }); - - // sub or (-) : Num a, Num a -> Num a - add_type(Symbol::NUM_SUB, { - let_tvars! { u, v, w, num }; - unique_function(vec![num_type(u, num), num_type(v, num)], num_type(w, num)) - }); - - // subWrap : Int, Int -> Int - add_type(Symbol::NUM_SUB_WRAP, { - let_tvars! { u, v, w, num }; - unique_function(vec![num_type(u, num), num_type(v, num)], num_type(w, num)) - }); - - // subChecked : Num a, Num a -> Result (Num a) [ Overflow ]* - add_type(Symbol::NUM_SUB_CHECKED, { - let_tvars! { u, v, w, num, result, star }; - unique_function( - vec![num_type(u, num), num_type(v, num)], - result_type(result, num_type(w, num), lift(star, overflow())), - ) - }); - - // mul or (*) : Num a, Num a -> Num a - add_type(Symbol::NUM_MUL, { - let_tvars! { u, v, w, num }; - unique_function(vec![num_type(u, num), num_type(v, num)], num_type(w, num)) - }); - - // mulWrap : Int, Int -> Int - add_type(Symbol::NUM_MUL_WRAP, { - let_tvars! { u, v, w , int }; - unique_function(vec![int_type(u, int), int_type(v, int)], int_type(w, int)) - }); - - // mulChecked : Num a, Num a -> Result (Num a) [ Overflow ]* - add_type(Symbol::NUM_MUL_CHECKED, { - let_tvars! { u, v, w, num, result, star }; - unique_function( - vec![num_type(u, num), num_type(v, num)], - result_type(result, num_type(w, num), lift(star, overflow())), - ) - }); - - // abs : Num a -> Num a - add_type(Symbol::NUM_ABS, { - let_tvars! { u, v, num }; - unique_function(vec![num_type(u, num)], num_type(v, num)) - }); - - // neg : Num a -> Num a - add_type(Symbol::NUM_NEG, { - let_tvars! { u, v, num }; - unique_function(vec![num_type(u, num)], num_type(v, num)) - }); - - let mut add_num_comparison = |symbol| { - add_type(symbol, { - let_tvars! { u, v, w, num }; - unique_function(vec![num_type(u, num), num_type(v, num)], bool_type(w)) - }); - }; - - // isLt or (<) : Num a, Num a -> Bool - add_num_comparison(Symbol::NUM_LT); - - // isLte or (<=) : Num a, Num a -> Bool - add_num_comparison(Symbol::NUM_LTE); - - // isGt or (>) : Num a, Num a -> Bool - add_num_comparison(Symbol::NUM_GT); - - // isGte or (>=) : Num a, Num a -> Bool - add_num_comparison(Symbol::NUM_GTE); - - // compare : Num a, Num a -> [ LT, EQ, GT ] - add_type(Symbol::NUM_COMPARE, { - let_tvars! { u, v, w, num }; - unique_function(vec![num_type(u, num), num_type(v, num)], ordering_type(w)) - }); - - // toFloat : Num a -> Float - add_type(Symbol::NUM_TO_FLOAT, { - let_tvars! { star1, star2, a }; - unique_function(vec![num_type(star1, a)], float_type(star2)) - }); - - // rem : Attr * Int, Attr * Int -> Attr * (Result (Attr * Int) (Attr * [ DivByZero ]*)) - add_type(Symbol::NUM_REM, { - let_tvars! { star1, star2, star3, star4, star5, int }; - unique_function( - vec![int_type(star1, int), int_type(star2, int)], - result_type(star3, int_type(star4, int), lift(star5, div_by_zero())), - ) - }); - - // maxInt : Int - add_type(Symbol::NUM_MAX_INT, { - let_tvars! { star, int }; - int_type(star, int) - }); - - // maxI128 : Int - add_type(Symbol::NUM_MAX_I128, { - let_tvars! { star, int }; - int_type(star, int) - }); - - // minInt : Int - add_type(Symbol::NUM_MIN_INT, { - let_tvars! { star, int }; - int_type(star, int) - }); - - // divFloor or (//) : Int, Int -> Result Int [ DivByZero ]* - add_type(Symbol::NUM_DIV_INT, { - let_tvars! { star1, star2, star3, star4, star5, int }; - unique_function( - vec![int_type(star1, int), int_type(star2, int)], - result_type(star3, int_type(star4, int), lift(star5, div_by_zero())), - ) - }); - - // bitwiseAnd : Attr * Int, Attr * Int -> Attr * Int - add_type(Symbol::NUM_BITWISE_AND, { - let_tvars! { star1, star2, star3, int }; - unique_function( - vec![int_type(star1, int), int_type(star2, int)], - int_type(star3, int), - ) - }); - - // bitwiseAnd : Attr * Int, Attr * Int -> Attr * Int - add_type(Symbol::NUM_BITWISE_XOR, { - let_tvars! { star1, star2, star3, int }; - unique_function( - vec![int_type(star1, int), int_type(star2, int)], - int_type(star3, int), - ) - }); - - // divFloat : Float, Float -> Float - add_type(Symbol::NUM_DIV_FLOAT, { - let_tvars! { star1, star2, star3, star4, star5}; - unique_function( - vec![float_type(star1), float_type(star2)], - result_type(star3, float_type(star4), lift(star5, div_by_zero())), - ) - }); - - // round : Float -> Int - add_type(Symbol::NUM_ROUND, { - let_tvars! { star1, star2, int }; - unique_function(vec![float_type(star1)], int_type(star2, int)) - }); - - // sqrt : Float -> Float - let sqrt_of_negative = SolvedType::TagUnion( - vec![(TagName::Global("SqrtOfNegative".into()), vec![])], - Box::new(SolvedType::Wildcard), - ); - - add_type(Symbol::NUM_SQRT, { - let_tvars! { star1, star2, star3, star4 }; - unique_function( - vec![float_type(star1)], - result_type(star2, float_type(star3), lift(star4, sqrt_of_negative)), - ) - }); - - // sin : Float -> Float - add_type(Symbol::NUM_SIN, { - let_tvars! { star1, star2 }; - unique_function(vec![float_type(star1)], float_type(star2)) - }); - - // cos : Float -> Float - add_type(Symbol::NUM_COS, { - let_tvars! { star1, star2 }; - unique_function(vec![float_type(star1)], float_type(star2)) - }); - - // tan : Float -> Float - add_type(Symbol::NUM_TAN, { - let_tvars! { star1, star2 }; - unique_function(vec![float_type(star1)], float_type(star2)) - }); - - // maxFloat : Float - add_type(Symbol::NUM_MAX_FLOAT, { - let_tvars! { star }; - float_type(star) - }); - - // minFloat : Float - add_type(Symbol::NUM_MIN_FLOAT, { - let_tvars! { star }; - float_type(star) - }); - - // isNegative : Num a -> Bool - add_type(Symbol::NUM_IS_NEGATIVE, { - let_tvars! { star1, star2, a }; - unique_function(vec![num_type(star1, a)], bool_type(star2)) - }); - - // isPositive : Num a -> Bool - add_type(Symbol::NUM_IS_POSITIVE, { - let_tvars! { star1, star2, a }; - unique_function(vec![num_type(star1, a)], bool_type(star2)) - }); - - // isZero : Num a -> Bool - add_type(Symbol::NUM_IS_ZERO, { - let_tvars! { star1, star2, a }; - unique_function(vec![num_type(star1, a)], bool_type(star2)) - }); - - // isEven : Num a -> Bool - add_type(Symbol::NUM_IS_EVEN, { - let_tvars! { star1, star2, a }; - unique_function(vec![num_type(star1, a)], bool_type(star2)) - }); - - // isOdd : Num a -> Bool - add_type(Symbol::NUM_IS_ODD, { - let_tvars! { star1, star2, a }; - unique_function(vec![num_type(star1, a)], bool_type(star2)) - }); - - // pow : Float, Float -> Float - add_type(Symbol::NUM_POW, { - let_tvars! { star1, star2, star3 }; - unique_function( - vec![float_type(star1), float_type(star2)], - float_type(star3), - ) - }); - - // ceiling : Float -> Int - add_type(Symbol::NUM_CEILING, { - let_tvars! { star1, star2, int }; - unique_function(vec![float_type(star1)], int_type(star2, int)) - }); - - // powInt : Int, Int -> Int - add_type(Symbol::NUM_POW_INT, { - let_tvars! { star1, star2, star3 , int }; - unique_function( - vec![int_type(star1, int), int_type(star2, int)], - int_type(star3, int), - ) - }); - - // floor : Float -> Int - add_type(Symbol::NUM_FLOOR, { - let_tvars! { star1, star2 , int}; - unique_function(vec![float_type(star1)], int_type(star2, int)) - }); - - // atan : Float -> Float - add_type(Symbol::NUM_ATAN, { - let_tvars! { star1, star2 }; - unique_function(vec![float_type(star1)], float_type(star2)) - }); - - // acos : Float -> Float - add_type(Symbol::NUM_ACOS, { - let_tvars! { star1, star2 }; - unique_function(vec![float_type(star1)], float_type(star2)) - }); - - // asin : Float -> Float - add_type(Symbol::NUM_ASIN, { - let_tvars! { star1, star2 }; - unique_function(vec![float_type(star1)], float_type(star2)) - }); - - // Bool module - - // isEq or (==) : Attr * a, Attr * a -> Attr * Bool - add_type(Symbol::BOOL_EQ, { - let_tvars! { star1, star2, star3, a }; - unique_function( - vec![attr_type(star1, a), attr_type(star2, a)], - bool_type(star3), - ) - }); - - // isNeq or (!=) : Attr * a, Attr * a -> Attr * Bool - add_type(Symbol::BOOL_NEQ, { - let_tvars! { star1, star2, star3, a }; - unique_function( - vec![attr_type(star1, a), attr_type(star2, a)], - bool_type(star3), - ) - }); - - // and or (&&) : Attr u1 Bool, Attr u2 Bool -> Attr u3 Bool - add_type(Symbol::BOOL_AND, { - let_tvars! { star1, star2, star3}; - unique_function(vec![bool_type(star1), bool_type(star2)], bool_type(star3)) - }); - - // or or (||) : Attr u1 Bool, Attr u2 Bool -> Attr u3 Bool - add_type(Symbol::BOOL_OR, { - let_tvars! { star1, star2, star3}; - unique_function(vec![bool_type(star1), bool_type(star2)], bool_type(star3)) - }); - - // xor : Attr u1 Bool, Attr u2 Bool -> Attr u3 Bool - add_type(Symbol::BOOL_XOR, { - let_tvars! { star1, star2, star3}; - unique_function(vec![bool_type(star1), bool_type(star2)], bool_type(star3)) - }); - - // not : Attr u1 Bool -> Attr u2 Bool - add_type(Symbol::BOOL_NOT, { - let_tvars! { star1, star2 }; - unique_function(vec![bool_type(star1)], bool_type(star2)) - }); - - // List module - - // isEmpty : Attr * (List *) -> Attr * Bool - add_type(Symbol::LIST_IS_EMPTY, { - let_tvars! { star1, a, star2 }; - unique_function(vec![list_type(star1, a)], bool_type(star2)) - }); - - // len : Attr * (List *) -> Attr * Int - add_type(Symbol::LIST_LEN, { - let_tvars! { star1, a, star2 , int }; - unique_function(vec![list_type(star1, a)], int_type(star2, int)) - }); - - fn list_was_empty() -> SolvedType { - SolvedType::TagUnion( - vec![(TagName::Global("ListWasEmpty".into()), vec![])], - Box::new(SolvedType::Wildcard), - ) - } - - // List.first : - // Attr (* | u) (List (Attr u a)), - // -> Attr * (Result (Attr u a) (Attr * [ OutOfBounds ]*)) - add_type(Symbol::LIST_FIRST, { - let_tvars! { a, u, star1, star2, star3 }; - - unique_function( - vec![SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - container(star1, vec![u]), - SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]), - ], - )], - result_type(star2, attr_type(u, a), lift(star3, list_was_empty())), - ) - }); - - // List.last : - // Attr (* | u) (List (Attr u a)), - // -> Attr * (Result (Attr u a) (Attr * [ OutOfBounds ]*)) - add_type(Symbol::LIST_LAST, { - let_tvars! { a, u, star1, star2, star3 }; - - unique_function( - vec![SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - container(star1, vec![u]), - SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]), - ], - )], - result_type(star2, attr_type(u, a), lift(star3, list_was_empty())), - ) - }); - - // List.get : - // Attr (* | u) (List (Attr u a)), - // Attr * Int - // -> Attr * (Result (Attr u a) (Attr * [ OutOfBounds ]*)) - let index_out_of_bounds = SolvedType::TagUnion( - vec![(TagName::Global("OutOfBounds".into()), vec![])], - Box::new(SolvedType::Wildcard), - ); - - add_type(Symbol::LIST_GET, { - let_tvars! { a, u, star1, star2, star3, star4, int}; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - container(star1, vec![u]), - SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]), - ], - ), - int_type(star2, int), - ], - result_type(star3, attr_type(u, a), lift(star4, index_out_of_bounds)), - ) - }); - - // List.set : - // Attr (w | u | v) (List (Attr u a)), - // Attr * Int, - // Attr (u | v) a - // -> Attr * (List (Attr u a)) - add_type(Symbol::LIST_SET, { - let_tvars! { u, v, w, star1, star2, a, int}; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - container(w, vec![u, v]), - SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]), - ], - ), - int_type(star1, int), - SolvedType::Apply(Symbol::ATTR_ATTR, vec![container(u, vec![v]), flex(a)]), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - boolean(star2), - SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]), - ], - ), - ) - }); - - // single : a -> Attr * (List a) - add_type(Symbol::LIST_SINGLE, { - let_tvars! { a, star }; - - unique_function( - vec![flex(a)], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - boolean(star), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - ) - }); - - // reverse : Attr * (List (Attr * a)) -> Attr * (List (Attr * a)) - add_type(Symbol::LIST_REVERSE, { - let_tvars! { a, star1, star2 }; - - unique_function( - vec![SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - )], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - boolean(star2), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - ) - }); - - // To repeat an item, it must be shared! - // - // repeat : Attr * Int - // , Attr Shared a - // -> Attr * (List (Attr Shared a)) - add_type(Symbol::LIST_REPEAT, { - let_tvars! { a, star1, star2, int }; - - unique_function( - vec![int_type(star1, int), shared(flex(a))], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - boolean(star2), - SolvedType::Apply(Symbol::LIST_LIST, vec![shared(flex(a))]), - ], - ), - ) - }); - - // concat : Attr * (List (Attr * a)), Attr * (List (Attr * a)) -> Attr * (List (Attr * a)) - add_type(Symbol::LIST_CONCAT, { - let_tvars! { a, star1, star2, star3 }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star2), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - boolean(star3), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - ) - }); - - // append : Attr * (List a) - // , a - // -> Attr * (List a) - // - // NOTE: we demand the new item to have the same uniqueness as the other list items. - // It could be allowed to add unique items to shared lists, but that requires special code gen - add_type(Symbol::LIST_APPEND, { - let_tvars! { a, star1, star2 }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - flex(a), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - boolean(star2), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - ) - }); - - // prepend : Attr * (List a) - // , a - // -> Attr * (List a) - // - // NOTE: we demand the new item to have the same uniqueness as the other list items. - // It could be allowed to add unique items to shared lists, but that requires special code gen - add_type(Symbol::LIST_PREPEND, { - let_tvars! { a, star1, star2 }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - flex(a), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - boolean(star2), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - ) - }); - - // contains : Attr * (List a) - // , a - // -> Attr * Bool - add_type(Symbol::LIST_CONTAINS, { - let_tvars! { a, star1, star2 }; - - unique_function(vec![list_type(star1, a), flex(a)], bool_type(star2)) - }); - - // sum : Attr * (List (Attr u (Num (Attr u num)))) - // -> Attr v (Num (Attr v num)) - add_type(Symbol::LIST_SUM, { - let_tvars! { star1, u, v, num }; - - unique_function( - vec![SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::LIST_LIST, vec![num_type(u, num)]), - ], - )], - num_type(v, num), - ) - }); - - // join : Attr * (List (Attr * (List a))) - // -> Attr * (List a) - add_type(Symbol::LIST_JOIN, { - let_tvars! { a, star1, star2, star3 }; - - unique_function( - vec![SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::LIST_LIST, vec![list_type(star2, a)]), - ], - )], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - boolean(star3), - SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)]), - ], - ), - ) - }); - - // List.map does not need to check the container rule on the input list. - // There is no way in which this signature can cause unique values to be duplicated - // - // foo : Attr Shared (List (Attr u a)) - // - // List.map : Attr * (List (Attr u a)) -> (Attr u a -> b) -> Attr * (List b) - // List.unsafeGet : Attr (* | u) (List (Attr u a)) -> Attr u a - // - // -- the elements still have uniqueness `u`, and will be made shared whenever accessing an element in `foo` - // bar1 : Attr * (List (Attr u a)) - // bar1 = List.map foo (\x -> x) - // - // -- no reference to `foo`'s elements can escape - // bar2 : Attr * (List (Attr * Int)) - // bar2 = List.map foo (\_ -> 32) - - // map : Attr * (List a) - // , Attr Shared (a -> b) - // -> Attr * (List b) - add_type(Symbol::LIST_MAP, { - let_tvars! { a, b, star1, star2, closure }; - - unique_function( - vec![ - list_type(star1, a), - shared(SolvedType::Func( - vec![flex(a)], - Box::new(flex(closure)), - Box::new(flex(b)), - )), - ], - list_type(star2, b), - ) - }); - - // keepIf : Attr * (List a) - // , Attr Shared (a -> Attr * Bool) - // -> Attr * (List a) - add_type(Symbol::LIST_KEEP_IF, { - let_tvars! { a, star1, star2, star3, closure }; - - unique_function( - vec![ - list_type(star1, a), - shared(SolvedType::Func( - vec![flex(a)], - Box::new(flex(closure)), - Box::new(bool_type(star2)), - )), - ], - list_type(star3, a), - ) - }); - - // walk : Attr (* | u) (List (Attr u a)) - // , Attr Shared (Attr u a -> b -> b) - // , b - // -> b - add_type(Symbol::LIST_WALK, { - let_tvars! { u, a, b, star1, closure }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - container(star1, vec![u]), - SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]), - ], - ), - shared(SolvedType::Func( - vec![attr_type(u, a), flex(b)], - Box::new(flex(closure)), - Box::new(flex(b)), - )), - flex(b), - ], - flex(b), - ) - }); - - // walkBackwards : Attr (* | u) (List (Attr u a)) - // , Attr Shared (Attr u a -> b -> b) - // , b - // -> b - add_type(Symbol::LIST_WALK_BACKWARDS, { - let_tvars! { u, a, b, star1, closure }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - container(star1, vec![u]), - SolvedType::Apply(Symbol::LIST_LIST, vec![attr_type(u, a)]), - ], - ), - shared(SolvedType::Func( - vec![attr_type(u, a), flex(b)], - Box::new(flex(closure)), - Box::new(flex(b)), - )), - flex(b), - ], - flex(b), - ) - }); - - // Dict module - - // : Attr * (Dict k v) -> Attr * Nat - add_type(Symbol::DICT_LEN, { - let_tvars! { star1, k , v, star2, int }; - - unique_function(vec![dict_type(star1, k, v)], int_type(star2, int)) - }); - - // empty : Attr * (Dict k v) - add_type(Symbol::DICT_EMPTY, { - let_tvars! { star, k , v }; - dict_type(star, k, v) - }); - - // single : k, v -> Attr * (Dict k v) - add_type(Symbol::DICT_SINGLE, { - let_tvars! { star, k , v }; - unique_function(vec![flex(k), flex(v)], dict_type(star, k, v)) - }); - - let key_not_found = SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - SolvedType::Wildcard, - SolvedType::TagUnion( - vec![(TagName::Global("KeyNotFound".into()), vec![])], - Box::new(SolvedType::Wildcard), - ), - ], - ); - - // get : Attr (* | u) (Dict (Attr * key) (Attr u val)) - // , Attr * key - // -> Attr * (Result (Attr u val) [ KeyNotFound ]*) - add_type(Symbol::DICT_GET, { - let_tvars! { u, key, val, star1, star2, star3, star4 }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - container(star1, vec![u]), - SolvedType::Apply( - Symbol::DICT_DICT, - vec![attr_type(star2, key), attr_type(u, val)], - ), - ], - ), - SolvedType::Apply(Symbol::ATTR_ATTR, vec![flex(star3), flex(key)]), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star4), - SolvedType::Apply( - Symbol::RESULT_RESULT, - vec![attr_type(u, val), key_not_found], - ), - ], - ), - ) - }); - - // insert : Attr * (Dict key value) - // , key - // , value - // , Attr * (Dict key value) - add_type(Symbol::DICT_INSERT, { - let_tvars! { star1, star2, key, value }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::DICT_DICT, vec![flex(key), flex(value)]), - ], - ), - flex(key), - flex(value), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star2), - SolvedType::Apply(Symbol::DICT_DICT, vec![flex(key), flex(value)]), - ], - ), - ) - }); - - // Set module - - // empty : Set a - add_type(Symbol::SET_EMPTY, { - let_tvars! { star, a }; - set_type(star, a) - }); - - // single : a -> Set a - add_type(Symbol::SET_SINGLE, { - let_tvars! { star, a }; - unique_function(vec![flex(a)], set_type(star, a)) - }); - - // union : Attr * (Set * a) - // , Attr * (Set * a) - // -> Attr * (Set * a) - let set_combine = { - let_tvars! { star1, star2, star3, star4, star5, star6, a }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::SET_SET, vec![attr_type(star2, a)]), - ], - ), - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star3), - SolvedType::Apply(Symbol::SET_SET, vec![attr_type(star4, a)]), - ], - ), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star5), - SolvedType::Apply(Symbol::SET_SET, vec![attr_type(star6, a)]), - ], - ), - ) - }; - - // union : Attr * (Set * a) - // , Attr * (Set * a) - // -> Attr * (Set * a) - add_type(Symbol::SET_UNION, set_combine.clone()); - - // diff : Attr * (Set * a) - // , Attr * (Set * a) - // -> Attr * (Set * a) - add_type(Symbol::SET_DIFFERENCE, set_combine); - - // foldl : Attr (* | u) (Set (Attr u a)) - // , Attr Shared (Attr u a -> b -> b) - // , b - // -> b - add_type(Symbol::SET_WALK, { - let_tvars! { star, u, a, b, closure }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - container(star, vec![u]), - SolvedType::Apply(Symbol::SET_SET, vec![attr_type(u, a)]), - ], - ), - shared(SolvedType::Func( - vec![attr_type(u, a), flex(b)], - Box::new(flex(closure)), - Box::new(flex(b)), - )), - flex(b), - ], - flex(b), - ) - }); - - // insert : Attr * (Set a) - // , a - // , Attr * (Set a) - add_type(Symbol::SET_INSERT, { - let_tvars! { star1, star2, a }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::SET_SET, vec![flex(a)]), - ], - ), - flex(a), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star2), - SolvedType::Apply(Symbol::SET_SET, vec![flex(a)]), - ], - ), - ) - }); - - // we can remove a key that is shared from a set of unique keys - // - // remove : Attr * (Set (Attr u a)) - // , Attr * a - // , Attr * (Set (Attr u a)) - add_type(Symbol::SET_REMOVE, { - let_tvars! { u, a, star1, star2, star3 }; - - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::SET_SET, vec![attr_type(u, a)]), - ], - ), - SolvedType::Apply(Symbol::ATTR_ATTR, vec![flex(star2), flex(a)]), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star3), - SolvedType::Apply(Symbol::SET_SET, vec![attr_type(u, a)]), - ], - ), - ) - }); - - // Str module - - // Str.split : - // Attr * Str, - // Attr * Str - // -> Attr * (List (Attr * Str)) - add_type(Symbol::STR_SPLIT, { - let_tvars! { star1, star2, star3, star4 }; - unique_function( - vec![str_type(star1), str_type(star2)], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star3), - SolvedType::Apply(Symbol::LIST_LIST, vec![str_type(star4)]), - ], - ), - ) - }); - - // isEmpty : Attr * Str -> Attr * Bool - add_type(Symbol::STR_IS_EMPTY, { - let_tvars! { star1, star2 }; - unique_function(vec![str_type(star1)], bool_type(star2)) - }); - - // Str.concat : Attr * Str, Attr * Str -> Attr * Str - add_type(Symbol::STR_CONCAT, { - let_tvars! { star1, star2, star3 }; - unique_function(vec![str_type(star1), str_type(star2)], str_type(star3)) - }); - - // Str.startsWith : Attr * Str, Attr * Str -> Attr * Bool - add_type(Symbol::STR_STARTS_WITH, { - let_tvars! { star1, star2, star3 }; - unique_function(vec![str_type(star1), str_type(star2)], bool_type(star3)) - }); - - // Str.endsWith : Attr * Str, Attr * Str -> Attr * Bool - add_type(Symbol::STR_ENDS_WITH, { - let_tvars! { star1, star2, star3 }; - unique_function(vec![str_type(star1), str_type(star2)], bool_type(star3)) - }); - - // Str.countGraphemes : Attr * Str, -> Attr * Int - add_type(Symbol::STR_COUNT_GRAPHEMES, { - let_tvars! { star1, star2, int }; - unique_function(vec![str_type(star1)], int_type(star2, int)) - }); - - // fromInt : Attr * Int -> Attr * Str - add_type(Symbol::STR_FROM_INT, { - let_tvars! { star1, star2, int }; - unique_function(vec![int_type(star1, int)], str_type(star2)) - }); - - // fromUtf8 : Attr * (List U8) -> Attr * (Result Str [ BadUtf8 Utf8Problem ]*) - let bad_utf8 = SolvedType::TagUnion( - vec![( - TagName::Global("BadUtf8".into()), - // vec![builtin_aliases::str_utf8_problem_type()], - vec![ - builtin_aliases::str_utf8_byte_problem_type(), - builtin_aliases::nat_type(), - ], - )], - Box::new(SolvedType::Wildcard), - ); - - add_type(Symbol::STR_FROM_UTF8, { - let_tvars! { star1, star2, star3, star4 }; - unique_function( - vec![u8_type(star1)], - result_type(star2, str_type(star3), lift(star4, bad_utf8)), - ) - }); - - // Result module - - // map : Attr * (Result (Attr a e)) - // , Attr * (a -> b) - // -> Attr * (Result b e) - add_type(Symbol::RESULT_MAP, { - let_tvars! { star1, star2, star3, a, b, e, closure }; - unique_function( - vec![ - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star1), - SolvedType::Apply(Symbol::RESULT_RESULT, vec![flex(a), flex(e)]), - ], - ), - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star2), - SolvedType::Func(vec![flex(a)], Box::new(flex(closure)), Box::new(flex(b))), - ], - ), - ], - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(star3), - SolvedType::Apply(Symbol::RESULT_RESULT, vec![flex(b), flex(e)]), - ], - ), - ) - }); - - types -} - -#[inline(always)] -fn flex(tvar: VarId) -> SolvedType { - SolvedType::Flex(tvar) -} - -#[inline(always)] -fn unique_function(args: Vec, ret: SolvedType) -> SolvedType { - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(FUVAR), - SolvedType::Func( - args, - Box::new(SolvedType::Flex(TOP_LEVEL_CLOSURE_VAR)), - Box::new(ret), - ), - ], - ) -} - -#[allow(dead_code)] -#[inline(always)] -fn attr_type(u: VarId, a: VarId) -> SolvedType { - SolvedType::Apply(Symbol::ATTR_ATTR, vec![flex(u), flex(a)]) -} - -#[inline(always)] -fn lift(u: VarId, a: SolvedType) -> SolvedType { - SolvedType::Apply(Symbol::ATTR_ATTR, vec![flex(u), a]) -} - -#[inline(always)] -fn float_type(u: VarId) -> SolvedType { - let inner_type = lift(u, flex(u)); - let fp = builtin_aliases::floatingpoint_type(inner_type.clone()); - let attr_fb = lift(u, fp); - let num = builtin_aliases::num_type(attr_fb); - - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(u), - SolvedType::Alias( - Symbol::NUM_FLOAT, - vec![("range".into(), inner_type)], - Box::new(num), - ), - ], - ) -} - -#[inline(always)] -fn int_type(u: VarId, range: VarId) -> SolvedType { - let inner_type = lift(u, flex(range)); - let integer = builtin_aliases::integer_type(inner_type.clone()); - let attr_fb = lift(u, integer); - let num = builtin_aliases::num_type(attr_fb); - - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(u), - SolvedType::Alias( - Symbol::NUM_INT, - vec![("range".into(), inner_type)], - Box::new(num), - ), - ], - ) -} - -#[inline(always)] -fn u8_type(u: VarId) -> SolvedType { - SolvedType::Apply(Symbol::ATTR_ATTR, vec![flex(u), builtin_aliases::u8_type()]) -} - -#[inline(always)] -fn bool_type(u: VarId) -> SolvedType { - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![flex(u), builtin_aliases::bool_type()], - ) -} - -#[inline(always)] -fn str_type(u: VarId) -> SolvedType { - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![flex(u), SolvedType::Apply(Symbol::STR_STR, Vec::new())], - ) -} - -#[inline(always)] -fn num_type(u: VarId, a: VarId) -> SolvedType { - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![flex(u), builtin_aliases::num_type(attr_type(u, a))], - ) -} - -#[inline(always)] -fn result_type(u: VarId, a: SolvedType, e: SolvedType) -> SolvedType { - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![flex(u), builtin_aliases::result_type(a, e)], - ) -} - -#[inline(always)] -fn list_type(u: VarId, a: VarId) -> SolvedType { - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![flex(u), SolvedType::Apply(Symbol::LIST_LIST, vec![flex(a)])], - ) -} - -#[inline(always)] -fn set_type(u: VarId, a: VarId) -> SolvedType { - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![flex(u), SolvedType::Apply(Symbol::SET_SET, vec![flex(a)])], - ) -} - -#[inline(always)] -fn dict_type(u: VarId, key: VarId, value: VarId) -> SolvedType { - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(u), - SolvedType::Apply(Symbol::DICT_DICT, vec![flex(key), flex(value)]), - ], - ) -} - -#[inline(always)] -fn ordering_type(u: VarId) -> SolvedType { - // [ LT, EQ, GT ] - SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![ - flex(u), - SolvedType::TagUnion( - vec![ - (TagName::Global("GT".into()), vec![]), - (TagName::Global("EQ".into()), vec![]), - (TagName::Global("LT".into()), vec![]), - ], - Box::new(SolvedType::EmptyTagUnion), - ), - ], - ) -} diff --git a/compiler/can/src/scope.rs b/compiler/can/src/scope.rs index 98d424c921..4c8c2b4ab5 100644 --- a/compiler/can/src/scope.rs +++ b/compiler/can/src/scope.rs @@ -49,7 +49,6 @@ impl Scope { typ, hidden_variables: MutSet::default(), vars: variables, - uniqueness: None, }; aliases.insert(symbol, alias); @@ -186,7 +185,6 @@ impl Scope { region, vars, hidden_variables, - uniqueness: None, typ, }; diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index e8273eb055..c9430e502c 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -3469,7 +3469,7 @@ pub fn with_hole<'a>( } List { - list_var, + list_var: _, elem_var, loc_elems, } => { @@ -3488,7 +3488,7 @@ pub fn with_hole<'a>( elems: arg_symbols, }; - let mode = crate::layout::mode_from_var(list_var, env.subs); + let mode = MemoryMode::Refcounted; let stmt = Stmt::Let( assigned, diff --git a/compiler/mono/src/layout.rs b/compiler/mono/src/layout.rs index 975b16d6f9..41654db7b8 100644 --- a/compiler/mono/src/layout.rs +++ b/compiler/mono/src/layout.rs @@ -1090,31 +1090,6 @@ fn layout_from_flat_type<'a>( Symbol::STR_STR => Ok(Layout::Builtin(Builtin::Str)), Symbol::LIST_LIST => list_layout_from_elem(env, args[0]), Symbol::DICT_DICT => dict_layout_from_key_value(env, args[0], args[1]), - Symbol::ATTR_ATTR => { - debug_assert_eq!(args.len(), 2); - - // The first argument is the uniqueness info; - // second is the base type - let wrapped_var = args[1]; - - // correct the memory mode of unique lists - match Layout::from_var(env, wrapped_var)? { - Layout::Builtin(Builtin::List(_ignored, elem_layout)) => { - let uniqueness_var = args[0]; - let uniqueness_content = - subs.get_without_compacting(uniqueness_var).content; - - let mode = if uniqueness_content.is_unique(subs) { - MemoryMode::Unique - } else { - MemoryMode::Refcounted - }; - - Ok(Layout::Builtin(Builtin::List(mode, elem_layout))) - } - other => Ok(other), - } - } Symbol::SET_SET => dict_layout_from_key_value(env, args[0], Variable::EMPTY_RECORD), _ => { panic!("TODO layout_from_flat_type for {:?}", Apply(symbol, args)); @@ -1270,9 +1245,6 @@ fn layout_from_flat_type<'a>( EmptyTagUnion => { panic!("TODO make Layout for empty Tag Union"); } - Boolean(_) => { - panic!("TODO make Layout for Boolean"); - } Erroneous(_) => Err(LayoutProblem::Erroneous), EmptyRecord => Ok(Layout::Struct(&[])), } @@ -1999,24 +1971,6 @@ pub fn list_layout_from_elem<'a>( } } -pub fn mode_from_var(var: Variable, subs: &Subs) -> MemoryMode { - match subs.get_without_compacting(var).content { - Content::Structure(FlatType::Apply(Symbol::ATTR_ATTR, args)) => { - debug_assert_eq!(args.len(), 2); - - let uvar = *args.get(0).unwrap(); - let content = subs.get_without_compacting(uvar).content; - - if content.is_unique(subs) { - MemoryMode::Unique - } else { - MemoryMode::Refcounted - } - } - _ => MemoryMode::Refcounted, - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct LayoutId(u32); diff --git a/compiler/reporting/src/error/type.rs b/compiler/reporting/src/error/type.rs index b2249518d5..af7c40c78d 100644 --- a/compiler/reporting/src/error/type.rs +++ b/compiler/reporting/src/error/type.rs @@ -1479,7 +1479,6 @@ pub fn to_doc<'b>( ext_to_doc(alloc, ext), ) } - Boolean(b) => alloc.string(format!("{:?}", b)), } } @@ -2476,7 +2475,6 @@ fn type_problem_to_pretty<'b>( alloc.reflow(" value"), ]), ), - Boolean(_) => bad_rigid_var(x, alloc.reflow("a uniqueness attribute value")), } } IntFloat => alloc.tip().append(alloc.concat(vec![ diff --git a/compiler/solve/src/solve.rs b/compiler/solve/src/solve.rs index dc46e66f66..4907e2aff3 100644 --- a/compiler/solve/src/solve.rs +++ b/compiler/solve/src/solve.rs @@ -4,7 +4,6 @@ use roc_collections::all::{ImMap, MutMap}; use roc_module::ident::TagName; use roc_module::symbol::Symbol; use roc_region::all::{Located, Region}; -use roc_types::boolean_algebra::{self, Bool}; use roc_types::solved_types::Solved; use roc_types::subs::{Content, Descriptor, FlatType, Mark, OptVariable, Rank, Subs, Variable}; use roc_types::types::Type::{self, *}; @@ -659,12 +658,6 @@ fn type_to_variable( EmptyTagUnion => Variable::EMPTY_TAG_UNION, // This case is important for the rank of boolean variables - Boolean(boolean_algebra::Bool::Container(cvar, mvars)) if mvars.is_empty() => *cvar, - Boolean(b) => { - let content = Content::Structure(FlatType::Boolean(b.clone())); - - register(subs, rank, pools, content) - } Function(args, closure_type, ret_type) => { let mut arg_vars = Vec::with_capacity(args.len()); @@ -972,28 +965,6 @@ fn check_for_infinite_type( _ => circular_error(subs, problems, symbol, &loc_var), } } - Content::Structure(FlatType::Boolean(Bool::Container(_cvar, _mvars))) => { - // We have a loop in boolean attributes. The attributes can be seen as constraints - // too, so if we have - // - // Container( u1, { u2, u3 } ) - // - // That means u1 >= u2 and u1 >= u3 - // - // Now if u1 occurs in the definition of u2, then that's like saying u1 >= u2 >= u1, - // which can only be true if u1 == u2. So that's what we do with unify. - for var in chain { - if let Content::Structure(FlatType::Boolean(_)) = - subs.get_without_compacting(var).content - { - // this unify just makes new pools. is that bad? - let outcome = unify(subs, recursive, var); - debug_assert!(matches!(outcome, roc_unify::unify::Unified::Success(_))); - } - } - - boolean_algebra::flatten(subs, recursive); - } _other => circular_error(subs, problems, symbol, &loc_var), } @@ -1285,18 +1256,6 @@ fn adjust_rank_content( rank } - Boolean(Bool::Shared) => Rank::toplevel(), - Boolean(Bool::Container(cvar, mvars)) => { - let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *cvar); - - for var in mvars { - rank = - rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var)); - } - - rank - } - Erroneous(_) => group_rank, } } @@ -1473,12 +1432,6 @@ fn instantiate_rigids_help( instantiate_rigids_help(subs, max_rank, pools, ext_var), ) } - - Boolean(b) => { - let mut mapper = |var| instantiate_rigids_help(subs, max_rank, pools, var); - - Boolean(b.map_variables(&mut mapper)) - } }; subs.set(copy, make_descriptor(Structure(new_flat_type))); @@ -1665,12 +1618,6 @@ fn deep_copy_var_help( deep_copy_var_help(subs, max_rank, pools, ext_var), ) } - - Boolean(b) => { - let mut mapper = |var| deep_copy_var_help(subs, max_rank, pools, var); - - Boolean(b.map_variables(&mut mapper)) - } }; subs.set(copy, make_descriptor(Structure(new_flat_type))); diff --git a/compiler/types/src/boolean_algebra.rs b/compiler/types/src/boolean_algebra.rs deleted file mode 100644 index 9e79804e18..0000000000 --- a/compiler/types/src/boolean_algebra.rs +++ /dev/null @@ -1,214 +0,0 @@ -use self::Bool::*; -use crate::subs::{Content, FlatType, Subs, Variable}; -use roc_collections::all::SendSet; - -/// Uniqueness types -/// -/// Roc uses uniqueness types to optimize programs. Uniqueness inference tries to find values that -/// are guaranteed to be unique (i.e. have a reference count of at most 1) at compile time. -/// -/// Such unique values can be updated in-place, something otherwise very unsafe in a pure -/// functional language. -/// -/// So how does that all work? Instead of inferring normal types like `Int`, we infer types -/// `Attr u a`. The `a` could be any "normal" type (it's called a base type), like `Int` or `Str`. -/// The `u` is the uniqueness attribute. It stores a value of type `Bool` (see definition below). -/// -/// Before doing type inference, variables are tagged as either exclusive or shared. A variable is -/// exclusive if we can be sure it's not duplicated. That's always true when the variable is used -/// just once, but also e.g. `foo.x + foo.y` does not duplicate references to `foo`. -/// -/// Next comes actual inference. Variables marked as shared always get the `Shared` uniqueness attribute. -/// For exclusive variables, the uniqueness attribute is initially an unbound type variable. -/// -/// An important detail is that there is no `Unique` annotation. Instead, uniqueness variables that -/// are unbound after type inference and monomorphization are interpreted as unique. This makes inference -/// easier and ensures we can never get type errors caused by uniqueness attributes. -/// -/// Besides normal type inference rules (e.g. in `f a` if `a : t` then it must be that `f : t -> s`), -/// uniqueness attributes must respect the container rule: -/// -/// > Container rule: to extract a unique value from a container, the container must itself be unique -/// -/// In this context a container can be a record, tag, built-in data structure (List, Set, etc) or -/// a function closure. -/// -/// Thus in the case of `List.get`, it must "check" the container rule. It's type is -/// -/// > Attr (Container(w, { u })) (List (Attr u a)), Int -> Result _ _ -/// -/// The container attribute means that the uniqueness of the container (variable w) is at least -/// uniqueness u. Unique is "more unique" than Shared. So if the elements are unique, the list must be unique. But if the list is -/// unique, the elements can be shared. -/// -/// As mentioned, we then use monomorphization to find values that are actually unique (those with -/// an unbound uniqueness attribute). Those values are treated differently. They don't have to be -/// reference counted, and can be mutated in-place. - -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum Bool { - Shared, - Container(Variable, SendSet), -} - -pub fn var_is_shared(subs: &Subs, var: Variable) -> bool { - matches!( - subs.get_without_compacting(var).content, - Content::Structure(FlatType::Boolean(Bool::Shared)) - ) -} - -/// Given the Subs -/// -/// 0 |-> Container (Var 1, { Var 2, Var 3 }) -/// 1 |-> Flex 'a' -/// 2 |-> Container(Var 4, { Var 5, Var 6 }) -/// 3 |-> Flex 'b' -/// 4 |-> Flex 'c' -/// 5 |-> Flex 'd' -/// 6 |-> Shared -/// -/// `flatten(subs, Var 0)` will rewrite it to -/// -/// 0 |-> Container (Var 1, { Var 4, Var 5, Var 3 }) -/// -/// So containers are "inlined", and Shared variables are discarded -pub fn flatten(subs: &mut Subs, var: Variable) { - match subs.get_without_compacting(var).content { - Content::Structure(FlatType::Boolean(Bool::Container(cvar, mvars))) => { - let flattened_mvars = var_to_variables(subs, cvar, &mvars); - - let content = - Content::Structure(FlatType::Boolean(Bool::Container(cvar, flattened_mvars))); - - subs.set_content(var, content); - } - Content::Structure(FlatType::Boolean(Bool::Shared)) => { - // do nothing - } - _ => { - // do nothing - } - } -} - -/// For a Container(cvar, start_vars), find (transitively) all the flex/rigid vars that are -/// occur in start_vars. -/// -/// Because type aliases in Roc can be recursive, we have to be a bit careful to not get stuck in -/// an infinite loop. -fn var_to_variables( - subs: &Subs, - cvar: Variable, - start_vars: &SendSet, -) -> SendSet { - let mut stack: Vec<_> = start_vars.into_iter().copied().collect(); - let mut seen = SendSet::default(); - seen.insert(cvar); - let mut result = SendSet::default(); - - while let Some(var) = stack.pop() { - if seen.contains(&var) { - continue; - } - - seen.insert(var); - - match subs.get_without_compacting(var).content { - Content::Structure(FlatType::Boolean(Bool::Container(cvar, mvars))) => { - let it = std::iter::once(cvar).chain(mvars.into_iter()); - - for v in it { - if !seen.contains(&v) { - stack.push(v); - } - } - } - Content::Structure(FlatType::Boolean(Bool::Shared)) => { - // do nothing - } - _other => { - result.insert(var); - } - } - } - - result -} - -impl Bool { - pub fn shared() -> Self { - Bool::Shared - } - - pub fn container(cvar: Variable, mvars: I) -> Self - where - I: IntoIterator, - { - Bool::Container(cvar, mvars.into_iter().collect()) - } - - pub fn variable(var: Variable) -> Self { - Bool::Container(var, SendSet::default()) - } - - pub fn is_fully_simplified(&self, subs: &Subs) -> bool { - match self { - Shared => true, - Container(cvar, mvars) => { - !var_is_shared(subs, *cvar) - && !(mvars.iter().any(|mvar| var_is_shared(subs, *mvar))) - } - } - } - - pub fn is_unique(&self, subs: &Subs) -> bool { - !matches!(self.simplify(subs), Shared) - } - - pub fn variables(&self) -> SendSet { - match self { - Shared => SendSet::default(), - Container(cvar, mvars) => { - let mut mvars = mvars.clone(); - mvars.insert(*cvar); - - mvars - } - } - } - - pub fn map_variables(&self, f: &mut F) -> Self - where - F: FnMut(Variable) -> Variable, - { - match self { - Bool::Shared => Bool::Shared, - Bool::Container(cvar, mvars) => { - let new_cvar = f(*cvar); - let new_mvars = mvars.iter().map(|var| f(*var)).collect(); - - Bool::Container(new_cvar, new_mvars) - } - } - } - - pub fn simplify(&self, subs: &Subs) -> Self { - match self { - Bool::Container(cvar, mvars) => { - let flattened_mvars = var_to_variables(subs, *cvar, mvars); - - // find the parent variable, to remove distinct variables that all have the same - // parent. This prevents the signature from rendering as e.g. `( a | b | b)` and - // instead makes it `( a | b )`. - let parent_mvars = flattened_mvars - .into_iter() - .map(|v| subs.get_root_key_without_compacting(v)) - .collect(); - - Bool::Container(*cvar, parent_mvars) - } - Bool::Shared => Bool::Shared, - } - } -} diff --git a/compiler/types/src/lib.rs b/compiler/types/src/lib.rs index 0ec67509c7..7c85065bd6 100644 --- a/compiler/types/src/lib.rs +++ b/compiler/types/src/lib.rs @@ -1,7 +1,6 @@ #![warn(clippy::all, clippy::dbg_macro)] // See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] -pub mod boolean_algebra; pub mod builtin_aliases; pub mod pretty_print; pub mod solved_types; diff --git a/compiler/types/src/pretty_print.rs b/compiler/types/src/pretty_print.rs index b4891ce080..9f9bacd42e 100644 --- a/compiler/types/src/pretty_print.rs +++ b/compiler/types/src/pretty_print.rs @@ -1,4 +1,3 @@ -use crate::boolean_algebra::Bool; use crate::subs::{Content, FlatType, Subs, Variable}; use crate::types::{name_type_var, RecordField}; use roc_collections::all::{MutMap, MutSet}; @@ -98,9 +97,6 @@ fn find_names_needed( let flat_type = FlatType::RecursiveTagUnion(rec_var, new_tags, ext_var); subs.set_content(recursive, Content::Structure(flat_type)); } - Content::Structure(FlatType::Boolean(Bool::Container(_cvar, _mvars))) => { - crate::boolean_algebra::flatten(subs, recursive); - } _ => panic!( "unfixable recursive type in roc_types::pretty_print {:?} {:?} {:?}", recursive, variable, content @@ -199,16 +195,6 @@ fn find_names_needed( find_names_needed(ext_var, subs, roots, root_appearances, names_taken); find_names_needed(rec_var, subs, roots, root_appearances, names_taken); } - Structure(Boolean(b)) => match b { - Bool::Shared => {} - Bool::Container(cvar, mvars) => { - find_names_needed(cvar, subs, roots, root_appearances, names_taken); - - for var in mvars { - find_names_needed(var, subs, roots, root_appearances, names_taken); - } - } - }, Alias(symbol, args, _actual) => { if let Symbol::ATTR_ATTR = symbol { find_names_needed(args[0].1, subs, roots, root_appearances, names_taken); @@ -590,9 +576,6 @@ fn write_flat_type(env: &Env, flat_type: FlatType, subs: &Subs, buf: &mut String parens, ) } - Boolean(b) => { - write_boolean(env, b, subs, buf, Parens::InTypeParam); - } Erroneous(problem) => { buf.push_str(&format!("", problem)); } @@ -655,65 +638,6 @@ pub fn chase_ext_record( } } -fn write_boolean(env: &Env, boolean: Bool, subs: &Subs, buf: &mut String, parens: Parens) { - use crate::boolean_algebra::var_is_shared; - - match boolean.simplify(subs) { - Bool::Shared => { - buf.push_str("Shared"); - } - Bool::Container(cvar, mvars) if mvars.iter().all(|v| var_is_shared(subs, *v)) => { - debug_assert!(!var_is_shared(subs, cvar)); - - write_content( - env, - subs.get_without_compacting(cvar).content, - subs, - buf, - Parens::Unnecessary, - ); - } - Bool::Container(cvar, mvars) => { - debug_assert!(!var_is_shared(subs, cvar)); - - let mut buffers = Vec::with_capacity(mvars.len()); - for v in mvars { - // don't print shared in a container - if var_is_shared(subs, v) { - continue; - } - - let mut inner_buf: String = "".to_string(); - write_content( - env, - subs.get_without_compacting(v).content, - subs, - &mut inner_buf, - parens, - ); - buffers.push(inner_buf); - } - - // sort type variables alphabetically - buffers.sort(); - - let combined = buffers.join(" | "); - - buf.push('('); - write_content( - env, - subs.get_without_compacting(cvar).content, - subs, - buf, - Parens::Unnecessary, - ); - buf.push_str(" | "); - buf.push_str(&combined); - buf.push(')'); - } - } -} - fn write_apply( env: &Env, symbol: Symbol, diff --git a/compiler/types/src/solved_types.rs b/compiler/types/src/solved_types.rs index 503b30dd97..a70bc2b7c8 100644 --- a/compiler/types/src/solved_types.rs +++ b/compiler/types/src/solved_types.rs @@ -1,4 +1,3 @@ -use crate::boolean_algebra::{self, Bool}; use crate::subs::{FlatType, Subs, VarId, VarStore, Variable}; use crate::types::{Problem, RecordField, Type}; use roc_collections::all::{ImMap, MutSet, SendMap}; @@ -85,7 +84,6 @@ fn hash_solved_type_help( } Rigid(name) => name.hash(state), Erroneous(problem) => problem.hash(state), - Boolean(solved_bool) => solved_bool.hash(state), Record { fields, ext } => { for (name, x) in fields { @@ -189,44 +187,10 @@ pub enum SolvedType { actual: Box, }, - /// a boolean algebra Bool - Boolean(SolvedBool), - /// A type error Error, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum SolvedBool { - SolvedShared, - SolvedContainer(VarId, Vec), -} - -impl SolvedBool { - pub fn from_bool(boolean: &boolean_algebra::Bool, subs: &Subs) -> Self { - match boolean { - Bool::Shared => SolvedBool::SolvedShared, - Bool::Container(cvar, mvars) => { - match subs.get_without_compacting(*cvar).content { - crate::subs::Content::FlexVar(_) => {} - crate::subs::Content::Structure(FlatType::Boolean(Bool::Shared)) => { - return SolvedBool::SolvedShared; - } - other => panic!("Container var is not flex but {:?}", other), - } - - SolvedBool::SolvedContainer( - VarId::from_var(*cvar, subs), - mvars - .iter() - .map(|mvar| VarId::from_var(*mvar, subs)) - .collect(), - ) - } - } - } -} - impl SolvedType { pub fn new(solved_subs: &Solved, var: Variable) -> Self { Self::from_var(solved_subs.inner(), var) @@ -350,7 +314,6 @@ impl SolvedType { actual: Box::new(solved_type), } } - Boolean(val) => SolvedType::Boolean(SolvedBool::from_bool(&val, solved_subs.inner())), Variable(var) => Self::from_var(solved_subs.inner(), *var), } } @@ -485,7 +448,6 @@ impl SolvedType { } EmptyRecord => SolvedType::EmptyRecord, EmptyTagUnion => SolvedType::EmptyTagUnion, - Boolean(val) => SolvedType::Boolean(SolvedBool::from_bool(&val, subs)), Erroneous(problem) => SolvedType::Erroneous(problem), } } @@ -624,16 +586,6 @@ pub fn to_type( Box::new(to_type(ext, free_vars, var_store)), ) } - Boolean(SolvedBool::SolvedShared) => Type::Boolean(Bool::Shared), - Boolean(SolvedBool::SolvedContainer(solved_cvar, solved_mvars)) => { - let cvar = var_id_to_flex_var(*solved_cvar, free_vars, var_store); - - let mvars = solved_mvars - .iter() - .map(|var_id| var_id_to_flex_var(*var_id, free_vars, var_store)); - - Type::Boolean(Bool::container(cvar, mvars)) - } Alias(symbol, solved_type_variables, solved_actual) => { let mut type_variables = Vec::with_capacity(solved_type_variables.len()); diff --git a/compiler/types/src/subs.rs b/compiler/types/src/subs.rs index e69523e33e..6f12c38677 100644 --- a/compiler/types/src/subs.rs +++ b/compiler/types/src/subs.rs @@ -1,4 +1,3 @@ -use crate::boolean_algebra; use crate::types::{name_type_var, ErrorType, Problem, RecordField, TypeExt}; use roc_collections::all::{ImMap, ImSet, MutMap, MutSet, SendMap}; use roc_module::ident::{Lowercase, TagName}; @@ -561,14 +560,6 @@ impl Content { ) } - pub fn is_unique(&self, subs: &Subs) -> bool { - match self { - Content::Structure(FlatType::Boolean(boolean)) => boolean.is_unique(subs), - Content::FlexVar(_) => true, - _ => false, - } - } - #[cfg(debug_assertions)] #[allow(dead_code)] pub fn dbg(self, subs: &Subs) -> Self { @@ -597,7 +588,6 @@ pub enum FlatType { Erroneous(Problem), EmptyRecord, EmptyTagUnion, - Boolean(boolean_algebra::Bool), } #[derive(PartialEq, Eq, Debug, Clone, Copy)] @@ -655,15 +645,6 @@ fn occurs( let it = once(&ext_var).chain(tags.values().flatten()); short_circuit(subs, root_var, &new_seen, it) } - Boolean(b) => { - for var in b.variables().iter() { - if let Some((v, mut vec)) = occurs(subs, &new_seen, *var) { - vec.push(root_var); - return Some((v, vec)); - } - } - None - } EmptyRecord | EmptyTagUnion | Erroneous(_) => None, } } @@ -783,8 +764,7 @@ fn explicit_substitute( subs.set_content(in_var, Structure(Record(vars_by_field, new_ext_var))); } - // NOTE assume we never substitute into a Boolean - EmptyRecord | EmptyTagUnion | Boolean(_) | Erroneous(_) => {} + EmptyRecord | EmptyTagUnion | Erroneous(_) => {} } in_var @@ -901,12 +881,6 @@ fn get_var_names( taken_names } - FlatType::Boolean(b) => b - .variables() - .into_iter() - .fold(taken_names, |answer, arg_var| { - get_var_names(subs, arg_var, answer) - }), }, } } @@ -1184,8 +1158,6 @@ fn flat_type_to_err_type( } } - Boolean(b) => ErrorType::Boolean(b), - Erroneous(problem) => { state.problems.push(problem); @@ -1252,11 +1224,6 @@ fn restore_content(subs: &mut Subs, content: &Content) { subs.restore(*rec_var); } - Boolean(b) => { - for var in b.variables() { - subs.restore(var); - } - } Erroneous(_) => (), }, Alias(_, args, var) => { diff --git a/compiler/types/src/types.rs b/compiler/types/src/types.rs index 81b0cf8965..f940eeb61f 100644 --- a/compiler/types/src/types.rs +++ b/compiler/types/src/types.rs @@ -1,4 +1,3 @@ -use crate::boolean_algebra; use crate::pretty_print::Parens; use crate::subs::{Subs, VarStore, Variable}; use inlinable_string::InlinableString; @@ -152,8 +151,6 @@ pub enum Type { RecursiveTagUnion(Variable, Vec<(TagName, Vec)>, Box), /// Applying a type to some arguments (e.g. Dict.Dict String Int) Apply(Symbol, Vec), - /// Boolean type used in uniqueness inference - Boolean(boolean_algebra::Bool), Variable(Variable), /// A type error, which will code gen to a runtime error Erroneous(Problem), @@ -353,7 +350,6 @@ impl fmt::Debug for Type { write!(f, " as <{:?}>", rec) } - Type::Boolean(b) => write!(f, "{:?}", b), } } } @@ -440,15 +436,6 @@ impl Type { arg.substitute(substitutions); } } - Boolean(b) => { - let mut mapper = |var| match substitutions.get(&var) { - Some(Type::Variable(new_var)) => *new_var, - Some(_) => panic!("cannot substitute boolean var for Type"), - None => var, - }; - - *b = b.map_variables(&mut mapper) - } EmptyRec | EmptyTagUnion | Erroneous(_) => {} } @@ -503,7 +490,7 @@ impl Type { arg.substitute_alias(rep_symbol, actual); } } - EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) | Boolean(_) => {} + EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) => {} } } @@ -537,7 +524,7 @@ impl Type { } Apply(symbol, _) if *symbol == rep_symbol => true, Apply(_, args) => args.iter().any(|arg| arg.contains_symbol(rep_symbol)), - EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) | Boolean(_) => false, + EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) => false, } } @@ -569,7 +556,7 @@ impl Type { Alias(_, _, actual_type) => actual_type.contains_variable(rep_variable), HostExposedAlias { actual, .. } => actual.contains_variable(rep_variable), Apply(_, args) => args.iter().any(|arg| arg.contains_variable(rep_variable)), - EmptyRec | EmptyTagUnion | Erroneous(_) | Boolean(_) => false, + EmptyRec | EmptyTagUnion | Erroneous(_) => false, } } @@ -632,35 +619,6 @@ impl Type { actual_type.instantiate_aliases(region, aliases, var_store, introduced); } - Apply(Symbol::ATTR_ATTR, attr_args) => { - use boolean_algebra::Bool; - - debug_assert_eq!(attr_args.len(), 2); - let mut it = attr_args.iter_mut(); - let uniqueness_type = it.next().unwrap(); - let base_type = it.next().unwrap(); - - // instantiate the rest - base_type.instantiate_aliases(region, aliases, var_store, introduced); - - // correct uniqueness type - // if this attr contains an alias of a recursive tag union, then the uniqueness - // attribute on the recursion variable must match the uniqueness of the whole tag - // union. We enforce that here. - - if let Some(Bool::Container(unbound_cvar, mvars1)) = - find_rec_var_uniqueness(base_type, aliases) - { - if let Type::Boolean(Bool::Container(bound_cvar, mvars2)) = uniqueness_type { - debug_assert!(mvars1.is_empty()); - debug_assert!(mvars2.is_empty()); - - let mut substitution = ImMap::default(); - substitution.insert(unbound_cvar, Type::Variable(*bound_cvar)); - base_type.substitute(&substitution); - } - } - } Apply(symbol, args) => { if let Some(alias) = aliases.get(symbol) { if args.len() != alias.vars.len() { @@ -693,8 +651,6 @@ impl Type { substitution.insert(*placeholder, filler); } - use boolean_algebra::Bool; - // Instantiate "hidden" uniqueness variables // // Aliases can hide uniqueness variables: e.g. in @@ -725,12 +681,6 @@ impl Type { // // And now we must make sure the `a`s stay the same variable, i.e. // don't re-instantiate it here. - if let Some(Bool::Container(unbound_cvar, _)) = alias.uniqueness { - if variable == unbound_cvar { - introduced.insert(variable); - continue; - } - } let var = var_store.fresh(); substitution.insert(variable, Type::Variable(var)); @@ -767,7 +717,7 @@ impl Type { } } } - EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) | Boolean(_) => {} + EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) => {} } } } @@ -813,7 +763,7 @@ fn symbols_help(tipe: &Type, accum: &mut ImSet) { accum.insert(*symbol); args.iter().for_each(|arg| symbols_help(arg, accum)); } - EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) | Boolean(_) => {} + EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) => {} } } @@ -822,11 +772,7 @@ fn variables_help(tipe: &Type, accum: &mut ImSet) { match tipe { EmptyRec | EmptyTagUnion | Erroneous(_) => (), - Boolean(b) => { - for v in b.variables() { - accum.insert(v); - } - } + Variable(v) => { accum.insert(*v); } @@ -894,34 +840,6 @@ fn variables_help(tipe: &Type, accum: &mut ImSet) { } } -/// We're looking for an alias whose actual type is a recursive tag union -/// if `base_type` is one, return the uniqueness variable of the alias. -fn find_rec_var_uniqueness( - base_type: &Type, - aliases: &ImMap, -) -> Option { - use Type::*; - - if let Alias(symbol, _, actual) = base_type { - match **actual { - Alias(_, _, _) => find_rec_var_uniqueness(actual, aliases), - RecursiveTagUnion(_, _, _) => { - if let Some(alias) = aliases.get(symbol) { - // alias with a recursive tag union must have its uniqueness set - debug_assert!(alias.uniqueness.is_some()); - - alias.uniqueness.clone() - } else { - unreachable!("aliases must be defined in the set of aliases!") - } - } - _ => None, - } - } else { - None - } -} - pub struct RecordStructure { pub fields: MutMap>, pub ext: Variable, @@ -1049,7 +967,6 @@ pub struct Alias { /// hidden type variables, like the closure variable in `a -> b` pub hidden_variables: MutSet, - pub uniqueness: Option, pub typ: Type, } @@ -1090,7 +1007,6 @@ pub enum ErrorType { RecursiveTagUnion(Box, SendMap>, TypeExt), Function(Vec, Box, Box), Alias(Symbol, Vec<(Lowercase, ErrorType)>, Box), - Boolean(boolean_algebra::Bool), Error, } @@ -1416,11 +1332,6 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: write_debug_error_type_help(*rec, buf, Parens::Unnecessary); } - - Boolean(boolean_algebra::Bool::Shared) => buf.push_str("Shared"), - Boolean(boolean_algebra::Bool::Container(mvar, cvars)) => { - buf.push_str(&format!("Container({:?}, {:?})", mvar, cvars)) - } } } diff --git a/compiler/unify/src/unify.rs b/compiler/unify/src/unify.rs index 39688d5527..a4cdfaad31 100644 --- a/compiler/unify/src/unify.rs +++ b/compiler/unify/src/unify.rs @@ -1,9 +1,6 @@ -use roc_collections::all::{ - default_hasher, get_shared, relative_complement, union, MutMap, SendSet, -}; +use roc_collections::all::{default_hasher, get_shared, relative_complement, union, MutMap}; use roc_module::ident::{Lowercase, TagName}; use roc_module::symbol::Symbol; -use roc_types::boolean_algebra::Bool; use roc_types::subs::Content::{self, *}; use roc_types::subs::{Descriptor, FlatType, Mark, OptVariable, Subs, Variable}; use roc_types::types::{gather_fields, ErrorType, Mismatch, RecordField, RecordStructure}; @@ -971,75 +968,6 @@ fn unify_flat_type( problems } - (Boolean(b1), Boolean(b2)) => { - use Bool::*; - - let b1 = b1.simplify(subs); - let b2 = b2.simplify(subs); - - match (&b1, &b2) { - (Shared, Shared) => merge(subs, ctx, Structure(left.clone())), - (Shared, Container(cvar, mvars)) => { - let mut outcome = vec![]; - // unify everything with shared - outcome.extend(unify_pool(subs, pool, ctx.first, *cvar)); - - for mvar in mvars { - outcome.extend(unify_pool(subs, pool, ctx.first, *mvar)); - } - - // set the first and second variables to Shared - let content = Content::Structure(FlatType::Boolean(Bool::Shared)); - outcome.extend(merge(subs, ctx, content)); - - outcome - } - (Container(cvar, mvars), Shared) => { - let mut outcome = vec![]; - // unify everything with shared - outcome.extend(unify_pool(subs, pool, ctx.second, *cvar)); - - for mvar in mvars { - outcome.extend(unify_pool(subs, pool, ctx.second, *mvar)); - } - - // set the first and second variables to Shared - let content = Content::Structure(FlatType::Boolean(Bool::Shared)); - outcome.extend(merge(subs, ctx, content)); - - outcome - } - (Container(cvar1, mvars1), Container(cvar2, mvars2)) => { - let mut outcome = vec![]; - - // unify cvar1 and cvar2? - outcome.extend(unify_pool(subs, pool, *cvar1, *cvar2)); - - let mvars: SendSet = mvars1 - .into_iter() - .chain(mvars2.into_iter()) - .copied() - .filter_map(|v| { - let root = subs.get_root_key(v); - - if roc_types::boolean_algebra::var_is_shared(subs, root) { - None - } else { - Some(root) - } - }) - .collect(); - - let content = - Content::Structure(FlatType::Boolean(Bool::Container(*cvar1, mvars))); - - outcome.extend(merge(subs, ctx, content)); - - outcome - } - } - } - (Apply(l_symbol, l_args), Apply(r_symbol, r_args)) if l_symbol == r_symbol => { let problems = unify_zip(subs, pool, l_args.iter(), r_args.iter());