rework trace label evaluation strategy
Namely: 1. Fully evaluate & type-check the label, irrespective of the trace level. So that labels using other variables do not generate "unused identifier" warnings when compiling with different trace mode (and so that the success of a build doesn't depend on the trace level). This was already done for trace arguments, but not for labels, somehow. 2. Move the requirement for compact trace label being String from errors down to warnings; following point (1), we shouldn't fail compilation for different trace levels. It seems more reasonable to simply raise a warning. Signed-off-by: KtorZ <matthias.benkort@gmail.com>
This commit is contained in:
parent
3fa25fecfa
commit
c88cbd8f28
|
@ -13,6 +13,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
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
@ -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