Skip to content

Fix temp vars referenced in parameter #38130

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

Merged
merged 2 commits into from
Apr 24, 2020
Merged

Fix temp vars referenced in parameter #38130

merged 2 commits into from
Apr 24, 2020

Conversation

rbuckton
Copy link
Member

As of ES2015 it is illegal for the evaluation of one parameter to reference another parameter or a variable declared in the body of the function. As a result, any time we introduce a temporary variable when we emit a parameter with an initializer or binding pattern when targeting ES2015 or later we must move the evaluation to the body of the function.

This also adds a heuristic to the checker to ensure the correct name resolution for cases where our emit moves the evaluation of the parameter to the body of the function, and thus report an error when a parameter refers to an identifier that is shadowed in the body of the function.

Fixes #36295

@rbuckton
Copy link
Member Author

@DanielRosenwasser I'd like some feedback on the change to the error message. I'm considering simplifying it to the following:

Parameter '{0}' cannot reference identifier '{1}' declared after it.

@rbuckton
Copy link
Member Author

/cc @weswigham, @andrewbranch for review as suggested reviewers isn't working.

@DanielRosenwasser
Copy link
Member

I think that for initializer, the old message or

The initializer of parameter '{0}' cannot reference '{1}' because it is declared after '{0}'.

or

'{0}' cannot reference '{1}' because it is declared after '{0}'.

both work.

I think that in the case of the binding pattern, you should special case the message to be a variation of that so that we don't confuse people with "or binding pattern"

@rbuckton
Copy link
Member Author

That message is somewhat redundant, isn't it? The initializer of parameter 'p' cannot reference 'x' because it is declared after 'p'.

The reason I like Parameter '{0}' cannot reference identifier '{1}' declared after it. is that it covers both cases without an extra message.

@rbuckton
Copy link
Member Author

My suggestion would also be similar to the other existing related message: Parameter '{0}' cannot be referenced in its own initializer, though that also probably needs to be changed to something like: Parameter '{0}' cannot reference itself..

@rbuckton
Copy link
Member Author

Regarding "cannot reference itself", the reason I might change that one as well is this:

function f({ [a]: a }) {}

Binding a references itself in its own name here, rather than its initializer.

@andrewbranch
Copy link
Member

Looking at the errors produced by parameterInitializersForwardReferencing.2.ts , this is a breaking change, isn’t it?

This currently compiles in 3.8.3 (and seems to work in every runtime I’ve tried), but looks like it’s an error in this PR?

@rbuckton
Copy link
Member Author

Are you trying them in ES2015 or ES5?

@rbuckton
Copy link
Member Author

Oh sorry. The error is introduced only when using syntax that introduces temporaries. Your example should continue to work fine, but if you do function f(p = a()?.b) {} then it should produce the error.

@andrewbranch
Copy link
Member

Ah ok, interesting. So this PR does issue an error where there wasn’t one before, but only in cases where runtime behavior was already broken because of a name/scope conflict introduced by downleveling. Is that right?

@rbuckton
Copy link
Member Author

Correct. Its the same error we introduce for the same reason when the target is ES5, there are just now more cases that are accurately covered now.

@rbuckton
Copy link
Member Author

@typescript-bot perf test

@typescript-bot
Copy link
Collaborator

typescript-bot commented Apr 23, 2020

Heya @rbuckton, I've started to run the perf test suite on this PR at 45eca94. You can monitor the build here.

Update: The results are in!

@andrewbranch
Copy link
Member

I do think if I happened to hit this error, I would have a really hard time understanding why TypeScript thinks that a was declared after the usage in the parameter default. I would definitely think I was witnessing a checker bug. I’m not sure how to concisely explain the problem, though. It seems like we want to nudge users to rename either the inner or the outer variable.

@rbuckton
Copy link
Member Author

Right now I'm erring on the side of emulating the same behavior as what happens with the ES5 target. We might want to consider improving that messaging across the board, but I don't have an idea of a concise message for that either.

@rbuckton
Copy link
Member Author

Maybe these?

  • Parameter '{0}' cannot reference itself. - For cases that should be considered incorrect regardless of emit target.
  • Parameter '{0}' cannot reference identifier '{1}' declared after it. - For cases that should be considered incorrect regardless of emit target.
  • Parameter '{0}' cannot reference identifier '{1}' declared both inside and outside of the function where the parameter is defined due to the current emit target. - For cases due to downleveling.

/cc @DanielRosenwasser

@rbuckton
Copy link
Member Author

Hmm. The third bullet point is a bit harder to determine while in the middle of resolveName. I think I'll just stick with the messages in the first two bullet points until we have a better idea for the third one.

@typescript-bot
Copy link
Collaborator

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

Here they are:

Comparison Report - master..38130

Metric master 38130 Delta Best Worst
Angular - node (v10.16.3, x64)
Memory used 327,681k (± 0.02%) 327,221k (± 0.02%) -461k (- 0.14%) 327,080k 327,414k
Parse Time 1.65s (± 0.58%) 1.63s (± 0.54%) -0.02s (- 0.97%) 1.62s 1.65s
Bind Time 0.89s (± 0.84%) 0.89s (± 1.09%) +0.00s (+ 0.23%) 0.87s 0.91s
Check Time 4.79s (± 0.69%) 4.79s (± 0.48%) -0.01s (- 0.21%) 4.74s 4.84s
Emit Time 5.36s (± 0.59%) 5.39s (± 0.44%) +0.03s (+ 0.62%) 5.32s 5.42s
Total Time 12.69s (± 0.43%) 12.69s (± 0.23%) +0.00s (+ 0.04%) 12.60s 12.75s
Monaco - node (v10.16.3, x64)
Memory used 327,063k (± 0.02%) 327,142k (± 0.01%) +80k (+ 0.02%) 327,044k 327,239k
Parse Time 1.27s (± 0.54%) 1.27s (± 0.75%) +0.01s (+ 0.63%) 1.26s 1.29s
Bind Time 0.78s (± 0.71%) 0.78s (± 0.63%) +0.01s (+ 0.77%) 0.77s 0.79s
Check Time 4.80s (± 0.42%) 4.80s (± 0.60%) -0.00s (- 0.08%) 4.73s 4.88s
Emit Time 2.94s (± 0.97%) 2.96s (± 0.70%) +0.02s (+ 0.78%) 2.91s 3.02s
Total Time 9.78s (± 0.49%) 9.81s (± 0.54%) +0.03s (+ 0.30%) 9.72s 9.97s
TFS - node (v10.16.3, x64)
Memory used 292,086k (± 0.02%) 292,138k (± 0.03%) +51k (+ 0.02%) 291,941k 292,266k
Parse Time 0.96s (± 0.77%) 0.96s (± 0.81%) +0.00s (+ 0.10%) 0.95s 0.98s
Bind Time 0.74s (± 0.49%) 0.75s (± 0.64%) +0.00s (+ 0.40%) 0.74s 0.76s
Check Time 4.31s (± 0.41%) 4.33s (± 0.70%) +0.02s (+ 0.49%) 4.28s 4.42s
Emit Time 3.07s (± 0.80%) 3.07s (± 1.28%) 0.00s ( 0.00%) 2.95s 3.15s
Total Time 9.09s (± 0.49%) 9.11s (± 0.59%) +0.03s (+ 0.29%) 9.03s 9.30s
material-ui - node (v10.16.3, x64)
Memory used 450,584k (± 0.02%) 450,389k (± 0.02%) -195k (- 0.04%) 450,164k 450,547k
Parse Time 1.78s (± 0.28%) 1.79s (± 0.46%) +0.00s (+ 0.11%) 1.77s 1.81s
Bind Time 0.69s (± 0.50%) 0.69s (± 0.48%) +0.00s (+ 0.44%) 0.68s 0.70s
Check Time 12.62s (± 0.69%) 12.68s (± 1.06%) +0.06s (+ 0.51%) 12.53s 13.13s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.09s (± 0.60%) 15.16s (± 0.88%) +0.07s (+ 0.46%) 15.02s 15.59s
Angular - node (v12.1.0, x64)
Memory used 303,102k (± 0.02%) 302,765k (± 0.04%) -338k (- 0.11%) 302,573k 303,049k
Parse Time 1.59s (± 0.48%) 1.59s (± 0.71%) -0.01s (- 0.31%) 1.57s 1.62s
Bind Time 0.88s (± 0.70%) 0.88s (± 0.54%) -0.00s (- 0.23%) 0.87s 0.89s
Check Time 4.65s (± 0.65%) 4.71s (± 0.61%) +0.06s (+ 1.31%) 4.63s 4.78s
Emit Time 5.53s (± 0.41%) 5.58s (± 0.57%) +0.05s (+ 0.94%) 5.51s 5.62s
Total Time 12.65s (± 0.41%) 12.76s (± 0.45%) +0.11s (+ 0.84%) 12.59s 12.86s
Monaco - node (v12.1.0, x64)
Memory used 307,064k (± 0.02%) 307,107k (± 0.02%) +44k (+ 0.01%) 306,962k 307,256k
Parse Time 1.22s (± 0.46%) 1.23s (± 0.79%) +0.01s (+ 0.90%) 1.21s 1.25s
Bind Time 0.75s (± 1.00%) 0.75s (± 1.10%) +0.01s (+ 0.94%) 0.74s 0.78s
Check Time 4.60s (± 0.48%) 4.60s (± 0.45%) -0.00s (- 0.02%) 4.56s 4.66s
Emit Time 2.98s (± 0.76%) 2.99s (± 0.78%) +0.02s (+ 0.57%) 2.93s 3.05s
Total Time 9.54s (± 0.47%) 9.57s (± 0.51%) +0.03s (+ 0.30%) 9.47s 9.70s
TFS - node (v12.1.0, x64)
Memory used 274,373k (± 0.02%) 274,467k (± 0.03%) +94k (+ 0.03%) 274,327k 274,656k
Parse Time 0.93s (± 0.64%) 0.94s (± 0.55%) +0.01s (+ 0.54%) 0.93s 0.95s
Bind Time 0.71s (± 0.99%) 0.71s (± 1.60%) +0.00s (+ 0.14%) 0.69s 0.74s
Check Time 4.22s (± 0.52%) 4.23s (± 0.78%) +0.01s (+ 0.33%) 4.15s 4.29s
Emit Time 3.09s (± 1.22%) 3.11s (± 0.97%) +0.02s (+ 0.68%) 3.06s 3.19s
Total Time 8.96s (± 0.60%) 9.00s (± 0.66%) +0.04s (+ 0.44%) 8.89s 9.11s
material-ui - node (v12.1.0, x64)
Memory used 427,961k (± 0.05%) 427,805k (± 0.01%) -157k (- 0.04%) 427,686k 427,884k
Parse Time 1.76s (± 0.62%) 1.76s (± 0.67%) +0.00s (+ 0.23%) 1.74s 1.79s
Bind Time 0.63s (± 1.15%) 0.63s (± 0.75%) +0.00s (+ 0.16%) 0.62s 0.64s
Check Time 11.35s (± 1.04%) 11.35s (± 0.59%) +0.00s (+ 0.02%) 11.19s 11.48s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 13.74s (± 0.92%) 13.75s (± 0.52%) +0.01s (+ 0.04%) 13.56s 13.87s
Angular - node (v8.9.0, x64)
Memory used 322,575k (± 0.01%) 322,179k (± 0.01%) -396k (- 0.12%) 322,080k 322,265k
Parse Time 2.13s (± 0.60%) 2.11s (± 0.48%) -0.01s (- 0.66%) 2.09s 2.13s
Bind Time 0.92s (± 0.79%) 0.93s (± 0.96%) +0.00s (+ 0.43%) 0.90s 0.94s
Check Time 5.54s (± 1.16%) 5.43s (± 1.60%) -0.11s (- 1.95%) 5.21s 5.57s
Emit Time 6.27s (± 2.01%) 6.23s (± 2.05%) -0.03s (- 0.51%) 5.97s 6.47s
Total Time 14.85s (± 1.16%) 14.70s (± 0.56%) -0.15s (- 1.02%) 14.52s 14.87s
Monaco - node (v8.9.0, x64)
Memory used 325,538k (± 0.01%) 325,730k (± 0.02%) +192k (+ 0.06%) 325,620k 325,840k
Parse Time 1.56s (± 0.53%) 1.55s (± 0.53%) -0.00s (- 0.13%) 1.54s 1.58s
Bind Time 0.90s (± 1.42%) 0.90s (± 0.94%) -0.00s (- 0.33%) 0.89s 0.92s
Check Time 5.36s (± 0.80%) 5.39s (± 0.31%) +0.03s (+ 0.54%) 5.36s 5.43s
Emit Time 3.48s (± 0.93%) 3.52s (± 0.52%) +0.03s (+ 0.92%) 3.46s 3.55s
Total Time 11.30s (± 0.58%) 11.36s (± 0.28%) +0.06s (+ 0.54%) 11.28s 11.40s
TFS - node (v8.9.0, x64)
Memory used 291,519k (± 0.02%) 291,679k (± 0.02%) +159k (+ 0.05%) 291,583k 291,791k
Parse Time 1.26s (± 1.15%) 1.26s (± 0.59%) -0.00s (- 0.40%) 1.24s 1.27s
Bind Time 0.75s (± 0.60%) 0.75s (± 0.99%) +0.01s (+ 0.67%) 0.74s 0.77s
Check Time 4.94s (± 1.66%) 4.98s (± 1.71%) +0.05s (+ 0.93%) 4.85s 5.21s
Emit Time 3.29s (± 2.51%) 3.27s (± 2.96%) -0.02s (- 0.49%) 3.03s 3.41s
Total Time 10.24s (± 0.38%) 10.27s (± 0.45%) +0.02s (+ 0.23%) 10.18s 10.39s
material-ui - node (v8.9.0, x64)
Memory used 453,129k (± 0.01%) 452,967k (± 0.01%) -163k (- 0.04%) 452,767k 453,056k
Parse Time 2.12s (± 0.29%) 2.11s (± 0.46%) -0.01s (- 0.47%) 2.08s 2.12s
Bind Time 0.81s (± 0.86%) 0.81s (± 0.90%) +0.00s (+ 0.12%) 0.79s 0.83s
Check Time 16.80s (± 0.99%) 16.80s (± 0.95%) -0.00s (- 0.01%) 16.42s 17.07s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 19.73s (± 0.85%) 19.72s (± 0.80%) -0.01s (- 0.07%) 19.34s 19.98s
Angular - node (v8.9.0, x86)
Memory used 185,719k (± 0.02%) 185,527k (± 0.02%) -192k (- 0.10%) 185,395k 185,629k
Parse Time 2.07s (± 0.74%) 2.05s (± 0.51%) -0.02s (- 0.92%) 2.03s 2.08s
Bind Time 1.07s (± 0.77%) 1.07s (± 0.69%) -0.00s (- 0.37%) 1.05s 1.08s
Check Time 5.03s (± 0.90%) 5.02s (± 0.64%) -0.00s (- 0.08%) 4.97s 5.11s
Emit Time 6.07s (± 0.78%) 6.14s (± 0.84%) +0.07s (+ 1.17%) 6.05s 6.29s
Total Time 14.24s (± 0.62%) 14.28s (± 0.46%) +0.04s (+ 0.31%) 14.14s 14.40s
Monaco - node (v8.9.0, x86)
Memory used 185,369k (± 0.02%) 185,504k (± 0.01%) +135k (+ 0.07%) 185,440k 185,541k
Parse Time 1.61s (± 0.66%) 1.60s (± 0.75%) -0.00s (- 0.19%) 1.58s 1.63s
Bind Time 0.77s (± 1.04%) 0.77s (± 0.68%) +0.00s (+ 0.13%) 0.76s 0.78s
Check Time 5.41s (± 0.52%) 5.41s (± 0.44%) +0.00s (+ 0.06%) 5.36s 5.47s
Emit Time 2.87s (± 1.17%) 2.89s (± 0.79%) +0.02s (+ 0.63%) 2.81s 2.92s
Total Time 10.65s (± 0.52%) 10.67s (± 0.31%) +0.02s (+ 0.21%) 10.57s 10.74s
TFS - node (v8.9.0, x86)
Memory used 166,963k (± 0.02%) 167,037k (± 0.02%) +74k (+ 0.04%) 166,961k 167,109k
Parse Time 1.29s (± 0.82%) 1.30s (± 0.64%) +0.01s (+ 0.78%) 1.28s 1.31s
Bind Time 0.71s (± 0.91%) 0.71s (± 0.48%) +0.00s (+ 0.14%) 0.71s 0.72s
Check Time 4.64s (± 0.56%) 4.65s (± 0.31%) +0.01s (+ 0.19%) 4.61s 4.68s
Emit Time 2.98s (± 1.52%) 2.97s (± 2.03%) -0.01s (- 0.37%) 2.89s 3.19s
Total Time 9.62s (± 0.64%) 9.63s (± 0.64%) +0.01s (+ 0.11%) 9.54s 9.84s
material-ui - node (v8.9.0, x86)
Memory used 256,526k (± 0.02%) 256,459k (± 0.01%) -67k (- 0.03%) 256,411k 256,499k
Parse Time 2.17s (± 0.38%) 2.19s (± 0.74%) +0.01s (+ 0.55%) 2.17s 2.24s
Bind Time 0.68s (± 1.21%) 0.69s (± 1.22%) +0.00s (+ 0.58%) 0.68s 0.72s
Check Time 15.30s (± 0.55%) 15.36s (± 1.07%) +0.06s (+ 0.41%) 14.96s 15.69s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 18.16s (± 0.47%) 18.23s (± 0.92%) +0.08s (+ 0.41%) 17.85s 18.54s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-166-generic
Architecturex64
Available Memory16 GB
Available Memory1 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v10.16.3, x64)
  • node (v12.1.0, x64)
  • node (v8.9.0, x64)
  • node (v8.9.0, x86)
Scenarios
  • Angular - node (v10.16.3, x64)
  • Angular - node (v12.1.0, x64)
  • Angular - node (v8.9.0, x64)
  • Angular - node (v8.9.0, x86)
  • Monaco - node (v10.16.3, x64)
  • Monaco - node (v12.1.0, x64)
  • Monaco - node (v8.9.0, x64)
  • Monaco - node (v8.9.0, x86)
  • TFS - node (v10.16.3, x64)
  • TFS - node (v12.1.0, x64)
  • TFS - node (v8.9.0, x64)
  • TFS - node (v8.9.0, x86)
  • material-ui - node (v10.16.3, x64)
  • material-ui - node (v12.1.0, x64)
  • material-ui - node (v8.9.0, x64)
  • material-ui - node (v8.9.0, x86)
Benchmark Name Iterations
Current 38130 10
Baseline master 10

@rbuckton
Copy link
Member Author

@DanielRosenwasser should I merge this and discuss changing the messages later, or should I wait?

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Apr 24, 2020

The messages seem fine overall, I'd just merge.

@DanielRosenwasser
Copy link
Member

(If you feel like they could be better, I encourage you to follow up, but don't let it block merging this)

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

Successfully merging this pull request may close these issues.

Optional chaining with default parameter fails
4 participants