Browse Source

Fix #3894: keep lambda parameter typing consistent

An anonymous parameter type cannot be named, so the original lambda must
have used implicit parameters throughout. Emit the whole parameter list
implicitly instead of mixing implicit and explicit declarations.

Assisted-by: Copilot:gpt-5.6-sol:GitHub Copilot CLI
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 86d2918e-5a24-48b4-9a86-41d331ec3720
pull/3897/head
Sebastien Lebreton 2 months ago committed by Daniel Grunwald
parent
commit
b1e5163873
  1. 13
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AnonymousTypes.cs
  2. 17
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

13
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AnonymousTypes.cs

@ -174,5 +174,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -174,5 +174,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return null;
}
#if ROSLYN
private static TValue GetOrCreate<TKey, TValue>(TKey key, Func<TKey, int, TValue> factory)
{
return factory(key, 1);
}
private static int MixedLambdaParameters()
{
return GetOrCreate(new {
Value = 1
}, (item, context) => item.Value + context);
}
#endif
}
}

17
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -2775,6 +2775,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2775,6 +2775,8 @@ namespace ICSharpCode.Decompiler.CSharp
IEnumerable<ParameterDeclaration> MakeParameters(IReadOnlyList<IParameter> parameters, ILFunction function)
{
var variables = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index!.Value);
var result = new List<ParameterDeclaration>(parameters.Count);
bool anyAnonymousType = false;
int i = 0;
foreach (var parameter in parameters)
{
@ -2790,10 +2792,21 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2790,10 +2792,21 @@ namespace ICSharpCode.Decompiler.CSharp
pd.Name = "P_" + i;
}
if (settings.AnonymousTypes && parameter.Type.ContainsAnonymousType())
pd.Type = null;
yield return pd;
anyAnonymousType = true;
result.Add(pd);
i++;
}
// An anonymous type cannot be named, so a lambda with such a parameter must be implicitly typed.
// C# also requires all lambda parameters to use the same form (CS0748). Drop every type when the
// remaining parameter syntax permits it; otherwise keep the converted declarations as a
// best-effort fallback for an unrepresentable signature.
if (anyAnonymousType && result.All(p => p.ParameterModifier == ReferenceKind.None
&& !p.IsParams && !p.IsScopedRef && p.Attributes.Count == 0 && p.DefaultExpression is null))
{
foreach (var pd in result)
pd.Type = null;
}
return result;
}
protected internal override TranslatedExpression VisitBlockContainer(BlockContainer container, TranslationContext context)

Loading…
Cancel
Save