Skip to content

Commit

Permalink
Functions with locals of structs with lifecycle hooks are not pure.
Browse files Browse the repository at this point in the history
  • Loading branch information
bbannier committed May 16, 2023
1 parent e01c950 commit f8378cd
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions hilti/toolchain/src/compiler/optimizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,17 @@ struct DeadCodeVisitor : OptimizerVisitor, visitor::PreOrder<bool, DeadCodeVisit
}
};

bool hasLifecycleHooks(const type::Struct& s) {
// NOLINTNEXTLINE(readability-use-anyofallof)
for ( const auto& f : s.fields() ) {
// Currently the only lifecycle hook we have is `~finally`.
if ( f.id().str() == "~finally" )
return true;
}

return false;
};

// An optimizer pass which annotates pure functions. This
// information can be used by other passes to remove dead code.
struct PureFunctionVisitor : OptimizerVisitor, visitor::PreOrder<bool, PureFunctionVisitor> {
Expand Down Expand Up @@ -1927,9 +1938,15 @@ struct PureFunctionVisitor : OptimizerVisitor, visitor::PreOrder<bool, PureFunct
if ( auto id = child.node.tryAs<expression::ResolvedID>() ) {
const auto& decl = id->declaration();

if ( decl.isA<declaration::LocalVariable>() )
// Functions accessing local variables can be pure.
if ( auto local = decl.tryAs<declaration::LocalVariable>() ) {
// Functions accessing local variables can be pure if they
// do not construct struct values of types with lifecycle
// hooks attached.
if ( auto s = local->type().tryAs<type::Struct>(); s && hasLifecycleHooks(*s) )
return {};

continue;
}

else if ( decl.isA<declaration::GlobalVariable>() )
// Functions accessing global variables cannot be pure.
Expand All @@ -1941,9 +1958,6 @@ struct PureFunctionVisitor : OptimizerVisitor, visitor::PreOrder<bool, PureFunct
return {};
}

// FIXME(bbannier): If we construct a struct we can trigger life-cycle
// hooks making such functions not pure. Reject them here.

// Accessing keywords is side-effect free.
else if ( const auto& e = decl.tryAs<declaration::Expression>();
e && e->expression().isA<expression::Keyword>() ) {
Expand Down

0 comments on commit f8378cd

Please sign in to comment.