mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
ensure VarId always encodes root var
otherwise variables with the same root, but different values would be different once imported in another module
This commit is contained in:
parent
c589be43c6
commit
36e6950daa
4 changed files with 45 additions and 23 deletions
|
@ -207,16 +207,7 @@ fn to_type(solved_type: &SolvedType, free_vars: &mut FreeVars, var_store: &mut V
|
||||||
Type::Variable(var)
|
Type::Variable(var)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Flex(var_id) => {
|
Flex(var_id) => Type::Variable(var_id_to_flex_var(*var_id, free_vars, var_store)),
|
||||||
if let Some(var) = free_vars.unnamed_vars.get(&var_id) {
|
|
||||||
Type::Variable(*var)
|
|
||||||
} else {
|
|
||||||
let var = var_store.fresh();
|
|
||||||
free_vars.unnamed_vars.insert(*var_id, var);
|
|
||||||
|
|
||||||
Type::Variable(var)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Wildcard => {
|
Wildcard => {
|
||||||
let var = var_store.fresh();
|
let var = var_store.fresh();
|
||||||
free_vars.wildcards.push(var);
|
free_vars.wildcards.push(var);
|
||||||
|
@ -274,11 +265,11 @@ fn to_type(solved_type: &SolvedType, free_vars: &mut FreeVars, var_store: &mut V
|
||||||
}
|
}
|
||||||
Boolean(SolvedBool::SolvedShared) => Type::Boolean(Bool::Shared),
|
Boolean(SolvedBool::SolvedShared) => Type::Boolean(Bool::Shared),
|
||||||
Boolean(SolvedBool::SolvedContainer(solved_cvar, solved_mvars)) => {
|
Boolean(SolvedBool::SolvedContainer(solved_cvar, solved_mvars)) => {
|
||||||
let cvar = var_id_to_var(*solved_cvar, free_vars, var_store);
|
let cvar = var_id_to_flex_var(*solved_cvar, free_vars, var_store);
|
||||||
|
|
||||||
let mvars = solved_mvars
|
let mvars = solved_mvars
|
||||||
.iter()
|
.iter()
|
||||||
.map(|var_id| var_id_to_var(*var_id, free_vars, var_store));
|
.map(|var_id| var_id_to_flex_var(*var_id, free_vars, var_store));
|
||||||
|
|
||||||
Type::Boolean(Bool::container(cvar, mvars))
|
Type::Boolean(Bool::container(cvar, mvars))
|
||||||
}
|
}
|
||||||
|
@ -298,7 +289,11 @@ fn to_type(solved_type: &SolvedType, free_vars: &mut FreeVars, var_store: &mut V
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn var_id_to_var(var_id: VarId, free_vars: &mut FreeVars, var_store: &mut VarStore) -> Variable {
|
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) {
|
if let Some(var) = free_vars.unnamed_vars.get(&var_id) {
|
||||||
*var
|
*var
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -286,7 +286,26 @@ mod test_uniq_load {
|
||||||
"w" => "Attr * (Dep1.Identity (Attr * {}))",
|
"w" => "Attr * (Dep1.Identity (Attr * {}))",
|
||||||
"succeed" => "Attr * (Attr b a -> Attr * (Dep1.Identity (Attr b a)))",
|
"succeed" => "Attr * (Attr b a -> Attr * (Dep1.Identity (Attr b a)))",
|
||||||
"yay" => "Attr * (Res.Res (Attr * {}) (Attr * err))",
|
"yay" => "Attr * (Res.Res (Attr * {}) (Attr * err))",
|
||||||
"withDefault" => "Attr * (Attr (* | * | *) (Res.Res (Attr * a) (Attr * *)), Attr * a -> Attr * a)",
|
"withDefault" => "Attr * (Attr (* | a | b) (Res.Res (Attr a c) (Attr b *)), Attr a c -> Attr a c)",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn load_custom_res() {
|
||||||
|
test_async(async {
|
||||||
|
let subs_by_module = MutMap::default();
|
||||||
|
let loaded_module = load_fixture("interface_with_deps", "Res", subs_by_module).await;
|
||||||
|
|
||||||
|
// the inferred signature for withDefault is wrong, part of the alias in alias issue.
|
||||||
|
// "withDefault" => "Attr * (Attr * (Res.Res (Attr a b) (Attr * *)), Attr a b -> Attr a b)",
|
||||||
|
expect_types(
|
||||||
|
loaded_module,
|
||||||
|
hashmap! {
|
||||||
|
"withDefault" =>"Attr * (Attr (* | b | c) (Res (Attr b a) (Attr c err)), Attr b a -> Attr b a)",
|
||||||
|
"map" => "Attr * (Attr (* | c | d) (Res (Attr d a) (Attr c err)), Attr * (Attr d a -> Attr e b) -> Attr * (Res (Attr e b) (Attr c err)))",
|
||||||
|
"andThen" => "Attr * (Attr (* | c | d) (Res (Attr d a) (Attr c err)), Attr * (Attr d a -> Attr e (Res (Attr f b) (Attr c err))) -> Attr e (Res (Attr f b) (Attr c err)))"
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -62,15 +62,18 @@ pub enum SolvedBool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SolvedBool {
|
impl SolvedBool {
|
||||||
pub fn from_bool(boolean: &boolean_algebra::Bool) -> Self {
|
pub fn from_bool(boolean: &boolean_algebra::Bool, subs: &Subs) -> Self {
|
||||||
use boolean_algebra::Bool;
|
use boolean_algebra::Bool;
|
||||||
|
|
||||||
// NOTE we blindly trust that `cvar` is a root and has a FlexVar as content
|
// NOTE we blindly trust that `cvar` is a root and has a FlexVar as content
|
||||||
match boolean {
|
match boolean {
|
||||||
Bool::Shared => SolvedBool::SolvedShared,
|
Bool::Shared => SolvedBool::SolvedShared,
|
||||||
Bool::Container(cvar, mvars) => SolvedBool::SolvedContainer(
|
Bool::Container(cvar, mvars) => SolvedBool::SolvedContainer(
|
||||||
VarId::from_var(*cvar),
|
VarId::from_var(*cvar, subs),
|
||||||
mvars.iter().map(|mvar| VarId::from_var(*mvar)).collect(),
|
mvars
|
||||||
|
.iter()
|
||||||
|
.map(|mvar| VarId::from_var(*mvar, subs))
|
||||||
|
.collect(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +158,7 @@ impl SolvedType {
|
||||||
}
|
}
|
||||||
|
|
||||||
SolvedType::RecursiveTagUnion(
|
SolvedType::RecursiveTagUnion(
|
||||||
VarId::from_var(rec_var),
|
VarId::from_var(rec_var, solved_subs.inner()),
|
||||||
solved_tags,
|
solved_tags,
|
||||||
Box::new(solved_ext),
|
Box::new(solved_ext),
|
||||||
)
|
)
|
||||||
|
@ -171,7 +174,7 @@ impl SolvedType {
|
||||||
|
|
||||||
SolvedType::Alias(symbol, solved_args, Box::new(solved_type))
|
SolvedType::Alias(symbol, solved_args, Box::new(solved_type))
|
||||||
}
|
}
|
||||||
Boolean(val) => SolvedType::Boolean(SolvedBool::from_bool(&val)),
|
Boolean(val) => SolvedType::Boolean(SolvedBool::from_bool(&val, solved_subs.inner())),
|
||||||
Variable(var) => Self::from_var(solved_subs.inner(), var),
|
Variable(var) => Self::from_var(solved_subs.inner(), var),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +183,7 @@ impl SolvedType {
|
||||||
use crate::subs::Content::*;
|
use crate::subs::Content::*;
|
||||||
|
|
||||||
match subs.get_without_compacting(var).content {
|
match subs.get_without_compacting(var).content {
|
||||||
FlexVar(_) => SolvedType::Flex(VarId::from_var(var)),
|
FlexVar(_) => SolvedType::Flex(VarId::from_var(var, subs)),
|
||||||
RigidVar(name) => SolvedType::Rigid(name),
|
RigidVar(name) => SolvedType::Rigid(name),
|
||||||
Structure(flat_type) => Self::from_flat_type(subs, flat_type),
|
Structure(flat_type) => Self::from_flat_type(subs, flat_type),
|
||||||
Alias(symbol, args, actual_var) => {
|
Alias(symbol, args, actual_var) => {
|
||||||
|
@ -270,11 +273,15 @@ impl SolvedType {
|
||||||
|
|
||||||
let ext = Self::from_var(subs, ext_var);
|
let ext = Self::from_var(subs, ext_var);
|
||||||
|
|
||||||
SolvedType::RecursiveTagUnion(VarId::from_var(rec_var), new_tags, Box::new(ext))
|
SolvedType::RecursiveTagUnion(
|
||||||
|
VarId::from_var(rec_var, subs),
|
||||||
|
new_tags,
|
||||||
|
Box::new(ext),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
EmptyRecord => SolvedType::EmptyRecord,
|
EmptyRecord => SolvedType::EmptyRecord,
|
||||||
EmptyTagUnion => SolvedType::EmptyTagUnion,
|
EmptyTagUnion => SolvedType::EmptyTagUnion,
|
||||||
Boolean(val) => SolvedType::Boolean(SolvedBool::from_bool(&val)),
|
Boolean(val) => SolvedType::Boolean(SolvedBool::from_bool(&val, subs)),
|
||||||
Erroneous(problem) => SolvedType::Erroneous(problem),
|
Erroneous(problem) => SolvedType::Erroneous(problem),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,8 @@ impl UnifyKey for Variable {
|
||||||
pub struct VarId(u32);
|
pub struct VarId(u32);
|
||||||
|
|
||||||
impl VarId {
|
impl VarId {
|
||||||
pub fn from_var(var: Variable) -> Self {
|
pub fn from_var(var: Variable, subs: &Subs) -> Self {
|
||||||
|
let var = subs.get_root_key_without_compacting(var);
|
||||||
let Variable(n) = var;
|
let Variable(n) = var;
|
||||||
|
|
||||||
VarId(n)
|
VarId(n)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue