1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

Merge pull request #798 from Zokrates/accept-explicit-generics

Accept explicit generic parameters for function calls
This commit is contained in:
Thibaut Schaeffer 2021-04-20 16:02:54 +02:00 committed by GitHub
commit f4faad94f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 4 deletions

View file

@ -0,0 +1 @@
Accept explicit generic parameters outside of definitions

View file

@ -0,0 +1,5 @@
def foo<N>() -> field[N]:
return [42; N]
def main() -> field[2]:
return foo() // N is currently not infered to 2 here

View file

@ -0,0 +1,6 @@
def foo<N>() -> field[N]:
return [42; N]
def main() -> field[2]:
field a = foo::<3>()[0]
return foo::<2>()

View file

@ -1923,16 +1923,19 @@ impl<'ast, T: Field> Checker<'ast, T> {
message: format!("Expected function call argument to be of type {}, found {}", e.1, e.0)
})?;
let output_types = signature.get_output_types(arguments_checked.iter().map(|a| a.get_type()).collect()).map_err(|e| ErrorInner {
let generics_checked = generics_checked.unwrap_or_else(|| vec![None; signature.generics.len()]);
let output_types = signature.get_output_types(
generics_checked.clone(),
arguments_checked.iter().map(|a| a.get_type()).collect()
).map_err(|e| ErrorInner {
pos: Some(pos),
message: format!(
"Failed to infer value for generic parameter `{}`, try being more explicit by using an intermediate variable",
"Failed to infer value for generic parameter `{}`, try providing an explicit value",
e,
),
})?;
let generics_checked = generics_checked.unwrap_or_else(|| vec![None; signature.generics.len()]);
// the return count has to be 1
match output_types.len() {
1 => match &output_types[0] {

View file

@ -1047,11 +1047,28 @@ pub mod signature {
pub fn get_output_types<T: Clone + PartialEq + fmt::Debug>(
&self,
generics: Vec<Option<UExpression<'ast, T>>>,
inputs: Vec<Type<'ast, T>>,
) -> Result<Vec<Type<'ast, T>>, GenericIdentifier<'ast>> {
// we keep track of the value of constants in a map, as a given constant can only have one value
let mut constants = GenericsAssignment::default();
// initialise the map with the explicitly provided generics
constants
.0
.extend(self.generics.iter().zip(generics).filter_map(|(g, v)| {
// only add to the map when there's indeed a generic value being provided
v.map(|v| {
(
match g.clone().unwrap() {
Constant::Generic(g) => g,
_ => unreachable!(),
},
v,
)
})
}));
// fill the map with the inputs
let _ = self
.inputs