Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Flag non-nullable functions inif statements as errors (tree walk version)#33178

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

@jwbay
Copy link
Contributor

@jwbayjwbay commentedAug 31, 2019
edited
Loading

This is an alternate version of#32802 -- see that one for context.

This version attempts to prevent false positives by doing a syntax walk to see if the checked function is used, as opposed to relying on a heuristic where the function returns a boolean. The first commit is the same for both PR; the second adds filtering that differs.

Opened as a separate PR by request (cc@RyanCavanaugh)

Notably, this change flagged a couple things in the compiler itself. Commented below for both.

jakubnavratil reacted with thumbs up emoji
// try to verify results of module resolution
for(const{oldFile:oldSourceFile,newFile:newSourceFile}ofmodifiedSourceFiles){
constnewSourceFilePath=getNormalizedAbsolutePath(newSourceFile.originalFileName,currentDirectory);
if(resolveModuleNamesWorker){
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Looks likeresolveModuleNamesWorker is always assigned above, so this was a dead check

exportfunctioncompose<T>(...args:((t:T)=>T)[]):(t:T)=>T;
exportfunctioncompose<T>(a:(t:T)=>T,b:(t:T)=>T,c:(t:T)=>T,d:(t:T)=>T,e:(t:T)=>T):(t:T)=>T{
if(e){
if(!!e){
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

This is a pretty good example of what TS would now consider suspicious-enough code to error on. Makinge optional would also have fixed this.

@orta
Copy link
Contributor

@typescript-bot test this
@typescript-bot user test this
@typescript-bot run dt

@typescript-bot
Copy link
Collaborator

typescript-bot commentedSep 11, 2019
edited
Loading

Heya@orta, I've started to run the extended test suite on this PR at3c9e338. You can monitor the buildhere. It should now contribute to this PR's status checks.

@typescript-bot
Copy link
Collaborator

typescript-bot commentedSep 11, 2019
edited
Loading

Heya@orta, I've started to run the parallelized community code test suite on this PR at3c9e338. You can monitor the buildhere. It should now contribute to this PR's status checks.

@typescript-bot
Copy link
Collaborator

typescript-bot commentedSep 11, 2019
edited
Loading

Heya@orta, I've started to run the parallelized Definitely Typed test suite on this PR at3c9e338. You can monitor the buildhere. It should now contribute to this PR's status checks.

@typescript-bot
Copy link
Collaborator

The user suite test run you requested has finished andfailed. I've opened aPR with the baseline diff from master.

@RyanCavanaugh
Copy link
Member

The RWC diff is unrelated.

The User Test Suite diff is a false positive, but not a bad one:https://github.com/npm/cli/blob/latest/test/tap/check-permissions.js#L27

@RyanCavanaugh
Copy link
Member

@typescript-bot perf test this

@typescript-bot
Copy link
Collaborator

typescript-bot commentedSep 11, 2019
edited
Loading

Heya@RyanCavanaugh, I've started to run the perf test suite on this PR at3c9e338. You can monitor the buildhere. It should now contribute to this PR's status checks.

Update:The results are in!

@typescript-bot
Copy link
Collaborator

@RyanCavanaugh
The results of the perf run you requested are in!

Here they are:

Comparison Report - master..33178

Metricmaster33178DeltaBestWorst
Angular - node (v12.1.0, x64)
Memory used331,291k (± 0.02%)325,798k (± 0.04%)-5,493k (- 1.66%)325,266k325,968k
Parse Time1.56s (± 0.54%)1.48s (± 0.45%)-0.08s (- 4.87%)1.47s1.50s
Bind Time0.78s (± 0.67%)0.75s (± 0.63%)-0.03s (- 3.34%)0.75s0.77s
Check Time4.25s (± 0.60%)4.19s (± 0.47%)-0.06s (- 1.48%)4.14s4.24s
Emit Time5.22s (± 0.59%)5.23s (± 0.48%)+0.01s (+ 0.21%)5.17s5.28s
Total Time11.82s (± 0.40%)11.66s (± 0.30%)-0.16s (- 1.32%)11.55s11.74s
Monaco - node (v12.1.0, x64)
Memory used346,015k (± 0.04%)345,898k (± 0.03%)-116k (- 0.03%)345,732k346,088k
Parse Time1.22s (± 0.60%)1.22s (± 0.91%)+0.00s (+ 0.16%)1.20s1.24s
Bind Time0.68s (± 0.74%)0.68s (± 1.47%)+0.01s (+ 1.33%)0.67s0.72s
Check Time4.25s (± 0.51%)4.26s (± 0.67%)+0.01s (+ 0.26%)4.20s4.34s
Emit Time2.88s (± 1.37%)2.86s (± 0.68%)-0.02s (- 0.70%)2.81s2.91s
Total Time9.02s (± 0.58%)9.03s (± 0.31%)+0.00s (+ 0.03%)8.98s9.11s
TFS - node (v12.1.0, x64)
Memory used301,407k (± 0.02%)301,420k (± 0.02%)+13k (+ 0.00%)301,314k301,503k
Parse Time0.95s (± 0.98%)0.94s (± 0.72%)-0.00s (- 0.42%)0.93s0.96s
Bind Time0.63s (± 1.03%)0.62s (± 1.33%)-0.00s (- 0.64%)0.61s0.65s
Check Time3.86s (± 0.41%)3.85s (± 0.54%)-0.00s (- 0.13%)3.79s3.90s
Emit Time2.97s (± 0.46%)2.96s (± 0.49%)-0.00s (- 0.13%)2.93s3.00s
Total Time8.40s (± 0.24%)8.38s (± 0.38%)-0.02s (- 0.18%)8.33s8.48s
Angular - node (v8.9.0, x64)
Memory used350,095k (± 0.02%)344,535k (± 0.01%)-5,559k (- 1.59%)344,452k344,644k
Parse Time2.09s (± 0.42%)1.99s (± 0.43%)-0.10s (- 4.83%)1.97s2.01s
Bind Time0.84s (± 0.57%)0.82s (± 0.79%)-0.02s (- 2.27%)0.80s0.83s
Check Time5.12s (± 0.59%)5.04s (± 0.75%)-0.08s (- 1.52%)4.97s5.12s
Emit Time5.97s (± 0.68%)6.15s (± 0.63%)+0.18s (+ 3.00%)6.08s6.25s
Total Time14.02s (± 0.37%)14.00s (± 0.48%)-0.02s (- 0.14%)13.89s14.16s
Monaco - node (v8.9.0, x64)
Memory used363,686k (± 0.01%)363,687k (± 0.01%)+2k (+ 0.00%)363,550k363,794k
Parse Time1.56s (± 0.52%)1.57s (± 0.32%)+0.00s (+ 0.32%)1.55s1.57s
Bind Time0.89s (± 1.12%)0.89s (± 1.01%)-0.00s (- 0.45%)0.86s0.90s
Check Time5.11s (± 1.30%)5.09s (± 1.22%)-0.02s (- 0.47%)5.00s5.26s
Emit Time3.14s (± 4.52%)3.25s (± 3.67%)+0.11s (+ 3.44%)2.90s3.39s
Total Time10.70s (± 0.89%)10.79s (± 0.68%)+0.09s (+ 0.82%)10.60s10.98s
TFS - node (v8.9.0, x64)
Memory used317,706k (± 0.01%)317,645k (± 0.01%)-60k (- 0.02%)317,584k317,721k
Parse Time1.26s (± 0.53%)1.25s (± 0.54%)-0.01s (- 0.71%)1.24s1.27s
Bind Time0.70s (± 5.02%)0.68s (± 3.63%)-0.02s (- 2.99%)0.66s0.78s
Check Time4.45s (± 1.36%)4.49s (± 0.87%)+0.04s (+ 0.83%)4.36s4.54s
Emit Time3.09s (± 0.60%)3.08s (± 0.87%)-0.01s (- 0.45%)3.00s3.12s
Total Time9.50s (± 0.52%)9.50s (± 0.44%)-0.00s (- 0.03%)9.37s9.57s
Angular - node (v8.9.0, x86)
Memory used198,187k (± 0.02%)195,180k (± 0.02%)-3,007k (- 1.52%)195,060k195,274k
Parse Time2.03s (± 0.47%)1.92s (± 0.47%)-0.11s (- 5.28%)1.90s1.94s
Bind Time0.95s (± 1.16%)0.94s (± 0.43%)-0.01s (- 1.26%)0.93s0.95s
Check Time4.66s (± 0.45%)4.57s (± 0.52%)-0.09s (- 1.85%)4.51s4.62s
Emit Time5.70s (± 0.56%)5.82s (± 1.76%)+0.11s (+ 2.00%)5.58s6.08s
Total Time13.35s (± 0.34%)13.25s (± 0.78%)-0.10s (- 0.73%)13.07s13.54s
Monaco - node (v8.9.0, x86)
Memory used203,221k (± 0.02%)203,189k (± 0.03%)-33k (- 0.02%)203,062k203,346k
Parse Time1.62s (± 0.78%)1.61s (± 0.69%)-0.01s (- 0.37%)1.60s1.64s
Bind Time0.72s (± 0.77%)0.72s (± 0.65%)+0.00s (+ 0.28%)0.71s0.73s
Check Time4.89s (± 0.59%)4.86s (± 0.58%)-0.03s (- 0.70%)4.80s4.94s
Emit Time3.19s (± 0.73%)3.15s (± 0.64%)-0.03s (- 1.04%)3.12s3.22s
Total Time10.41s (± 0.50%)10.34s (± 0.38%)-0.07s (- 0.67%)10.26s10.46s
TFS - node (v8.9.0, x86)
Memory used178,509k (± 0.01%)178,518k (± 0.01%)+10k (+ 0.01%)178,460k178,582k
Parse Time1.31s (± 0.72%)1.32s (± 0.88%)+0.00s (+ 0.15%)1.30s1.34s
Bind Time0.65s (± 0.77%)0.64s (± 1.75%)-0.00s (- 0.62%)0.63s0.68s
Check Time4.31s (± 0.61%)4.28s (± 0.53%)-0.03s (- 0.79%)4.23s4.32s
Emit Time2.88s (± 1.00%)2.86s (± 1.53%)-0.02s (- 0.69%)2.77s2.96s
Total Time9.15s (± 0.38%)9.10s (± 0.60%)-0.05s (- 0.58%)8.97s9.24s
Angular - node (v9.0.0, x64)
Memory used349,762k (± 0.03%)344,113k (± 0.02%)-5,648k (- 1.61%)343,976k344,249k
Parse Time1.82s (± 0.45%)1.72s (± 0.64%)-0.10s (- 5.49%)1.69s1.74s
Bind Time0.78s (± 0.77%)0.77s (± 0.64%)-0.01s (- 1.16%)0.76s0.78s
Check Time4.88s (± 0.65%)4.76s (± 0.38%)-0.12s (- 2.54%)4.73s4.79s
Emit Time5.78s (± 1.32%)5.70s (± 1.63%)-0.08s (- 1.42%)5.52s5.89s
Total Time13.26s (± 0.68%)12.95s (± 0.86%)-0.31s (- 2.35%)12.74s13.16s
Monaco - node (v9.0.0, x64)
Memory used363,480k (± 0.02%)363,441k (± 0.02%)-40k (- 0.01%)363,284k363,702k
Parse Time1.32s (± 0.61%)1.32s (± 0.46%)-0.00s (- 0.23%)1.30s1.33s
Bind Time0.83s (± 1.49%)0.84s (± 1.13%)+0.01s (+ 1.44%)0.81s0.86s
Check Time5.07s (± 1.60%)4.92s (± 0.89%)-0.15s (- 2.92%)4.86s5.08s
Emit Time3.08s (± 5.47%)3.30s (± 3.09%)+0.22s (+ 7.13%)2.90s3.40s
Total Time10.30s (± 1.04%)10.38s (± 0.74%)+0.08s (+ 0.81%)10.10s10.50s
TFS - node (v9.0.0, x64)
Memory used317,468k (± 0.01%)317,422k (± 0.01%)-46k (- 0.01%)317,296k317,557k
Parse Time1.04s (± 0.50%)1.05s (± 0.35%)+0.01s (+ 0.48%)1.04s1.05s
Bind Time0.62s (± 0.72%)0.62s (± 0.79%)+0.00s (+ 0.32%)0.61s0.63s
Check Time4.38s (± 0.57%)4.38s (± 0.42%)-0.00s (- 0.02%)4.35s4.42s
Emit Time3.20s (± 0.78%)3.19s (± 0.41%)-0.00s (- 0.13%)3.17s3.22s
Total Time9.24s (± 0.51%)9.24s (± 0.27%)-0.00s (- 0.01%)9.19s9.30s
Angular - node (v9.0.0, x86)
Memory used198,329k (± 0.02%)195,251k (± 0.04%)-3,079k (- 1.55%)195,113k195,376k
Parse Time1.73s (± 0.58%)1.63s (± 0.38%)-0.10s (- 5.99%)1.62s1.65s
Bind Time0.90s (± 0.56%)0.89s (± 0.87%)-0.00s (- 0.45%)0.87s0.91s
Check Time4.35s (± 0.50%)4.25s (± 0.30%)-0.10s (- 2.25%)4.23s4.28s
Emit Time5.53s (± 0.69%)5.51s (± 0.28%)-0.03s (- 0.49%)5.48s5.56s
Total Time12.51s (± 0.37%)12.28s (± 0.18%)-0.23s (- 1.83%)12.24s12.33s
Monaco - node (v9.0.0, x86)
Memory used203,274k (± 0.02%)203,274k (± 0.03%)+1k (+ 0.00%)203,155k203,372k
Parse Time1.36s (± 0.74%)1.35s (± 0.52%)-0.01s (- 0.44%)1.33s1.36s
Bind Time0.64s (± 1.18%)0.65s (± 0.73%)+0.00s (+ 0.31%)0.64s0.66s
Check Time4.72s (± 0.48%)4.69s (± 0.49%)-0.03s (- 0.61%)4.64s4.74s
Emit Time3.10s (± 1.07%)3.10s (± 0.52%)-0.00s (- 0.03%)3.07s3.15s
Total Time9.82s (± 0.48%)9.79s (± 0.31%)-0.03s (- 0.31%)9.72s9.85s
TFS - node (v9.0.0, x86)
Memory used178,596k (± 0.02%)178,585k (± 0.02%)-11k (- 0.01%)178,504k178,673k
Parse Time1.07s (± 0.54%)1.07s (± 0.65%)+0.00s (+ 0.37%)1.05s1.08s
Bind Time0.58s (± 0.57%)0.58s (± 0.86%)-0.00s (- 0.69%)0.57s0.59s
Check Time4.16s (± 0.55%)4.15s (± 1.17%)-0.01s (- 0.14%)4.06s4.30s
Emit Time2.79s (± 1.85%)2.79s (± 0.99%)-0.00s (- 0.07%)2.71s2.85s
Total Time8.59s (± 0.64%)8.59s (± 0.86%)-0.01s (- 0.08%)8.45s8.81s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-161-generic
Architecturex64
Available Memory16 GB
Available Memory10 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v12.1.0, x64)
  • node (v8.9.0, x64)
  • node (v8.9.0, x86)
  • node (v9.0.0, x64)
  • node (v9.0.0, x86)
Scenarios
  • Angular - node (v12.1.0, x64)
  • Angular - node (v8.9.0, x64)
  • Angular - node (v8.9.0, x86)
  • Angular - node (v9.0.0, x64)
  • Angular - node (v9.0.0, x86)
  • Monaco - node (v12.1.0, x64)
  • Monaco - node (v8.9.0, x64)
  • Monaco - node (v8.9.0, x86)
  • Monaco - node (v9.0.0, x64)
  • Monaco - node (v9.0.0, x86)
  • TFS - node (v12.1.0, x64)
  • TFS - node (v8.9.0, x64)
  • TFS - node (v8.9.0, x86)
  • TFS - node (v9.0.0, x64)
  • TFS - node (v9.0.0, x86)
BenchmarkNameIterations
Current3317810
Baselinemaster10

@orta
Copy link
Contributor

Hrm, none of these builds have accessible logs.

I bet it's likely that community projects will need changes like:

-        if (e) {+       if (!!e) {

Will re-run and take a look.

@typescript-bot test this
@typescript-bot user test this

@typescript-bot
Copy link
Collaborator

typescript-bot commentedSep 23, 2019
edited
Loading

Heya@orta, I've started to run the extended test suite on this PR at3c9e338. You can monitor the buildhere. It should now contribute to this PR's status checks.

@typescript-bot
Copy link
Collaborator

typescript-bot commentedSep 23, 2019
edited
Loading

Heya@orta, I've started to run the parallelized community code test suite on this PR at3c9e338. You can monitor the buildhere. It should now contribute to this PR's status checks.

@typescript-bot
Copy link
Collaborator

The user suite test run you requested has finished andfailed. I've opened aPR with the baseline diff from master.

@orta
Copy link
Contributor

OK@jwbay - to get this mergeable you'll need to acceptjwbay#3

jwbayand others added2 commitsSeptember 24, 2019 19:50
…nonNullableCallSignaturesTreeWalk🤖 User test baselines have changed for nonNullableCallSignaturesTreeWalk
@ortaorta added the Update Docs on Next ReleaseIndicates that this PR affects docs labelSep 25, 2019
@orta
Copy link
Contributor

OK, perf looks acceptable to me.

The idea is a good one, and I feel good about the implementation - thanks@jwbay!

jwbay reacted with hooray emoji

@ortaorta merged commit91be368 intomicrosoft:masterSep 25, 2019
@DanielRosenwasserDanielRosenwasser added the Breaking ChangeWould introduce errors in existing code labelOct 1, 2019
@user753
Copy link

@jwbay
Is there any reason why it affects only functions and not arrays, records, etc?

function foo(array: string[]) {  if (array) {    return true  }}function bar(record: Record<string, string>) {  if (record) {    return true  }}

@RyanCavanaugh
Copy link
Member

@user753 a few major problems appeared when we tried that approach.

Array access is optimistically assumed to be in-bounds, so code like this gets incorrectly flagged as an error. The same thing happens forMap.get and a few other APIs that are assumed to "always return non-undefined values when used correctly".

constarr=[rec,rec,rec];constel=arr[someIndex];if(el){// do something}

Separately, many definition files were written prior to the introduction ofstrictNullChecks, so correctnull/undefined checks on properties from those definitions would get incorrectly flagged as an error.

Ultimately the very narrow check implemented here was the only one that didn't generate a huge amount of false positives.

@user753
Copy link

user753 commentedOct 3, 2019
edited
Loading

@RyanCavanaugh Thanks.
Do I understand correctly that It isn't a problem for functions because a function inside an array isn't a common use case?

const arr = [func, func, func];const el = arr[someIndex];if (el) {  // do something}

@RyanCavanaugh
Copy link
Member

Normally if that does happen, a call toel() appears in the body of theif, which is the additional check that this PR implements. Ifel *isn't` called, that'll be a false positive.

user753 reacted with thumbs up emoji

@RyanCavanaugh
Copy link
Member

@jwbay this might be my favorite check this release.https://github.com/microsoft/vscode/blob/ecba37c6ef3aab85b7a9b15afb3610bbe4eaac8c/extensions/css-language-features/server/src/cssServerMain.ts#L78

jwbay reacted with hooray emojijwbay reacted with rocket emojijwbay reacted with eyes emoji

@twavv
Copy link

It would be great if this was extended to functions that return promises as well.

In the announcement for 3.7 (which I'mthrilled about!!!), you include this code example.

functiondoAdminThing(user:User){if(user.isAdministrator){//  ~~~~~~~~~~~~~~~~~~~~// error! This condition will always return true since the function is always defined.//        Did you mean to call it instead?t

It would be incredible if this was also extended to raise an error when the function returns a promise and it's not awaited before using it in a condition (I've personally been bitten by this exact bug before).

classUser{// ...asyncisAdministrator(){/* ... */}}functiondoAdminThing(user:User){if(user.isAdministrator()){//  ~~~~~~~~~~~~~~~~~~~~~~// error! This condition will always return true since a promise is always truthy.//        Did you mean to await it instead?

I tried searching for issues related to this but couldn't find any (it's possible that I just missed it because there are so many issues and I'm not sure what keywords to search).

I've definitely been bitten by a bug where I did something like this:

asyncfunctionpasswordMatches(email:string,password:string){/* return true if the password matches the result in the database */}if(passwordMatches("foo@bar.gov","passw0rd")){/* issue auth token */}
heathkit, weakish, and MaxNanasy reacted with thumbs up emoji

@omidkrad
Copy link

Regarding Uncalled Function Checks, I think it'd be pretty safe to also error on this:

functionprocess(){console.log('Processing...');}process;

@bgub
Copy link

BTW this is breaking all of my polyfills, like checks forif (String.prototype.trimLeft) {}. Any way to disable this?

vinothbabu reacted with thumbs up emoji

@vinothbabu
Copy link

The problem with this is, it's not allowing any of the valid ways to pass. As@nebrelbug pointed above.

if (String.prototype.trimLeft) {} //fails
if (typeof String.prototype.trimLeft === 'function') {} //fails
if ('trimLeft' in String.prototype) //fails

We had to adapt to this, which passes

// eslint-disable-next-line no-extra-boolean-cast
if (!!String.prototype.trimLeft)

MaxNanasy reacted with thumbs up emoji

@microsoftmicrosoft locked asresolvedand limited conversation to collaboratorsOct 21, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@ortaortaAwaiting requested review from orta

Assignees

@ortaorta

Labels

Breaking ChangeWould introduce errors in existing codeUpdate Docs on Next ReleaseIndicates that this PR affects docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

11 participants

@jwbay@orta@typescript-bot@RyanCavanaugh@user753@twavv@omidkrad@bgub@vinothbabu@BernsteinA@DanielRosenwasser

[8]ページ先頭

©2009-2025 Movatter.jp