mirror of https://github.com/icsharpcode/ILSpy.git
Tree:
052aec9b89
christophwille/closedhierarchies
christophwille/membench
compound-assignment-operators
fix/1982-params-attribute-args
fix/2040-invalid-xml-characters
fix/2093-navigateto-reference-assembly
fix/2362-xalz-references
fix/2372-address-taken-by
fix/3282-indexer-optional-arguments
fix/3568-record-member-order
fix/4059-deconstruct-out-slots
fix/lambda-parameter-syntax
fix/scroll-children-on-expand
gh-pages
ldmembertoken
master
natural-type-lambdas-methods
null-coalescing-assignment
release/10.1
release/6.2
release/7.1
release/7.2
release/8.1
substring-optimizations
tests/829-async-method-builder-override
tests/829-collection-expressions
tests/829-compound-assignment-operators
tests/829-coverage-audit
tests/829-expression-tree-named-optional-args
tests/829-expression-variables-in-initializers
tests/829-extended-property-patterns
tests/829-extension-members
tests/829-extension-operators
tests/829-file-local-types
tests/829-improved-definite-assignment
tests/829-improved-overload-candidates
tests/829-inline-arrays
tests/829-interpolated-string-improvements
tests/829-lambda-param-modifiers
tests/829-list-patterns
tests/829-lock-object
tests/829-mixed-deconstruction
tests/829-null-coalescing-assignment
tests/829-null-conditional-assignment
tests/829-object-initializer-indexer
tests/829-overload-resolution-priority
tests/829-params-collections
tests/829-pattern-matching-improvements
tests/829-primary-constructors
tests/829-ref-unsafe-in-iterators-async
tests/829-sealed-record-tostring
tests/829-target-typed-conditional
tests/829-tuple-comparison
win-a11y-textsize
1.0-Beta
1.0-M1
1.0-M2
1.0-M3
1.0.0
2.0.0
2.1
2.2
2.3
2.3.1
3.0-Preview1
3.0-Preview2
3.0.2
v10.0
v10.0-preview1
v10.0-preview2
v10.0-preview3
v10.0.1
v10.1
v10.1.1
v11.0
v11.0-preview1
v11.0-rc
v2.3.2
v2.4
v3.0
v3.0-beta1
v3.0-beta2
v3.0-beta2a
v3.0-beta3
v3.0-beta4
v3.0.1
v3.1-beta1
v3.1-final
v3.1-rc
v3.2-beta
v3.2-rc
v3.2.0
v4.0
v4.0-alpha1
v4.0-beta1
v4.0-beta2
v4.0-beta3
v4.0-rc1
v4.0-rc2
v4.0.1
v5.0
v5.0-preview1
v5.0-preview2
v5.0-preview3
v5.0-preview4
v5.0-rc1
v5.0.1
v5.0.2
v6.0
v6.0-preview1
v6.0-preview2
v6.0-preview3
v6.0-preview4
v6.0-rc1
v6.1
v6.2
v6.2-preview1
v6.2-preview2
v6.2.1
v7.0
v7.0-preview1
v7.0-preview2
v7.0-preview3
v7.0-rc1
v7.0-rc2
v7.1
v7.2
v7.2-preview1
v7.2-preview2
v7.2-preview3
v7.2-preview4
v7.2-rc
v7.2.1
v8.0
v8.0-preview1
v8.0-preview2
v8.0-preview3
v8.0-preview4
v8.0-rc1
v8.1
v8.1.1
v8.2
v9.0
v9.0-preview1
v9.0-preview2
v9.0-preview3
v9.0-rc
v9.1
${ noResults }
2 Commits (052aec9b89a8d79a50cb176b2a162c2ce676dafa)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
8ab3f93f5e |
Fix #3704: keep the static type of a dynamic call target
A dynamic call site that names a type passes typeof(T) as its target. When a later argument contains control flow, the compiler stores that typeof in a temporary. ILInlining does not undo this: it inlines a store only into the immediately following instruction, so an intervening statement leaves the typeof behind, and the expression builder printed the temporary instead of the type. Substituting the typeof back into the target slot is not an option either, because a call there has side effects and blocks inlining of the remaining arguments. The type is therefore stored on the instruction. Object creation already did this, but kept the field private, so the expression builder re-derived the type from the target argument and failed on the spilled form. Member invocation gets the same field. Both drop the target from Arguments, so the dead-argument handling removes the store; ArgumentInfo keeps its entry for the target, because the invocation symbol is built from it. The type of an object creation is not nullable: the transform returns before constructing the instruction when it cannot match the typeof, and substitutes the unknown type otherwise. An unresolvable type therefore reaches the expression builder as the unresolved type it is, and prints as `?` like any other, rather than being indistinguishable from a missing one. Those two are also the only binder method kinds that ever see CSharpArgumentInfoFlags.IsStaticType. Every other way of naming a type as the receiver binds statically and leaves only a conversion of the dynamic operand behind. Assisted-by: Claude:claude-opus-5[1m]:Claude Code |
3 weeks ago |
|
|
c52a0f29f6 |
Fix #1388, #1928: decompile await on dynamic expressions
Awaiting a dynamic value lowers GetAwaiter/IsCompleted/GetResult to dynamic callsites, which async decompilation could not recognize: await detection ran before DynamicCallSiteTransform, so the await was emitted as a raw state machine (or crashed in AnalyzeAwaitBlock, #1388). AnalyzeStateMachine now collapses the awaiter callsites per block, folds the runtime ICriticalNotifyCompletion branch the compiler emits for an awaiter not statically known to implement it into the canonical single call, and re-joins the branch chains the collapse leaves so each dynamic await sits in one block. DetectAwaitPattern matches the dynamic GetAwaiter/IsCompleted/GetResult shape and emits `await expr`; a synthesized dynamic GetResult method gives the await and its local the dynamic type. DynamicCallSiteTransform also follows callsite targets spilled into state-machine locals, so an awaited value flowing into a dynamic callsite (e.g. d.Result = await ..., #1928) decompiles too. Assisted-by: Claude:claude-fable-5:Claude Code |
2 months ago |