feat(validator): move return type and arity check to infer
This commit is contained in:
parent
a88a193383
commit
d03288cece
|
@ -756,6 +756,30 @@ The best thing to do from here is to remove it."#))]
|
||||||
location: Span,
|
location: Span,
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[error("A validator must return {}", "Bool".bright_blue().bold())]
|
||||||
|
#[diagnostic(code("illegal::validator_return_type"))]
|
||||||
|
#[diagnostic(help(r#"While analyzing the return type of your validator, I found it to be:
|
||||||
|
|
||||||
|
╰─▶ {signature}
|
||||||
|
|
||||||
|
...but I expected this to be a {type_Bool}. If I am inferring the wrong type, you may want to add a type annotation to the function."#
|
||||||
|
, type_Bool = "Bool".bright_blue().bold()
|
||||||
|
, signature = return_type.to_pretty(0).red()
|
||||||
|
))]
|
||||||
|
ValidatorMustReturnBool {
|
||||||
|
#[label("invalid return type")]
|
||||||
|
location: Span,
|
||||||
|
return_type: Arc<Type>,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[error("Validators requires at least {} arguments.", at_least.to_string().purple().bold())]
|
||||||
|
#[diagnostic(code("illegal::validator_arity"))]
|
||||||
|
WrongValidatorArity {
|
||||||
|
at_least: u8,
|
||||||
|
#[label("not enough arguments")]
|
||||||
|
location: Span,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
|
@ -1210,13 +1234,16 @@ pub enum Warning {
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("I came across a validator in a {} module\nwhich means I'm going to ignore it.\n", "lib/".purple())]
|
#[error("I came across a validator in a {} module which means\nI'm going to ignore it.\n", "lib/".purple())]
|
||||||
#[diagnostic(help(
|
#[diagnostic(help(
|
||||||
"No big deal, but you might want to move it to a\n{} module or remove it to get rid of that warning.",
|
"No big deal, but you might want to move it to a {} module\nor remove it to get rid of that warning.",
|
||||||
"validators/".purple()
|
"validators/".purple()
|
||||||
))]
|
))]
|
||||||
#[diagnostic(code("unused::validator"))]
|
#[diagnostic(code("unused::validator"))]
|
||||||
ValidatorInLibraryModule { location: Span },
|
ValidatorInLibraryModule {
|
||||||
|
#[label("unused")]
|
||||||
|
location: Span,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
|
|
@ -268,19 +268,22 @@ fn infer_definition(
|
||||||
environment,
|
environment,
|
||||||
kind,
|
kind,
|
||||||
)? {
|
)? {
|
||||||
// Do we want to do this here?
|
if !typed_fun.return_type.is_bool() {
|
||||||
// or should we remove this and keep the later check
|
return Err(Error::ValidatorMustReturnBool {
|
||||||
// the later check has a much more specific error message
|
return_type: typed_fun.return_type.clone(),
|
||||||
// we may want to not do this here
|
location: typed_fun.location,
|
||||||
environment.unify(
|
});
|
||||||
typed_fun.return_type.clone(),
|
}
|
||||||
builtins::bool(),
|
|
||||||
typed_fun.location,
|
|
||||||
false,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let typed_params = typed_fun.arguments.drain(0..params_length).collect();
|
let typed_params = typed_fun.arguments.drain(0..params_length).collect();
|
||||||
|
|
||||||
|
if typed_fun.arguments.len() < 2 {
|
||||||
|
return Err(Error::WrongValidatorArity {
|
||||||
|
at_least: 2,
|
||||||
|
location: typed_fun.location,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Definition::Validator(Validator {
|
Ok(Definition::Validator(Validator {
|
||||||
doc,
|
doc,
|
||||||
end_position,
|
end_position,
|
||||||
|
|
|
@ -1,44 +1,11 @@
|
||||||
use super::schema;
|
use super::schema;
|
||||||
use crate::module::CheckedModule;
|
use aiken_lang::ast::Span;
|
||||||
use aiken_lang::{
|
|
||||||
ast::{Span, TypedFunction},
|
|
||||||
tipo::Type,
|
|
||||||
};
|
|
||||||
use miette::{Diagnostic, NamedSource};
|
use miette::{Diagnostic, NamedSource};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use std::{fmt::Debug, sync::Arc};
|
use std::fmt::Debug;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, Diagnostic)]
|
#[derive(Debug, thiserror::Error, Diagnostic)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("A validator must return {}", "Bool".bright_blue().bold())]
|
|
||||||
#[diagnostic(code("aiken::blueprint::invalid::return_type"))]
|
|
||||||
#[diagnostic(help(r#"While analyzing the return type of your validator, I found it to be:
|
|
||||||
|
|
||||||
╰─▶ {signature}
|
|
||||||
|
|
||||||
...but I expected this to be a {type_Bool}. If I am inferring the wrong type, you may want to add a type annotation to the function."#
|
|
||||||
, type_Bool = "Bool".bright_blue().bold()
|
|
||||||
, signature = return_type.to_pretty(0).red()
|
|
||||||
))]
|
|
||||||
ValidatorMustReturnBool {
|
|
||||||
#[label("invalid return type")]
|
|
||||||
location: Span,
|
|
||||||
#[source_code]
|
|
||||||
source_code: NamedSource,
|
|
||||||
return_type: Arc<Type>,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("A {} validator requires at least {} arguments.", name.purple().bold(), at_least.to_string().purple().bold())]
|
|
||||||
#[diagnostic(code("aiken::blueprint::invalid::arity"))]
|
|
||||||
WrongValidatorArity {
|
|
||||||
name: String,
|
|
||||||
at_least: u8,
|
|
||||||
#[label("not enough arguments")]
|
|
||||||
location: Span,
|
|
||||||
#[source_code]
|
|
||||||
source_code: NamedSource,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("{}", error)]
|
#[error("{}", error)]
|
||||||
#[diagnostic(help("{}", error.help()))]
|
#[diagnostic(help("{}", error.help()))]
|
||||||
#[diagnostic(code("aiken::blueprint::interface"))]
|
#[diagnostic(code("aiken::blueprint::interface"))]
|
||||||
|
@ -64,38 +31,3 @@ pub enum Error {
|
||||||
#[diagnostic(help("I can only compute addresses of validators that are fully applied. For example, a {keyword_spend} validator must have exactly 3 arguments: a datum, a redeemer and a context. If it has more, they need to be provided beforehand and applied directly in the validator. Applying parameters change the validator's compiled code, and thus the address.\n\nThis is why I need you to apply parmeters first.", keyword_spend = "spend".purple()))]
|
#[diagnostic(help("I can only compute addresses of validators that are fully applied. For example, a {keyword_spend} validator must have exactly 3 arguments: a datum, a redeemer and a context. If it has more, they need to be provided beforehand and applied directly in the validator. Applying parameters change the validator's compiled code, and thus the address.\n\nThis is why I need you to apply parmeters first.", keyword_spend = "spend".purple()))]
|
||||||
ParameterizedValidator { n: usize },
|
ParameterizedValidator { n: usize },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_return_bool(module: &CheckedModule, def: &TypedFunction) -> Result<(), Error> {
|
|
||||||
if !def.return_type.is_bool() {
|
|
||||||
Err(Error::ValidatorMustReturnBool {
|
|
||||||
return_type: def.return_type.clone(),
|
|
||||||
location: def.location,
|
|
||||||
source_code: NamedSource::new(
|
|
||||||
module.input_path.display().to_string(),
|
|
||||||
module.code.clone(),
|
|
||||||
),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn assert_min_arity(
|
|
||||||
module: &CheckedModule,
|
|
||||||
def: &TypedFunction,
|
|
||||||
at_least: u8,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if def.arguments.len() < at_least as usize {
|
|
||||||
Err(Error::WrongValidatorArity {
|
|
||||||
name: def.name.clone(),
|
|
||||||
at_least,
|
|
||||||
location: def.location,
|
|
||||||
source_code: NamedSource::new(
|
|
||||||
module.input_path.display().to_string(),
|
|
||||||
module.code.clone(),
|
|
||||||
),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue