Merge pull request #1125 from aiken-lang/always-typecheck-trace-label
rework trace label evaluation strategy
This commit is contained in:
commit
e872b9eb2e
|
@ -14,6 +14,7 @@
|
||||||
- **aiken-lang**: Change default placeholder for `trace` to `Void` instead of `todo`. @KtorZ
|
- **aiken-lang**: Change default placeholder for `trace` to `Void` instead of `todo`. @KtorZ
|
||||||
- **aiken-lang**: Disallow (parse error) dangling colon `:` in traces. See [#1113](https://github.com/aiken-lang/aiken/issues/1113). @KtorZ
|
- **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**: 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
|
||||||
- **aiken-lang**: Formatter was removing comments from function type annotation args @rvcas
|
- **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**: 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-lang**: Fix hint when suggesting to use named fields, wrongly suggesting args in lexicographical order instead of definition order. @KtorZ
|
||||||
|
|
|
@ -1321,8 +1321,8 @@ fn trace_non_string_label_compact() {
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
check_with_verbosity(parse(source_code), TraceLevel::Compact),
|
&check_with_verbosity(parse(source_code), TraceLevel::Compact),
|
||||||
Err((_, Error::CouldNotUnify { .. }))
|
Ok((warnings, _)) if warnings == &[Warning::CompactTraceLabelIsNotstring { location: Span::create(40, 7) }],
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1865,6 +1865,15 @@ pub enum Warning {
|
||||||
location: Span,
|
location: Span,
|
||||||
suggestion: UntypedPattern,
|
suggestion: UntypedPattern,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[error("I noticed a (compact) dynamic trace label which is not a string")]
|
||||||
|
#[diagnostic(help("Compiling with a compact trace-level, you are probably expecting compact traces although here, the entire label will need to be serialise *at runtime* which will add a significant overhead.\n\nAs a reminder, trace arguments are fully ignored in compact tracing. Hence, you probably want to put a cute little label here and move the current trace as argument!"))]
|
||||||
|
#[diagnostic(code("trace::label_is_not_string"))]
|
||||||
|
#[diagnostic(url("https://aiken-lang.org/language-tour/troubleshooting#traces"))]
|
||||||
|
CompactTraceLabelIsNotstring {
|
||||||
|
#[label("compact trace label is not String")]
|
||||||
|
location: Span,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtraData for Warning {
|
impl ExtraData for Warning {
|
||||||
|
@ -1884,6 +1893,7 @@ impl ExtraData for Warning {
|
||||||
| Warning::UnusedVariable { .. }
|
| Warning::UnusedVariable { .. }
|
||||||
| Warning::DiscardedLetAssignment { .. }
|
| Warning::DiscardedLetAssignment { .. }
|
||||||
| Warning::ValidatorInLibraryModule { .. }
|
| Warning::ValidatorInLibraryModule { .. }
|
||||||
|
| Warning::CompactTraceLabelIsNotstring { .. }
|
||||||
| Warning::UseWhenInstead { .. } => None,
|
| Warning::UseWhenInstead { .. } => None,
|
||||||
Warning::Utf8ByteArrayIsValidHexString { value, .. } => Some(value.clone()),
|
Warning::Utf8ByteArrayIsValidHexString { value, .. } => Some(value.clone()),
|
||||||
Warning::UnusedImportedModule { location, .. } => {
|
Warning::UnusedImportedModule { location, .. } => {
|
||||||
|
|
|
@ -2506,6 +2506,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
|
|
||||||
#[allow(clippy::result_large_err)]
|
#[allow(clippy::result_large_err)]
|
||||||
fn infer_trace_arg(&mut self, arg: UntypedExpr) -> Result<TypedExpr, Error> {
|
fn infer_trace_arg(&mut self, arg: UntypedExpr) -> Result<TypedExpr, Error> {
|
||||||
|
let location = arg.location();
|
||||||
let typed_arg = self.infer(arg)?;
|
let typed_arg = self.infer(arg)?;
|
||||||
match self.unify(
|
match self.unify(
|
||||||
Type::string(),
|
Type::string(),
|
||||||
|
@ -2514,6 +2515,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
false,
|
false,
|
||||||
) {
|
) {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
if matches!(self.tracing.trace_level(false), TraceLevel::Compact) {
|
||||||
|
self.environment
|
||||||
|
.warnings
|
||||||
|
.push(Warning::CompactTraceLabelIsNotstring { location });
|
||||||
|
}
|
||||||
|
|
||||||
self.unify(Type::data(), typed_arg.tipo(), typed_arg.location(), true)?;
|
self.unify(Type::data(), typed_arg.tipo(), typed_arg.location(), true)?;
|
||||||
Ok(diagnose_expr(typed_arg))
|
Ok(diagnose_expr(typed_arg))
|
||||||
}
|
}
|
||||||
|
@ -2546,44 +2553,38 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let label = self.infer_trace_arg(label)?;
|
||||||
|
|
||||||
|
let text = if typed_arguments.is_empty() {
|
||||||
|
label.clone()
|
||||||
|
} else {
|
||||||
|
let delimiter = |ix| TypedExpr::String {
|
||||||
|
location: Span::empty(),
|
||||||
|
tipo: Type::string(),
|
||||||
|
value: if ix == 0 { ": " } else { ", " }.to_string(),
|
||||||
|
};
|
||||||
|
typed_arguments
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.fold(label.clone(), |text, (ix, arg)| {
|
||||||
|
append_string_expr(append_string_expr(text, delimiter(ix)), arg)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
match self.tracing.trace_level(false) {
|
match self.tracing.trace_level(false) {
|
||||||
TraceLevel::Silent => Ok(then),
|
TraceLevel::Silent => Ok(then),
|
||||||
TraceLevel::Compact => {
|
TraceLevel::Compact => Ok(TypedExpr::Trace {
|
||||||
let text = self.infer(label)?;
|
location,
|
||||||
self.unify(Type::string(), text.tipo(), text.location(), false)?;
|
tipo,
|
||||||
Ok(TypedExpr::Trace {
|
then: Box::new(then),
|
||||||
location,
|
text: Box::new(label),
|
||||||
tipo,
|
}),
|
||||||
then: Box::new(then),
|
TraceLevel::Verbose => Ok(TypedExpr::Trace {
|
||||||
text: Box::new(text),
|
location,
|
||||||
})
|
tipo,
|
||||||
}
|
then: Box::new(then),
|
||||||
TraceLevel::Verbose => {
|
text: Box::new(text),
|
||||||
let label = self.infer_trace_arg(label)?;
|
}),
|
||||||
|
|
||||||
let text = if typed_arguments.is_empty() {
|
|
||||||
label
|
|
||||||
} else {
|
|
||||||
let delimiter = |ix| TypedExpr::String {
|
|
||||||
location: Span::empty(),
|
|
||||||
tipo: Type::string(),
|
|
||||||
value: if ix == 0 { ": " } else { ", " }.to_string(),
|
|
||||||
};
|
|
||||||
typed_arguments
|
|
||||||
.into_iter()
|
|
||||||
.enumerate()
|
|
||||||
.fold(label, |text, (ix, arg)| {
|
|
||||||
append_string_expr(append_string_expr(text, delimiter(ix)), arg)
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(TypedExpr::Trace {
|
|
||||||
location,
|
|
||||||
tipo,
|
|
||||||
then: Box::new(then),
|
|
||||||
text: Box::new(text),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue