Skip to content

feat(core): handle logical operators#6550

Merged
arendjr merged 5 commits intobiomejs:nextfrom
arendjr:handle-logical-operators
Jun 26, 2025
Merged

feat(core): handle logical operators#6550
arendjr merged 5 commits intobiomejs:nextfrom
arendjr:handle-logical-operators

Conversation

@arendjr
Copy link
Copy Markdown
Contributor

@arendjr arendjr commented Jun 25, 2025

Summary

Type inference is now able to handle logical expressions: &&, ||, and ??.

Examples

// We can now infer that because `true` is truthy, the entire expression
// evaluates to a `Promise`.
true && Promise.reject("logical operator bypass");

// And we know that this doesn't:
false && Promise.reject("logical operator bypass");

// Truthiness, falsiness, and non-nullishness can all be determined on more
// complex expressions as well. So the following also works:
type Nullish = null | undefined;

type Params = {
    booleanOption: boolean | Nullish;
    falsyOption: false | Nullish;
};

function foo({ booleanOption, falsyOption }: Params) {
    // This may be a Promise:
    booleanOption ?? Promise.reject("logical operator bypass");
    
    // But this never is:
    falsyOption && Promise.reject("logical operator bypass");
}

Test Plan

Tests added.

@arendjr arendjr requested review from a team June 25, 2025 14:47
@arendjr arendjr added the A-Type-Inference Area: type inference label Jun 25, 2025
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 25, 2025

🦋 Changeset detected

Latest commit: 54c7313

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-win32-x64 Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/wasm-web Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added A-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Jun 25, 2025
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Jun 25, 2025

CodSpeed Performance Report

Merging #6550 will create unknown performance changes

Comparing arendjr:handle-logical-operators (54c7313) with next (c8c738e)

Summary

🆕 115 new benchmarks
⁉️ 95 dropped benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark BASE HEAD Change
🆕 deserialize_from_json_str[biome.json] N/A 361.7 µs N/A
🆕 css_analyzer[bootstrap_18416142857265205439.css] N/A 487.6 ms N/A
🆕 css_analyzer[bulma_5641719244145477318.css] N/A 1.1 s N/A
🆕 css_analyzer[foundation_11602414662825430680.css] N/A 177.2 ms N/A
🆕 css_analyzer[pure_9395922602181450299.css] N/A 18.9 ms N/A
🆕 css_analyzer[tachyons_11778168428173736564.css] N/A 133.1 ms N/A
🆕 css_formatter[bootstrap_18416142857265205439.css] N/A 115.7 ms N/A
🆕 css_formatter[bulma_5641719244145477318.css] N/A 366 ms N/A
🆕 css_formatter[foundation_11602414662825430680.css] N/A 77.1 ms N/A
🆕 css_formatter[full_5814491140539129161.css] N/A 1.3 s N/A
🆕 css_formatter[materialize_5526761731747548557.css] N/A 83.9 ms N/A
🆕 css_formatter[pure_9395922602181450299.css] N/A 9.5 ms N/A
🆕 css_formatter[semantic_4685287698740288120.css] N/A 370 ms N/A
🆕 css_formatter[tachyons_11778168428173736564.css] N/A 36.9 ms N/A
🆕 bootstrap_18416142857265205439.css[cached] N/A 35.2 ms N/A
🆕 bootstrap_18416142857265205439.css[uncached] N/A 39 ms N/A
🆕 bulma_5641719244145477318.css[cached] N/A 110.6 ms N/A
🆕 bulma_5641719244145477318.css[uncached] N/A 118.3 ms N/A
🆕 foundation_11602414662825430680.css[cached] N/A 23.1 ms N/A
🆕 foundation_11602414662825430680.css[uncached] N/A 24.9 ms N/A
... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

// We need to look up the prototype chain, which may
// yield duplicate member names. We deduplicate
// using a map before constructing a new object.
let members: BTreeMap<Text, ResolvedTypeMember> = subject
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not relevant to this PR, but why do we order members based on their name, instead - for example - text range?

Copy link
Copy Markdown
Contributor Author

@arendjr arendjr Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it's not so much about ordering as it is about eliminating duplicates, and using text range wouldn't help with the latter. For instance, if we have these definitions:

class Base {
    foo() {}
}

class Sub extends Base {
    foo() {}
}

foo() will exist twice in the prototype chain, but only the latter one should become part of the new object.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. Would you mind a comment so we don't forget? Also, does the HashMap increase performance? Asking because last time this helped

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do, and I'll give it a shot with a hash table indeed :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created an optimised implementation, but it doesn't change much. I should've expected that, since it only affects the creation of rest objects :)

Comment thread crates/biome_js_type_info/src/format_type_info.rs Outdated
Comment thread crates/biome_js_type_info/src/local_inference.rs Outdated
Comment thread crates/biome_js_type_info/src/type_info/literal.rs
@github-actions github-actions Bot added the A-Project Area: project label Jun 26, 2025
@arendjr arendjr force-pushed the handle-logical-operators branch from cd5e653 to 54c7313 Compare June 26, 2025 13:47
@arendjr arendjr merged commit b424f46 into biomejs:next Jun 26, 2025
25 of 26 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Linter Area: linter A-Project Area: project A-Type-Inference Area: type inference L-JavaScript Language: JavaScript and super languages

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants