Fix default annotation for spend's optional datum and mint argument.

When there's no type annotation in a validator handler signature, we
  provide default annotation to help the type-checker. However, for
  spend's datum and mint policy_id, those annotations mustn't be `Data`,
  but rather Option<Data> and Bytearray.

  Without that, when no annotation are provided, the compiler infer
  invalid types and fails with incongruous errors.
This commit is contained in:
KtorZ 2024-08-27 18:34:37 +02:00
parent 0510ca58f7
commit 4003343444
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
2 changed files with 43 additions and 9 deletions

View File

@ -266,6 +266,16 @@ pub struct Function<T, Expr, Arg> {
pub on_test_failure: OnTestFailure, pub on_test_failure: OnTestFailure,
} }
impl<T, Expr, Arg> Function<T, Expr, Arg> {
pub fn is_spend(&self) -> bool {
self.name == HANDLER_SPEND
}
pub fn is_mint(&self) -> bool {
self.name == HANDLER_MINT
}
}
impl TypedFunction { impl TypedFunction {
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> { pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
self.arguments self.arguments
@ -279,10 +289,6 @@ impl TypedFunction {
}) })
} }
pub fn is_spend(&self) -> bool {
self.name == HANDLER_SPEND
}
pub fn has_valid_purpose_name(&self) -> bool { pub fn has_valid_purpose_name(&self) -> bool {
self.name == HANDLER_SPEND self.name == HANDLER_SPEND
|| self.name == HANDLER_PUBLISH || self.name == HANDLER_PUBLISH
@ -1245,6 +1251,15 @@ impl Annotation {
} }
} }
pub fn option(inner: Annotation) -> Self {
Annotation::Constructor {
name: "Option".to_string(),
module: None,
location: inner.location(),
arguments: vec![inner],
}
}
pub fn is_logically_equal(&self, other: &Annotation) -> bool { pub fn is_logically_equal(&self, other: &Annotation) -> bool {
match self { match self {
Annotation::Constructor { Annotation::Constructor {

View File

@ -1275,10 +1275,9 @@ impl<'a> Environment<'a> {
location, location,
end_position: _, end_position: _,
}) if kind.is_validator() => { }) if kind.is_validator() => {
let default_annotation = |mut arg: UntypedArg| { let default_annotation = |mut arg: UntypedArg, ann: Annotation| {
if arg.annotation.is_none() { if arg.annotation.is_none() {
arg.annotation = Some(Annotation::data(arg.location)); arg.annotation = Some(ann);
arg arg
} else { } else {
arg arg
@ -1287,12 +1286,29 @@ impl<'a> Environment<'a> {
let mut handler_names = vec![]; let mut handler_names = vec![];
let params_len = params.len();
for handler in handlers { for handler in handlers {
let temp_params: Vec<UntypedArg> = params let temp_params: Vec<UntypedArg> = params
.iter() .iter()
.cloned() .cloned()
.chain(handler.arguments.clone()) .chain(handler.arguments.clone())
.map(default_annotation) .enumerate()
.map(|(ix, arg)| {
let is_datum = handler.is_spend() && ix == params_len;
let is_mint_policy = handler.is_mint() && ix == params_len + 1;
let location = arg.location;
default_annotation(
arg,
if is_datum {
Annotation::option(Annotation::data(location))
} else if is_mint_policy {
Annotation::bytearray(location)
} else {
Annotation::data(location)
},
)
})
.collect(); .collect();
handler_names.push(handler.name.clone()); handler_names.push(handler.name.clone());
@ -1312,7 +1328,10 @@ impl<'a> Environment<'a> {
.iter() .iter()
.cloned() .cloned()
.chain(fallback.arguments.clone()) .chain(fallback.arguments.clone())
.map(default_annotation) .map(|arg| {
let location = arg.location;
default_annotation(arg, Annotation::data(location))
})
.collect(); .collect();
self.register_function( self.register_function(