Skip to content

Problem: unable to soundly guard parts of programs #415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
yjbanov opened this issue Jun 21, 2019 · 3 comments
Open

Problem: unable to soundly guard parts of programs #415

yjbanov opened this issue Jun 21, 2019 · 3 comments

Comments

@yjbanov
Copy link

yjbanov commented Jun 21, 2019

Frequently developers want to make sure that particular functionality is accessible only under certain conditions. Use-cases:

  • A debug function/method should only be called if assertions are enabled.
  • A platform-specific implementation of a function should only be called if the program is running on that platform.
  • A stateful object may only allow certain method calls when it is in a particular state. More generally, you want to guard member access based on a condition that's outside the member's signature.
    • Examples: a button should only be click()ed if it is enabled, a tree node may only be detached if it is currently detached, RenderObject.paint() may only be called during the frame's painting phase, a scrollable view should only scroll after the drag gesture started.
  • A feature should only be used if it is available.
    • Examples: web browsers are in a perpetual catch-up mode with web standards. Frequently, a feature is available in some browsers but not others.

As of today, most of guarding is done via runtime assertions. Unfortunately, this only gives runtime protection and only available during debugging. There is no static checking that could also protect production builds. Let's take the button example. Currently, if you want to protect that button from being clicked when it is disabled you'd typically do the following:

class Button {
  bool enabled;

  void click() {
    assert(enabled);
    ...
  }
}

This has the following issues.

  1. You can still write, compile and run the following incorrect code:
final b = Button()
  ..enabled = false;
b.click();
  1. The bug manifests itself in production in a hard-to-debug way. Namely, the assertion is not triggered and the program keeps on trucking. The exception may be thrown in a completely unrelated part of the code.

  2. The assert as a language construct has canned semantics and it not usable for anything other than runtime assertions in the -c mode. For example, it is not useful for distinguishing between profile and release modes.

Desired properties

(where I say "compiler" I also include the analyzer)

  • Statically analyzable: the compiler should be able to catch errors when parts of a program are entered in a wrong state.
  • Sound: in the absence of compiler errors it is not possible execute guarded parts of the program. Preferably, most of this is prevented statically, but some runtime checks are acceptable for flexibility.
  • Scalable: the solution would not be a large collection of features, but one easy-to-understand language feature that addresses most use-cases.
  • Tree-shakeable: parts of programs that cannot possibly be executed for a given build configuration must be tree-shaken off (e.g. debug vs release mode, target platform).
@rrousselGit
Copy link

What about using constant expressions to hide some elements?

#if !kReleaseMode
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
}
#endif

For the platform dependent issue, Flutter could implement a code generator that creates a constant variant of defaultTargetPlatform (a code-generator being needed for development/hot-reload).

@yjbanov
Copy link
Author

yjbanov commented Jun 21, 2019

I wrote a proposal here: #416

@yjbanov
Copy link
Author

yjbanov commented Jun 21, 2019

Edit: I added a "Desired properties" section to the description of the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants