Merge branch 'main' into always-typecheck-trace-label

This commit is contained in:
Matthias Benkort 2025-03-21 10:40:50 +01:00 committed by GitHub
commit 9354a5bad4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 168 additions and 74 deletions

View File

@ -6,6 +6,7 @@
- **aiken**: New `-S` flag on `check` and `build` that blocks the printing of warnings but it still shows the total warning count. @rvcas
- **aiken-lang**: Allow types to be used as namespaces for constructors. Importing each constructor variants independently is no longer required in neither pattern-matches nor value construction. One can simply use the type name as a prefix/namespace now. @KtorZ
- **aiken-lang**: Allow capture on constructor calls. @KtorZ
### Changed
@ -14,12 +15,10 @@
- **aiken-lang**: Disallow (parse error) dangling colon `:` in traces. See [#1113](https://github.com/aiken-lang/aiken/issues/1113). @KtorZ
- **aiken-lang**: Fix `aiken blueprint apply` wrongly overriding all validators handlers names & ABI to the mint's one. See [#1099](https://github.com/aiken-lang/aiken/issues/1099). @KtorZ
- **aiken-lang**: Always type-check trace label irrespective of the trace level, to avoid unnecessary warnings in compact or silent mode. See [#1122](https://github.com/aiken-lang/aiken/issues/1122). @KtorZ
### Fixed
- **aiken-lang**: Formatter was removing comments from function type annotation args @rvcas
- **aiken-lang**: Parser wrongly merged two adjacent sequences together, effectively fusioning scopes. @KtorZ
- **aiken-lang**: Fix hint when suggesting to use named fields, wrongly suggesting args in lexicographical order instead of definition order. @KtorZ
- **aiken-project**: Better errors on `blueprint apply` when matching multiple or no validators. See [#1127](https://github.com/aiken-lang/aiken/issues/1127) @KtorZ
## v1.1.13 - 2025-02-26

View File

@ -29,24 +29,16 @@ pub fn parser(
.then_ignore(just(Token::Colon))
.then(choice((
r.clone(),
select! {Token::DiscardName {name} => name }.validate(
|_name, span, emit| {
emit(ParseError::expected_input_found(
span,
None,
Some(error::Pattern::Discard),
));
UntypedExpr::Var {
location: span,
name: ast::CAPTURE_VARIABLE.to_string(),
}
choice((select! {Token::DiscardName {name} => name }.map_with_span(
|name, span| UntypedExpr::Var {
location: span,
name,
},
),
),)),
)))
.map_with_span(|(label, value), span| ast::CallArg {
location: span,
value,
value: Some(value),
label: Some(label),
}),
choice((
@ -111,7 +103,7 @@ pub fn parser(
)
.map(|(value, name)| ast::CallArg {
location: value.location(),
value,
value: Some(value),
label: Some(name),
}),
))
@ -144,24 +136,16 @@ pub fn parser(
.or_not()
.then(choice((
r.clone(),
select! {Token::DiscardName {name} => name }.validate(
|_name, span, emit| {
emit(ParseError::expected_input_found(
span,
None,
Some(error::Pattern::Discard),
));
UntypedExpr::Var {
location: span,
name: ast::CAPTURE_VARIABLE.to_string(),
}
},
),
select! {Token::DiscardName {name} => name }.map_with_span(|name, span| {
UntypedExpr::Var {
location: span,
name,
}
}),
)))
.map(|(_label, value)| ast::CallArg {
location: value.location(),
value,
value: Some(value),
label: None,
})
.separated_by(just(Token::Comma))
@ -208,11 +192,7 @@ pub fn parser(
},
};
UntypedExpr::Call {
arguments,
fun: Box::new(fun),
location: span,
}
fun.call(arguments, span)
},
)
}

View File

@ -13,7 +13,7 @@ use aiken_lang::gen_uplc::CodeGenerator;
use definitions::Definitions;
pub use error::Error;
use schema::{Annotated, Schema};
use std::fmt::Debug;
use std::{collections::BTreeSet, fmt::Debug};
use validator::Validator;
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
@ -99,15 +99,7 @@ impl Blueprint {
let mut validator = None;
for v in self.validators.iter() {
let mut split = v.title.split('.');
let known_module_name = split
.next()
.expect("validator's name must have two dot-separated components.");
let known_validator_name = split
.next()
.expect("validator's name must have two dot-separated components.");
let (known_module_name, known_validator_name) = v.get_module_and_name();
let is_target = match (want_module_name, want_validator_name) {
(None, None) => true,
@ -143,8 +135,8 @@ impl Blueprint {
&self,
module_name: Option<&str>,
validator_name: Option<&str>,
when_too_many: fn(Vec<String>) -> E,
when_missing: fn(Vec<String>) -> E,
when_too_many: fn(BTreeSet<(String, String, bool)>) -> E,
when_missing: fn(BTreeSet<(String, String, bool)>) -> E,
action: F,
) -> Result<A, E>
where
@ -153,10 +145,35 @@ impl Blueprint {
match self.lookup(module_name, validator_name) {
Some(LookupResult::One(_, validator)) => action(validator),
Some(LookupResult::Many) => Err(when_too_many(
self.validators.iter().map(|v| v.title.clone()).collect(),
self.validators
.iter()
.filter_map(|v| {
let (l, r) = v.get_module_and_name();
if let Some(module_name) = module_name {
if l != module_name {
return None;
}
}
if let Some(validator_name) = validator_name {
if r != validator_name {
return None;
}
}
Some((l.to_string(), r.to_string(), !v.parameters.is_empty()))
})
.collect(),
)),
None => Err(when_missing(
self.validators.iter().map(|v| v.title.clone()).collect(),
self.validators
.iter()
.map(|v| {
let (l, r) = v.get_module_and_name();
(l.to_string(), r.to_string(), !v.parameters.is_empty())
})
.collect(),
)),
}
}

View File

@ -46,6 +46,20 @@ pub struct Validator {
}
impl Validator {
pub fn get_module_and_name(&self) -> (&str, &str) {
let mut split = self.title.split('.');
let known_module_name = split
.next()
.expect("validator's name must have two dot-separated components.");
let known_validator_name = split
.next()
.expect("validator's name must have two dot-separated components.");
(known_module_name, known_validator_name)
}
pub fn from_checked_module(
modules: &CheckedModules,
generator: &mut CodeGenerator,

View File

@ -15,6 +15,7 @@ use owo_colors::{
Stream::{Stderr, Stdout},
};
use std::{
collections::BTreeSet,
fmt::{self, Debug, Display},
io,
path::{Path, PathBuf},
@ -137,10 +138,14 @@ pub enum Error {
},
#[error("I didn't find any validator matching your criteria.")]
NoValidatorNotFound { known_validators: Vec<String> },
NoValidatorNotFound {
known_validators: BTreeSet<(String, String, bool)>,
},
#[error("I found multiple suitable validators and I need you to tell me which one to pick.")]
MoreThanOneValidatorFound { known_validators: Vec<String> },
MoreThanOneValidatorFound {
known_validators: BTreeSet<(String, String, bool)>,
},
#[error("I couldn't find any exportable function named '{name}' in module '{module}'.")]
ExportNotFound { module: String, name: String },
@ -423,27 +428,13 @@ impl Diagnostic for Error {
None => String::new(),
}
))),
Error::NoValidatorNotFound { known_validators } => Some(Box::new(format!(
"Here's a list of all validators I've found in your project. Please double-check this list against the options that you've provided:\n\n{}",
known_validators
.iter()
.map(|title| format!(
"→ {title}",
title = title.if_supports_color(Stdout, |s| s.purple())
))
.collect::<Vec<String>>()
.join("\n")
Error::NoValidatorNotFound { known_validators } => Some(Box::new(hint_validators(
known_validators,
"Here's a list of all validators I've found in your project.\nPlease double-check this list against the options that you've provided."
))),
Error::MoreThanOneValidatorFound { known_validators } => Some(Box::new(format!(
"Here's a list of all validators I've found in your project. Select one of them using the appropriate options:\n\n{}",
known_validators
.iter()
.map(|title| format!(
"→ {title}",
title = title.if_supports_color(Stdout, |s| s.purple())
))
.collect::<Vec<String>>()
.join("\n")
Error::MoreThanOneValidatorFound { known_validators } => Some(Box::new(hint_validators(
known_validators,
"Here's a list of matching validators I've found in your project.\nPlease narrow the selection using additional options.",
))),
Error::Module(e) => e.help(),
}
@ -809,3 +800,53 @@ fn default_miette_handler(context_lines: usize) -> MietteHandler {
.context_lines(context_lines)
.build()
}
fn hint_validators(known_validators: &BTreeSet<(String, String, bool)>, hint: &str) -> String {
let (pad_module, pad_validator) = known_validators.iter().fold(
(9, 12),
|(module_len, validator_len), (module, validator, _)| {
(
module_len.max(module.len()),
validator_len.max(validator.len()),
)
},
);
format!(
"{hint}\n\n\
{:<pad_module$} {:<pad_validator$}\n\
{:<pad_module$} {:<pad_validator$}\n\
{}\n\nFor convenience, I have highlighted in {bold_green} suitable candidates that {has_params}.",
"module(s)",
"validator(s)",
"",
"",
{
known_validators
.iter()
.map(|(module, validator, has_params)| {
let title = format!(
"{:>pad_module$} . {:<pad_validator$}",
module,
validator,
);
if *has_params {
title
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.green())
.to_string()
} else {
title
}
})
.collect::<Vec<String>>()
.join("\n")
},
bold_green = "bold green"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.green()),
has_params = "can take parameters"
.if_supports_color(Stderr, |s| s.bold())
.if_supports_color(Stderr, |s| s.green()),
)
}

View File

@ -0,0 +1,9 @@
name = "aiken-lang/121"
version = "0.0.0"
license = "Apache-2.0"
description = "Aiken contracts for project 'aiken-lang/121'"
[repository]
user = "aiken-lang"
project = "121"
platform = "github"

View File

@ -0,0 +1,34 @@
pub type Foo {
i: Int,
b: Bool,
}
const give_i: fn(Int) -> Foo = Foo { i: _, b: True }
const give_b: fn(Bool) -> Foo = Foo(1337, _)
fn foo_i(i: Int) -> fn(Bool) -> Foo {
Foo { i: i, b: _bool }
}
fn foo_b(b: Bool) -> fn(Int) -> Foo {
Foo(_, b)
}
test test_1() {
let bar = foo_i(14)
and {
foo_i(42)(True) == Foo(42, True),
bar(False) == Foo { i: 14, b: False },
give_i(1337) == Foo { i: 1337, b: True },
}
}
test test_2() {
let bar = foo_b(False)
and {
foo_b(True)(42) == Foo(42, True),
bar(14) == Foo { i: 14, b: False },
give_b(False) == Foo { i: 1337, b: False },
}
}