Correctly generate type constraints for required symbols in platform

This commit is contained in:
Ayaz Hafiz 2022-05-05 16:43:37 -04:00 committed by Richard Feldman
parent e8fbda44fc
commit c7142da116
No known key found for this signature in database
GPG key ID: 7E4127D1E4241798
7 changed files with 35 additions and 17 deletions

View file

@ -1300,7 +1300,7 @@ pub fn constrain_decls(
constraint constraint
} }
fn constrain_def_pattern( pub fn constrain_def_pattern(
constraints: &mut Constraints, constraints: &mut Constraints,
env: &Env, env: &Env,
loc_pattern: &Loc<Pattern>, loc_pattern: &Loc<Pattern>,
@ -1706,7 +1706,7 @@ fn constrain_def(
} }
} }
fn constrain_def_make_constraint( pub fn constrain_def_make_constraint(
constraints: &mut Constraints, constraints: &mut Constraints,
new_rigid_variables: Vec<Variable>, new_rigid_variables: Vec<Variable>,
new_infer_variables: Vec<Variable>, new_infer_variables: Vec<Variable>,

View file

@ -11,6 +11,8 @@ use roc_types::solved_types::{FreeVars, SolvedType};
use roc_types::subs::{VarStore, Variable}; use roc_types::subs::{VarStore, Variable};
use roc_types::types::{Category, Type}; use roc_types::types::{Category, Type};
use crate::expr::{constrain_def_make_constraint, constrain_def_pattern, Env};
/// The types of all exposed values/functions of a collection of modules /// The types of all exposed values/functions of a collection of modules
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct ExposedByModule { pub struct ExposedByModule {
@ -116,28 +118,43 @@ fn constrain_symbols_from_requires(
home: ModuleId, home: ModuleId,
constraint: Constraint, constraint: 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 symbols_from_requires
.into_iter() .into_iter()
.fold(constraint, |constraint, (symbol, loc_type)| { .fold(constraint, |constraint, (symbol, loc_type)| {
if symbol.module_id() == home { if symbol.module_id() == home {
constraints.let_constraint( // 1. Required symbols can only be specified in package modules
rigid_vars.clone(), // 2. Required symbols come from app modules
flex_vars.clone(), // But, if we are running e.g. `roc check` on a package module, there is no app
std::iter::once((symbol, loc_type)), // module, and we will have instead put the required symbols in the package module
// namespace. If this is the case, we want to introduce the symbols as if they had
// the types they are annotated with.
let rigids = Default::default();
let env = Env { home, rigids };
let pattern = Loc::at_zero(roc_can::pattern::Pattern::Identifier(symbol));
let def_pattern_state =
constrain_def_pattern(constraints, &env, &pattern, loc_type.value.clone());
constrain_def_make_constraint(
constraints,
// No new rigids or flex vars because they are represented in the type
// annotation.
vec![],
vec![],
Constraint::True, Constraint::True,
constraint, constraint,
def_pattern_state,
) )
} else { } else {
constraints.lookup( // Otherwise, this symbol comes from an app module - we want to check that the type
// provided by the app is in fact what the package module requires.
let provided_eq_requires_constr = constraints.lookup(
symbol, symbol,
// TODO give it a real expectation, so errors can be helpful // TODO give it a real expectation, so errors can be helpful
Expected::NoExpectation(loc_type.value), Expected::NoExpectation(loc_type.value),
loc_type.region, loc_type.region,
) );
constraints.and_constraint([provided_eq_requires_constr, constraint])
} }
}) })
} }

View file

@ -6,7 +6,7 @@ app "deriv"
# based on: https://github.com/koka-lang/koka/blob/master/test/bench/haskell/deriv.hs # based on: https://github.com/koka-lang/koka/blob/master/test/bench/haskell/deriv.hs
IO a : Task.Task a [] IO a : Task.Task a []
main : IO {} main : Task.Task {} []
main = main =
Task.after Task.after
Task.getInt Task.getInt

View file

@ -1,5 +1,5 @@
platform "benchmarks" platform "benchmarks"
requires {} { main : Effect {} } requires {} { main : Task {} [] }
exposes [] exposes []
packages {} packages {}
imports [ Task.{ Task } ] imports [ Task.{ Task } ]

View file

@ -1,5 +1,5 @@
platform "effects" platform "effects"
requires {} { main : Effect {} } requires {} { main : Effect.Effect {} }
exposes [] exposes []
packages {} packages {}
imports [ pf.Effect ] imports [ pf.Effect ]

View file

@ -1,5 +1,5 @@
platform "tui" platform "tui"
requires { Model } { main : Effect {} } requires { Model } { main : { init : ({} -> Model), update : (Model, Str -> Model), view : (Model -> Str) } }
exposes [] exposes []
packages {} packages {}
imports [] imports []

View file

@ -385,7 +385,8 @@ impl<'a> RocDocAllocator<'a> {
pub fn tag_name(&'a self, tn: TagName) -> DocBuilder<'a, Self, Annotation> { pub fn tag_name(&'a self, tn: TagName) -> DocBuilder<'a, Self, Annotation> {
match tn { match tn {
TagName::Tag(uppercase) => self.tag(uppercase), TagName::Tag(uppercase) => self.tag(uppercase),
TagName::Closure(_symbol) => unreachable!("closure tags are internal only"), TagName::Closure(symbol) => self.symbol_qualified(symbol),
// TagName::Closure(_symbol) => unreachable!("closure tags are internal only"),
} }
} }