mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Only open extension variable when feature is turned on
This commit is contained in:
parent
9a7e280e9c
commit
ed23461165
4 changed files with 43 additions and 15 deletions
|
@ -19,3 +19,7 @@ bumpalo = { version = "3.8.0", features = ["collections"] }
|
|||
[features]
|
||||
default = []
|
||||
debug-derived-symbols = ["roc_module/debug-symbols"]
|
||||
# Enables open extension variables for constructed records and tag unions.
|
||||
# This is not necessary for code generation, but may be necessary if you are
|
||||
# constraining and solving generated derived bodies.
|
||||
open-extension-vars = []
|
||||
|
|
|
@ -17,7 +17,7 @@ use roc_types::subs::{
|
|||
};
|
||||
use roc_types::types::{AliasKind, RecordField};
|
||||
|
||||
use crate::util::Env;
|
||||
use crate::util::{Env, ExtensionKind};
|
||||
use crate::{synth_var, DerivedBody};
|
||||
|
||||
pub(crate) fn derive_decoder(
|
||||
|
@ -353,7 +353,7 @@ fn decoder_record_step_field(
|
|||
region: Region::zero(),
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Tag {
|
||||
tag_union_var: result_field_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
|
||||
name: "Ok".into(),
|
||||
arguments: vec![(
|
||||
field_var,
|
||||
|
@ -365,14 +365,14 @@ fn decoder_record_step_field(
|
|||
|
||||
let updated_record = Expr::Update {
|
||||
record_var: state_record_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||
symbol: state_arg_symbol,
|
||||
updates,
|
||||
};
|
||||
|
||||
Expr::Tag {
|
||||
tag_union_var: when_expr_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
|
||||
name: "Ok".into(),
|
||||
arguments: vec![(state_record_var, Loc::at_zero(updated_record))],
|
||||
}
|
||||
|
@ -413,7 +413,7 @@ fn decoder_record_step_field(
|
|||
}],
|
||||
value: Loc::at_zero(Expr::Tag {
|
||||
tag_union_var: when_expr_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
|
||||
name: "Err".into(),
|
||||
arguments: vec![(
|
||||
decode_err_var,
|
||||
|
@ -431,7 +431,7 @@ fn decoder_record_step_field(
|
|||
Expr::When {
|
||||
loc_cond: Box::new(Loc::at_zero(Expr::Access {
|
||||
record_var: rec_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||
field_var: rec_dot_result,
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol))),
|
||||
field: "result".into(),
|
||||
|
@ -460,7 +460,7 @@ fn decoder_record_step_field(
|
|||
region: Region::zero(),
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Access {
|
||||
record_var: rec_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||
field_var: Variable::LIST_U8,
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol))),
|
||||
field: "rest".into(),
|
||||
|
@ -624,7 +624,7 @@ fn decoder_record_step_field(
|
|||
// )
|
||||
Expr::Tag {
|
||||
tag_union_var: keep_or_skip_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
|
||||
name: "Keep".into(),
|
||||
arguments: vec![(decode_custom_ret_var, Loc::at_zero(decode_custom))],
|
||||
}
|
||||
|
@ -664,7 +664,7 @@ fn decoder_record_step_field(
|
|||
}],
|
||||
value: Loc::at_zero(Expr::Tag {
|
||||
tag_union_var: keep_or_skip_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
|
||||
name: "Skip".into(),
|
||||
arguments: Vec::new(),
|
||||
}),
|
||||
|
@ -804,7 +804,7 @@ fn decoder_record_finalizer(
|
|||
|
||||
Expr::Tag {
|
||||
tag_union_var: return_type_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
|
||||
name: "Ok".into(),
|
||||
arguments: vec![(done_record_var, Loc::at_zero(done_record))],
|
||||
}
|
||||
|
@ -825,7 +825,7 @@ fn decoder_record_finalizer(
|
|||
// when rec.first is
|
||||
let cond_expr = Expr::Access {
|
||||
record_var: state_record_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||
field_var: result_field_var,
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(state_arg_symbol))),
|
||||
field: field_name.clone(),
|
||||
|
@ -855,7 +855,7 @@ fn decoder_record_finalizer(
|
|||
}],
|
||||
value: Loc::at_zero(Expr::Tag {
|
||||
tag_union_var: return_type_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
|
||||
name: "Err".into(),
|
||||
arguments: vec![(
|
||||
decode_err_var,
|
||||
|
@ -928,10 +928,10 @@ fn decoder_record_initial_state(
|
|||
field_vars: &mut Vec<Variable>,
|
||||
result_field_vars: &mut Vec<Variable>,
|
||||
) -> (Variable, Expr) {
|
||||
let subs = &mut env.subs;
|
||||
let mut initial_state_fields = SendMap::default();
|
||||
|
||||
for field_name in field_names {
|
||||
let subs = &mut env.subs;
|
||||
let field_var = subs.fresh_unnamed_flex_var();
|
||||
|
||||
field_vars.push(field_var);
|
||||
|
@ -956,7 +956,7 @@ fn decoder_record_initial_state(
|
|||
);
|
||||
let field_expr = Expr::Tag {
|
||||
tag_union_var: result_var,
|
||||
ext_var: subs.fresh_unnamed_flex_var(),
|
||||
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
|
||||
name: err_label.into(),
|
||||
arguments: vec![(no_field_var, Loc::at_zero(no_field))],
|
||||
};
|
||||
|
@ -970,6 +970,7 @@ fn decoder_record_initial_state(
|
|||
initial_state_fields.insert(field_name.clone(), field);
|
||||
}
|
||||
|
||||
let subs = &mut env.subs;
|
||||
let record_field_iter = field_names
|
||||
.iter()
|
||||
.zip(result_field_vars.iter())
|
||||
|
|
|
@ -152,4 +152,27 @@ impl Env<'_> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an extension variable for a tag union or record.
|
||||
///
|
||||
/// Derivers should always construct tag union and record types such that they are closed.
|
||||
/// If the `open-extension-vars` feature is turned on, flex extension vars will be
|
||||
/// returned; otherwise, the appropriate closed extension variable for the type will be
|
||||
/// returned.
|
||||
#[inline(always)]
|
||||
pub fn new_ext_var(&mut self, kind: ExtensionKind) -> Variable {
|
||||
if cfg!(feature = "open-extension-vars") {
|
||||
self.subs.fresh_unnamed_flex_var()
|
||||
} else {
|
||||
match kind {
|
||||
ExtensionKind::Record => Variable::EMPTY_RECORD,
|
||||
ExtensionKind::TagUnion => Variable::EMPTY_TAG_UNION,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum ExtensionKind {
|
||||
Record,
|
||||
TagUnion,
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ roc_builtins = { path = "../builtins" }
|
|||
roc_load_internal = { path = "../load_internal" }
|
||||
roc_can = { path = "../can" }
|
||||
roc_derive_key = { path = "../derive_key" }
|
||||
roc_derive = { path = "../derive", features = ["debug-derived-symbols"] }
|
||||
roc_derive = { path = "../derive", features = ["debug-derived-symbols", "open-extension-vars"] }
|
||||
roc_target = { path = "../roc_target" }
|
||||
roc_types = { path = "../types" }
|
||||
roc_reporting = { path = "../../reporting" }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue