feat: error when an expression is implicitly discarded

This commit is contained in:
rvcas 2023-01-16 14:53:33 -05:00 committed by Lucas
parent 844570caf5
commit 4024add4da
2 changed files with 22 additions and 3 deletions

View File

@ -50,6 +50,9 @@ pub enum Error {
#[error("I found a data type that has a function type in it. This is not allowed.")]
FunctionTypeInData { location: Span },
#[error("I found a discarded expression not bound to a variable.")]
ImplicityDiscardedExpression { location: Span },
#[error("I saw a {} fields in a context where there should be {}.\n", given.purple(), expected.purple())]
IncorrectFieldsArity {
location: Span,
@ -372,6 +375,9 @@ impl Diagnostic for Error {
Self::DuplicateName { .. } => Some(Box::new("duplicate_name")),
Self::DuplicateTypeName { .. } => Some(Box::new("duplicate_type_name")),
Self::FunctionTypeInData { .. } => Some(Box::new("function_type_in_data")),
Self::ImplicityDiscardedExpression { .. } => {
Some(Box::new("implicitly_discarded_expr"))
}
Self::IncorrectFieldsArity { .. } => Some(Box::new("incorrect_fields_arity")),
Self::IncorrectFunctionCallArity { .. } => Some(Box::new("incorrect_fn_arity")),
Self::IncorrectPatternArity { .. } => Some(Box::new("incorrect_pattern_arity")),
@ -488,6 +494,7 @@ impl Diagnostic for Error {
Self::FunctionTypeInData { .. } => Some(Box::new("Data types can't have functions in them due to how Plutus Data works.")),
Self::ImplicityDiscardedExpression { .. } => Some(Box::new("Everything is an expression and returns a value.\nTry assigning this expression to a variable.")),
Self::IncorrectFieldsArity { .. } => None,
Self::IncorrectFunctionCallArity { expected, .. } => Some(Box::new(formatdoc! {
@ -1149,6 +1156,10 @@ impl Diagnostic for Error {
Self::FunctionTypeInData { location } => Some(Box::new(
vec![LabeledSpan::new_with_span(None, *location)].into_iter(),
)),
Self::ImplicityDiscardedExpression { location, .. } => Some(Box::new(
vec![LabeledSpan::new_with_span(None, *location)].into_iter(),
)),
Self::IncorrectFieldsArity { location, .. } => Some(Box::new(
vec![LabeledSpan::new_with_span(None, *location)].into_iter(),
)),
@ -1282,6 +1293,7 @@ impl Diagnostic for Error {
Self::DuplicateName { .. } => None,
Self::DuplicateTypeName { .. } => None,
Self::FunctionTypeInData { .. } => None,
Self::ImplicityDiscardedExpression { .. } => None,
Self::IncorrectFieldsArity { .. } => Some(Box::new(
"https://aiken-lang.org/language-tour/custom-types",
)),

View File

@ -171,7 +171,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
/// Emit a warning if the given expressions should not be discarded.
/// e.g. because it's a literal (why was it made in the first place?)
/// e.g. because it's of the `Result` type (errors should be handled)
fn expression_discarded(&mut self, discarded: &TypedExpr) {
fn _expression_discarded(&mut self, discarded: &TypedExpr) {
if discarded.is_literal() {
self.environment.warnings.push(Warning::UnusedLiteral {
location: discarded.location(),
@ -1684,9 +1684,16 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
let expression = self.infer(expression)?;
// This isn't the final expression in the sequence, so call the
// `expression_discarded` function to see if anything is being
// discarded that we think shouldn't be.
// discarded that we think shouldn't be. We also want to make sure
// that there are no implicitly discarded expressions
if i < count - 1 {
self.expression_discarded(&expression);
// self.expression_discarded(&expression);
if !matches!(expression, TypedExpr::Assignment { .. }) {
return Err(Error::ImplicityDiscardedExpression {
location: expression.location(),
});
}
}
expressions.push(expression);