Repository: dotnet/roslyn
File: src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs (C#)

Code before:
            Debug.Assert(TypeSymbol.Equals(analysis.FromType, analysis.Operator.GetParameterType(0), TypeCompareKind.AllIgnoreOptions));
            Debug.Assert(TypeSymbol.Equals(destination.StrippedType(), analysis.Operator.ContainingType, TypeCompareKind.AllIgnoreOptions));
            Debug.Assert(TypeSymbol.Equals(destination.StrippedType(), analysis.ToType, TypeCompareKind.AllIgnoreOptions));
            Debug.Assert(analysis.TargetConversion is { IsIdentity: true } or { IsNullable: true, IsImplicit: true });

            conversion.MarkUnderlyingConversionsChecked();

            // Original expression --> conversion's "from" type
            BoundExpression convertedOperand = CreateConversion(
                syntax: syntax,
                source: source,
                conversion: analysis.SourceConversion,
                isCast: false,
                conversionGroupOpt: conversionGroup,
                InConversionGroupFlags.UnionSourceConversion,
                wasCompilerGenerated: true,
                destination: analysis.FromType,
                diagnostics: diagnostics);

            var unionConversion = new BoundConversion(
                    syntax,
                    convertedOperand,
                    conversion,
                    @checked: CheckOverflowAtRuntime,
                    explicitCastInCode: isCast,
                    conversionGroup,
                    InConversionGroupFlags.UnionConstructor,
                    constantValueOpt: ConstantValue.NotAvailable,
                    type: analysis.ToType)
            { WasCompilerGenerated = true };

            // Conversion's "to" type --> final type
            BoundExpression finalConversion = CreateConversion(
                syntax: syntax,
                source: unionConversion,
                conversion: analysis.TargetConversion,
                isCast: false,
                conversionGroupOpt: conversionGroup,
                InConversionGroupFlags.UnionFinal,
                wasCompilerGenerated: true, // NOTE: doesn't necessarily set flag on resulting bound expression.
                destination: destination,
                diagnostics: diagnostics);

            conversion.AssertUnderlyingConversionsCheckedRecursive();

            finalConversion.ResetCompilerGenerated(source.WasCompilerGenerated);

            return finalConversion;
        }

        private BoundExpression CreateFunctionTypeConversion(

Review comment (suggestion):
Required members? `CompilerFeatureRequired` on the constructor? Definitely seems like binding object creation would be the sensible way to handle this.

Code after:
            Debug.Assert(TypeSymbol.Equals(analysis.FromType, analysis.Operator.GetParameterType(0), TypeCompareKind.AllIgnoreOptions));
            Debug.Assert(TypeSymbol.Equals(destination.StrippedType(), analysis.Operator.ContainingType, TypeCompareKind.AllIgnoreOptions));
            Debug.Assert(TypeSymbol.Equals(destination.StrippedType(), analysis.ToType, TypeCompareKind.AllIgnoreOptions));
            Debug.Assert(analysis.TargetConversion is { IsIdentity: true } or { IsNullable: true, IsImplicit: true });

            conversion.MarkUnderlyingConversionsChecked();

            // Original expression --> conversion's "from" type
            BoundExpression convertedOperand = CreateConversion(
                syntax: syntax,
                source: source,
                conversion: analysis.SourceConversion,
                isCast: false,
                conversionGroupOpt: conversionGroup,
                InConversionGroupFlags.UnionSourceConversion,
                wasCompilerGenerated: true,
                destination: analysis.FromType,
                diagnostics: diagnostics);

            if (analysis.Operator.ContainingType.IsAbstract)
            {
                // Report error for new of abstract type.
                diagnostics.Add(ErrorCode.ERR_NoNewAbstract, syntax.Location, analysis.Operator.ContainingType);
            }

            // PROTOTYPE: Any other validations to perform? Perhaps we should simply bind object creation, drop the node, but keep diagnostics.

            var unionConversion = new BoundConversion(
                    syntax,
                    convertedOperand,
                    conversion,
                    @checked: CheckOverflowAtRuntime,
                    explicitCastInCode: isCast,
                    conversionGroup,
                    InConversionGroupFlags.UnionConstructor,
                    constantValueOpt: ConstantValue.NotAvailable,
                    type: analysis.ToType)
            { WasCompilerGenerated = true };

            // Conversion's "to" type --> final type
            BoundExpression finalConversion = CreateConversion(
                syntax: syntax,
                source: unionConversion,
                conversion: analysis.TargetConversion,
                isCast: false,
                conversionGroupOpt: conversionGroup,
                InConversionGroupFlags.UnionFinal,
                wasCompilerGenerated: true, // NOTE: doesn't necessarily set flag on resulting bound expression.
                destination: destination,
                diagnostics: diagnostics);