- 19 2月, 2018 3 次提交
-
-
由 Jared Parsons 提交于
-
由 Jared Parsons 提交于
-
由 Jared Parsons 提交于
-
- 17 2月, 2018 1 次提交
-
-
由 Jared Parsons 提交于
This unifies our API naming convention. When standard is in the name then we are using the netstandard2.0 API set and when it is not then it is the simple desktop mscorlib46. Both variants are necessary for CompileAndVerify style functions because many of our tests that use it can only run on desktop or simply need to have some of the netstandard2.0 API set missing.
-
- 09 2月, 2018 1 次提交
-
-
由 Julien Couvreur 提交于
-
- 05 1月, 2018 1 次提交
-
-
由 vsadov 提交于
-
- 24 10月, 2017 1 次提交
-
-
- 13 10月, 2017 1 次提交
-
-
由 Charles Stoner 提交于
-
- 05 10月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Fixes #21768 Fixes #22027
-
- 16 9月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Fixes #21811 Fixes #21645 Fixes #21543
-
- 02 9月, 2017 1 次提交
-
-
由 Tomáš Matoušek 提交于
-
- 25 8月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
In order for EnC and other mechanisms to work we have to add synthesized members to a list in the CommonPEModuleBuilder for a compilation (these synthesized members are then queried as part of compilation stages). If those members are struct fields, we don't add them to the struct definition, only to the list of synthesized members. This works for emit, since we explicitly emit everything in the synthesized list, but it doesn't work for any compiler pass that examines the members of the struct for semantically meaningful reasons. This is the case for the CaptureWalker for async and iterator expressions. The walker checks the members of structs when a field of a struct is assigned to see if the struct has been assigned piecewise (each of its members has been assigned individually). If so, it will mark the entire struct as assigned. By not including synthesized fields as proper members of the struct type, the assignment pass believes that many fields have been assigned that have not, and thus marks the full struct as assigned, leading to losing track of variables captured across await/yield statements. This PR fixes the problem by adding the fields to the SynthesizedContainer, but exlcuding them from emit, since we should continue to use the emit mechanism used for CommonPEModuleBuilder. Fixes #21409
-
- 19 8月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
-
- 17 8月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Perform synthesis of closure methods in an early pass before visitation, meaning we no longer need to do a second visitation of the tree to lower local functions. The baselines have been changed because we now do closure id and synthessis in order of closure visitation, rather than bound node visitation. Closure visitation visits all the closures in a given scope, then recurs into nested scopes, while BoundNode visitation treats closures as scopes themselves, so nested closures are visited before closures declared in the same scope. Fixes https://github.com/dotnet/roslyn/projects/26#card-3753331
-
- 16 8月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
In the introduction of the new 'this' optimization routine, one of the things which was changed was to treat 'this' more like a formal parameter of the method, as opposed to a variable living in an implicit, higher scope. This has some advantages in simplicity for analysis, but created a problem when it came to proxies. The current analysis builds the proxy list by walking the tree and finding all captured variables and adding them to the proxy dictionary keyed by the original variable symbol. For instance, if a local variable is captured to a field, during rewriting it will be added to the proxy list as (original symbol, hoisted field). Since most symbols are only ever captured to a single replacement field, this usually works fine -- all proxies can exist side-by-side in the proxy list since there is no intersection. However, this is not true for captured environment pointers. When a new environment is introduced, a local will be created to point to that environment. That local may itself be captured by nested variables, creating a linked list from nested scopes to parent scope. Most notably, *multiple* nested environments may capture the *same* environment pointer in *different* hoisted fields. This means that the proxies dictionary cannot hold all mappings at once, since the mapping for a given captured environment pointer will depend on the current scope. The current code actually accounts for this already by adding a captured environment pointer to the proxy list on a nested scope's introduction, and removing it upon leaving that scope. By changing 'this' to be treated like a formal parameter, I circumvented this logic, introducing a bug. When two scopes tried to capture the 'this' pointer, the compiler crashed due to trying to add two mappings to the same key. This change fixes this problem by treating the 'this' parameter like an environment pointer for the purposes of capturing and hoisting. It's possible that we want to treat it like a formal parameter, but if so it's probably better to treat all captured environment pointers the same way and introduce a scope-aware notion of proxies, rather than having a global dictionary. Fixes #21506
-
- 14 8月, 2017 1 次提交
-
-
由 Ashley Hauck 提交于
-
- 12 8月, 2017 2 次提交
-
-
由 Ashley Hauck 提交于
-
由 Ashley Hauck 提交于
-
- 11 8月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Currently, the lambda rewriter has an early optimization pass in analysis that tries to find all local functions that only capture 'this' and remove references to local functions that do the same. There are two problems with this approach: 1) Generally, removing information from the tree is a bad idea because it hurts further analysis passes that may have needed that information. 2) The optimization strategy itself is very tricky and has a number of complex corner cases. This has lead to bugs, for example #19033. This PR deletes the current method and adds a new optimization routine at the end of the analysis, operating on assigned scopes and environments rather than removing captured variable analysis. The new optimization is as follows: if we end up with an environment containing only 'this', the environment can be removed, all containing methods can be moved to the top-level type, and all environments which capture the 'this' environment can instead directly capture the 'this' parameter. This produces almost the same results as the previous optimization, but is easier to validate as an algebraic equivalence. The baseline changes come from the new optimization being less aggressive about moving functions which only capture 'this' to the top level. This appears to be a wash -- some codegen gets slightly better, some gets slightly worse. Fixes #19033 Fixes #20577
-
- 08 8月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
The frame creation pass now considers scope of captured variable introduction instead of closure creation, so the ordering can change if two or more nested functions access variables 'outside-in', e.g. ```csharp { int x = 0; { int y = 0; int L1() => y; { int z = 0; int L2() => x; } } } ``` If we visit closures in-order in the previous example, we create frames for L1, then L2. If we visit captured variables scopes, however, we visit `x` (captured by L2), then `y` (captued by L1).
-
- 02 8月, 2017 1 次提交
-
-
由 CyrusNajmabadi 提交于
* Rename Foo to Goo * Rename ifoo to igoo * Add back BOMs
-
- 18 7月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Swaps out all uses of CapturedVariablesByLambda for functions on the Scope tree. The reason the baseline changed is that the order of enumerating closures changed. I briefly looked into matching the behavior, but the problem is that the closure order in the old visitors is determined by the visitation of captured variables, not visitation of the closures themselves. More specifically, an item is only added to the CapturedVariablesByLambda dictionary when ReferenceVariable encounters a captured variable. In contrast, the visitation of the Scope tree looks at closures in an in-order traversal of the tree, stopping at the first introduced closure, not necessarily the closure which first captured a variable. One obvious consequence of this changing is that the old ordering for a series of nested lambdas was effectively post-order -- the interior closures would be added to the visitation first, since they would be added from the perspective of the captured variable looking up, instead of the visitor looking down. This particular case is responsible for all the baseline changes that I have seen. When I looked into replicating this traversal order I found it complicated and pretty counter-intuitive. Since the baseline change was so low in emitted IL, I thought it better to keep a very natural in-order tree traversal and just rebaseline a few tests. Fixes https://github.com/dotnet/roslyn/projects/26#card-3753318
-
- 30 6月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
When lowering local functions that capture struct frames, the frames are added as ref parameters to the lowered method. Normally, when the local function captures variables from multiple levels up the intermediate closures are also rewritten to take the ref parameters. However, if one of the intermediate closures captures no variables, the closure conversion code can skip adding ref environments to that closure. This can cause the inner-most closure to no longer have access to all of the ref structs it expects, which crashes the compiler. Fixes #18814, #18918
-
- 20 6月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
-
- 17 5月, 2017 1 次提交
-
-
由 Charles Stoner 提交于
-
- 16 5月, 2017 1 次提交
-
-
由 Tomas Matousek 提交于
-
- 29 4月, 2017 2 次提交
-
-
由 vsadov 提交于
-
-
- 08 4月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
-
- 20 3月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Lambda rewriting currently allows frames to be structs in the instance where The variables in the frame are not captured by any closures converted to delegates. A closure nested inside the struct closure captures a separate variable that does require a class frame. This poses a problem when the "outer" closure is in the same frame as the variable that requires a class closure. The problem is that we treat scopes and frames as essentially the same thing -- if any scope is perceived to require a particular environment type, all captured variables in that scope will be captured on that frame and all closures will be lowered onto that frame. This creates a conflict between class-based environment capturing, where we want to capture the frame pointer as a field, and struct-based frame capturing, where we want to add arguments as ref parameters. Doing both results in breaking the delegate contract (no signature rewriting) or losing required struct arguments to intermediate closures. To elaborate on the problem here, let's consider the example: ```csharp using System; class C { public void M() { int x = 0; { int y= 0; void Local() { if (x == 0) { Action a = () => y++; a(); } } Local(); } } } ``` The current problem in the compiler is in the code now in GetStructClosures. The previous implementation only built struct closure if the closure was being lowered onto a struct frame. However, in the example, y is being captured by a lambda, meaning that y must be in a class frame. Since Local lives in the same scope it also lives in the same frame and contains the lambda capturing y, meaning that it must live in a class frame as well. Of course, it is not converted to a delegate, nor does it capture any variables that are captured by closures converted to delegates, so its signature is free to be rewritten to take variables which are not captured by closures converted to delegates as struct environment parameters. Here is the expected lowering for the previous example: ```csharp void M() { var env1 = new Env1(); env1.x = 0; var env2 = new Env2(); env2.y = 0; env2.<>_L(ref env1); } struct Env1 { public int x; } class Env2 { public int y; public void <>_L(ref Env1 env1) { if (env1.x == 0) { var env3 = new Env3(); env3.env2 = this; Action a = env3.<>_anon; a(); } } } class Env3 { Env2 env2; public void <>_anon() => this.env2.y++; } ``` The problem comes when calculating the struct frames needed to be passed to Local. In the current implementation, unless the "container" is a struct, no struct frames are added. If we fix that to check for struct frames that are required as parent frames, regardless of the type of container we run into another problem. In this case, the lambda also includes struct frames in its parent "context", but adding any struct frames to a closure that is converted to a delegate is incorrect. The previous problem can be solved by a check to see if the closure can take new ref parameters. This is true for all closures except for ones marked async or iterators or ones converted to delegates. This works because of something we already know from the analysis: if we assume that struct environments are only created when the their capturing closure can take ref parameters, we can assume that any struct environments in scope are "safe" to use, even if those frames are in the "parent context" of the closure. Fixes #16895
-
- 07 3月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Make local function default parameter value binding lazy Current strict binding can cause circularity problems when local functions are referenced. This change causes local functions to use lazy default parameter binding, similar to methods, and then forces their construction when diagnostics are requested for the local function. This also requires a mechanism for recording declaration diagnostics outside of adding to the compilation's DeclarationDiagnostics. A new type, DeclarationDiagnosticStore is introduced as an abstraction to store declaration diagnostics on either the compilation or in a local DiagnosticBag, depending on the needs of the symbol storing diagnostics. Fixes #16451, #17293
-
- 28 1月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Fixes #16352
-
- 25 1月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Attributes will not be permitted on type parameters or parameters of local functions. This matches the existing behavior for the return type and symbol itself, neither of which allow attributes to be applied to them. Fixes #1640
-
- 14 1月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
* Add regression test for #16399 Closes #16399
-
- 06 1月, 2017 1 次提交
-
-
由 Andy Gocke 提交于
Fixes #16038
-
- 21 12月, 2016 1 次提交
-
-
由 Andy Gocke 提交于
See #15751
-
- 20 12月, 2016 1 次提交
-
-
由 Andy Gocke 提交于
There were two root causes here: 1) The rewriter was treating the difference between the symbol and `symbol.ConstructedFrom` as whether or not there were any type parameters remaining that may need substitution. This is invalid for recursive local functions. 2) The local function reference rewriter was including type parameters from the containing type in the list of parameters to substitute. This should happen iff the containing type is a lambda frame used to capture variables, which is not always the case for local functions (although it is always the case for lambdas). Fixes #15751
-
- 18 12月, 2016 1 次提交
-
-
由 Andy Gocke 提交于
Local functions have already implemented their own frame management, including frame pointer "capturing" (which is implemented by passing a list of frames to the local function by-ref, rather than traditional lambda capturing which is implemented by keeping a linked list of frame pointers to parent frames). PR #14736 wired up local function lowering to the lambda frame pointer machinery, which is necessary for when a local function is captured by a lambda or converted to a delegate, but in the process it diverted control flow for pure local function capturing to the frame pointer machinery, which can't handle the structure of local function struct frame pointers. This PR resolves the issue by restoring the control flow for local functions capturing other local functions with by-ref struct frames. Fixes #15599
-
- 14 12月, 2016 1 次提交
-
-
由 Andy Gocke 提交于
When local functions are declared in unsafe regions (unsafe statement, unsafe member, unsafe type), their bodies should be considered unsafe regions, even if unsafe is not a declaration modifier on the local function. Fixes #13172
-
- 01 12月, 2016 1 次提交
-
-
由 Andy Gocke 提交于
Prior to C# 7 we tried to avoid giving duplicate errors when the user used a variable before it was declared (which is both a use-before-declared and a use-before-assigned error), but the line here is blurred with local functions, which can use variables before they are declared in subtle ways that can't be detected based on declaration order in syntax. It may be possible to provide the earlier behavior, but the current optimization is definitely insufficient and hides legitimate errors in user programs. Fixes #15298 Fixes #15322 (cherry picked from commit 1c8372ce)
-