feat(validators): unused param warning
Params being unused were being incorrectly reported. This was because params need to be initialized at a scope above both the validator functions. This manifested when using a multi-validator where one of the params was not used in both validators. The easy fix was to add a field called `is_validator_param` to `ArgName`. Then when infering a function we don't initialize args that are validator params. We now handle this in a scope that is created before in the match branch for validator in the `infer_definition` function. In there we call `.in_new_scope` and initialize params for usage detection.
This commit is contained in:
parent
8fad5b77c6
commit
d8cbcde61d
|
@ -564,6 +564,7 @@ pub enum ArgName {
|
||||||
name: String,
|
name: String,
|
||||||
label: String,
|
label: String,
|
||||||
location: Span,
|
location: Span,
|
||||||
|
is_validator_param: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -675,6 +675,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
name: "self".to_string(),
|
name: "self".to_string(),
|
||||||
label: "self".to_string(),
|
label: "self".to_string(),
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -724,6 +725,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -770,6 +772,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -830,6 +833,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
name: "f".to_string(),
|
name: "f".to_string(),
|
||||||
label: "f".to_string(),
|
label: "f".to_string(),
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -845,6 +849,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
name: "b".to_string(),
|
name: "b".to_string(),
|
||||||
label: "b".to_string(),
|
label: "b".to_string(),
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -855,6 +860,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
|
|
@ -242,44 +242,9 @@ pub fn type_alias_parser() -> impl Parser<Token, ast::UntypedDefinition, Error =
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validator_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
|
pub fn validator_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
|
||||||
let func_parser = just(Token::Fn)
|
|
||||||
.ignore_then(select! {Token::Name {name} => name})
|
|
||||||
.then(
|
|
||||||
fn_param_parser()
|
|
||||||
.separated_by(just(Token::Comma))
|
|
||||||
.allow_trailing()
|
|
||||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
|
||||||
.map_with_span(|arguments, span| (arguments, span)),
|
|
||||||
)
|
|
||||||
.then(just(Token::RArrow).ignore_then(type_parser()).or_not())
|
|
||||||
.then(
|
|
||||||
expr_seq_parser()
|
|
||||||
.or_not()
|
|
||||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
|
|
||||||
)
|
|
||||||
.map_with_span(
|
|
||||||
|(((name, (arguments, args_span)), return_annotation), body), span| ast::Function {
|
|
||||||
arguments,
|
|
||||||
body: body.unwrap_or_else(|| expr::UntypedExpr::todo(span, None)),
|
|
||||||
doc: None,
|
|
||||||
location: Span {
|
|
||||||
start: span.start,
|
|
||||||
end: return_annotation
|
|
||||||
.as_ref()
|
|
||||||
.map(|l| l.location().end)
|
|
||||||
.unwrap_or_else(|| args_span.end),
|
|
||||||
},
|
|
||||||
end_position: span.end - 1,
|
|
||||||
name,
|
|
||||||
public: false,
|
|
||||||
return_annotation,
|
|
||||||
return_type: (),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
just(Token::Validator)
|
just(Token::Validator)
|
||||||
.ignore_then(
|
.ignore_then(
|
||||||
fn_param_parser()
|
fn_param_parser(true)
|
||||||
.separated_by(just(Token::Comma))
|
.separated_by(just(Token::Comma))
|
||||||
.allow_trailing()
|
.allow_trailing()
|
||||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||||
|
@ -287,12 +252,20 @@ pub fn validator_parser() -> impl Parser<Token, ast::UntypedDefinition, Error =
|
||||||
.or_not(),
|
.or_not(),
|
||||||
)
|
)
|
||||||
.then(
|
.then(
|
||||||
func_parser
|
fn_parser()
|
||||||
.repeated()
|
.repeated()
|
||||||
.at_least(1)
|
.at_least(1)
|
||||||
.at_most(2)
|
.at_most(2)
|
||||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace))
|
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace))
|
||||||
.map(IntoIterator::into_iter),
|
.map(|defs| {
|
||||||
|
defs.into_iter().map(|def| {
|
||||||
|
let ast::UntypedDefinition::Fn(fun) = def else {
|
||||||
|
unreachable!("It should be a fn definition");
|
||||||
|
};
|
||||||
|
|
||||||
|
fun
|
||||||
|
})
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.map_with_span(|(opt_extra_params, mut functions), span| {
|
.map_with_span(|(opt_extra_params, mut functions), span| {
|
||||||
let (params, params_span) = opt_extra_params.unwrap_or((
|
let (params, params_span) = opt_extra_params.unwrap_or((
|
||||||
|
@ -326,7 +299,7 @@ pub fn fn_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseEr
|
||||||
.then_ignore(just(Token::Fn))
|
.then_ignore(just(Token::Fn))
|
||||||
.then(select! {Token::Name {name} => name})
|
.then(select! {Token::Name {name} => name})
|
||||||
.then(
|
.then(
|
||||||
fn_param_parser()
|
fn_param_parser(false)
|
||||||
.separated_by(just(Token::Comma))
|
.separated_by(just(Token::Comma))
|
||||||
.allow_trailing()
|
.allow_trailing()
|
||||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||||
|
@ -489,7 +462,9 @@ pub fn bytearray_parser(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fn_param_parser() -> impl Parser<Token, ast::UntypedArg, Error = ParseError> {
|
pub fn fn_param_parser(
|
||||||
|
is_validator_param: bool,
|
||||||
|
) -> impl Parser<Token, ast::UntypedArg, Error = ParseError> {
|
||||||
choice((
|
choice((
|
||||||
select! {Token::Name {name} => name}
|
select! {Token::Name {name} => name}
|
||||||
.then(select! {Token::DiscardName {name} => name})
|
.then(select! {Token::DiscardName {name} => name})
|
||||||
|
@ -507,15 +482,17 @@ pub fn fn_param_parser() -> impl Parser<Token, ast::UntypedArg, Error = ParseErr
|
||||||
}),
|
}),
|
||||||
select! {Token::Name {name} => name}
|
select! {Token::Name {name} => name}
|
||||||
.then(select! {Token::Name {name} => name})
|
.then(select! {Token::Name {name} => name})
|
||||||
.map_with_span(|(label, name), span| ast::ArgName::Named {
|
.map_with_span(move |(label, name), span| ast::ArgName::Named {
|
||||||
label,
|
label,
|
||||||
name,
|
name,
|
||||||
location: span,
|
location: span,
|
||||||
|
is_validator_param,
|
||||||
}),
|
}),
|
||||||
select! {Token::Name {name} => name}.map_with_span(|name, span| ast::ArgName::Named {
|
select! {Token::Name {name} => name}.map_with_span(move |name, span| ast::ArgName::Named {
|
||||||
label: name.clone(),
|
label: name.clone(),
|
||||||
name,
|
name,
|
||||||
location: span,
|
location: span,
|
||||||
|
is_validator_param,
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
.then(just(Token::Colon).ignore_then(type_parser()).or_not())
|
.then(just(Token::Colon).ignore_then(type_parser()).or_not())
|
||||||
|
@ -541,6 +518,7 @@ pub fn anon_fn_param_parser() -> impl Parser<Token, ast::UntypedArg, Error = Par
|
||||||
label: name.clone(),
|
label: name.clone(),
|
||||||
name,
|
name,
|
||||||
location: span,
|
location: span,
|
||||||
|
is_validator_param: false,
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
.then(just(Token::Colon).ignore_then(type_parser()).or_not())
|
.then(just(Token::Colon).ignore_then(type_parser()).or_not())
|
||||||
|
@ -1169,6 +1147,7 @@ pub fn expr_parser(
|
||||||
label: name.clone(),
|
label: name.clone(),
|
||||||
name,
|
name,
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
tipo: (),
|
tipo: (),
|
||||||
});
|
});
|
||||||
|
|
|
@ -113,6 +113,47 @@ fn validator_in_lib_warning() {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_validator() {
|
||||||
|
let source_code = r#"
|
||||||
|
validator(foo: ByteArray, bar: Int) {
|
||||||
|
fn spend(_d, _r, _c) {
|
||||||
|
foo == #"aabb"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mint(_r, _c) {
|
||||||
|
bar == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let (warnings, _) = check_validator(parse(source_code)).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(warnings.len(), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_validator_warning() {
|
||||||
|
let source_code = r#"
|
||||||
|
validator(foo: ByteArray, bar: Int) {
|
||||||
|
fn spend(_d, _r, _c) {
|
||||||
|
foo == #"aabb"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mint(_r, _c) {
|
||||||
|
True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let (warnings, _) = check_validator(parse(source_code)).unwrap();
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
warnings[0],
|
||||||
|
Warning::UnusedVariable { ref name, .. } if name == "bar"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_scoping() {
|
fn if_scoping() {
|
||||||
let source_code = r#"
|
let source_code = r#"
|
||||||
|
|
|
@ -60,6 +60,7 @@ fn validator() {
|
||||||
name: "datum".to_string(),
|
name: "datum".to_string(),
|
||||||
label: "datum".to_string(),
|
label: "datum".to_string(),
|
||||||
location: Span::new((), 21..26),
|
location: Span::new((), 21..26),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 21..26),
|
location: Span::new((), 21..26),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -70,6 +71,7 @@ fn validator() {
|
||||||
name: "rdmr".to_string(),
|
name: "rdmr".to_string(),
|
||||||
label: "rdmr".to_string(),
|
label: "rdmr".to_string(),
|
||||||
location: Span::new((), 28..32),
|
location: Span::new((), 28..32),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 28..32),
|
location: Span::new((), 28..32),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -80,6 +82,7 @@ fn validator() {
|
||||||
name: "ctx".to_string(),
|
name: "ctx".to_string(),
|
||||||
label: "ctx".to_string(),
|
label: "ctx".to_string(),
|
||||||
location: Span::new((), 34..37),
|
location: Span::new((), 34..37),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 34..37),
|
location: Span::new((), 34..37),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -131,6 +134,7 @@ fn double_validator() {
|
||||||
name: "datum".to_string(),
|
name: "datum".to_string(),
|
||||||
label: "datum".to_string(),
|
label: "datum".to_string(),
|
||||||
location: Span::new((), 21..26),
|
location: Span::new((), 21..26),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 21..26),
|
location: Span::new((), 21..26),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -141,6 +145,7 @@ fn double_validator() {
|
||||||
name: "rdmr".to_string(),
|
name: "rdmr".to_string(),
|
||||||
label: "rdmr".to_string(),
|
label: "rdmr".to_string(),
|
||||||
location: Span::new((), 28..32),
|
location: Span::new((), 28..32),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 28..32),
|
location: Span::new((), 28..32),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -151,6 +156,7 @@ fn double_validator() {
|
||||||
name: "ctx".to_string(),
|
name: "ctx".to_string(),
|
||||||
label: "ctx".to_string(),
|
label: "ctx".to_string(),
|
||||||
location: Span::new((), 34..37),
|
location: Span::new((), 34..37),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 34..37),
|
location: Span::new((), 34..37),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -176,6 +182,7 @@ fn double_validator() {
|
||||||
name: "rdmr".to_string(),
|
name: "rdmr".to_string(),
|
||||||
label: "rdmr".to_string(),
|
label: "rdmr".to_string(),
|
||||||
location: Span::new((), 64..68),
|
location: Span::new((), 64..68),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 64..68),
|
location: Span::new((), 64..68),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -186,6 +193,7 @@ fn double_validator() {
|
||||||
name: "ctx".to_string(),
|
name: "ctx".to_string(),
|
||||||
label: "ctx".to_string(),
|
label: "ctx".to_string(),
|
||||||
location: Span::new((), 70..73),
|
location: Span::new((), 70..73),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 70..73),
|
location: Span::new((), 70..73),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -589,6 +597,7 @@ fn plus_binop() {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
location: Span::new((), 15..16),
|
location: Span::new((), 15..16),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 15..16),
|
location: Span::new((), 15..16),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -640,6 +649,7 @@ fn pipeline() {
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
label: "thing".to_string(),
|
label: "thing".to_string(),
|
||||||
location: Span::new((), 13..20),
|
location: Span::new((), 13..20),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 13..25),
|
location: Span::new((), 13..25),
|
||||||
annotation: Some(ast::Annotation::Constructor {
|
annotation: Some(ast::Annotation::Constructor {
|
||||||
|
@ -808,6 +818,7 @@ fn let_bindings() {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
location: Span::new((), 11..12),
|
location: Span::new((), 11..12),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 11..17),
|
location: Span::new((), 11..17),
|
||||||
annotation: Some(ast::Annotation::Constructor {
|
annotation: Some(ast::Annotation::Constructor {
|
||||||
|
@ -934,6 +945,7 @@ fn block() {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
location: Span::new((), 12..13),
|
location: Span::new((), 12..13),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 12..18),
|
location: Span::new((), 12..18),
|
||||||
annotation: Some(ast::Annotation::Constructor {
|
annotation: Some(ast::Annotation::Constructor {
|
||||||
|
@ -1027,6 +1039,7 @@ fn when() {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
location: Span::new((), 12..13),
|
location: Span::new((), 12..13),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 12..18),
|
location: Span::new((), 12..18),
|
||||||
annotation: Some(ast::Annotation::Constructor {
|
annotation: Some(ast::Annotation::Constructor {
|
||||||
|
@ -1160,6 +1173,7 @@ fn anonymous_function() {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
location: Span::new((), 43..44),
|
location: Span::new((), 43..44),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 43..49),
|
location: Span::new((), 43..49),
|
||||||
annotation: Some(ast::Annotation::Constructor {
|
annotation: Some(ast::Annotation::Constructor {
|
||||||
|
@ -1243,6 +1257,7 @@ fn field_access() {
|
||||||
label: "user".to_string(),
|
label: "user".to_string(),
|
||||||
name: "user".to_string(),
|
name: "user".to_string(),
|
||||||
location: Span::new((), 8..12),
|
location: Span::new((), 8..12),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 8..18),
|
location: Span::new((), 8..18),
|
||||||
annotation: Some(ast::Annotation::Constructor {
|
annotation: Some(ast::Annotation::Constructor {
|
||||||
|
@ -1325,6 +1340,7 @@ fn call() {
|
||||||
label: "_capture__0".to_string(),
|
label: "_capture__0".to_string(),
|
||||||
name: "_capture__0".to_string(),
|
name: "_capture__0".to_string(),
|
||||||
location: Span::new((), 0..0),
|
location: Span::new((), 0..0),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 0..0),
|
location: Span::new((), 0..0),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -1351,6 +1367,7 @@ fn call() {
|
||||||
label: "y".to_string(),
|
label: "y".to_string(),
|
||||||
name: "y".to_string(),
|
name: "y".to_string(),
|
||||||
location: Span::new((), 69..70),
|
location: Span::new((), 69..70),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 69..70),
|
location: Span::new((), 69..70),
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -1450,6 +1467,7 @@ fn record_update() {
|
||||||
label: "user".to_string(),
|
label: "user".to_string(),
|
||||||
name: "user".to_string(),
|
name: "user".to_string(),
|
||||||
location: Span::new((), 15..19),
|
location: Span::new((), 15..19),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 15..25),
|
location: Span::new((), 15..25),
|
||||||
annotation: Some(ast::Annotation::Constructor {
|
annotation: Some(ast::Annotation::Constructor {
|
||||||
|
@ -1465,6 +1483,7 @@ fn record_update() {
|
||||||
label: "name".to_string(),
|
label: "name".to_string(),
|
||||||
name: "name".to_string(),
|
name: "name".to_string(),
|
||||||
location: Span::new((), 27..31),
|
location: Span::new((), 27..31),
|
||||||
|
is_validator_param: false,
|
||||||
},
|
},
|
||||||
location: Span::new((), 27..42),
|
location: Span::new((), 27..42),
|
||||||
annotation: Some(ast::Annotation::Constructor {
|
annotation: Some(ast::Annotation::Constructor {
|
||||||
|
|
|
@ -1480,15 +1480,19 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
) -> Result<(Vec<TypedArg>, TypedExpr), Error> {
|
) -> Result<(Vec<TypedArg>, TypedExpr), Error> {
|
||||||
self.assert_no_assignment(&body)?;
|
self.assert_no_assignment(&body)?;
|
||||||
|
|
||||||
for (arg, t) in args.iter().zip(args.iter().map(|arg| arg.tipo.clone())) {
|
for arg in &args {
|
||||||
match &arg.arg_name {
|
match &arg.arg_name {
|
||||||
ArgName::Named { name, .. } => {
|
ArgName::Named {
|
||||||
|
name,
|
||||||
|
is_validator_param,
|
||||||
|
..
|
||||||
|
} if !is_validator_param => {
|
||||||
self.environment.insert_variable(
|
self.environment.insert_variable(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
ValueConstructorVariant::LocalVariable {
|
ValueConstructorVariant::LocalVariable {
|
||||||
location: arg.location,
|
location: arg.location,
|
||||||
},
|
},
|
||||||
t,
|
arg.tipo.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.environment.init_usage(
|
self.environment.init_usage(
|
||||||
|
@ -1497,7 +1501,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
arg.location,
|
arg.location,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ArgName::Discarded { .. } => (),
|
ArgName::Named { .. } | ArgName::Discarded { .. } => (),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
DataType, Definition, Function, Layer, ModuleConstant, ModuleKind, RecordConstructor,
|
ArgName, DataType, Definition, Function, Layer, ModuleConstant, ModuleKind,
|
||||||
RecordConstructorArg, Span, Tracing, TypeAlias, TypedDefinition, TypedFunction,
|
RecordConstructor, RecordConstructorArg, Span, Tracing, TypeAlias, TypedDefinition,
|
||||||
TypedModule, UntypedDefinition, UntypedModule, Use, Validator,
|
TypedFunction, TypedModule, UntypedDefinition, UntypedModule, Use, Validator,
|
||||||
},
|
},
|
||||||
builtins,
|
builtins,
|
||||||
builtins::function,
|
builtins::function,
|
||||||
|
@ -262,6 +262,43 @@ fn infer_definition(
|
||||||
let temp_params = params.iter().cloned().chain(fun.arguments);
|
let temp_params = params.iter().cloned().chain(fun.arguments);
|
||||||
fun.arguments = temp_params.collect();
|
fun.arguments = temp_params.collect();
|
||||||
|
|
||||||
|
environment.in_new_scope(|environment| {
|
||||||
|
let preregistered_fn = environment
|
||||||
|
.get_variable(&fun.name)
|
||||||
|
.expect("Could not find preregistered type for function");
|
||||||
|
|
||||||
|
|
||||||
|
let preregistered_type = preregistered_fn.tipo.clone();
|
||||||
|
|
||||||
|
let (args_types, _return_type) = preregistered_type
|
||||||
|
.function_types()
|
||||||
|
.expect("Preregistered type for fn was not a fn");
|
||||||
|
|
||||||
|
for (arg, t) in params.iter().zip(args_types[0..params.len()].iter()) {
|
||||||
|
match &arg.arg_name {
|
||||||
|
ArgName::Named {
|
||||||
|
name,
|
||||||
|
is_validator_param,
|
||||||
|
..
|
||||||
|
} if *is_validator_param => {
|
||||||
|
environment.insert_variable(
|
||||||
|
name.to_string(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: arg.location,
|
||||||
|
},
|
||||||
|
t.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
environment.init_usage(
|
||||||
|
name.to_string(),
|
||||||
|
EntityKind::Variable,
|
||||||
|
arg.location,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ArgName::Named { .. } | ArgName::Discarded { .. } => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let Definition::Fn(mut typed_fun) = infer_definition(
|
let Definition::Fn(mut typed_fun) = infer_definition(
|
||||||
Definition::Fn(fun),
|
Definition::Fn(fun),
|
||||||
module_name,
|
module_name,
|
||||||
|
@ -316,7 +353,9 @@ fn infer_definition(
|
||||||
|
|
||||||
other_typed_fun.arguments.drain(0..params_length);
|
other_typed_fun.arguments.drain(0..params_length);
|
||||||
|
|
||||||
if other_typed_fun.arguments.len() < 2 || other_typed_fun.arguments.len() > 3 {
|
if other_typed_fun.arguments.len() < 2
|
||||||
|
|| other_typed_fun.arguments.len() > 3
|
||||||
|
{
|
||||||
return Err(Error::IncorrectValidatorArity {
|
return Err(Error::IncorrectValidatorArity {
|
||||||
count: other_typed_fun.arguments.len() as u32,
|
count: other_typed_fun.arguments.len() as u32,
|
||||||
location: other_typed_fun.location,
|
location: other_typed_fun.location,
|
||||||
|
@ -343,6 +382,7 @@ fn infer_definition(
|
||||||
location,
|
location,
|
||||||
params: typed_params,
|
params: typed_params,
|
||||||
}))
|
}))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Definition::Test(f) => {
|
Definition::Test(f) => {
|
||||||
|
|
Loading…
Reference in New Issue