Repository: dotnet/roslyn
File: src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEntryPointSymbol.cs (C#)

Code before:
                var arguments = Parameters.SelectAsArray((p, s) => (BoundExpression)new BoundParameter(s, p, p.Type), _userMainReturnTypeSyntax);

                // Main(args) or Main()
                BoundCall userMainInvocation = new BoundCall(
                        syntax: _userMainReturnTypeSyntax,
                        receiverOpt: null,
                        initialBindingReceiverIsSubjectToCloning: ThreeState.Unknown,
                        method: userMain,
                        arguments: arguments,
                        argumentNamesOpt: default(ImmutableArray<string>),
                        argumentRefKindsOpt: default(ImmutableArray<RefKind>),
                        isDelegateCall: false,
                        expanded: false,
                        invokedAsExtensionMethod: false,
                        argsToParamsOpt: default(ImmutableArray<int>),
                        defaultArguments: default(BitVector),
                        resultKind: LookupResultKind.Viable,
                        type: userMain.ReturnType)
                { WasCompilerGenerated = true };

                // Try to use the new HandleAsyncEntryPoint API if it exists
                var specialMember = userMain.ReturnType.IsGenericTaskType(compilation)
                    ? SpecialMember.System_Runtime_CompilerServices_AsyncHelpers__HandleAsyncEntryPoint_Task_T
                    : SpecialMember.System_Runtime_CompilerServices_AsyncHelpers__HandleAsyncEntryPoint_Task;

                _handleAsyncEntryPointMethod = compilation.GetSpecialTypeMember(specialMember) as MethodSymbol;

                // If the new API is not available, fall back to the old GetAwaiter/GetResult pattern
                if (_handleAsyncEntryPointMethod == null)
                {
                    // The diagnostics that would be produced here will already have been captured and returned.
                    var success = binder.GetAwaitableExpressionInfo(userMainInvocation, out _getAwaiterGetResultCall!, runtimeAsyncAwaitCall: out _, _userMainReturnTypeSyntax, BindingDiagnosticBag.Discarded);
                }

                Debug.Assert(
                    ReturnType.IsVoidType() ||
                    ReturnType.SpecialType == SpecialType.System_Int32);
                Debug.Assert(!compilation.IsRuntimeAsyncEnabledIn(this));
            }

            internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder<CSharpAttributeData> attributes)
            {
                base.AddSynthesizedAttributes(moduleBuilder, ref attributes);

                AddSynthesizedAttribute(ref attributes, this.DeclaringCompilation.SynthesizeDebuggerStepThroughAttribute());
            }

            public override string Name => MainName;

            public override ImmutableArray<ParameterSymbol> Parameters => _parameters;


Review comment (suggestion):
@copilot Use `Binder.TryGetSpecialMember` instead, with `isOptional: true` specified. #Resolved

Code after:
                // Main(args) or Main()
                BoundCall userMainInvocation = new BoundCall(
                        syntax: _userMainReturnTypeSyntax,
                        receiverOpt: null,
                        initialBindingReceiverIsSubjectToCloning: ThreeState.Unknown,
                        method: userMain,
                        arguments: arguments,
                        argumentNamesOpt: default(ImmutableArray<string>),
                        argumentRefKindsOpt: default(ImmutableArray<RefKind>),
                        isDelegateCall: false,
                        expanded: false,
                        invokedAsExtensionMethod: false,
                        argsToParamsOpt: default(ImmutableArray<int>),
                        defaultArguments: default(BitVector),
                        resultKind: LookupResultKind.Viable,
                        type: userMain.ReturnType)
                { WasCompilerGenerated = true };

                // Try to use the new HandleAsyncEntryPoint API if it exists
                var specialMember = userMain.ReturnType.IsGenericTaskType(compilation)
                    ? SpecialMember.System_Runtime_CompilerServices_AsyncHelpers__HandleAsyncEntryPoint_Task_Int32
                    : SpecialMember.System_Runtime_CompilerServices_AsyncHelpers__HandleAsyncEntryPoint_Task;

                if (Binder.TryGetSpecialTypeMember(compilation, specialMember, _userMainReturnTypeSyntax, BindingDiagnosticBag.Discarded, out MethodSymbol handleAsyncEntryPointMethod, isOptional: true)
                    && handleAsyncEntryPointMethod.Parameters[0].Type.Equals(userMain.ReturnType, TypeCompareKind.AllIgnoreOptions))
                {
                    // Use the new HandleAsyncEntryPoint API
                    _userEntryPointInvocation = new BoundCall(
                            syntax: _userMainReturnTypeSyntax,
                            receiverOpt: null,
                            initialBindingReceiverIsSubjectToCloning: ThreeState.Unknown,
                            method: handleAsyncEntryPointMethod,
                            arguments: [userMainInvocation],
                            argumentNamesOpt: default(ImmutableArray<string>),
                            argumentRefKindsOpt: default(ImmutableArray<RefKind>),
                            isDelegateCall: false,
                            expanded: false,
                            invokedAsExtensionMethod: false,
                            argsToParamsOpt: default(ImmutableArray<int>),
                            defaultArguments: default(BitVector),
                            resultKind: LookupResultKind.Viable,
                            type: handleAsyncEntryPointMethod.ReturnType)
                    { WasCompilerGenerated = true };
                }
                else
                {
                    // Fall back to the old GetAwaiter().GetResult() pattern
                    // The diagnostics that would be produced here will already have been captured and returned.
                    var success = binder.GetAwaitableExpressionInfo(userMainInvocation, out _userEntryPointInvocation!, runtimeAsyncAwaitCall: out _, _userMainReturnTypeSyntax, BindingDiagnosticBag.Discarded);
                }