fix: generic edge case with tuples that allowed 2 tuples and 3 tuples to use the same monomorphized function.
Also massively reduced the space taken up by generics in scripts when using generics with list and tuples
This commit is contained in:
@@ -27,7 +27,7 @@ use crate::{
|
||||
gen_uplc::builder::{
|
||||
check_replaceable_opaque_type, convert_opaque_type, erase_opaque_type_operations,
|
||||
find_and_replace_generics, find_list_clause_or_default_first, get_arg_type_name,
|
||||
get_generic_id_and_type, get_src_code_by_span, get_variant_name, monomorphize,
|
||||
get_generic_id_and_type, get_generic_variant_name, get_src_code_by_span, monomorphize,
|
||||
pattern_has_conditions, wrap_as_multi_validator, wrap_validator_condition, CodeGenFunction,
|
||||
SpecificClause,
|
||||
},
|
||||
@@ -3547,6 +3547,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
.push((generic_function_key.clone(), "".to_string()));
|
||||
}
|
||||
|
||||
// Code gen functions are already monomorphized
|
||||
if let Some(func_variants) = function_usage.get_mut(&generic_function_key) {
|
||||
let (path, _) = func_variants.get_mut("").unwrap();
|
||||
*path = path.common_ancestor(tree_path);
|
||||
@@ -3606,20 +3607,20 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
let mono_types: IndexMap<u64, Rc<Type>> = if !function_def_types.is_empty() {
|
||||
function_def_types
|
||||
.into_iter()
|
||||
.zip(function_var_types)
|
||||
.iter()
|
||||
.zip(function_var_types.iter())
|
||||
.flat_map(|(func_tipo, var_tipo)| {
|
||||
get_generic_id_and_type(&func_tipo, &var_tipo)
|
||||
get_generic_id_and_type(func_tipo, var_tipo)
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
IndexMap::new()
|
||||
};
|
||||
|
||||
// Don't sort here. Mono types map is already in argument order.
|
||||
let variant = mono_types
|
||||
.iter()
|
||||
.sorted_by(|(id, _), (id2, _)| id.cmp(id2))
|
||||
.map(|(_, tipo)| get_variant_name(tipo))
|
||||
.map(|(_, tipo)| get_generic_variant_name(tipo))
|
||||
.join("");
|
||||
|
||||
*variant_name = variant.clone();
|
||||
|
||||
@@ -589,7 +589,7 @@ pub fn handle_clause_guard(clause_guard: &TypedClauseGuard) -> AirTree {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_variant_name(t: &Rc<Type>) -> String {
|
||||
pub fn get_generic_variant_name(t: &Rc<Type>) -> String {
|
||||
if t.is_string() {
|
||||
"_string".to_string()
|
||||
} else if t.is_int() {
|
||||
@@ -605,27 +605,13 @@ pub fn get_variant_name(t: &Rc<Type>) -> String {
|
||||
} else if t.is_ml_result() {
|
||||
"_ml_result".to_string()
|
||||
} else if t.is_map() {
|
||||
let mut full_type = vec!["_map".to_string()];
|
||||
let pair_type = &t.get_inner_types()[0];
|
||||
let fst_type = &pair_type.get_inner_types()[0];
|
||||
let snd_type = &pair_type.get_inner_types()[1];
|
||||
full_type.push(get_variant_name(fst_type));
|
||||
full_type.push(get_variant_name(snd_type));
|
||||
full_type.join("")
|
||||
"_map".to_string()
|
||||
} else if t.is_2_tuple() {
|
||||
"_pair".to_string()
|
||||
} else if t.is_list() {
|
||||
let full_type = "_list".to_string();
|
||||
let list_type = &t.get_inner_types()[0];
|
||||
|
||||
format!("{}{}", full_type, get_variant_name(list_type))
|
||||
"_list".to_string()
|
||||
} else if t.is_tuple() {
|
||||
let mut full_type = vec!["_tuple".to_string()];
|
||||
|
||||
let inner_types = t.get_inner_types();
|
||||
|
||||
for arg_type in inner_types {
|
||||
full_type.push(get_variant_name(&arg_type));
|
||||
}
|
||||
full_type.join("")
|
||||
"_tuple".to_string()
|
||||
} else if t.is_unbound() {
|
||||
"_unbound".to_string()
|
||||
} else {
|
||||
|
||||
@@ -186,15 +186,10 @@ impl Type {
|
||||
match self {
|
||||
Self::App {
|
||||
module, name, args, ..
|
||||
} if "List" == name && module.is_empty() => {
|
||||
if let Type::Tuple { elems } = &*args[0] {
|
||||
elems.len() == 2
|
||||
} else if let Type::Var { tipo } = &*args[0] {
|
||||
matches!(tipo.borrow().get_uplc_type(), Some(UplcType::Pair(_, _)))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
} if "List" == name && module.is_empty() => args
|
||||
.first()
|
||||
.expect("unreachable: List should have an inner type")
|
||||
.is_2_tuple(),
|
||||
Self::Var { tipo } => tipo.borrow().is_map(),
|
||||
_ => false,
|
||||
}
|
||||
@@ -322,6 +317,12 @@ impl Type {
|
||||
Self::Var { tipo } => tipo.borrow().get_uplc_type().unwrap(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else if self.is_bls381_12_g1() {
|
||||
UplcType::Bls12_381G1Element
|
||||
} else if self.is_bls381_12_g2() {
|
||||
UplcType::Bls12_381G2Element
|
||||
} else if self.is_ml_result() {
|
||||
UplcType::Bls12_381MlResult
|
||||
} else {
|
||||
UplcType::Data
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user