vrl/compiler/expression/
return.rs1use std::fmt;
2
3use crate::compiler::{
4 Context, Expression, Span, TypeDef,
5 expression::Resolved,
6 state::{TypeInfo, TypeState},
7};
8use crate::diagnostic::{DiagnosticMessage, Label, Note};
9use crate::parser::ast::Node;
10
11use super::{Expr, ExpressionError};
12
13#[derive(Debug, Clone, PartialEq)]
14pub struct Return {
15 span: Span,
16 expr: Box<Expr>,
17}
18
19impl Return {
20 pub fn new(span: Span, expr: Node<Expr>, state: &TypeState) -> Result<Self, Error> {
24 let (expr_span, expr) = expr.take();
25 let type_def = expr.type_info(state).result;
26
27 if type_def.is_fallible() {
28 return Err(Error {
29 variant: ErrorVariant::FallibleExpr,
30 expr_span,
31 });
32 }
33
34 Ok(Self {
35 span,
36 expr: Box::new(expr),
37 })
38 }
39}
40
41impl Expression for Return {
42 fn resolve(&self, ctx: &mut Context) -> Resolved {
43 Err(ExpressionError::Return {
44 span: self.span,
45 value: self.expr.resolve(ctx)?,
46 })
47 }
48
49 fn type_info(&self, state: &TypeState) -> TypeInfo {
50 let value = self.expr.type_info(state);
51 TypeInfo::new(
52 state,
53 TypeDef::never().with_returns(value.result.kind().clone()),
54 )
55 }
56}
57
58impl fmt::Display for Return {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 write!(f, "return")
61 }
62}
63
64#[derive(Debug)]
67pub struct Error {
68 variant: ErrorVariant,
69 expr_span: Span,
70}
71
72#[derive(thiserror::Error, Debug)]
73pub(crate) enum ErrorVariant {
74 #[error("unhandled fallible expression")]
75 FallibleExpr,
76}
77
78impl fmt::Display for Error {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 write!(f, "{:#}", self.variant)
81 }
82}
83
84impl std::error::Error for Error {
85 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
86 Some(&self.variant)
87 }
88}
89
90impl DiagnosticMessage for Error {
91 fn code(&self) -> usize {
92 use ErrorVariant::FallibleExpr;
93
94 match self.variant {
95 FallibleExpr => 631,
96 }
97 }
98
99 fn labels(&self) -> Vec<Label> {
100 match &self.variant {
101 ErrorVariant::FallibleExpr => vec![
102 Label::primary(
103 "return only accepts an infallible expression argument",
104 self.expr_span,
105 ),
106 Label::context(
107 "handle errors before using the expression as a return value",
108 self.expr_span,
109 ),
110 ],
111 }
112 }
113
114 fn notes(&self) -> Vec<Note> {
115 match self.variant {
116 ErrorVariant::FallibleExpr => vec![Note::SeeErrorDocs],
117 }
118 }
119}