mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
Merge pull request #3476 from rtfeldman/i3469
Remove more builtins code
This commit is contained in:
commit
f1aae6f480
10 changed files with 119 additions and 426 deletions
|
@ -4,6 +4,8 @@ interface Json
|
|||
format,
|
||||
]
|
||||
imports [
|
||||
List,
|
||||
Str,
|
||||
Encode.{
|
||||
Encoder,
|
||||
custom,
|
||||
|
|
|
@ -41,7 +41,7 @@ interface Str
|
|||
walkScalars,
|
||||
walkScalarsUntil,
|
||||
]
|
||||
imports [Bool.{ Bool }, Result.{ Result }]
|
||||
imports [Bool.{ Bool }, Result.{ Result }, List]
|
||||
|
||||
## # Types
|
||||
##
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use crate::expr::{constrain_def_make_constraint, constrain_def_pattern, Env};
|
||||
use roc_builtins::std::StdLib;
|
||||
use roc_can::abilities::{PendingAbilitiesStore, PendingMemberType};
|
||||
use roc_can::constraint::{Constraint, Constraints};
|
||||
use roc_can::expected::Expected;
|
||||
|
@ -7,8 +6,6 @@ use roc_can::expr::Declarations;
|
|||
use roc_can::pattern::Pattern;
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_types::solved_types::{FreeVars, SolvedType};
|
||||
use roc_types::subs::{VarStore, Variable};
|
||||
use roc_types::types::{AnnotationSource, Category, Type};
|
||||
|
||||
pub fn constrain_module(
|
||||
|
@ -146,90 +143,3 @@ pub fn frontload_ability_constraints(
|
|||
}
|
||||
constraint
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Import {
|
||||
pub loc_symbol: Loc<Symbol>,
|
||||
pub solved_type: SolvedType,
|
||||
}
|
||||
|
||||
pub fn introduce_builtin_imports(
|
||||
constraints: &mut Constraints,
|
||||
imports: Vec<Symbol>,
|
||||
body_con: Constraint,
|
||||
var_store: &mut VarStore,
|
||||
) -> Constraint {
|
||||
let stdlib = roc_builtins::std::borrow_stdlib();
|
||||
let (rigid_vars, def_types) = constrain_builtin_imports(stdlib, imports, var_store);
|
||||
constraints.let_import_constraint(rigid_vars, def_types, body_con, &[])
|
||||
}
|
||||
|
||||
pub fn constrain_builtin_imports(
|
||||
stdlib: &StdLib,
|
||||
imports: Vec<Symbol>,
|
||||
var_store: &mut VarStore,
|
||||
) -> (Vec<Variable>, Vec<(Symbol, Loc<roc_types::types::Type>)>) {
|
||||
let mut def_types = Vec::new();
|
||||
let mut rigid_vars = Vec::new();
|
||||
|
||||
for symbol in imports {
|
||||
let mut free_vars = FreeVars::default();
|
||||
|
||||
let import = match stdlib.types.get(&symbol) {
|
||||
Some((solved_type, region)) => {
|
||||
let loc_symbol = Loc {
|
||||
value: symbol,
|
||||
region: *region,
|
||||
};
|
||||
|
||||
Import {
|
||||
loc_symbol,
|
||||
solved_type: solved_type.clone(),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let loc_symbol = import.loc_symbol;
|
||||
|
||||
// an imported symbol can be either an alias or a value
|
||||
match import.solved_type {
|
||||
SolvedType::Alias(symbol, _, _, _, _) if symbol == loc_symbol.value => {
|
||||
// do nothing, in the future the alias definitions should not be in the list of imported values
|
||||
}
|
||||
_ => {
|
||||
let typ = roc_types::solved_types::to_type(
|
||||
&import.solved_type,
|
||||
&mut free_vars,
|
||||
var_store,
|
||||
);
|
||||
|
||||
def_types.push((
|
||||
loc_symbol.value,
|
||||
Loc {
|
||||
region: loc_symbol.region,
|
||||
value: typ,
|
||||
},
|
||||
));
|
||||
|
||||
for (_, var) in free_vars.named_vars {
|
||||
rigid_vars.push(var);
|
||||
}
|
||||
|
||||
for var in free_vars.wildcards {
|
||||
rigid_vars.push(var);
|
||||
}
|
||||
|
||||
// Variables can lose their name during type inference. But the unnamed
|
||||
// variables are still part of a signature, and thus must be treated as rigids here!
|
||||
for (_, var) in free_vars.unnamed_vars {
|
||||
rigid_vars.push(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(rigid_vars, def_types)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ use crossbeam::deque::{Injector, Stealer, Worker};
|
|||
use crossbeam::thread;
|
||||
use parking_lot::Mutex;
|
||||
use roc_builtins::roc::module_source;
|
||||
use roc_builtins::std::borrow_stdlib;
|
||||
use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedSpecializations};
|
||||
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
|
||||
use roc_can::expr::Declarations;
|
||||
|
@ -14,7 +13,7 @@ use roc_can::module::{
|
|||
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
|
||||
};
|
||||
use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet};
|
||||
use roc_constrain::module::{constrain_builtin_imports, constrain_module};
|
||||
use roc_constrain::module::constrain_module;
|
||||
use roc_debug_flags::dbg_do;
|
||||
#[cfg(debug_assertions)]
|
||||
use roc_debug_flags::{
|
||||
|
@ -977,7 +976,6 @@ enum BuildTask<'a> {
|
|||
Solve {
|
||||
module: Module,
|
||||
ident_ids: IdentIds,
|
||||
imported_builtins: Vec<Symbol>,
|
||||
exposed_for_module: ExposedForModule,
|
||||
module_timing: ModuleTiming,
|
||||
constraints: Constraints,
|
||||
|
@ -2048,6 +2046,12 @@ fn update<'a>(
|
|||
.insert(Ident::from("Bool"), (Symbol::BOOL_BOOL, Region::zero()));
|
||||
}
|
||||
|
||||
if header.module_id == ModuleId::NUM {
|
||||
header
|
||||
.exposed_imports
|
||||
.insert(Ident::from("List"), (Symbol::LIST_LIST, Region::zero()));
|
||||
}
|
||||
|
||||
if !header.module_id.is_builtin() {
|
||||
header
|
||||
.package_qualified_imported_modules
|
||||
|
@ -3785,18 +3789,10 @@ impl<'a> BuildTask<'a> {
|
|||
let exposed_for_module =
|
||||
ExposedForModule::new(module.referenced_values.iter(), exposed_by_module);
|
||||
|
||||
let imported_builtins = module
|
||||
.referenced_values
|
||||
.iter()
|
||||
.filter(|s| s.is_builtin())
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
// Next, solve this module in the background.
|
||||
Self::Solve {
|
||||
module,
|
||||
ident_ids,
|
||||
imported_builtins,
|
||||
exposed_for_module,
|
||||
constraints,
|
||||
constraint,
|
||||
|
@ -3811,6 +3807,45 @@ impl<'a> BuildTask<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn synth_import(subs: &mut Subs, content: roc_types::subs::Content) -> Variable {
|
||||
use roc_types::subs::{Descriptor, Mark, OptVariable, Rank};
|
||||
subs.fresh(Descriptor {
|
||||
content,
|
||||
rank: Rank::import(),
|
||||
mark: Mark::NONE,
|
||||
copy: OptVariable::NONE,
|
||||
})
|
||||
}
|
||||
|
||||
fn synth_list_len_type(subs: &mut Subs) -> Variable {
|
||||
use roc_types::subs::{Content, FlatType, LambdaSet, OptVariable, SubsSlice, UnionLabels};
|
||||
|
||||
// List.len : List a -> Nat
|
||||
let a = synth_import(subs, Content::FlexVar(None));
|
||||
let a_slice = SubsSlice::extend_new(&mut subs.variables, [a]);
|
||||
let list_a = synth_import(
|
||||
subs,
|
||||
Content::Structure(FlatType::Apply(Symbol::LIST_LIST, a_slice)),
|
||||
);
|
||||
let fn_var = synth_import(subs, Content::Error);
|
||||
let solved_list_len = UnionLabels::insert_into_subs(subs, [(Symbol::LIST_LEN, [])]);
|
||||
let clos_list_len = synth_import(
|
||||
subs,
|
||||
Content::LambdaSet(LambdaSet {
|
||||
solved: solved_list_len,
|
||||
recursion_var: OptVariable::NONE,
|
||||
unspecialized: SubsSlice::default(),
|
||||
ambient_function: fn_var,
|
||||
}),
|
||||
);
|
||||
let fn_args_slice = SubsSlice::extend_new(&mut subs.variables, [list_a]);
|
||||
subs.set_content(
|
||||
fn_var,
|
||||
Content::Structure(FlatType::Func(fn_args_slice, clos_list_len, Variable::NAT)),
|
||||
);
|
||||
fn_var
|
||||
}
|
||||
|
||||
pub fn add_imports(
|
||||
my_module: ModuleId,
|
||||
subs: &mut Subs,
|
||||
|
@ -3819,6 +3854,8 @@ pub fn add_imports(
|
|||
def_types: &mut Vec<(Symbol, Loc<roc_types::types::Type>)>,
|
||||
rigid_vars: &mut Vec<Variable>,
|
||||
) -> (Vec<Variable>, AbilitiesStore) {
|
||||
use roc_types::types::Type;
|
||||
|
||||
let mut import_variables = Vec::new();
|
||||
|
||||
let mut cached_symbol_vars = VecMap::default();
|
||||
|
@ -3846,7 +3883,7 @@ pub fn add_imports(
|
|||
|
||||
def_types.push((
|
||||
$symbol,
|
||||
Loc::at_zero(roc_types::types::Type::Variable(copied_import.variable)),
|
||||
Loc::at_zero(Type::Variable(copied_import.variable)),
|
||||
));
|
||||
|
||||
// not a typo; rigids are turned into flex during type inference, but when imported we must
|
||||
|
@ -3873,6 +3910,17 @@ pub fn add_imports(
|
|||
import_var_for_symbol!(subs, exposed_for_module.exposed_by_module, symbol, continue);
|
||||
}
|
||||
|
||||
// Patch used symbols from circular dependencies.
|
||||
if my_module == ModuleId::NUM {
|
||||
// Num needs List.len, but List imports Num.
|
||||
let list_len_type = synth_list_len_type(subs);
|
||||
def_types.push((
|
||||
Symbol::LIST_LEN,
|
||||
Loc::at_zero(Type::Variable(list_len_type)),
|
||||
));
|
||||
import_variables.push(list_len_type);
|
||||
}
|
||||
|
||||
// TODO: see if we can reduce the amount of specializations we need to import.
|
||||
// One idea is to just always assume external modules fulfill their specialization obligations
|
||||
// and save lambda set resolution for mono.
|
||||
|
@ -3930,12 +3978,11 @@ pub fn add_imports(
|
|||
|
||||
#[allow(clippy::complexity)]
|
||||
fn run_solve_solve(
|
||||
imported_builtins: Vec<Symbol>,
|
||||
exposed_for_module: ExposedForModule,
|
||||
mut constraints: Constraints,
|
||||
constraint: ConstraintSoa,
|
||||
pending_derives: PendingDerives,
|
||||
mut var_store: VarStore,
|
||||
var_store: VarStore,
|
||||
module: Module,
|
||||
derived_symbols: GlobalDerivedSymbols,
|
||||
) -> (
|
||||
|
@ -3953,8 +4000,8 @@ fn run_solve_solve(
|
|||
..
|
||||
} = module;
|
||||
|
||||
let (mut rigid_vars, mut def_types) =
|
||||
constrain_builtin_imports(borrow_stdlib(), imported_builtins, &mut var_store);
|
||||
let mut rigid_vars: Vec<Variable> = Vec::new();
|
||||
let mut def_types: Vec<(Symbol, Loc<roc_types::types::Type>)> = Vec::new();
|
||||
|
||||
let mut subs = Subs::new_from_varstore(var_store);
|
||||
|
||||
|
@ -4033,7 +4080,6 @@ fn run_solve<'a>(
|
|||
module: Module,
|
||||
ident_ids: IdentIds,
|
||||
mut module_timing: ModuleTiming,
|
||||
imported_builtins: Vec<Symbol>,
|
||||
exposed_for_module: ExposedForModule,
|
||||
constraints: Constraints,
|
||||
constraint: ConstraintSoa,
|
||||
|
@ -4055,7 +4101,6 @@ fn run_solve<'a>(
|
|||
if module_id.is_builtin() {
|
||||
match cached_subs.lock().remove(&module_id) {
|
||||
None => run_solve_solve(
|
||||
imported_builtins,
|
||||
exposed_for_module,
|
||||
constraints,
|
||||
constraint,
|
||||
|
@ -4078,7 +4123,6 @@ fn run_solve<'a>(
|
|||
}
|
||||
} else {
|
||||
run_solve_solve(
|
||||
imported_builtins,
|
||||
exposed_for_module,
|
||||
constraints,
|
||||
constraint,
|
||||
|
@ -4890,7 +4934,6 @@ fn run_task<'a>(
|
|||
Solve {
|
||||
module,
|
||||
module_timing,
|
||||
imported_builtins,
|
||||
exposed_for_module,
|
||||
constraints,
|
||||
constraint,
|
||||
|
@ -4905,7 +4948,6 @@ fn run_task<'a>(
|
|||
module,
|
||||
ident_ids,
|
||||
module_timing,
|
||||
imported_builtins,
|
||||
exposed_for_module,
|
||||
constraints,
|
||||
constraint,
|
||||
|
|
|
@ -422,7 +422,7 @@ fn test_load_and_typecheck() {
|
|||
"intTest" => "I64",
|
||||
"constantNum" => "Num *",
|
||||
"divisionTest" => "F64",
|
||||
"divDep1ByDep2" => "Float *",
|
||||
"divDep1ByDep2" => "Float a",
|
||||
"fromDep2" => "Float *",
|
||||
},
|
||||
);
|
||||
|
|
|
@ -3434,7 +3434,7 @@ mod solve_expr {
|
|||
Dict.insert
|
||||
"#
|
||||
),
|
||||
"Dict a b, a, b -> Dict a b",
|
||||
"Dict k v, k, v -> Dict k v",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3446,7 +3446,7 @@ mod solve_expr {
|
|||
Num.toFrac
|
||||
"#
|
||||
),
|
||||
"Num * -> Float *",
|
||||
"Num * -> Float a",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3470,7 +3470,7 @@ mod solve_expr {
|
|||
Num.ceiling
|
||||
"#
|
||||
),
|
||||
"Float * -> Int *",
|
||||
"Float * -> Int a",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3482,7 +3482,7 @@ mod solve_expr {
|
|||
Num.floor
|
||||
"#
|
||||
),
|
||||
"Float * -> Int *",
|
||||
"Float * -> Int a",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4037,7 +4037,7 @@ mod solve_expr {
|
|||
List.walkBackwards
|
||||
"#
|
||||
),
|
||||
"List a, b, (b, a -> b) -> b",
|
||||
"List elem, state, (state, elem -> state) -> state",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4065,7 +4065,7 @@ mod solve_expr {
|
|||
List.dropAt
|
||||
"#
|
||||
),
|
||||
"List a, Nat -> List a",
|
||||
"List elem, Nat -> List elem",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4101,7 +4101,7 @@ mod solve_expr {
|
|||
List.takeFirst
|
||||
"#
|
||||
),
|
||||
"List a, Nat -> List a",
|
||||
"List elem, Nat -> List elem",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4113,7 +4113,7 @@ mod solve_expr {
|
|||
List.takeLast
|
||||
"#
|
||||
),
|
||||
"List a, Nat -> List a",
|
||||
"List elem, Nat -> List elem",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4125,7 +4125,7 @@ mod solve_expr {
|
|||
List.sublist
|
||||
"#
|
||||
),
|
||||
"List a, { len : Nat, start : Nat } -> List a",
|
||||
"List elem, { len : Nat, start : Nat } -> List elem",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4133,7 +4133,7 @@ mod solve_expr {
|
|||
fn list_split() {
|
||||
infer_eq_without_problem(
|
||||
indoc!("List.split"),
|
||||
"List a, Nat -> { before : List a, others : List a }",
|
||||
"List elem, Nat -> { before : List elem, others : List elem }",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4145,7 +4145,7 @@ mod solve_expr {
|
|||
List.dropLast
|
||||
"#
|
||||
),
|
||||
"List a -> List a",
|
||||
"List elem -> List elem",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4157,7 +4157,7 @@ mod solve_expr {
|
|||
List.intersperse
|
||||
"#
|
||||
),
|
||||
"List a, a -> List a",
|
||||
"List elem, elem -> List elem",
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
|
@ -5517,7 +5517,7 @@ mod solve_expr {
|
|||
}
|
||||
"#
|
||||
),
|
||||
r#"{ toI128 : Int * -> I128, toI16 : Int * -> I16, toI32 : Int * -> I32, toI64 : Int * -> I64, toI8 : Int * -> I8, toNat : Int * -> Nat, toU128 : Int * -> U128, toU16 : Int * -> U16, toU32 : Int * -> U32, toU64 : Int * -> U64, toU8 : Int * -> U8 }"#,
|
||||
r#"{ toI128 : Int * -> I128, toI16 : Int a -> I16, toI32 : Int b -> I32, toI64 : Int c -> I64, toI8 : Int d -> I8, toNat : Int e -> Nat, toU128 : Int f -> U128, toU16 : Int g -> U16, toU32 : Int h -> U32, toU64 : Int i -> U64, toU8 : Int j -> U8 }"#,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -5532,7 +5532,7 @@ mod solve_expr {
|
|||
}
|
||||
"#
|
||||
),
|
||||
r#"{ toF32 : Num * -> F32, toF64 : Num * -> F64 }"#,
|
||||
r#"{ toF32 : Num * -> F32, toF64 : Num a -> F64 }"#,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::subs::{VarId, VarStore, Variable};
|
||||
use crate::types::{AliasKind, OptAbleType, Problem, RecordField, Type, TypeExtension};
|
||||
use roc_collections::all::{ImMap, SendMap};
|
||||
use crate::subs::{VarId, Variable};
|
||||
use crate::types::{AliasKind, Problem, RecordField};
|
||||
use roc_collections::all::ImMap;
|
||||
use roc_module::ident::{Lowercase, TagName};
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_region::all::{Loc, Region};
|
||||
|
@ -88,219 +88,3 @@ pub struct FreeVars {
|
|||
pub unnamed_vars: ImMap<VarId, Variable>,
|
||||
pub wildcards: Vec<Variable>,
|
||||
}
|
||||
|
||||
pub fn to_type(
|
||||
solved_type: &SolvedType,
|
||||
free_vars: &mut FreeVars,
|
||||
var_store: &mut VarStore,
|
||||
) -> Type {
|
||||
use SolvedType::*;
|
||||
|
||||
match solved_type {
|
||||
Func(args, closure, ret) => {
|
||||
let mut new_args = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in args {
|
||||
new_args.push(to_type(arg, free_vars, var_store));
|
||||
}
|
||||
|
||||
let new_ret = to_type(ret, free_vars, var_store);
|
||||
let new_closure = to_type(closure, free_vars, var_store);
|
||||
|
||||
Type::Function(new_args, Box::new(new_closure), Box::new(new_ret))
|
||||
}
|
||||
Apply(symbol, args) => {
|
||||
let mut new_args = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in args {
|
||||
new_args.push(to_type(arg, free_vars, var_store));
|
||||
}
|
||||
|
||||
Type::Apply(*symbol, new_args, Region::zero())
|
||||
}
|
||||
Rigid(lowercase) => {
|
||||
if let Some(var) = free_vars.named_vars.get(lowercase) {
|
||||
Type::Variable(*var)
|
||||
} else {
|
||||
let var = var_store.fresh();
|
||||
free_vars.named_vars.insert(lowercase.clone(), var);
|
||||
Type::Variable(var)
|
||||
}
|
||||
}
|
||||
Flex(var_id) => Type::Variable(var_id_to_flex_var(*var_id, free_vars, var_store)),
|
||||
Wildcard => {
|
||||
let var = var_store.fresh();
|
||||
free_vars.wildcards.push(var);
|
||||
Type::Variable(var)
|
||||
}
|
||||
Record { fields, ext } => {
|
||||
use RecordField::*;
|
||||
|
||||
let mut new_fields = SendMap::default();
|
||||
|
||||
for (label, field) in fields {
|
||||
let field_val = match field {
|
||||
Required(typ) => Required(to_type(typ, free_vars, var_store)),
|
||||
Optional(typ) => Optional(to_type(typ, free_vars, var_store)),
|
||||
Demanded(typ) => Demanded(to_type(typ, free_vars, var_store)),
|
||||
};
|
||||
|
||||
new_fields.insert(label.clone(), field_val);
|
||||
}
|
||||
|
||||
let ext = match ext.as_ref() {
|
||||
SolvedType::EmptyRecord => TypeExtension::Closed,
|
||||
other => TypeExtension::Open(Box::new(to_type(other, free_vars, var_store))),
|
||||
};
|
||||
|
||||
Type::Record(new_fields, ext)
|
||||
}
|
||||
EmptyRecord => Type::EmptyRec,
|
||||
EmptyTagUnion => Type::EmptyTagUnion,
|
||||
TagUnion(tags, ext) => {
|
||||
let mut new_tags = Vec::with_capacity(tags.len());
|
||||
|
||||
for (tag_name, args) in tags {
|
||||
let mut new_args = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in args.iter() {
|
||||
new_args.push(to_type(arg, free_vars, var_store));
|
||||
}
|
||||
|
||||
new_tags.push((tag_name.clone(), new_args));
|
||||
}
|
||||
|
||||
let ext = match ext.as_ref() {
|
||||
SolvedType::EmptyTagUnion => TypeExtension::Closed,
|
||||
other => TypeExtension::Open(Box::new(to_type(other, free_vars, var_store))),
|
||||
};
|
||||
|
||||
Type::TagUnion(new_tags, ext)
|
||||
}
|
||||
LambdaTag(name, args) => {
|
||||
let mut new_args = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in args.iter() {
|
||||
new_args.push(to_type(arg, free_vars, var_store));
|
||||
}
|
||||
|
||||
Type::ClosureTag {
|
||||
name: *name,
|
||||
captures: new_args,
|
||||
ambient_function: var_store.fresh(),
|
||||
}
|
||||
}
|
||||
FunctionOrTagUnion(tag_name, symbol, ext) => {
|
||||
let ext = match ext.as_ref() {
|
||||
SolvedType::EmptyTagUnion => TypeExtension::Closed,
|
||||
other => TypeExtension::Open(Box::new(to_type(other, free_vars, var_store))),
|
||||
};
|
||||
|
||||
Type::FunctionOrTagUnion(tag_name.clone(), *symbol, ext)
|
||||
}
|
||||
RecursiveTagUnion(rec_var_id, tags, ext) => {
|
||||
let mut new_tags = Vec::with_capacity(tags.len());
|
||||
|
||||
for (tag_name, args) in tags {
|
||||
let mut new_args = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in args.iter() {
|
||||
new_args.push(to_type(arg, free_vars, var_store));
|
||||
}
|
||||
|
||||
new_tags.push((tag_name.clone(), new_args));
|
||||
}
|
||||
|
||||
let ext = match ext.as_ref() {
|
||||
SolvedType::EmptyTagUnion => TypeExtension::Closed,
|
||||
other => TypeExtension::Open(Box::new(to_type(other, free_vars, var_store))),
|
||||
};
|
||||
|
||||
let rec_var = free_vars
|
||||
.unnamed_vars
|
||||
.get(rec_var_id)
|
||||
.expect("rec var not in unnamed vars");
|
||||
|
||||
Type::RecursiveTagUnion(*rec_var, new_tags, ext)
|
||||
}
|
||||
Alias(symbol, solved_type_variables, solved_lambda_sets, solved_actual, kind) => {
|
||||
let mut type_variables = Vec::with_capacity(solved_type_variables.len());
|
||||
|
||||
for solved_arg in solved_type_variables {
|
||||
type_variables.push(OptAbleType {
|
||||
typ: to_type(solved_arg, free_vars, var_store),
|
||||
// TODO: is this always correct?
|
||||
opt_ability: None,
|
||||
});
|
||||
}
|
||||
|
||||
let mut lambda_set_variables = Vec::with_capacity(solved_lambda_sets.len());
|
||||
for solved_set in solved_lambda_sets {
|
||||
lambda_set_variables.push(crate::types::LambdaSet(to_type(
|
||||
&solved_set.0,
|
||||
free_vars,
|
||||
var_store,
|
||||
)))
|
||||
}
|
||||
|
||||
let actual = to_type(solved_actual, free_vars, var_store);
|
||||
|
||||
Type::Alias {
|
||||
symbol: *symbol,
|
||||
type_arguments: type_variables,
|
||||
lambda_set_variables,
|
||||
actual: Box::new(actual),
|
||||
kind: *kind,
|
||||
}
|
||||
}
|
||||
HostExposedAlias {
|
||||
name,
|
||||
arguments: solved_type_variables,
|
||||
lambda_set_variables: solved_lambda_sets,
|
||||
actual_var,
|
||||
actual: solved_actual,
|
||||
} => {
|
||||
let mut type_variables = Vec::with_capacity(solved_type_variables.len());
|
||||
|
||||
for solved_arg in solved_type_variables {
|
||||
type_variables.push(to_type(solved_arg, free_vars, var_store));
|
||||
}
|
||||
|
||||
let mut lambda_set_variables = Vec::with_capacity(solved_lambda_sets.len());
|
||||
for solved_set in solved_lambda_sets {
|
||||
lambda_set_variables.push(crate::types::LambdaSet(to_type(
|
||||
&solved_set.0,
|
||||
free_vars,
|
||||
var_store,
|
||||
)))
|
||||
}
|
||||
|
||||
let actual = to_type(solved_actual, free_vars, var_store);
|
||||
|
||||
Type::HostExposedAlias {
|
||||
name: *name,
|
||||
type_arguments: type_variables,
|
||||
lambda_set_variables,
|
||||
actual_var: var_id_to_flex_var(*actual_var, free_vars, var_store),
|
||||
actual: Box::new(actual),
|
||||
}
|
||||
}
|
||||
Error => Type::Erroneous(Problem::SolvedTypeError),
|
||||
Erroneous(problem) => Type::Erroneous(problem.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn var_id_to_flex_var(
|
||||
var_id: VarId,
|
||||
free_vars: &mut FreeVars,
|
||||
var_store: &mut VarStore,
|
||||
) -> Variable {
|
||||
if let Some(var) = free_vars.unnamed_vars.get(&var_id) {
|
||||
*var
|
||||
} else {
|
||||
let var = var_store.fresh();
|
||||
free_vars.unnamed_vars.insert(var_id, var);
|
||||
|
||||
var
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,7 +403,7 @@ fn list_contains() {
|
|||
#[cfg(not(feature = "wasm"))]
|
||||
#[test]
|
||||
fn list_sum() {
|
||||
expect_success("List.sum []", "0 : Num *");
|
||||
expect_success("List.sum []", "0 : Num a");
|
||||
expect_success("List.sum [1, 2, 3]", "6 : Num *");
|
||||
expect_success("List.sum [1.1, 2.2, 3.3]", "6.6 : Float *");
|
||||
}
|
||||
|
@ -417,7 +417,7 @@ fn list_first() {
|
|||
);
|
||||
expect_success(
|
||||
"List.first []",
|
||||
"Err ListWasEmpty : Result * [ListWasEmpty]*",
|
||||
"Err ListWasEmpty : Result a [ListWasEmpty]*",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -431,7 +431,7 @@ fn list_last() {
|
|||
|
||||
expect_success(
|
||||
"List.last []",
|
||||
"Err ListWasEmpty : Result * [ListWasEmpty]*",
|
||||
"Err ListWasEmpty : Result a [ListWasEmpty]*",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ use roc_can::operator;
|
|||
use roc_can::scope::Scope;
|
||||
use roc_collections::all::{ImMap, MutMap, SendSet};
|
||||
use roc_constrain::expr::constrain_expr;
|
||||
use roc_constrain::module::introduce_builtin_imports;
|
||||
use roc_derive_key::GlobalDerivedSymbols;
|
||||
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds};
|
||||
use roc_parse::parser::{SourceError, SyntaxError};
|
||||
|
@ -18,7 +17,7 @@ use roc_problem::can::Problem;
|
|||
use roc_region::all::Loc;
|
||||
use roc_solve::solve::{self, Aliases};
|
||||
use roc_types::subs::{Content, Subs, VarStore, Variable};
|
||||
use roc_types::types::{AliasVar, Type};
|
||||
use roc_types::types::Type;
|
||||
use std::hash::Hash;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
|
@ -157,10 +156,6 @@ pub fn can_expr_with<'a>(
|
|||
|
||||
let mut scope = Scope::new(home, IdentIds::default(), Default::default());
|
||||
|
||||
// to skip loading other modules, we populate the scope with the builtin aliases
|
||||
// that makes the reporting tests much faster
|
||||
add_aliases(&mut scope, &mut var_store);
|
||||
|
||||
let dep_idents = IdentIds::exposed_builtins(0);
|
||||
let mut env = Env::new(arena, home, &dep_idents, &module_ids);
|
||||
let (loc_expr, output) = canonicalize_expr(
|
||||
|
@ -184,15 +179,6 @@ pub fn can_expr_with<'a>(
|
|||
expected,
|
||||
);
|
||||
|
||||
let imports = roc_builtins::std::borrow_stdlib()
|
||||
.types
|
||||
.keys()
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
let constraint =
|
||||
introduce_builtin_imports(&mut constraints, imports, constraint, &mut var_store);
|
||||
|
||||
let mut all_ident_ids = IdentIds::exposed_builtins(1);
|
||||
all_ident_ids.insert(home, scope.locals.ident_ids);
|
||||
|
||||
|
@ -214,37 +200,6 @@ pub fn can_expr_with<'a>(
|
|||
})
|
||||
}
|
||||
|
||||
fn add_aliases(scope: &mut Scope, var_store: &mut VarStore) {
|
||||
use roc_types::solved_types::{BuiltinAlias, FreeVars};
|
||||
|
||||
let solved_aliases = roc_types::builtin_aliases::aliases();
|
||||
|
||||
for (symbol, builtin_alias) in solved_aliases {
|
||||
let BuiltinAlias {
|
||||
region,
|
||||
vars,
|
||||
typ,
|
||||
kind,
|
||||
} = builtin_alias;
|
||||
|
||||
let mut free_vars = FreeVars::default();
|
||||
let typ = roc_types::solved_types::to_type(&typ, &mut free_vars, var_store);
|
||||
|
||||
let mut variables = Vec::new();
|
||||
// make sure to sort these variables to make them line up with the type arguments
|
||||
let mut type_variables: Vec<_> = free_vars.unnamed_vars.into_iter().collect();
|
||||
type_variables.sort();
|
||||
for (loc_name, (_, var)) in vars.iter().zip(type_variables) {
|
||||
variables.push(Loc::at(
|
||||
loc_name.region,
|
||||
AliasVar::unbound(loc_name.value.clone(), var),
|
||||
));
|
||||
}
|
||||
|
||||
scope.add_alias(symbol, region, variables, typ, kind);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn mut_map_from_pairs<K, V, I>(pairs: I) -> MutMap<K, V>
|
||||
where
|
||||
|
|
|
@ -8941,7 +8941,7 @@ All branches in an `if` must have the same type!
|
|||
go goal new
|
||||
"#
|
||||
),
|
||||
@r#"
|
||||
@r###"
|
||||
── TYPE MISMATCH ───────────────────────────────────────── /code/proj/Main.roc ─
|
||||
|
||||
The 1st argument to `remove` is not what I expect:
|
||||
|
@ -8955,7 +8955,7 @@ All branches in an `if` must have the same type!
|
|||
|
||||
But `remove` needs the 1st argument to be:
|
||||
|
||||
Set a
|
||||
Set k
|
||||
|
||||
Tip: The type annotation uses the type variable `a` to say that this
|
||||
definition can produce any type of value. But in the body I see that
|
||||
|
@ -8988,7 +8988,7 @@ All branches in an `if` must have the same type!
|
|||
infinitely.
|
||||
|
||||
Set ∞
|
||||
"#
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue