Files
2026-08-27 10:56:38 -06:00

299 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp;
internal sealed class BoundLambda : BoundExpression, IBoundLambdaOrFunction
{
internal sealed class BlockReturns : BoundTreeWalker
{
private readonly ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)> _builder;
private BlockReturns(ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)> builder)
{
_builder = builder;
}
public static void GetReturnTypes(ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)> builder, BoundBlock block)
{
new BlockReturns(builder).Visit(block);
}
public override BoundNode? Visit(BoundNode node)
{
if (!(node is BoundExpression))
{
return base.Visit(node);
}
return null;
}
protected override BoundExpression VisitExpressionWithoutStackGuard(BoundExpression node)
{
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs", 365);
}
public override BoundNode? VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
{
return null;
}
public override BoundNode? VisitReturnStatement(BoundReturnStatement node)
{
BoundExpression expressionOpt = node.ExpressionOpt;
TypeSymbol typeSymbol = ((expressionOpt == null) ? NoReturnExpression : expressionOpt.Type?.SetUnknownNullabilityForReferenceTypes());
_builder.Add((node, TypeWithAnnotations.Create(typeSymbol)));
return null;
}
}
internal static readonly TypeSymbol NoReturnExpression = new UnsupportedMetadataTypeSymbol();
public override Symbol ExpressionSymbol => Symbol;
public override object Display => MessageID.Localize();
public MessageID MessageID
{
get
{
if (Syntax.Kind() != SyntaxKind.AnonymousMethodExpression)
{
return MessageID.IDS_Lambda;
}
return MessageID.IDS_AnonMethod;
}
}
internal InferredLambdaReturnType InferredReturnType { get; }
internal bool InAnonymousFunctionConversion { get; private set; }
MethodSymbol IBoundLambdaOrFunction.Symbol => Symbol;
SyntaxNode IBoundLambdaOrFunction.Syntax => Syntax;
public UnboundLambda UnboundLambda { get; }
public LambdaSymbol Symbol { get; }
public new TypeSymbol? Type => base.Type;
public BoundBlock Body { get; }
public ImmutableBindingDiagnostic<AssemblySymbol> Diagnostics { get; }
public Binder Binder { get; }
public BoundLambda(SyntaxNode syntax, UnboundLambda unboundLambda, BoundBlock body, ImmutableBindingDiagnostic<AssemblySymbol> diagnostics, Binder binder, TypeSymbol? delegateType, InferredLambdaReturnType inferredReturnType)
: this(syntax, unboundLambda.WithNoCache(), (LambdaSymbol)binder.ContainingMemberOrLambda, body, diagnostics, binder, delegateType)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
InferredReturnType = inferredReturnType;
}
internal BoundLambda WithInAnonymousFunctionConversion()
{
if (InAnonymousFunctionConversion)
{
return this;
}
BoundLambda obj = (BoundLambda)MemberwiseClone();
obj.InAnonymousFunctionConversion = true;
return obj;
}
public TypeWithAnnotations GetInferredReturnType(ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, out bool inferredFromFunctionType)
{
return GetInferredReturnType(null, null, ref useSiteInfo, out inferredFromFunctionType);
}
public TypeWithAnnotations GetInferredReturnType(ConversionsBase? conversions, NullableWalker.VariableState? nullableState, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, out bool inferredFromFunctionType)
{
if (!InferredReturnType.UseSiteDiagnostics.IsEmpty)
{
useSiteInfo.AddDiagnostics(InferredReturnType.UseSiteDiagnostics);
}
if (!InferredReturnType.Dependencies.IsEmpty)
{
useSiteInfo.AddDependencies(InferredReturnType.Dependencies);
}
InferredLambdaReturnType inferredLambdaReturnType;
if (nullableState == null || InferredReturnType.IsExplicitType)
{
inferredLambdaReturnType = InferredReturnType;
}
else
{
ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)> instance = ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)>.GetInstance();
DiagnosticBag instance2 = DiagnosticBag.GetInstance();
NamedTypeSymbol delegateType = Type.GetDelegateType();
NullableWalker.Analyze(Binder.Compilation, this, (Conversions)conversions, instance2, delegateType?.DelegateInvokeMethod, nullableState, instance);
instance2.Free();
inferredLambdaReturnType = InferReturnType(instance, this, Binder, delegateType, Symbol.IsAsync, conversions);
instance.Free();
}
inferredFromFunctionType = inferredLambdaReturnType.InferredFromFunctionType;
return inferredLambdaReturnType.TypeWithAnnotations;
}
internal LambdaSymbol CreateLambdaSymbol(NamedTypeSymbol delegateType, Symbol containingSymbol)
{
return UnboundLambda.Data.CreateLambdaSymbol(delegateType, containingSymbol);
}
internal LambdaSymbol CreateLambdaSymbol(Symbol containingSymbol, TypeWithAnnotations returnType, ImmutableArray<TypeWithAnnotations> parameterTypes, ImmutableArray<RefKind> parameterRefKinds, RefKind refKind)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
return UnboundLambda.Data.CreateLambdaSymbol(containingSymbol, returnType, parameterTypes, parameterRefKinds.IsDefault ? Enumerable.Repeat<RefKind>((RefKind)0, parameterTypes.Length).ToImmutableArray() : parameterRefKinds, refKind);
}
internal static InferredLambdaReturnType InferReturnType(ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)> returnTypes, BoundLambda node, Binder binder, TypeSymbol? delegateType, bool isAsync, ConversionsBase conversions)
{
return InferReturnTypeImpl(returnTypes, node, binder, delegateType, isAsync, conversions, node.UnboundLambda.WithDependencies);
}
internal static InferredLambdaReturnType InferReturnType(ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)> returnTypes, UnboundLambda node, Binder binder, TypeSymbol? delegateType, bool isAsync, ConversionsBase conversions)
{
return InferReturnTypeImpl(returnTypes, node, binder, delegateType, isAsync, conversions, node.WithDependencies);
}
private static InferredLambdaReturnType InferReturnTypeImpl(ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)> returnTypes, BoundNode node, Binder binder, TypeSymbol? delegateType, bool isAsync, ConversionsBase conversions, bool withDependencies)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
ArrayBuilder<(BoundExpression, TypeWithAnnotations, bool)> instance = ArrayBuilder<(BoundExpression, TypeWithAnnotations, bool)>.GetInstance();
bool hadExpressionlessReturn = false;
RefKind refKind = (RefKind)0;
Enumerator<(BoundReturnStatement, TypeWithAnnotations)> enumerator = returnTypes.GetEnumerator();
while (enumerator.MoveNext())
{
(BoundReturnStatement, TypeWithAnnotations) current = enumerator.Current;
BoundReturnStatement item = current.Item1;
TypeWithAnnotations item2 = current.Item2;
RefKind refKind2 = item.RefKind;
if ((int)refKind2 != 0)
{
refKind = refKind2;
}
if ((object)item2.Type == NoReturnExpression)
{
hadExpressionlessReturn = true;
}
else
{
instance.Add((item.ExpressionOpt, item2, item.Checked));
}
}
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = (withDependencies ? new CompoundUseSiteInfo<AssemblySymbol>(binder.Compilation.Assembly) : CompoundUseSiteInfo<AssemblySymbol>.DiscardedDependencies);
bool inferredFromFunctionType;
TypeWithAnnotations typeWithAnnotations = CalculateReturnType(binder, conversions, delegateType, instance, isAsync, node, ref useSiteInfo, out inferredFromFunctionType);
int count = instance.Count;
instance.Free();
return new InferredLambdaReturnType(count, isExplicitType: false, hadExpressionlessReturn, refKind, typeWithAnnotations, inferredFromFunctionType, ImmutableArrayExtensions.AsImmutableOrEmpty<DiagnosticInfo>((IEnumerable<DiagnosticInfo>)useSiteInfo.Diagnostics), useSiteInfo.AccumulatesDependencies ? ImmutableArrayExtensions.AsImmutableOrEmpty<AssemblySymbol>((IEnumerable<AssemblySymbol>)useSiteInfo.Dependencies) : ImmutableArray<AssemblySymbol>.Empty);
}
private static TypeWithAnnotations CalculateReturnType(Binder binder, ConversionsBase conversions, TypeSymbol? delegateType, ArrayBuilder<(BoundExpression expr, TypeWithAnnotations resultType, bool isChecked)> returns, bool isAsync, BoundNode node, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, out bool inferredFromFunctionType)
{
int count = returns.Count;
TypeWithAnnotations typeWithAnnotations;
switch (count)
{
case 0:
inferredFromFunctionType = false;
typeWithAnnotations = default(TypeWithAnnotations);
break;
case 1:
{
if (conversions.IncludeNullability)
{
inferredFromFunctionType = false;
typeWithAnnotations = returns[0].Item2;
break;
}
TypeSymbol typeSymbol = returns[0].Item1.GetTypeOrFunctionType();
if (typeSymbol is FunctionTypeSymbol functionTypeSymbol)
{
typeSymbol = functionTypeSymbol.GetInternalDelegateType();
inferredFromFunctionType = (object)typeSymbol != null;
}
else
{
inferredFromFunctionType = false;
}
typeWithAnnotations = TypeWithAnnotations.Create(typeSymbol);
break;
}
default:
typeWithAnnotations = ((!conversions.IncludeNullability) ? TypeWithAnnotations.Create(BestTypeInferrer.InferBestType(ArrayBuilderExtensions.SelectAsArray<(BoundExpression, TypeWithAnnotations, bool), BoundExpression>(returns, (Func<(BoundExpression, TypeWithAnnotations, bool), BoundExpression>)(((BoundExpression expr, TypeWithAnnotations resultType, bool isChecked) pair) => pair.expr)), conversions, ref useSiteInfo, out inferredFromFunctionType)) : NullableWalker.BestTypeForLambdaReturns(returns, binder, node, (Conversions)conversions, out inferredFromFunctionType));
break;
}
if (!isAsync)
{
return typeWithAnnotations;
}
NamedTypeSymbol namedTypeSymbol = null;
if (delegateType?.GetDelegateType()?.DelegateInvokeMethod?.ReturnType is NamedTypeSymbol namedTypeSymbol2 && !namedTypeSymbol2.IsVoidType() && namedTypeSymbol2.IsCustomTaskType(out object _))
{
namedTypeSymbol = namedTypeSymbol2.ConstructedFrom;
}
if (count == 0)
{
return TypeWithAnnotations.Create(((object)namedTypeSymbol != null && namedTypeSymbol.Arity == 0) ? namedTypeSymbol : binder.Compilation.GetWellKnownType((WellKnownType)95));
}
if (!typeWithAnnotations.HasType || typeWithAnnotations.IsVoidType())
{
return default(TypeWithAnnotations);
}
return TypeWithAnnotations.Create((((object)namedTypeSymbol != null && namedTypeSymbol.Arity == 1) ? namedTypeSymbol : binder.Compilation.GetWellKnownType((WellKnownType)96)).Construct(ImmutableArray.Create(typeWithAnnotations)));
}
public BoundLambda(SyntaxNode syntax, UnboundLambda unboundLambda, LambdaSymbol symbol, BoundBlock body, ImmutableBindingDiagnostic<AssemblySymbol> diagnostics, Binder binder, TypeSymbol? type, bool hasErrors = false)
: base(BoundKind.Lambda, syntax, type, hasErrors || unboundLambda.HasErrors() || body.HasErrors())
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
UnboundLambda = unboundLambda;
Symbol = symbol;
Body = body;
Diagnostics = diagnostics;
Binder = binder;
}
[DebuggerStepThrough]
public override BoundNode? Accept(BoundTreeVisitor visitor)
{
return visitor.VisitLambda(this);
}
public BoundLambda Update(UnboundLambda unboundLambda, LambdaSymbol symbol, BoundBlock body, ImmutableBindingDiagnostic<AssemblySymbol> diagnostics, Binder binder, TypeSymbol? type)
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
if (unboundLambda != UnboundLambda || !SymbolEqualityComparer.ConsiderEverything.Equals(symbol, Symbol) || body != Body || diagnostics != Diagnostics || binder != Binder || !TypeSymbol.Equals(type, Type, (TypeCompareKind)0))
{
BoundLambda boundLambda = new BoundLambda(Syntax, unboundLambda, symbol, body, diagnostics, binder, type, base.HasErrors);
boundLambda.CopyAttributes(this);
return boundLambda;
}
return this;
}
}