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:
microproofs
2024-01-13 16:34:38 -05:00
committed by Kasey
parent f934e87b1d
commit c7af27a6ba
33 changed files with 171 additions and 62 deletions

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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
}