Skip to content

Commit

Permalink
Refactor Declaration::ImplicitReturnExpression as Expression::Implici…
Browse files Browse the repository at this point in the history
…tReturn.
  • Loading branch information
tritao committed Jan 12, 2024
1 parent 493f470 commit b635722
Show file tree
Hide file tree
Showing 23 changed files with 149 additions and 172 deletions.
5 changes: 4 additions & 1 deletion sway-core/src/control_flow_analysis/analyze_return_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ fn connect_node<'eng: 'cfg, 'cfg>(
expression: ty::TyExpressionVariant::Return(..),
..
})
| ty::TyAstNodeContent::ImplicitReturnExpression(_) => {
| ty::TyAstNodeContent::Expression(ty::TyExpression {
expression: ty::TyExpressionVariant::ImplicitReturn(..),
..
}) => {
let this_index = graph.add_node(ControlFlowGraphNode::from_node(node));
for leaf_ix in leaves {
graph.add_edge(*leaf_ix, this_index, "".into());
Expand Down
36 changes: 2 additions & 34 deletions sway-core/src/control_flow_analysis/dead_code_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,34 +353,6 @@ fn connect_node<'eng: 'cfg, 'cfg>(
// let mut graph = graph.clone();
let span = node.span.clone();
Ok(match &node.content {
ty::TyAstNodeContent::ImplicitReturnExpression(expr) => {
let this_index = graph.add_node(ControlFlowGraphNode::from_node_with_parent(
node,
options.parent_node,
));
for leaf_ix in leaves {
graph.add_edge(*leaf_ix, this_index, "".into());
}
// evaluate the expression

let return_contents = connect_expression(
engines,
&expr.expression,
graph,
&[this_index],
exit_node,
"",
tree_type,
expr.span.clone(),
options,
)?;

// connect return to the exit node
if let Some(exit_node) = exit_node {
graph.add_edge(this_index, exit_node, "return".into());
}
(return_contents, None)
}
ty::TyAstNodeContent::Expression(ty::TyExpression {
expression: expr_variant,
span,
Expand Down Expand Up @@ -1832,7 +1804,7 @@ fn connect_expression<'eng: 'cfg, 'cfg>(
options,
)
}
Return(exp) => {
ImplicitReturn(exp) | Return(exp) => {
let this_index = graph.add_node("return entry".into());
for leaf in leaves {
graph.add_edge(*leaf, this_index, "".into());
Expand Down Expand Up @@ -2130,10 +2102,7 @@ fn construct_dead_code_warning_from_node(
// Otherwise, this is unreachable.
ty::TyAstNode {
span,
content:
ty::TyAstNodeContent::ImplicitReturnExpression(_)
| ty::TyAstNodeContent::Expression(_)
| ty::TyAstNodeContent::SideEffect(_),
content: ty::TyAstNodeContent::Expression(_) | ty::TyAstNodeContent::SideEffect(_),
} => CompileWarning {
span: span.clone(),
warning_content: Warning::UnreachableCode,
Expand Down Expand Up @@ -2304,7 +2273,6 @@ fn allow_dead_code_ast_node(decl_engine: &DeclEngine, node: &ty::TyAstNode) -> b
ty::TyDecl::StorageDecl { .. } => false,
},
ty::TyAstNodeContent::Expression(_) => false,
ty::TyAstNodeContent::ImplicitReturnExpression(_) => false,
ty::TyAstNodeContent::SideEffect(_) => false,
ty::TyAstNodeContent::Error(_, _) => false,
}
Expand Down
18 changes: 9 additions & 9 deletions sway-core/src/ir_generation/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,15 @@ fn const_eval_typed_expr(
})
}
},
ty::TyExpressionVariant::ImplicitReturn(e) => {
if let Ok(Some(constant)) = const_eval_typed_expr(lookup, known_consts, e) {
Some(constant)
} else {
return Err(ConstEvalError::CannotBeEvaluatedToConst {
span: e.span.clone(),
});
}
}
// we could allow non-local control flow in pure functions, but it would
// require some more work and at this point it's not clear if it is too useful
// for constant initializers -- the user can always refactor their pure functions
Expand Down Expand Up @@ -700,15 +709,6 @@ fn const_eval_codeblock(
Ok(None)
}
}
ty::TyAstNodeContent::ImplicitReturnExpression(e) => {
if let Ok(Some(constant)) = const_eval_typed_expr(lookup, known_consts, e) {
Ok(Some(constant))
} else {
Err(ConstEvalError::CannotBeEvaluatedToConst {
span: e.span.clone(),
})
}
}
ty::TyAstNodeContent::SideEffect(_) => Err(ConstEvalError::CannotBeEvaluatedToConst {
span: ast_node.span.clone(),
}),
Expand Down
5 changes: 1 addition & 4 deletions sway-core/src/ir_generation/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,6 @@ impl<'eng> FnCompiler<'eng> {
Ok(None)
}
}
ty::TyAstNodeContent::ImplicitReturnExpression(te) => self
.compile_expression_to_value(context, md_mgr, te)
.map(Some),
// a side effect can be () because it just impacts the type system/namespacing.
// There should be no new IR generated.
ty::TyAstNodeContent::SideEffect(_) => Ok(None),
Expand Down Expand Up @@ -557,7 +554,7 @@ impl<'eng> FnCompiler<'eng> {
ty::TyExpressionVariant::Reassignment(reassignment) => {
self.compile_reassignment(context, md_mgr, reassignment, span_md_idx)
}
ty::TyExpressionVariant::Return(exp) => {
ty::TyExpressionVariant::ImplicitReturn(exp) | ty::TyExpressionVariant::Return(exp) => {
self.compile_return(context, md_mgr, exp, span_md_idx)
}
ty::TyExpressionVariant::Ref(exp) => {
Expand Down
6 changes: 6 additions & 0 deletions sway-core/src/language/parsed/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,12 @@ pub enum ExpressionKind {
Break,
Continue,
Reassignment(ReassignmentExpression),
/// An implicit return expression is different from a [Expression::Return] because
/// it is not a control flow item. Therefore it is a different variant.
///
/// An implicit return expression is an [Expression] at the end of a code block which has no
/// semicolon, denoting that it is the [Expression] to be returned from that block.
ImplicitReturn(Box<Expression>),
Return(Box<Expression>),
Ref(Box<Expression>),
Deref(Box<Expression>),
Expand Down
6 changes: 0 additions & 6 deletions sway-core/src/language/parsed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,6 @@ pub enum AstNodeContent {
Declaration(Declaration),
/// Any type of expression, of which there are quite a few. See [Expression] for more details.
Expression(Expression),
/// An implicit return expression is different from a [Expression::Return] because
/// it is not a control flow item. Therefore it is a different variant.
///
/// An implicit return expression is an [Expression] at the end of a code block which has no
/// semicolon, denoting that it is the [Expression] to be returned from that block.
ImplicitReturnExpression(Expression),
/// A statement of the form `mod foo::bar;` which imports/includes another source file.
IncludeStatement(IncludeStatement),
/// A malformed statement.
Expand Down
39 changes: 3 additions & 36 deletions sway-core/src/language/ty/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ impl DebugWithEngines for TyAstNode {
match &self.content {
Declaration(typed_decl) => DebugWithEngines::fmt(typed_decl, f, engines),
Expression(exp) => DebugWithEngines::fmt(exp, f, engines),
ImplicitReturnExpression(exp) => write!(f, "return {:?}", engines.help_out(exp)),
SideEffect(_) => f.write_str(""),
Error(_, _) => f.write_str("error"),
}
Expand All @@ -64,9 +63,6 @@ impl DebugWithEngines for TyAstNode {
impl SubstTypes for TyAstNode {
fn subst_inner(&mut self, type_mapping: &TypeSubstMap, engines: &Engines) {
match self.content {
TyAstNodeContent::ImplicitReturnExpression(ref mut exp) => {
exp.subst(type_mapping, engines)
}
TyAstNodeContent::Declaration(ref mut decl) => decl.subst(type_mapping, engines),
TyAstNodeContent::Expression(ref mut expr) => expr.subst(type_mapping, engines),
TyAstNodeContent::SideEffect(_) => (),
Expand All @@ -83,9 +79,6 @@ impl ReplaceDecls for TyAstNode {
ctx: &mut TypeCheckContext,
) -> Result<(), ErrorEmitted> {
match self.content {
TyAstNodeContent::ImplicitReturnExpression(ref mut exp) => {
exp.replace_decls(decl_mapping, handler, ctx)
}
TyAstNodeContent::Declaration(TyDecl::VariableDecl(ref mut decl)) => {
decl.body.replace_decls(decl_mapping, handler, ctx)
}
Expand All @@ -102,9 +95,6 @@ impl ReplaceDecls for TyAstNode {
impl UpdateConstantExpression for TyAstNode {
fn update_constant_expression(&mut self, engines: &Engines, implementing_type: &TyDecl) {
match self.content {
TyAstNodeContent::ImplicitReturnExpression(ref mut expr) => {
expr.update_constant_expression(engines, implementing_type)
}
TyAstNodeContent::Declaration(_) => {}
TyAstNodeContent::Expression(ref mut expr) => {
expr.update_constant_expression(engines, implementing_type)
Expand Down Expand Up @@ -150,9 +140,7 @@ impl DeterministicallyAborts for TyAstNode {
use TyAstNodeContent::*;
match &self.content {
Declaration(_) => false,
Expression(exp) | ImplicitReturnExpression(exp) => {
exp.deterministically_aborts(decl_engine, check_call_body)
}
Expression(exp) => exp.deterministically_aborts(decl_engine, check_call_body),
SideEffect(_) => false,
Error(_, _) => false,
}
Expand All @@ -172,7 +160,6 @@ impl TyAstNode {
/// _only_ for explicit returns.
pub(crate) fn gather_return_statements(&self) -> Vec<&TyExpression> {
match &self.content {
TyAstNodeContent::ImplicitReturnExpression(ref exp) => exp.gather_return_statements(),
// assignments and reassignments can happen during control flow and can abort
TyAstNodeContent::Declaration(TyDecl::VariableDecl(decl)) => {
decl.body.gather_return_statements()
Expand All @@ -189,8 +176,7 @@ impl TyAstNode {
TyAstNodeContent::Declaration(decl) => decl.visibility(decl_engine).is_public(),
TyAstNodeContent::Expression(_)
| TyAstNodeContent::SideEffect(_)
| TyAstNodeContent::Error(_, _)
| TyAstNodeContent::ImplicitReturnExpression(_) => false,
| TyAstNodeContent::Error(_, _) => false,
}
}

Expand Down Expand Up @@ -325,9 +311,6 @@ impl TyAstNode {
TyAstNodeContent::Expression(TyExpression { return_type, .. }) => {
(*type_engine.get(*return_type)).clone()
}
TyAstNodeContent::ImplicitReturnExpression(TyExpression { return_type, .. }) => {
(*type_engine.get(*return_type)).clone()
}
TyAstNodeContent::SideEffect(_) => TypeInfo::Tuple(Vec::new()),
TyAstNodeContent::Error(_, error) => TypeInfo::ErrorRecovery(*error),
}
Expand Down Expand Up @@ -395,9 +378,6 @@ impl TyAstNode {
TyAstNodeContent::Expression(node) => {
node.check_deprecated(engines, handler, allow_deprecated);
}
TyAstNodeContent::ImplicitReturnExpression(node) => {
node.check_deprecated(engines, handler, allow_deprecated);
}
TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => {}
}
}
Expand Down Expand Up @@ -438,7 +418,6 @@ impl TyAstNode {
| TyDecl::TypeAliasDecl(_) => {}
},
TyAstNodeContent::Expression(_node) => {}
TyAstNodeContent::ImplicitReturnExpression(_node) => {}
TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => {}
};
Ok(())
Expand All @@ -450,7 +429,6 @@ impl TyAstNode {
pub enum TyAstNodeContent {
Declaration(TyDecl),
Expression(TyExpression),
ImplicitReturnExpression(TyExpression),
// a no-op node used for something that just issues a side effect, like an import statement.
SideEffect(TySideEffect),
Error(Box<[Span]>, ErrorEmitted),
Expand All @@ -462,9 +440,6 @@ impl PartialEqWithEngines for TyAstNodeContent {
match (self, other) {
(Self::Declaration(x), Self::Declaration(y)) => x.eq(y, engines),
(Self::Expression(x), Self::Expression(y)) => x.eq(y, engines),
(Self::ImplicitReturnExpression(x), Self::ImplicitReturnExpression(y)) => {
x.eq(y, engines)
}
(Self::SideEffect(_), Self::SideEffect(_)) => true,
_ => false,
}
Expand All @@ -479,7 +454,7 @@ impl HashWithEngines for TyAstNodeContent {
Declaration(decl) => {
decl.hash(state, engines);
}
Expression(exp) | ImplicitReturnExpression(exp) => {
Expression(exp) => {
exp.hash(state, engines);
}
SideEffect(effect) => {
Expand All @@ -499,9 +474,6 @@ impl TypeCheckAnalysis for TyAstNodeContent {
match self {
TyAstNodeContent::Declaration(node) => node.type_check_analyze(handler, ctx)?,
TyAstNodeContent::Expression(node) => node.type_check_analyze(handler, ctx)?,
TyAstNodeContent::ImplicitReturnExpression(node) => {
node.type_check_analyze(handler, ctx)?
}
TyAstNodeContent::SideEffect(_) => {}
TyAstNodeContent::Error(_, _) => {}
}
Expand All @@ -518,9 +490,6 @@ impl TypeCheckFinalization for TyAstNodeContent {
match self {
TyAstNodeContent::Declaration(node) => node.type_check_finalize(handler, ctx)?,
TyAstNodeContent::Expression(node) => node.type_check_finalize(handler, ctx)?,
TyAstNodeContent::ImplicitReturnExpression(node) => {
node.type_check_finalize(handler, ctx)?
}
TyAstNodeContent::SideEffect(_) => {}
TyAstNodeContent::Error(_, _) => {}
}
Expand All @@ -538,7 +507,6 @@ impl CollectTypesMetadata for TyAstNodeContent {
match self {
Declaration(decl) => decl.collect_types_metadata(handler, ctx),
Expression(expr) => expr.collect_types_metadata(handler, ctx),
ImplicitReturnExpression(expr) => expr.collect_types_metadata(handler, ctx),
SideEffect(_) => Ok(vec![]),
Error(_, _) => Ok(vec![]),
}
Expand All @@ -550,7 +518,6 @@ impl GetDeclIdent for TyAstNodeContent {
match self {
TyAstNodeContent::Declaration(decl) => decl.get_decl_ident(),
TyAstNodeContent::Expression(_expr) => None, //expr.get_decl_ident(),
TyAstNodeContent::ImplicitReturnExpression(_expr) => None, //expr.get_decl_ident(),
TyAstNodeContent::SideEffect(_) => None,
TyAstNodeContent::Error(_, _) => None,
}
Expand Down
6 changes: 4 additions & 2 deletions sway-core/src/language/ty/expression/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,9 @@ impl CollectTypesMetadata for TyExpression {
res.append(&mut content.collect_types_metadata(handler, ctx)?);
}
}
Return(exp) => res.append(&mut exp.collect_types_metadata(handler, ctx)?),
ImplicitReturn(exp) | Return(exp) => {
res.append(&mut exp.collect_types_metadata(handler, ctx)?)
}
Ref(exp) | Deref(exp) => res.append(&mut exp.collect_types_metadata(handler, ctx)?),
// storage access can never be generic
// variable expressions don't ever have return types themselves, they're stored in
Expand Down Expand Up @@ -405,7 +407,7 @@ impl DeterministicallyAborts for TyExpression {
// Also, is it necessary to check the expression to see if avoids the return? eg.
// someone could write `return break;` in a loop, which would mean the return never
// gets executed.
Return(_) => true,
ImplicitReturn(_) | Return(_) => true,
Ref(exp) | Deref(exp) => exp.deterministically_aborts(decl_engine, check_call_body),
}
}
Expand Down
Loading

0 comments on commit b635722

Please sign in to comment.