Skip to content

Remove unnecessary blocks when cleaning up unused unsafe #1596

@randomPoison

Description

@randomPoison

The fix_unused_unsafe transform fixes unused unsafe by removing the unsafe keyword from unsafe blocks, but it leaves the blocks in place. In many cases it would be more idiomatic to remove the block entirely, preserving the block's contents. So for code like unsafe { foo(); }, we currently transform that to { foo(); }, but it would be better to generate just foo();.

There are some edge cases to keep in mind here:

  • Blocks can have comments attached, and deleting the block would take the comment along with it. If the block has a comment we need to make sure we move the comment to the first statement in the block to make sure it's not lost. If the block is empty such that there's nowhere to move the comment to, we should probably leave the block there so as to preserve the comment (a human or an LLM may be needed to make the judgement of what to do with the comment).
  • If the block is used as an expression, i.e. if it's returning a value, we probably want to keep the block in place and just remove the unsafe keyword (which is the current behavior).
  • If the block has anything inside it that requires Drop, we should leave the block in place so as not to alter drop order (this is another place where human or LLM judgement is necessary to decide if the changed drop order matters). This is maybe not a big concern because c2rust-transpile won't generate any code that relies on Drop, but could be a problem if fix_unused_unsafe is used later in the lifting process after other changes have been made. If it's easy to detect this case we should support it, but if drop analysis would be difficult or complex we can probably disregard this case for now.
  • Some blocks are labeled, and shouldn't be removed as the labels are needed for control flow. These blocks generally shouldn't be unsafe, but depending on how we implement this logic that might be something that needs to be kept in mind.

I also think we should start by making this extra logic a part of fix_unused_unsafe, rather than pulling this out into its own transform. We have a few other transforms generating blocks in different ways, but it's not yet clear that any of them need this extra "remove unnecessary blocks" step. For now let's keep this cleanup logic part of fix_unused_unsafe to keep the use case narrow until we have a more concrete idea of where else this functionality would be useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestrefactorerThis issue relates to the refactoring tool

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions