diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index d21462e08b..cd7d5e2981 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -54,7 +54,7 @@ pub struct Annotation { pub(crate) struct CanDefs { defs: Vec>, def_ordering: DefOrdering, - + pub(crate) abilities_in_scope: Vec, aliases: VecMap, } @@ -523,6 +523,7 @@ pub(crate) fn canonicalize_defs<'a>( CanDefs { defs, def_ordering, + abilities_in_scope, // The result needs a thread-safe `SendMap` aliases, }, @@ -766,8 +767,11 @@ pub(crate) fn sort_can_defs( mut defs, def_ordering, aliases, + abilities_in_scope, } = defs; + output.abilities_in_scope = abilities_in_scope; + for (symbol, alias) in aliases.into_iter() { output.aliases.insert(symbol, alias); } diff --git a/compiler/can/src/expr.rs b/compiler/can/src/expr.rs index b60a552f5c..12748b16ec 100644 --- a/compiler/can/src/expr.rs +++ b/compiler/can/src/expr.rs @@ -30,6 +30,7 @@ pub struct Output { pub introduced_variables: IntroducedVariables, pub aliases: VecMap, pub non_closures: VecSet, + pub abilities_in_scope: Vec, } impl Output { diff --git a/compiler/can/src/module.rs b/compiler/can/src/module.rs index ffba784309..a9fecd2323 100644 --- a/compiler/can/src/module.rs +++ b/compiler/can/src/module.rs @@ -1,4 +1,5 @@ use crate::abilities::AbilitiesStore; +use crate::annotation::canonicalize_annotation; use crate::def::{canonicalize_defs, sort_can_defs, Declaration, Def}; use crate::effect_module::HostedGeneratedFunctions; use crate::env::Env; @@ -11,7 +12,7 @@ use roc_collections::{MutMap, SendMap, VecSet}; use roc_module::ident::Ident; use roc_module::ident::Lowercase; use roc_module::symbol::{IdentIds, IdentIdsByModule, ModuleId, ModuleIds, Symbol}; -use roc_parse::ast; +use roc_parse::ast::{self, TypeAnnotation}; use roc_parse::header::HeaderFor; use roc_parse::pattern::PatternType; use roc_problem::can::{Problem, RuntimeError}; @@ -49,6 +50,7 @@ pub struct ModuleOutput { pub problems: Vec, pub referenced_values: VecSet, pub referenced_types: VecSet, + pub symbols_from_requires: Vec<(Symbol, Loc)>, pub scope: Scope, } @@ -156,16 +158,17 @@ fn has_no_implementation(expr: &Expr) -> bool { // TODO trim these down #[allow(clippy::too_many_arguments)] pub fn canonicalize_module_defs<'a>( - arena: &Bump, + arena: &'a Bump, loc_defs: &'a [Loc>], header_for: &roc_parse::header::HeaderFor, home: ModuleId, - module_ids: &ModuleIds, + module_ids: &'a ModuleIds, exposed_ident_ids: IdentIds, dep_idents: &'a IdentIdsByModule, aliases: MutMap, exposed_imports: MutMap, exposed_symbols: &VecSet, + symbols_from_requires: &[(Symbol, Loc>)], var_store: &mut VarStore, ) -> Result { let mut can_exposed_imports = MutMap::default(); @@ -349,9 +352,37 @@ pub fn canonicalize_module_defs<'a>( }; match sort_can_defs(&mut env, defs, new_output) { - (Ok(mut declarations), output) => { + (Ok(mut declarations), mut output) => { use crate::def::Declaration::*; + let symbols_from_requires = symbols_from_requires + .iter() + .map(|(symbol, loc_ann)| { + let ann = canonicalize_annotation( + &mut env, + &mut scope, + &loc_ann.value, + loc_ann.region, + var_store, + &output.abilities_in_scope, + ); + + ann.add_to( + &mut output.aliases, + &mut output.references, + &mut output.introduced_variables, + ); + + ( + *symbol, + Loc { + value: ann.typ, + region: loc_ann.region, + }, + ) + }) + .collect(); + if let GeneratedInfo::Hosted { effect_symbol, generated_functions, @@ -545,6 +576,7 @@ pub fn canonicalize_module_defs<'a>( referenced_types, exposed_imports: can_exposed_imports, problems: env.problems, + symbols_from_requires, lookups, }; diff --git a/compiler/constrain/src/module.rs b/compiler/constrain/src/module.rs index f0761ea965..c193405bea 100644 --- a/compiler/constrain/src/module.rs +++ b/compiler/constrain/src/module.rs @@ -94,12 +94,14 @@ pub enum ExposedModuleTypes { pub fn constrain_module( constraints: &mut Constraints, + symbols_from_requires: Vec<(Symbol, Loc)>, abilities_store: &AbilitiesStore, declarations: &[Declaration], home: ModuleId, ) -> Constraint { let constraint = crate::expr::constrain_decls(constraints, home, declarations); - + let constraint = + constrain_symbols_from_requires(constraints, symbols_from_requires, home, constraint); let constraint = frontload_ability_constraints(constraints, abilities_store, constraint); // The module constraint should always save the environment at the end. @@ -108,6 +110,38 @@ pub fn constrain_module( constraint } +fn constrain_symbols_from_requires( + constraints: &mut Constraints, + symbols_from_requires: Vec<(Symbol, Loc)>, + home: ModuleId, + constraint: Constraint, +) -> Constraint { + // TODO thread through rigid_vars and flex_vars + let rigid_vars = std::iter::empty(); + let flex_vars = std::iter::empty(); + + symbols_from_requires + .into_iter() + .fold(constraint, |constraint, (symbol, loc_type)| { + if symbol.module_id() == home { + constraints.let_constraint( + rigid_vars.clone(), + flex_vars.clone(), + std::iter::once((symbol, loc_type)), + Constraint::True, + constraint, + ) + } else { + constraints.lookup( + symbol, + // TODO give it a real expectation, so errors can be helpful + Expected::NoExpectation(loc_type.value), + loc_type.region, + ) + } + }) +} + pub fn frontload_ability_constraints( constraints: &mut Constraints, abilities_store: &AbilitiesStore, diff --git a/compiler/load_internal/src/file.rs b/compiler/load_internal/src/file.rs index fef510bdad..f0a82ef6e8 100644 --- a/compiler/load_internal/src/file.rs +++ b/compiler/load_internal/src/file.rs @@ -30,7 +30,7 @@ use roc_mono::ir::{ UpdateModeIds, }; use roc_mono::layout::{Layout, LayoutCache, LayoutProblem}; -use roc_parse::ast::{self, ExtractSpaces, Spaced, StrLiteral}; +use roc_parse::ast::{self, ExtractSpaces, Spaced, StrLiteral, TypeAnnotation}; use roc_parse::header::{ExposedName, ImportsEntry, PackageEntry, PlatformHeader, To, TypedIdent}; use roc_parse::header::{HeaderFor, ModuleNameEnum, PackageName}; use roc_parse::ident::UppercaseIdent; @@ -512,8 +512,9 @@ struct ModuleHeader<'a> { exposes: Vec, exposed_imports: MutMap, parse_state: roc_parse::state::State<'a>, - module_timing: ModuleTiming, header_for: HeaderFor<'a>, + symbols_from_requires: Vec<(Symbol, Loc>)>, + module_timing: ModuleTiming, } #[derive(Debug)] @@ -603,6 +604,7 @@ struct ParsedModule<'a> { exposed_imports: MutMap, parsed_defs: &'a [Loc>], module_name: ModuleNameEnum<'a>, + symbols_from_requires: Vec<(Symbol, Loc>)>, header_for: HeaderFor<'a>, } @@ -3228,8 +3230,9 @@ fn send_header<'a>( exposes: exposed, parse_state, exposed_imports: scope, - module_timing, + symbols_from_requires: Vec::new(), header_for: extra, + module_timing, }), ) } @@ -3269,6 +3272,7 @@ fn send_header_two<'a>( } = info; let declared_name: ModuleName = "".into(); + let mut symbols_from_requires = Vec::with_capacity(requires.len()); let mut imported: Vec<(QualifiedModuleName, Vec, Region)> = Vec::with_capacity(imports.len()); @@ -3372,6 +3376,7 @@ fn send_header_two<'a>( debug_assert!(!scope.contains_key(&ident.clone())); scope.insert(ident, (symbol, entry.ident.region)); + symbols_from_requires.push((symbol, entry.ann)); } for entry in requires_types { @@ -3471,6 +3476,7 @@ fn send_header_two<'a>( parse_state, exposed_imports: scope, module_timing, + symbols_from_requires, header_for: extra, }), ) @@ -3814,6 +3820,7 @@ fn canonicalize_and_constrain<'a>( exposed_imports, imported_modules, mut module_timing, + symbols_from_requires, .. } = parsed; @@ -3831,6 +3838,7 @@ fn canonicalize_and_constrain<'a>( aliases, exposed_imports, &exposed_symbols, + &symbols_from_requires, &mut var_store, ); @@ -3875,6 +3883,7 @@ fn canonicalize_and_constrain<'a>( } else { constrain_module( &mut constraints, + module_output.symbols_from_requires, &module_output.scope.abilities_store, &module_output.declarations, module_id, @@ -3986,6 +3995,7 @@ fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result, Loadi exposed_imports, module_path, header_for, + symbols_from_requires, .. } = header; @@ -4000,6 +4010,7 @@ fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result, Loadi exposed_ident_ids, exposed_imports, parsed_defs, + symbols_from_requires, header_for, };