-
-
Notifications
You must be signed in to change notification settings - Fork 472
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
refactor(semantic): make control flow generation optional. #3737
refactor(semantic): make control flow generation optional. #3737
Conversation
Your org has enabled the Graphite merge queue for merging into mainAdd the label “merge” to the PR and Graphite will automatically add it to the merge queue when it’s ready to merge. Or use the label “hotfix” to add to the merge queue as a hot fix. You must have a Graphite account and log in to Graphite in order to use the merge queue. Sign up using this link. |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
CodSpeed Performance ReportMerging #3737 will improve performances by 9.97%Comparing Summary
Benchmarks breakdown
|
0b7ad53
to
a282f8d
Compare
Nice! Would be nice if we get rid of the macro. I'll make it off by default in the next PR. |
I'm working on making it disabled by default in the next few PRs, I have to first make linter tests to generate CFG optionally(so we can mark it if we need cfg for the rule to work). |
Ok, shall we merge or get rid of the macro? |
Do we want to feature gate the CFG in the future? If that's the case I think macro can help us, Otherwise, we should be fine with mapping the option. I can also give the inline function another try, Maybe I can find a safe trick to make it work. |
Ok, let's merge and iterate. |
Sounds good to me, I'll give the inline function another try and let you know about the results. |
Merge activity
|
3fdf236
to
61b69c3
Compare
For maximum backward compatibility, we generate CFG by default. Note: It can't be done with a simple method since lifetimes make it impossible(at least without unsafe trickery) I've tried to do it without a macro but it was just unintuitive.
d04848b
to
a4160d2
Compare
61b69c3
to
1ccbd3a
Compare
For maximum backward compatibility, we generate CFG by default. Note: It can't be done with a simple method since lifetimes make it impossible(at least without unsafe trickery) I've tried to do it without a macro but it was just unintuitive.
a4160d2
to
37adcb3
Compare
For maximum backward compatibility, we generate CFG by default. Note: It can't be done with a simple method since lifetimes make it impossible(at least without unsafe trickery) I've tried to do it without a macro but it was just unintuitive.
37adcb3
to
ccb7d32
Compare
For maximum backward compatibility, we generate CFG by default. Note: It can't be done with a simple method since lifetimes make it impossible(at least without unsafe trickery) I've tried to do it without a macro but it was just unintuitive.
ccb7d32
to
8bfea7b
Compare
For maximum backward compatibility, we generate CFG by default. Note: It can't be done with a simple method since lifetimes make it impossible(at least without unsafe trickery) I've tried to do it without a macro but it was just unintuitive.
97bcb64
to
0537d29
Compare
8bfea7b
to
d8ad321
Compare
@@ -55,16 +55,19 @@ declare_oxc_lint!( | |||
|
|||
impl Rule for GetterReturn { | |||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { | |||
// control flow dependant | |||
let Some(cfg) = ctx.semantic().cfg() else { return }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be let cfg = ctx.semantic().cfg().unwrap()
? i.e. Panic if linter has been passed a Semantic
instance which doesn't have CFG.
It's not ideal to have runtime panics, but on the other hand, if there's some mistake and linter gets passed a Semantic
with no CFG, then these lint rules will just silently fail to run, and user will be told "Lint successful! No problem with your code." regardless of whether that's true or not.
This is why my preference was for a Semantic<CfgType>
generic type - then this would be enforced at compile time.
I'm not sure. There's arguments on both sides. Maybe a compromise would be:
debug_assert!(ctx.semantic().cfg().is_some());
let Some(cfg) = ctx.semantic().cfg() else { return };
I think this at least communicates to someone reading the code that cfg
must be Some(_)
, and that it's not actually optional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was intentional, I was thinking that we can make the linter to omit CFG generation and disable the rules depending on it. Or the other way around if we have no rule dependent on CFG enabled we can disable the CFG generation altogether.
But we can go either way since it has no difference at the moment. I had no objection against unwrap/panics here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we have no rule dependent on CFG enabled we can disable the CFG generation altogether.
That's a nice optimization. I think that way around is the better option, in which case it could be unwrap
here.
I have a broader feeling that we need a convention for communicating in code when (1) something is actually optional vs (2) there's an unstated invariant that means this branch must always go one way. When delving into parts of Oxc codebase which I'm new to, this ambiguity has left me scratching my head quite a few times, wondering "in what circumstances can this happen?", and it turns out the answer is "it can't".
unwrap
/unreachable!
is one way to communicate that, but it has the downside of bloating the ASM with panic code for the unreachable branch. So I don't have a good answer to this.
Anyway, it's a broader problem, so I think we can just leave it as is in this PR, since I was too late with my review.
@@ -31,6 +31,16 @@ use crate::{ | |||
Semantic, | |||
}; | |||
|
|||
macro_rules! cfg { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this macro be called control_flow!
rather than cfg!
? Rust's standard library already has a cfg!
macro, and I think it's potentially confusing to override it. https://doc.rust-lang.org/std/macro.cfg.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I was thinking we can use std::cfg directly if needed, Named it cfg
since it is a repeating pattern all over this file and it looks like the comments. I'll change it to control_flow
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I find the use of "cfg" as abbreviation for "control flow graph" confusing in general. There's quite a strong convention in Rust that "cfg" is short for "config" e.g. #[cfg(...)]
.
When I first started looking at semantic's code, I kept asking myself "what's this 'config' all about?". It didn't take me too long to figure it out, but still I think it's useful to remember what your first encounter with the codebase felt like, to put yourself in the position of a new contributor (who of course we want to welcome). The principle of minimum surprise and all that...
That's a broader point, and not such a big deal. But on this specific one, personally I think overriding part of the standard prelude is a step too far! If you would be willing to change it, I think it'd be ideal. If you don't have time, just say so, and I'll do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've already changed it in a subsequent PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha! I am too slow again! Thanks for doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries mate! Winds are blowing fast, "Jibe Ho" ⚓
@@ -467,8 +484,11 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { | |||
program.scope_id.set(Some(self.current_scope_id)); | |||
|
|||
/* cfg */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you can be bothered, I think all these /* cfg */
comments could be removed, as the cfg!
macro now performs same function of delimiting the code related to CFG. But this is just a style nit - feel free to ignore if you don't have time/don't agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought of it but didn't do it since there are a handful of instances where we have cfg related code outside of this macro, Wanted to keep it as a convention for that reason, and I'd love to remove these when it is a bit more mature and we know all of our cfg logics can be contained in these macro scopes.
Oh poop. PR got merged while I was reviewing! @rzvxa I don't know if you think any of my comments above are worth considering and addressing in follow ups, or not? |
@overlookmotel I've made some comments about the review conversations above, Let me know about your thoughts so I can integrate them in the next PR(s). |
As requested here #3737 (comment)
## [0.15.0] - 2024-06-18 - 0537d29 cfg: [**BREAKING**] Move control flow to its own crate. (#3728) (rzvxa) - 5c38a0f codegen: [**BREAKING**] New code gen API (#3740) (Boshen) - 4bce59d semantic/cfg: [**BREAKING**] Re-export `petgraph` as `control_flow::graph`. (#3722) (rzvxa) - 534242a codegen: [**BREAKING**] Remove `CodegenOptions::enable_typescript` (#3674) (Boshen) - 0578ece ast: [**BREAKING**] Remove `ExportDefaultDeclarationKind::TSEnumDeclaration` (#3666) (Dunqing) ### Features - 5a99d30 codegen: Improve codegen formatting (#3735) (Boshen) - bf9b38a codegen: Improve codegen formatting (#3731) (Boshen) - 4a004e2 codegen: Print TSImport remaining fields (#3695) (Dunqing) - a56cb1b codegen: Print accessibility for MethodDefinition (#3690) (Dunqing) - 38a75e5 coverage: Improve codegen (#3729) (Boshen) - 750a534 coverage: Transformer idempotency test (#3691) (Boshen) - ee627c3 isolated-declarations: Create unique name for `_default` (#3730) (Dunqing) - 81e9526 isolated-declarations: Inferring set accessor parameter type from get accessor return type (#3725) (Dunqing) - 77d5533 isolated-declarations: Report errors that are consistent with typescript. (#3720) (Dunqing) - 8f5655d linter: Add eslint/no-useless-constructor (#3594) (Don Isaac) - 046ff3f linter/eslint: Add `no_unreachable` rule. (#3238) (rzvxa) - 0b8098a napi: Isolated-declaration (#3718) (Boshen) - 527bfc8 npm/oxc-transform: Setup npm/oxc-transform and publish (Boshen) - d65c652 parser: Display jsx mismatch error, e.g. `<Foo></Bar>` (#3696) (Boshen) - 9c31ed9 semantic/cfg: Propagate unreachable edges through subgraphs. (#3648) (rzvxa) - d9c5b33 semantic/cfg: Add `Condition` instruction. (#3567) (Ali Rezvani) - f2dfd66 semantic/cfg: Add iteration instructions. (#3566) (rzvxa) - 910193e transformer-dts: Report error for super class (#3711) (Dunqing) - 413d7be transformer-dts: Transform enum support (#3710) (Dunqing) - 35c382e transformer-dts: Remove type annotation from private field (#3689) (Dunqing) - 0e6d3ce transformer-dts: Report error for async function and generator (#3688) (Dunqing) - b22b59a transformer-dts: Transform namespace support (#3683) (Dunqing) - 4f2db46 transformer-dts: `--isolatedDeclarations` dts transform (#3664) (Dunqing) ### Bug Fixes - 2158268 ast: Incorrect visit order in function (#3681) (Dunqing) - da1e2d0 codegen: Improve typescript codegen (#3708) (Boshen) - f1b793f isolated-declarations: Function overloads reaching unreachable (#3739) (Dunqing) - 0fbecdc isolated-declarations: Should be added to references, not bindings (#3726) (Dunqing) - 8f64d99 minifier: Respect `join_vars: false` option (#3724) (mysteryven) - 70fc69b semantic: Add Eq to CtxFlags (#3651) (Yuji Sugiura) - 7a58fec semantic/cfg: Issue in unlabeled `Ctx`s. (#3678) (rzvxa) - abd6ac8 semantic/cfg: Discrete finalization path after `NewFunction`s. (#3671) (rzvxa) - e148a32 semantic/cfg: Correct unreachability propagation in try-finally. (#3667) (Ali Rezvani) - 59666e0 transformer: Do not rename accessible identifier references (#3623) (Dunqing) - 90743e2 traverse: Change visit order for `Function` (#3685) (overlookmotel) ### Performance - 2717a1a semantic/cfg: Lower the visits in `neighbors_filtered_by_edge_weight`. (#3676) (rzvxa) ### Refactor - fa7a6ba codegen: Add `gen` method to ast nodes (#3687) (Boshen) - 09b92b6 codegen: Move `gen_ts` into `gen` to make searching things easier (#3680) (Boshen) - 3c59735 isolated-declarations: Remove `TransformDtsCtx` (#3719) (Boshen) - 815260e isolated-declarations: Decouple codegen (#3715) (Boshen) - 7ec44f8 semantic: Rename `cfg` macro to `control_flow`. (#3742) (rzvxa) - d8ad321 semantic: Make control flow generation optional. (#3737) (rzvxa) - a94a72d semantic: Expose 1 checker function instead of 2 (#3694) (Boshen) - bd8d115 semantic/cfg: Remove unused types. (#3677) (rzvxa) - f702fb9 semantic/cfg: Cleanup control flow and it's builder. (#3650) (rzvxa) - 4f16664 transformer_dts: Create a `Program` for codegen (#3679) (Boshen) Co-authored-by: Boshen <Boshen@users.noreply.github.com>
## [0.5.0] - 2024-06-27 - 6796891 ast: [**BREAKING**] Rename all instances of `BigintLiteral` to `BigIntLiteral`. (#3898) (rzvxa) - ae09a97 ast: [**BREAKING**] Remove `Modifiers` from ts nodes (#3846) (Boshen) - 1af5ed3 ast: [**BREAKING**] Replace `Modifiers` with `declare` and `const` on `EnumDeclaration` (#3845) (Boshen) - ee6ec4e ast: [**BREAKING**] Replace `Modifiers` with `declare` and `abstract` on `Class` (#3841) (Boshen) - 4456034 ast: [**BREAKING**] Add `IdentifierReference` to `ExportSpecifier` (#3820) (Boshen) - 0537d29 cfg: [**BREAKING**] Move control flow to its own crate. (#3728) (rzvxa) - 5c38a0f codegen: [**BREAKING**] New code gen API (#3740) (Boshen) - 4bce59d semantic/cfg: [**BREAKING**] Re-export `petgraph` as `control_flow::graph`. (#3722) (rzvxa) ### Features - 3ae2628 linter: Change `no-import-assign` to correctness (#3928) (Boshen) - a89d501 linter: Implement @typescript-eslint/no-non-null-asserted-nulli… (#3850) (kaykdm) - fc48cb4 linter: �eslint-plugin-jest/prefer-jest-mocked (#3865) (cinchen) - 63b98bd linter: Accept multiple fixes when fix code (#3842) (mysteryven) - 328445b linter: Support `vitest/no-disabled-tests` (#3717) (mysteryven) - 8c61f9c linter: Implement @typescript-eslint/no-non-null-assertion (#3825) (kaykdm) - 080ecbd linter: Add `no-fallthrough`. (#3673) (rzvxa) - 9493fbe linter: Add `oxc/no-optional-chaining` rule (#3700) (mysteryven) - 139adfe linter: Add `@typescript-eslint/no-import-type-side_effects` (#3699) (mysteryven) - 5f84500 linter/eslint-plugin-react: Implement prefer-es6-class (#3812) (Jelle van der Waa) - fafe67c linter/import: Implement max-dependencies (#3814) (Jelle van der Waa) - d5f6aeb semantic: Check for illegal symbol modifiers (#3838) (Don Isaac) ### Bug Fixes - 4bd2c88 linter: Fix and promote `getter-return` to correctness. (#3777) (rzvxa) - 1190dee linter: False positives with setters in the `getter-return` rule. (#3714) (rzvxa) - de0690f linter: Do not run getter-return in typescript (#3693) (Boshen) - cf71c23 linter: Edge case with infinite loops. (#3672) (rzvxa) - 5902331 oxlint: Properly report error (#3889) (Luca Bruno) - 99a40ce semantic: `export default foo` should have `ExportLocalName::Default(NameSpan)` entry (#3823) (Boshen) - abd6ac8 semantic/cfg: Discrete finalization path after `NewFunction`s. (#3671) (rzvxa) ### Performance - 4f7ff7e Do not pass `&Atom` to functions (#3818) (overlookmotel) ### Refactor - 4d2b7f1 linter: `LintContext` can now only be constructed with a cfg enabled semantic. (#3761) (rzvxa) - 7302429 linter/prefer_number_properties: Remove the unused `IdentifierName` check (#3822) (Boshen) - d8ad321 semantic: Make control flow generation optional. (#3737) (rzvxa) ### Testing - 887da40 linter: Enable `no-fallthrough` test with `disable-next-line`. (#3766) (rzvxa) Co-authored-by: Boshen <Boshen@users.noreply.github.com>
For maximum backward compatibility, we generate CFG by default.
Note: It can't be done with a simple method since lifetimes make it impossible(at least without unsafe trickery) I've tried to do it without a macro but it was just unintuitive.