mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Add constraint generation for opaque types
This commit is contained in:
parent
d3acf34415
commit
86aa0df661
13 changed files with 499 additions and 172 deletions
|
@ -12,13 +12,12 @@ use roc_can::expr::Expr::{self, *};
|
|||
use roc_can::expr::{ClosureData, Field, WhenBranch};
|
||||
use roc_can::pattern::Pattern;
|
||||
use roc_collections::all::{ImMap, Index, MutSet, SendMap};
|
||||
use roc_error_macros::todo_opaques;
|
||||
use roc_module::ident::{Lowercase, TagName};
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_types::subs::Variable;
|
||||
use roc_types::types::Type::{self, *};
|
||||
use roc_types::types::{AnnotationSource, Category, PReason, Reason, RecordField};
|
||||
use roc_types::types::{AliasKind, AnnotationSource, Category, PReason, Reason, RecordField};
|
||||
|
||||
/// This is for constraining Defs
|
||||
#[derive(Default, Debug)]
|
||||
|
@ -917,7 +916,71 @@ pub fn constrain_expr(
|
|||
exists(vars, And(arg_cons))
|
||||
}
|
||||
|
||||
OpaqueRef { .. } => todo_opaques!(),
|
||||
OpaqueRef {
|
||||
opaque_var,
|
||||
name,
|
||||
argument,
|
||||
specialized_def_type,
|
||||
type_arguments,
|
||||
lambda_set_variables,
|
||||
} => {
|
||||
let (arg_var, arg_loc_expr) = &**argument;
|
||||
let arg_type = Type::Variable(*arg_var);
|
||||
|
||||
let opaque_type = Type::Alias {
|
||||
symbol: *name,
|
||||
type_arguments: type_arguments.clone(),
|
||||
lambda_set_variables: lambda_set_variables.clone(),
|
||||
actual: Box::new(arg_type.clone()),
|
||||
kind: AliasKind::Opaque,
|
||||
};
|
||||
|
||||
// Constrain the argument
|
||||
let arg_con = constrain_expr(
|
||||
env,
|
||||
arg_loc_expr.region,
|
||||
&arg_loc_expr.value,
|
||||
Expected::NoExpectation(arg_type.clone()),
|
||||
);
|
||||
|
||||
// Link the entire wrapped opaque type (with the now-constrained argument) to the
|
||||
// expected type
|
||||
let opaque_con = Eq(
|
||||
opaque_type,
|
||||
expected.clone(),
|
||||
Category::OpaqueWrap(*name),
|
||||
region,
|
||||
);
|
||||
|
||||
// Link the entire wrapped opaque type (with the now-constrained argument) to the type
|
||||
// variables of the opaque type
|
||||
// TODO: better expectation here
|
||||
let link_type_variables_con = Eq(
|
||||
(**specialized_def_type).clone(),
|
||||
Expected::NoExpectation(arg_type),
|
||||
Category::OpaqueWrap(*name),
|
||||
arg_loc_expr.region,
|
||||
);
|
||||
|
||||
// Store the entire wrapped opaque type in `opaque_var`
|
||||
let storage_con = Eq(
|
||||
Type::Variable(*opaque_var),
|
||||
expected,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
region,
|
||||
);
|
||||
|
||||
exists(
|
||||
// TODO: may need to extend with vars from `type_arguments` and `lambda_set_variables` here!
|
||||
vec![*arg_var, *opaque_var],
|
||||
And(vec![
|
||||
arg_con,
|
||||
opaque_con,
|
||||
link_type_variables_con,
|
||||
storage_con,
|
||||
]),
|
||||
)
|
||||
}
|
||||
|
||||
RunLowLevel { args, ret_var, op } => {
|
||||
// This is a modified version of what we do for function calls.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue