diff --git a/docs/contributing/Compiler Test Plan.md b/docs/contributing/Compiler Test Plan.md index f07aed318d2c4..099cbe4798941 100644 --- a/docs/contributing/Compiler Test Plan.md +++ b/docs/contributing/Compiler Test Plan.md @@ -209,6 +209,7 @@ a[e] x++ x-- new X() +new() typeof(T) default(T) default diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 5605f63f329a2..e10725077c95a 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -130,6 +130,11 @@ protected BoundExpression CreateConversion( } } + if (conversion.IsObjectCreation) + { + return ConvertObjectCreationExpression(syntax, (BoundUnconvertedObjectCreationExpression)source, isCast, destination, diagnostics); + } + if (conversion.IsUserDefined) { // User-defined conversions are likely to be represented as multiple @@ -157,6 +162,67 @@ protected BoundExpression CreateConversion( { WasCompilerGenerated = wasCompilerGenerated }; } + private BoundExpression ConvertObjectCreationExpression(SyntaxNode syntax, BoundUnconvertedObjectCreationExpression node, bool isCast, TypeSymbol destination, DiagnosticBag diagnostics) + { + var arguments = AnalyzedArguments.GetInstance(node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt); + BoundExpression expr = BindObjectCreationExpression(node, destination.StrippedType(), arguments, diagnostics); + if (destination.IsNullableType()) + { + // We manually create an ImplicitNullable conversion + // if the destination is nullable, in which case we + // target the underlying type e.g. `S? x = new();` + // is actually identical to `S? x = new S();`. + HashSet? useSiteDiagnostics = null; + var conversion = Conversions.ClassifyStandardConversion(null, expr.Type, destination, ref useSiteDiagnostics); + expr = new BoundConversion( + node.Syntax, + operand: expr, + conversion: conversion, + @checked: false, + explicitCastInCode: isCast, + conversionGroupOpt: new ConversionGroup(conversion), + constantValueOpt: expr.ConstantValue, + type: destination); + + diagnostics.Add(syntax, useSiteDiagnostics); + } + arguments.Free(); + return expr; + } + + private BoundExpression BindObjectCreationExpression(BoundUnconvertedObjectCreationExpression node, TypeSymbol type, AnalyzedArguments arguments, DiagnosticBag diagnostics) + { + var syntax = node.Syntax; + switch (type.TypeKind) + { + case TypeKind.Struct: + case TypeKind.Class when !type.IsAnonymousType: // We don't want to enable object creation with unspeakable types + return BindClassCreationExpression(syntax, type.Name, typeNode: syntax, (NamedTypeSymbol)type, arguments, diagnostics, node.InitializerOpt, wasTargetTyped: true); + case TypeKind.TypeParameter: + return BindTypeParameterCreationExpression(syntax, (TypeParameterSymbol)type, arguments, node.InitializerOpt, typeSyntax: syntax, diagnostics); + case TypeKind.Delegate: + return BindDelegateCreationExpression(syntax, (NamedTypeSymbol)type, arguments, node.InitializerOpt, diagnostics); + case TypeKind.Array: + case TypeKind.Enum: + case TypeKind.Class: + Error(diagnostics, ErrorCode.ERR_TypelessNewIllegalTargetType, syntax, type); + goto case TypeKind.Error; + case TypeKind.Interface: + Error(diagnostics, ErrorCode.ERR_NoNewAbstract, syntax, type); + goto case TypeKind.Error; + case TypeKind.Pointer: + Error(diagnostics, ErrorCode.ERR_UnsafeTypeInObjectCreation, syntax, type); + goto case TypeKind.Error; + case TypeKind.Dynamic: + Error(diagnostics, ErrorCode.ERR_NoConstructors, syntax, type); + goto case TypeKind.Error; + case TypeKind.Error: + return MakeBadExpressionForObjectCreation(syntax, type, arguments, node.InitializerOpt, typeSyntax: syntax, diagnostics); + case var v: + throw ExceptionUtilities.UnexpectedValue(v); + } + } + /// /// Rewrite the expressions in the switch expression arms to add a conversion to the destination type. /// diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 376ffadc11f05..e12a0c3090c5c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -231,9 +231,9 @@ internal BoundExpression BindValue(ExpressionSyntax node, DiagnosticBag diagnost return CheckValue(result, valueKind, diagnostics); } - internal BoundExpression BindRValueWithoutTargetType(ExpressionSyntax node, DiagnosticBag diagnostics, bool reportDefaultMissingType = true) + internal BoundExpression BindRValueWithoutTargetType(ExpressionSyntax node, DiagnosticBag diagnostics, bool reportNoTargetType = true) { - return BindToNaturalType(BindValue(node, diagnostics, BindValueKind.RValue), diagnostics, reportDefaultMissingType); + return BindToNaturalType(BindValue(node, diagnostics, BindValueKind.RValue), diagnostics, reportNoTargetType); } internal BoundExpression BindToTypeForErrorRecovery(BoundExpression expression, TypeSymbol type = null) @@ -243,7 +243,7 @@ internal BoundExpression BindToTypeForErrorRecovery(BoundExpression expression, var discardedDiagnostics = DiagnosticBag.GetInstance(); var result = !expression.NeedsToBeConverted() ? expression : - type is null ? BindToNaturalType(expression, discardedDiagnostics, reportDefaultMissingType: false) : + type is null ? BindToNaturalType(expression, discardedDiagnostics, reportNoTargetType: false) : GenerateConversionForAssignment(type, expression, discardedDiagnostics); discardedDiagnostics.Free(); return result; @@ -256,7 +256,7 @@ internal BoundExpression BindToTypeForErrorRecovery(BoundExpression expression, /// that such a conversion occurs when needed. It also handles tuple expressions which need to be /// converted to their own natural type because they may contain switch expressions. /// - internal BoundExpression BindToNaturalType(BoundExpression expression, DiagnosticBag diagnostics, bool reportDefaultMissingType = true) + internal BoundExpression BindToNaturalType(BoundExpression expression, DiagnosticBag diagnostics, bool reportNoTargetType = true) { BoundExpression result; switch (expression) @@ -280,7 +280,7 @@ internal BoundExpression BindToNaturalType(BoundExpression expression, Diagnosti var boundArgs = ArrayBuilder.GetInstance(sourceTuple.Arguments.Length); foreach (var arg in sourceTuple.Arguments) { - boundArgs.Add(BindToNaturalType(arg, diagnostics, reportDefaultMissingType)); + boundArgs.Add(BindToNaturalType(arg, diagnostics, reportNoTargetType)); } result = new BoundConvertedTupleLiteral( sourceTuple.Syntax, @@ -295,7 +295,7 @@ internal BoundExpression BindToNaturalType(BoundExpression expression, Diagnosti break; case BoundDefaultLiteral defaultExpr: { - if (reportDefaultMissingType) + if (reportNoTargetType) { // In some cases, we let the caller report the error diagnostics.Add(ErrorCode.ERR_DefaultLiteralNoTargetType, defaultExpr.Syntax.GetLocation()); @@ -315,6 +315,16 @@ internal BoundExpression BindToNaturalType(BoundExpression expression, Diagnosti var type = new PointerTypeSymbol(TypeWithAnnotations.Create(boundStackAlloc.ElementType)); result = GenerateConversionForAssignment(type, boundStackAlloc, diagnostics); break; + case BoundUnconvertedObjectCreationExpression expr: + { + if (reportNoTargetType) + { + diagnostics.Add(ErrorCode.ERR_TypelessNewNoTargetType, expr.Syntax.GetLocation(), expr.Display); + } + + result = BindObjectCreationForErrorRecovery(expr, diagnostics); + } + break; default: result = expression; break; @@ -488,6 +498,8 @@ private BoundExpression BindExpressionInternal(ExpressionSyntax node, Diagnostic return BindImplicitStackAllocArrayCreationExpression((ImplicitStackAllocArrayCreationExpressionSyntax)node, diagnostics); case SyntaxKind.ObjectCreationExpression: return BindObjectCreationExpression((ObjectCreationExpressionSyntax)node, diagnostics); + case SyntaxKind.ImplicitObjectCreationExpression: + return BindImplicitObjectCreationExpression((ImplicitObjectCreationExpressionSyntax)node, diagnostics); case SyntaxKind.IdentifierName: case SyntaxKind.GenericName: return BindIdentifier((SimpleNameSyntax)node, invoked, indexed, diagnostics); @@ -3948,6 +3960,20 @@ private BoundExpression BindConstructorInitializerCore( } } + private BoundExpression BindImplicitObjectCreationExpression(ImplicitObjectCreationExpressionSyntax node, DiagnosticBag diagnostics) + { + var arguments = AnalyzedArguments.GetInstance(); + BindArgumentsAndNames(node.ArgumentList, diagnostics, arguments, allowArglist: true); + var result = new BoundUnconvertedObjectCreationExpression( + node, + arguments.Arguments.ToImmutable(), + arguments.Names.ToImmutableOrNull(), + arguments.RefKinds.ToImmutableOrNull(), + node.Initializer); + arguments.Free(); + return result; + } + protected BoundExpression BindObjectCreationExpression(ObjectCreationExpressionSyntax node, DiagnosticBag diagnostics) { var typeWithAnnotations = BindType(node.Type, diagnostics); @@ -4000,176 +4026,172 @@ protected BoundExpression BindObjectCreationExpression(ObjectCreationExpressionS private BoundExpression BindDelegateCreationExpression(ObjectCreationExpressionSyntax node, NamedTypeSymbol type, DiagnosticBag diagnostics) { - // Get the bound arguments and the argument names. AnalyzedArguments analyzedArguments = AnalyzedArguments.GetInstance(); + BindArgumentsAndNames(node.ArgumentList, diagnostics, analyzedArguments, isDelegateCreation: true); + var result = BindDelegateCreationExpression(node, type, analyzedArguments, node.Initializer, diagnostics); + analyzedArguments.Free(); + return result; + } - try + private BoundExpression BindDelegateCreationExpression(SyntaxNode node, NamedTypeSymbol type, AnalyzedArguments analyzedArguments, InitializerExpressionSyntax initializerOpt, DiagnosticBag diagnostics) + { + bool hasErrors = false; + if (analyzedArguments.HasErrors) { - BindArgumentsAndNames(node.ArgumentList, diagnostics, analyzedArguments, isDelegateCreation: true); + // Let's skip this part of further error checking without marking hasErrors = true here, + // as the argument could be an unbound lambda, and the error could come from inside. + // We'll check analyzedArguments.HasErrors again after we find if this is not the case. + } + else if (analyzedArguments.Arguments.Count == 0) + { + diagnostics.Add(ErrorCode.ERR_BadCtorArgCount, node.Location, type, 0); + hasErrors = true; + } + else if (analyzedArguments.Names.Count != 0 || analyzedArguments.RefKinds.Count != 0 || analyzedArguments.Arguments.Count != 1) + { + // Use a smaller span that excludes the parens. + var argSyntax = analyzedArguments.Arguments[0].Syntax; + var start = argSyntax.SpanStart; + var end = analyzedArguments.Arguments[analyzedArguments.Arguments.Count - 1].Syntax.Span.End; + var errorSpan = new TextSpan(start, end - start); - bool hasErrors = false; - if (analyzedArguments.HasErrors) - { - // Let's skip this part of further error checking without marking hasErrors = true here, - // as the argument could be an unbound lambda, and the error could come from inside. - // We'll check analyzedArguments.HasErrors again after we find if this is not the case. - } - else if (node.ArgumentList == null || analyzedArguments.Arguments.Count == 0) - { - diagnostics.Add(ErrorCode.ERR_BadCtorArgCount, node.Location, type, 0); - hasErrors = true; - } - else if (analyzedArguments.Names.Count != 0 || analyzedArguments.RefKinds.Count != 0 || analyzedArguments.Arguments.Count != 1) - { - // Use a smaller span that excludes the parens. - var argSyntax = analyzedArguments.Arguments[0].Syntax; - var start = argSyntax.SpanStart; - var end = analyzedArguments.Arguments[analyzedArguments.Arguments.Count - 1].Syntax.Span.End; - var errorSpan = new TextSpan(start, end - start); + var loc = new SourceLocation(argSyntax.SyntaxTree, errorSpan); - var loc = new SourceLocation(argSyntax.SyntaxTree, errorSpan); + diagnostics.Add(ErrorCode.ERR_MethodNameExpected, loc); + hasErrors = true; + } - diagnostics.Add(ErrorCode.ERR_MethodNameExpected, loc); - hasErrors = true; - } + if (initializerOpt != null) + { + Error(diagnostics, ErrorCode.ERR_ObjectOrCollectionInitializerWithDelegateCreation, node); + hasErrors = true; + } - if (node.Initializer != null) - { - Error(diagnostics, ErrorCode.ERR_ObjectOrCollectionInitializerWithDelegateCreation, node); - hasErrors = true; - } + BoundExpression argument = BindToNaturalType(analyzedArguments.Arguments.Count >= 1 ? analyzedArguments.Arguments[0] : null, diagnostics); - BoundExpression argument = BindToNaturalType(analyzedArguments.Arguments.Count >= 1 ? analyzedArguments.Arguments[0] : null, diagnostics); + if (hasErrors) + { + // skip the rest of this binding + } - if (hasErrors) + // There are four cases for a delegate creation expression (7.6.10.5): + // 1. An anonymous function is treated as a conversion from the anonymous function to the delegate type. + else if (argument is UnboundLambda unboundLambda) + { + // analyzedArguments.HasErrors could be true, + // but here the argument is an unbound lambda, the error comes from inside + // eg: new Action(x => x.) + // We should try to bind it anyway in order for intellisense to work. + + HashSet useSiteDiagnostics = null; + var conversion = this.Conversions.ClassifyConversionFromExpression(unboundLambda, type, ref useSiteDiagnostics); + diagnostics.Add(node, useSiteDiagnostics); + // Attempting to make the conversion caches the diagnostics and the bound state inside + // the unbound lambda. Fetch the result from the cache. + BoundLambda boundLambda = unboundLambda.Bind(type); + + if (!conversion.IsImplicit || !conversion.IsValid) { - // skip the rest of this binding + GenerateImplicitConversionError(diagnostics, unboundLambda.Syntax, conversion, unboundLambda, type); } - - // There are four cases for a delegate creation expression (7.6.10.5): - // 1. An anonymous function is treated as a conversion from the anonymous function to the delegate type. - else if (argument is UnboundLambda) + else { - // analyzedArguments.HasErrors could be true, - // but here the argument is an unbound lambda, the error comes from inside - // eg: new Action(x => x.) - // We should try to bind it anyway in order for intellisense to work. - - UnboundLambda unboundLambda = (UnboundLambda)argument; - HashSet useSiteDiagnostics = null; - var conversion = this.Conversions.ClassifyConversionFromExpression(unboundLambda, type, ref useSiteDiagnostics); - diagnostics.Add(node, useSiteDiagnostics); - // Attempting to make the conversion caches the diagnostics and the bound state inside - // the unbound lambda. Fetch the result from the cache. - BoundLambda boundLambda = unboundLambda.Bind(type); + // We're not going to produce an error, but it is possible that the conversion from + // the lambda to the delegate type produced a warning, which we have not reported. + // Instead, we've cached it in the bound lambda. Report it now. + diagnostics.AddRange(boundLambda.Diagnostics); + } - if (!conversion.IsImplicit || !conversion.IsValid) - { - GenerateImplicitConversionError(diagnostics, unboundLambda.Syntax, conversion, unboundLambda, type); - } - else - { - // We're not going to produce an error, but it is possible that the conversion from - // the lambda to the delegate type produced a warning, which we have not reported. - // Instead, we've cached it in the bound lambda. Report it now. - diagnostics.AddRange(boundLambda.Diagnostics); - } + // Just stuff the bound lambda into the delegate creation expression. When we lower the lambda to + // its method form we will rewrite this expression to refer to the method. - // Just stuff the bound lambda into the delegate creation expression. When we lower the lambda to - // its method form we will rewrite this expression to refer to the method. + return new BoundDelegateCreationExpression(node, boundLambda, methodOpt: null, isExtensionMethod: false, type: type, hasErrors: !conversion.IsImplicit); + } - return new BoundDelegateCreationExpression(node, boundLambda, methodOpt: null, isExtensionMethod: false, type: type, hasErrors: !conversion.IsImplicit); - } + else if (analyzedArguments.HasErrors) + { + // There is no hope, skip. + } - else if (analyzedArguments.HasErrors) - { - // There is no hope, skip. - } + // 2. A method group + else if (argument.Kind == BoundKind.MethodGroup) + { + Conversion conversion; + BoundMethodGroup methodGroup = (BoundMethodGroup)argument; + hasErrors = MethodGroupConversionDoesNotExistOrHasErrors(methodGroup, type, node.Location, diagnostics, out conversion); + methodGroup = FixMethodGroupWithTypeOrValue(methodGroup, conversion, diagnostics); + return new BoundDelegateCreationExpression(node, methodGroup, conversion.Method, conversion.IsExtensionMethod, type, hasErrors); + } - // 2. A method group - else if (argument.Kind == BoundKind.MethodGroup) - { - Conversion conversion; - BoundMethodGroup methodGroup = (BoundMethodGroup)argument; - hasErrors = MethodGroupConversionDoesNotExistOrHasErrors(methodGroup, type, node.Location, diagnostics, out conversion); - methodGroup = FixMethodGroupWithTypeOrValue(methodGroup, conversion, diagnostics); - return new BoundDelegateCreationExpression(node, methodGroup, conversion.Method, conversion.IsExtensionMethod, type, hasErrors); - } + else if ((object)argument.Type == null) + { + diagnostics.Add(ErrorCode.ERR_MethodNameExpected, argument.Syntax.Location); + } - else if ((object)argument.Type == null) - { - diagnostics.Add(ErrorCode.ERR_MethodNameExpected, argument.Syntax.Location); - } + // 3. A value of the compile-time type dynamic (which is dynamically case 4), or + else if (argument.HasDynamicType()) + { + return new BoundDelegateCreationExpression(node, argument, methodOpt: null, isExtensionMethod: false, type: type); + } - // 3. A value of the compile-time type dynamic (which is dynamically case 4), or - else if (argument.HasDynamicType()) + // 4. A delegate type. + else if (argument.Type.TypeKind == TypeKind.Delegate) + { + var sourceDelegate = (NamedTypeSymbol)argument.Type; + MethodGroup methodGroup = MethodGroup.GetInstance(); + try { - return new BoundDelegateCreationExpression(node, argument, methodOpt: null, isExtensionMethod: false, type: type); - } + if (ReportDelegateInvokeUseSiteDiagnostic(diagnostics, argument.Type, node: node)) + { + // We want failed "new" expression to use the constructors as their symbols. + return new BoundBadExpression(node, LookupResultKind.NotInvocable, StaticCast.From(type.InstanceConstructors), ImmutableArray.Create(argument), type); + } - // 4. A delegate type. - else if (argument.Type.TypeKind == TypeKind.Delegate) - { - var sourceDelegate = (NamedTypeSymbol)argument.Type; - MethodGroup methodGroup = MethodGroup.GetInstance(); - try + methodGroup.PopulateWithSingleMethod(argument, sourceDelegate.DelegateInvokeMethod); + HashSet useSiteDiagnostics = null; + Conversion conv = Conversions.MethodGroupConversion(argument.Syntax, methodGroup, type, ref useSiteDiagnostics); + diagnostics.Add(node, useSiteDiagnostics); + if (!conv.Exists) { - if (ReportDelegateInvokeUseSiteDiagnostic(diagnostics, argument.Type, node: node)) + var boundMethodGroup = new BoundMethodGroup( + argument.Syntax, default, WellKnownMemberNames.DelegateInvokeName, ImmutableArray.Create(sourceDelegate.DelegateInvokeMethod), + sourceDelegate.DelegateInvokeMethod, null, BoundMethodGroupFlags.None, argument, LookupResultKind.Viable); + if (!Conversions.ReportDelegateMethodGroupDiagnostics(this, boundMethodGroup, type, diagnostics)) { - // We want failed "new" expression to use the constructors as their symbols. - return new BoundBadExpression(node, LookupResultKind.NotInvocable, StaticCast.From(type.InstanceConstructors), ImmutableArray.Create(argument), type); + // If we could not produce a more specialized diagnostic, we report + // No overload for '{0}' matches delegate '{1}' + diagnostics.Add(ErrorCode.ERR_MethDelegateMismatch, node.Location, + sourceDelegate.DelegateInvokeMethod, + type); } + } + else + { + Debug.Assert(!conv.IsExtensionMethod); + Debug.Assert(conv.IsValid); // i.e. if it exists, then it is valid. - methodGroup.PopulateWithSingleMethod(argument, sourceDelegate.DelegateInvokeMethod); - HashSet useSiteDiagnostics = null; - Conversion conv = Conversions.MethodGroupConversion(argument.Syntax, methodGroup, type, ref useSiteDiagnostics); - diagnostics.Add(node, useSiteDiagnostics); - if (!conv.Exists) + if (!this.MethodGroupConversionHasErrors(argument.Syntax, conv, argument, conv.IsExtensionMethod, type, diagnostics)) { - var boundMethodGroup = new BoundMethodGroup( - argument.Syntax, default, WellKnownMemberNames.DelegateInvokeName, ImmutableArray.Create(sourceDelegate.DelegateInvokeMethod), - sourceDelegate.DelegateInvokeMethod, null, BoundMethodGroupFlags.None, argument, LookupResultKind.Viable); - if (!Conversions.ReportDelegateMethodGroupDiagnostics(this, boundMethodGroup, type, diagnostics)) - { - // If we could not produce a more specialized diagnostic, we report - // No overload for '{0}' matches delegate '{1}' - diagnostics.Add(ErrorCode.ERR_MethDelegateMismatch, node.Location, - sourceDelegate.DelegateInvokeMethod, - type); - } + // we do not place the "Invoke" method in the node, indicating that it did not appear in source. + return new BoundDelegateCreationExpression(node, argument, methodOpt: null, isExtensionMethod: false, type: type); } - else - { - Debug.Assert(!conv.IsExtensionMethod); - Debug.Assert(conv.IsValid); // i.e. if it exists, then it is valid. - - if (!this.MethodGroupConversionHasErrors(argument.Syntax, conv, argument, conv.IsExtensionMethod, type, diagnostics)) - { - // we do not place the "Invoke" method in the node, indicating that it did not appear in source. - return new BoundDelegateCreationExpression(node, argument, methodOpt: null, isExtensionMethod: false, type: type); - } - } - } - finally - { - methodGroup.Free(); } } - - // Not a valid delegate creation expression - else + finally { - diagnostics.Add(ErrorCode.ERR_MethodNameExpected, argument.Syntax.Location); + methodGroup.Free(); } - - // Note that we want failed "new" expression to use the constructors as their symbols. - var childNodes = BuildArgumentsForErrorRecovery(analyzedArguments); - return new BoundBadExpression(node, LookupResultKind.OverloadResolutionFailure, StaticCast.From(type.InstanceConstructors), childNodes, type); } - finally + + // Not a valid delegate creation expression + else { - analyzedArguments.Free(); + diagnostics.Add(ErrorCode.ERR_MethodNameExpected, argument.Syntax.Location); } + + // Note that we want failed "new" expression to use the constructors as their symbols. + var childNodes = BuildArgumentsForErrorRecovery(analyzedArguments); + return new BoundBadExpression(node, LookupResultKind.OverloadResolutionFailure, StaticCast.From(type.InstanceConstructors), childNodes, type); } private BoundExpression BindClassCreationExpression(ObjectCreationExpressionSyntax node, NamedTypeSymbol type, string typeName, DiagnosticBag diagnostics, TypeSymbol initializerType = null) @@ -4202,15 +4224,28 @@ private BoundExpression BindClassCreationExpression(ObjectCreationExpressionSynt } } + internal BoundExpression BindObjectCreationForErrorRecovery(BoundUnconvertedObjectCreationExpression node, DiagnosticBag diagnostics) + { + var arguments = AnalyzedArguments.GetInstance(node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt); + var result = MakeBadExpressionForObjectCreation(node.Syntax, CreateErrorType(), arguments, node.InitializerOpt, typeSyntax: node.Syntax, diagnostics); + arguments.Free(); + return result; + } + private BoundExpression MakeBadExpressionForObjectCreation(ObjectCreationExpressionSyntax node, TypeSymbol type, AnalyzedArguments analyzedArguments, DiagnosticBag diagnostics) + { + return MakeBadExpressionForObjectCreation(node, type, analyzedArguments, node.Initializer, node.Type, diagnostics); + } + + private BoundExpression MakeBadExpressionForObjectCreation(SyntaxNode node, TypeSymbol type, AnalyzedArguments analyzedArguments, InitializerExpressionSyntax initializerOpt, SyntaxNode typeSyntax, DiagnosticBag diagnostics) { var children = ArrayBuilder.GetInstance(); children.AddRange(BuildArgumentsForErrorRecovery(analyzedArguments)); - if (node.Initializer != null) + if (initializerOpt != null) { - var boundInitializer = BindInitializerExpression(syntax: node.Initializer, + var boundInitializer = BindInitializerExpression(syntax: initializerOpt, type: type, - typeSyntax: node.Type, + typeSyntax: typeSyntax, diagnostics: diagnostics); children.Add(boundInitializer); } @@ -4947,14 +4982,15 @@ private bool IsConstructorAccessible(MethodSymbol constructor, ref HashSet 0; - - try + private BoundExpression BindTypeParameterCreationExpression(SyntaxNode node, TypeParameterSymbol typeParameter, AnalyzedArguments analyzedArguments, InitializerExpressionSyntax initializerOpt, SyntaxNode typeSyntax, DiagnosticBag diagnostics) + { + if (!typeParameter.HasConstructorConstraint && !typeParameter.IsValueType) { - if (!typeParameter.HasConstructorConstraint && !typeParameter.IsValueType) - { - diagnostics.Add(ErrorCode.ERR_NoNewTyvar, node.Location, typeParameter); - } - else if (hasArguments) - { - diagnostics.Add(ErrorCode.ERR_NewTyvarWithArgs, node.Location, typeParameter); - } - else - { - var boundInitializerOpt = node.Initializer == null ? - null : - BindInitializerExpression( - syntax: node.Initializer, - type: typeParameter, - typeSyntax: node.Type, - diagnostics: diagnostics); - return new BoundNewT(node, boundInitializerOpt, typeParameter); - } - - return MakeBadExpressionForObjectCreation(node, typeParameter, analyzedArguments, diagnostics); + diagnostics.Add(ErrorCode.ERR_NoNewTyvar, node.Location, typeParameter); } - finally + else if (analyzedArguments.Arguments.Count > 0) { - analyzedArguments.Free(); + diagnostics.Add(ErrorCode.ERR_NewTyvarWithArgs, node.Location, typeParameter); + } + else + { + var boundInitializerOpt = initializerOpt == null ? + null : + BindInitializerExpression( + syntax: initializerOpt, + type: typeParameter, + typeSyntax: typeSyntax, + diagnostics: diagnostics); + return new BoundNewT(node, boundInitializerOpt, typeParameter); } + + return MakeBadExpressionForObjectCreation(node, typeParameter, analyzedArguments, initializerOpt, typeSyntax, diagnostics); } /// @@ -5787,7 +5821,7 @@ private BoundExpression BindMemberAccessWithBoundLeft( // No member accesses on default if (boundLeft.IsLiteralDefault()) { - DiagnosticInfo diagnosticInfo = new CSDiagnosticInfo(ErrorCode.ERR_BadUnaryOp, SyntaxFacts.GetText(operatorToken.Kind()), "default"); + DiagnosticInfo diagnosticInfo = new CSDiagnosticInfo(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, SyntaxFacts.GetText(operatorToken.Kind()), boundLeft.Display); diagnostics.Add(new CSDiagnostic(diagnosticInfo, operatorToken.GetLocation())); return BadExpression(node, boundLeft); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index 8c1fe47eb58b1..3b71843b5e592 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -958,6 +958,7 @@ private BoundCall BindInvocationExpressionContinued( var boundWithErrors = unboundLambda.BindForErrorRecovery(); diagnostics.AddRange(boundWithErrors.Diagnostics); break; + case BoundUnconvertedObjectCreationExpression _: case BoundTupleLiteral _: // Tuple literals can contain unbound lambdas or switch expressions. _ = BindToNaturalType(argument, diagnostics); @@ -1550,6 +1551,7 @@ private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax no } } + boundArgument = BindToNaturalType(boundArgument, diagnostics, reportNoTargetType: false); return new BoundNameOfOperator(node, boundArgument, ConstantValue.Create(name), Compilation.GetSpecialType(SpecialType.System_String)); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs index 38175d09885e6..f3c62193c5971 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs @@ -589,8 +589,8 @@ private BoundExpression BindSimpleBinaryOperator(BinaryExpressionSyntax node, Di { // If we found an operator, we'll have given the `default` literal a type. // Otherwise, we'll have reported the problem in ReportBinaryOperatorError. - resultLeft = BindToNaturalType(resultLeft, diagnostics, reportDefaultMissingType: false); - resultRight = BindToNaturalType(resultRight, diagnostics, reportDefaultMissingType: false); + resultLeft = BindToNaturalType(resultLeft, diagnostics, reportNoTargetType: false); + resultRight = BindToNaturalType(resultRight, diagnostics, reportNoTargetType: false); } hasErrors = hasErrors || resultConstant != null && resultConstant.IsBad; @@ -655,8 +655,8 @@ private bool BindSimpleBinaryOperatorParts(BinaryExpressionSyntax node, Diagnost { resultSignature = signature; HashSet useSiteDiagnostics = null; - bool leftDefault = left.IsLiteralDefault(); - bool rightDefault = right.IsLiteralDefault(); + bool leftDefault = left.IsLiteralDefaultOrTypelessNew(); + bool rightDefault = right.IsLiteralDefaultOrTypelessNew(); foundOperator = !isObjectEquality || BuiltInOperators.IsValidObjectEquality(Conversions, leftType, leftNull, leftDefault, rightType, rightNull, rightDefault, ref useSiteDiagnostics); diagnostics.Add(node, useSiteDiagnostics); } @@ -701,30 +701,32 @@ private static void ReportBinaryOperatorError(ExpressionSyntax node, DiagnosticB { bool leftDefault = left.IsLiteralDefault(); bool rightDefault = right.IsLiteralDefault(); - if ((operatorToken.Kind() == SyntaxKind.EqualsEqualsToken || operatorToken.Kind() == SyntaxKind.ExclamationEqualsToken)) + if (operatorToken.Kind() != SyntaxKind.EqualsEqualsToken && operatorToken.Kind() != SyntaxKind.ExclamationEqualsToken) { - if (leftDefault && rightDefault) + if (leftDefault || rightDefault) { - Error(diagnostics, ErrorCode.ERR_AmbigBinaryOpsOnDefault, node, operatorToken.Text); - return; - } - else if (leftDefault && right.Type is TypeParameterSymbol) - { - Debug.Assert(!right.Type.IsReferenceType); - Error(diagnostics, ErrorCode.ERR_AmbigBinaryOpsOnUnconstrainedDefault, node, operatorToken.Text, right.Type); - return; - } - else if (rightDefault && left.Type is TypeParameterSymbol) - { - Debug.Assert(!left.Type.IsReferenceType); - Error(diagnostics, ErrorCode.ERR_AmbigBinaryOpsOnUnconstrainedDefault, node, operatorToken.Text, left.Type); + // other than == and !=, binary operators are disallowed on `default` literal + Error(diagnostics, ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, node, operatorToken.Text, "default"); return; } } - else if (leftDefault || rightDefault) + + if ((leftDefault || left.IsTypelessNew()) && + (rightDefault || right.IsTypelessNew())) + { + Error(diagnostics, ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, node, operatorToken.Text, left.Display, right.Display); + return; + } + else if (leftDefault && right.Type is TypeParameterSymbol) { - // other than == and !=, binary operators are disallowed on `default` literal - Error(diagnostics, ErrorCode.ERR_BadOpOnNullOrDefault, node, operatorToken.Text, "default"); + Debug.Assert(!right.Type.IsReferenceType); + Error(diagnostics, ErrorCode.ERR_AmbigBinaryOpsOnUnconstrainedDefault, node, operatorToken.Text, right.Type); + return; + } + else if (rightDefault && left.Type is TypeParameterSymbol) + { + Debug.Assert(!left.Type.IsReferenceType); + Error(diagnostics, ErrorCode.ERR_AmbigBinaryOpsOnUnconstrainedDefault, node, operatorToken.Text, left.Type); return; } @@ -1127,7 +1129,7 @@ private TypeSymbol GetBinaryOperatorErrorType(BinaryOperatorKind kind, Diagnosti private BinaryOperatorAnalysisResult BinaryOperatorOverloadResolution(BinaryOperatorKind kind, BoundExpression left, BoundExpression right, CSharpSyntaxNode node, DiagnosticBag diagnostics, out LookupResultKind resultKind, out ImmutableArray originalUserDefinedOperators) { - if (!IsDefaultLiteralAllowedInBinaryOperator(kind, left, right)) + if (!IsTypelessExpressionAllowedInBinaryOperator(kind, left, right)) { resultKind = LookupResultKind.OverloadResolutionFailure; originalUserDefinedOperators = default(ImmutableArray); @@ -1196,8 +1198,21 @@ private void ReportObsoleteAndFeatureAvailabilityDiagnostics(MethodSymbol operat } } - private bool IsDefaultLiteralAllowedInBinaryOperator(BinaryOperatorKind kind, BoundExpression left, BoundExpression right) + private bool IsTypelessExpressionAllowedInBinaryOperator(BinaryOperatorKind kind, BoundExpression left, BoundExpression right) { + // The default literal is only allowed with equality operators and both operands cannot be typeless at the same time. + // Note: we only need to restrict expressions that can be converted to *any* type, in which case the resolution could always succeed. + + if (left.IsTypelessNew()) + { + return !right.IsLiteralDefaultOrTypelessNew(); + } + + if (right.IsTypelessNew()) + { + return !left.IsLiteralDefault(); + } + bool isEquality = kind == BinaryOperatorKind.Equal || kind == BinaryOperatorKind.NotEqual; if (isEquality) { @@ -2327,7 +2342,7 @@ private BoundExpression BindUnaryOperatorCore(CSharpSyntaxNode node, string oper { // Dev10 does not allow unary prefix operators to be applied to the null literal // (or other typeless expressions). - Error(diagnostics, ErrorCode.ERR_BadOpOnNullOrDefault, node, operatorText, operand.Display); + Error(diagnostics, ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, node, operatorText, operand.Display); } // If the operand is bad, avoid generating cascading errors. @@ -3434,7 +3449,7 @@ private BoundExpression BindNullCoalescingOperator(BinaryExpressionSyntax node, // The specification does not permit the left hand side to be a default literal if (leftOperand.IsLiteralDefault()) { - Error(diagnostics, ErrorCode.ERR_BadOpOnNullOrDefault, node, node.OperatorToken.Text, "default"); + Error(diagnostics, ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, node, node.OperatorToken.Text, "default"); return new BoundNullCoalescingOperator(node, leftOperand, rightOperand, Conversion.NoConversion, BoundNullCoalescingOperatorResultKind.NoCommonType, CreateErrorType(), hasErrors: true); @@ -3876,6 +3891,8 @@ private BoundExpression BindConditionalOperator(ConditionalExpressionSyntax node hasErrors = constantValue != null && constantValue.IsBad; } + trueExpr = BindToNaturalType(trueExpr, diagnostics, reportNoTargetType: false); + falseExpr = BindToNaturalType(falseExpr, diagnostics, reportNoTargetType: false); return new BoundConditionalOperator(node, isRef, condition, trueExpr, falseExpr, constantValue, type, hasErrors); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs index e0dd1a5ad06e3..de7483478ad9a 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs @@ -737,6 +737,10 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r { diagnostics.Add(ErrorCode.ERR_DefaultLiteralNotValid, node.Location); } + else if (ultimateReceiver.IsTypelessNew()) + { + diagnostics.Add(ErrorCode.ERR_TypelessNewNotValid, node.Location); + } else if (ultimateReceiver.Kind == BoundKind.NamespaceExpression) { diagnostics.Add(ErrorCode.ERR_BadSKunknown, ultimateReceiver.Syntax.Location, ultimateReceiver.Syntax, MessageID.IDS_SK_NAMESPACE.Localize()); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_TupleOperators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_TupleOperators.cs index aa6db90638658..caebd11e46d3a 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_TupleOperators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_TupleOperators.cs @@ -46,7 +46,7 @@ private BoundExpression ApplyConvertedTypes(BoundExpression expr, TupleBinaryOpe var multiple = (TupleBinaryOperatorInfo.Multiple)@operator; if (multiple.Operators.Length == 0) { - return BindToNaturalType(expr, diagnostics, reportDefaultMissingType: false); + return BindToNaturalType(expr, diagnostics, reportNoTargetType: false); } ImmutableArray arguments = tuple.Arguments; @@ -64,7 +64,7 @@ private BoundExpression ApplyConvertedTypes(BoundExpression expr, TupleBinaryOpe } // This element isn't getting a converted type - return BindToNaturalType(expr, diagnostics, reportDefaultMissingType: false); + return BindToNaturalType(expr, diagnostics, reportNoTargetType: false); } // We were able to determine a converted type (for this tuple literal or element), we can just convert to it @@ -193,11 +193,11 @@ private TupleBinaryOperatorInfo BindTupleDynamicBinaryOperatorSingleInfo(BinaryE private TupleBinaryOperatorInfo.Multiple BindTupleBinaryOperatorNestedInfo(BinaryExpressionSyntax node, BinaryOperatorKind kind, BoundExpression left, BoundExpression right, DiagnosticBag diagnostics) { - left = GiveTupleTypeToDefaultLiteralIfNeeded(left, right.Type); - right = GiveTupleTypeToDefaultLiteralIfNeeded(right, left.Type); + left = GiveTupleTypeToTypelessExpressionIfNeeded(left, right.Type, diagnostics); + right = GiveTupleTypeToTypelessExpressionIfNeeded(right, left.Type, diagnostics); - if ((left.Type is null && left.IsLiteralDefault()) || - (right.Type is null && right.IsLiteralDefault())) + if ((left.Type is null && left.IsLiteralDefaultOrTypelessNew()) || + (right.Type is null && right.IsLiteralDefaultOrTypelessNew())) { Error(diagnostics, ErrorCode.ERR_AmbigBinaryOps, node, node.OperatorToken.Text, left.Display, right.Display); return TupleBinaryOperatorInfo.Multiple.ErrorInstance; @@ -313,27 +313,36 @@ private static void ReportNamesMismatchesIfAny(BoundExpression left, BoundExpres } } - internal static BoundExpression GiveTupleTypeToDefaultLiteralIfNeeded(BoundExpression expr, TypeSymbol targetType) + internal BoundExpression GiveTupleTypeToTypelessExpressionIfNeeded(BoundExpression expr, TypeSymbol targetType, DiagnosticBag diagnostics) { - if (!expr.IsLiteralDefault() || targetType is null) + if (targetType is object) { - return expr; + if (expr.IsLiteralDefault()) + { + Debug.Assert(targetType.StrippedType().IsTupleType); + return new BoundDefaultExpression(expr.Syntax, targetType); + } + + if (expr is BoundUnconvertedObjectCreationExpression objectCreation) + { + return ConvertObjectCreationExpression(expr.Syntax, objectCreation, isCast: false, targetType, diagnostics); + } } - Debug.Assert(targetType.StrippedType().IsTupleType); - return new BoundDefaultExpression(expr.Syntax, targetType); + return expr; } private static bool IsTupleBinaryOperation(BoundExpression left, BoundExpression right) { - bool leftDefault = left.IsLiteralDefault(); - bool rightDefault = right.IsLiteralDefault(); - if (leftDefault && rightDefault) + bool leftDefaultOrNew = left.IsLiteralDefaultOrTypelessNew(); + bool rightDefaultOrNew = right.IsLiteralDefaultOrTypelessNew(); + if (leftDefaultOrNew && rightDefaultOrNew) { return false; } - return (GetTupleCardinality(left) > 1 || leftDefault) && (GetTupleCardinality(right) > 1 || rightDefault); + return (GetTupleCardinality(left) > 1 || leftDefaultOrNew) && + (GetTupleCardinality(right) > 1 || rightDefaultOrNew); } private static int GetTupleCardinality(BoundExpression expr) diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs index 1048b8cd05ef2..b8b55629d49a4 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs @@ -223,6 +223,7 @@ internal static Conversion GetTrivialConversion(ConversionKind kind) internal static Conversion ImplicitReference => new Conversion(ConversionKind.ImplicitReference); internal static Conversion ImplicitEnumeration => new Conversion(ConversionKind.ImplicitEnumeration); internal static Conversion ImplicitThrow => new Conversion(ConversionKind.ImplicitThrow); + internal static Conversion ObjectCreation => new Conversion(ConversionKind.ObjectCreation); internal static Conversion AnonymousFunction => new Conversion(ConversionKind.AnonymousFunction); internal static Conversion Boxing => new Conversion(ConversionKind.Boxing); internal static Conversion NullLiteral => new Conversion(ConversionKind.NullLiteral); @@ -523,6 +524,17 @@ public bool IsThrow } } + /// + /// Returns true if the conversion is an implicit object creation expression conversion. + /// + internal bool IsObjectCreation + { + get + { + return Kind == ConversionKind.ObjectCreation; + } + } + /// /// Returns true if the conversion is an implicit switch expression conversion. /// diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs index fc86109cc9d99..475321ce4b7ec 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs @@ -56,5 +56,6 @@ internal enum ConversionKind : byte PinnedObjectToPointer, DefaultLiteral, // a conversion from a `default` literal to any type + ObjectCreation, // a conversion from a `new()` expression to any type } } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKindExtensions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKindExtensions.cs index 3e67c8e382301..926b959dadd9c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKindExtensions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKindExtensions.cs @@ -50,6 +50,7 @@ public static bool IsImplicitConversion(this ConversionKind conversionKind) case Deconstruction: case StackAllocToPointerType: case StackAllocToSpanType: + case ObjectCreation: return true; case ExplicitNumeric: diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs index 7617ad45bee8d..b499da68a95a2 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs @@ -929,6 +929,9 @@ private Conversion ClassifyImplicitBuiltInConversionFromExpression(BoundExpressi case BoundKind.ThrowExpression: return Conversion.ImplicitThrow; + + case BoundKind.UnconvertedObjectCreationExpression: + return Conversion.ObjectCreation; } return Conversion.NoConversion; diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/AnalyzedArguments.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/AnalyzedArguments.cs index 2ecb021d0fe4d..278d89ce17db8 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/AnalyzedArguments.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/AnalyzedArguments.cs @@ -140,6 +140,26 @@ public static AnalyzedArguments GetInstance(AnalyzedArguments original) return instance; } + public static AnalyzedArguments GetInstance( + ImmutableArray arguments, + ImmutableArray argumentRefKindsOpt, + ImmutableArray argumentNamesOpt) + { + var instance = GetInstance(); + instance.Arguments.AddRange(arguments); + if (!argumentRefKindsOpt.IsDefault) + { + instance.RefKinds.AddRange(argumentRefKindsOpt); + } + + if (!argumentNamesOpt.IsDefault) + { + instance.Names.AddRange(argumentNamesOpt); + } + + return instance; + } + public void Free() { this.Clear(); diff --git a/src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs b/src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs index 6c1a152979793..0ad48fa961b1a 100644 --- a/src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs @@ -207,7 +207,7 @@ private void BuildSwitchLabels(SyntaxList labelsSyntax, Binde // compute the constant value to place in the label symbol var caseLabel = (CaseSwitchLabelSyntax)labelSyntax; Debug.Assert(caseLabel.Value != null); - var boundLabelExpression = sectionBinder.BindRValueWithoutTargetType(caseLabel.Value, tempDiagnosticBag); + var boundLabelExpression = sectionBinder.BindValue(caseLabel.Value, tempDiagnosticBag, BindValueKind.RValue); boundLabelExpression = ConvertCaseExpression(labelSyntax, boundLabelExpression, sectionBinder, out boundLabelConstantOpt, tempDiagnosticBag); break; diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs index f0430b81267a3..031cf60d4d20c 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs @@ -56,6 +56,7 @@ internal bool NeedsToBeConverted() { case BoundKind.TupleLiteral: case BoundKind.UnconvertedSwitchExpression: + case BoundKind.UnconvertedObjectCreationExpression: return true; case BoundKind.StackAllocArrayCreation: // A BoundStackAllocArrayCreation is given a null type when it is in a diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs index ef68101c101a2..aa0ffbce30c33 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs @@ -45,9 +45,14 @@ public static bool IsLiteralDefault(this BoundExpression node) return node.Kind == BoundKind.DefaultLiteral; } - public static bool IsLiteralNullOrDefault(this BoundExpression node) + public static bool IsTypelessNew(this BoundExpression node) { - return node.IsLiteralNull() || node.IsLiteralDefault(); + return node.Kind == BoundKind.UnconvertedObjectCreationExpression; + } + + public static bool IsLiteralDefaultOrTypelessNew(this BoundExpression node) + { + return node.IsLiteralDefault() || node.IsTypelessNew(); } // returns true when expression has no side-effects and produces diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml index 451a9f8ea9744..e0571989f87c0 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml @@ -1542,6 +1542,19 @@ + + + + + + + + + + diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundObjectCreationExpression.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundObjectCreationExpression.cs index 171e1b75d8e6c..3abdec70db36b 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundObjectCreationExpression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundObjectCreationExpression.cs @@ -12,13 +12,20 @@ internal partial class BoundObjectCreationExpression public BoundObjectCreationExpression(SyntaxNode syntax, MethodSymbol constructor, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, bool expanded, ImmutableArray argsToParamsOpt, ConstantValue constantValueOpt, BoundObjectInitializerExpressionBase initializerExpressionOpt, Binder binderOpt, TypeSymbol type, bool hasErrors = false) - : this(syntax, constructor, ImmutableArray.Empty, arguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, constantValueOpt, initializerExpressionOpt, binderOpt, type, hasErrors) + : this(syntax, constructor, ImmutableArray.Empty, arguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, constantValueOpt, initializerExpressionOpt, wasTargetTyped: false, binderOpt, type, hasErrors) { } public BoundObjectCreationExpression Update(MethodSymbol constructor, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, bool expanded, ImmutableArray argsToParamsOpt, ConstantValue constantValueOpt, BoundObjectInitializerExpressionBase initializerExpressionOpt, Binder binderOpt, TypeSymbol type) { - return this.Update(constructor, ImmutableArray.Empty, arguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, constantValueOpt, initializerExpressionOpt, binderOpt, type); + return this.Update(constructor, ImmutableArray.Empty, arguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, constantValueOpt, initializerExpressionOpt, this.WasTargetTyped, binderOpt, type); + } + + public BoundObjectCreationExpression Update(MethodSymbol constructor, ImmutableArray constructorsGroup, ImmutableArray arguments, + ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, bool expanded, ImmutableArray argsToParamsOpt, + ConstantValue constantValueOpt, BoundObjectInitializerExpressionBase initializerExpressionOpt, Binder binderOpt, TypeSymbol type) + { + return this.Update(constructor, constructorsGroup, arguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, constantValueOpt, initializerExpressionOpt, this.WasTargetTyped, binderOpt, type); } } } diff --git a/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs b/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs index f8edda2c2a1fb..f40e232d111d5 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs @@ -165,4 +165,39 @@ internal partial class BoundPassByCopy { public override object Display => Expression.Display; } + + internal partial class BoundUnconvertedObjectCreationExpression + { + public override object Display + { + get + { + var arguments = this.Arguments; + if (arguments.Length == 0) + { + return "new()"; + } + + var pooledBuilder = PooledStringBuilder.GetInstance(); + var builder = pooledBuilder.Builder; + var argumentDisplays = new object[arguments.Length]; + + builder.Append("new"); + builder.Append('('); + builder.Append("{0}"); + argumentDisplays[0] = arguments[0].Display; + + for (int i = 1; i < arguments.Length; i++) + { + builder.Append($", {{{i.ToString()}}}"); + argumentDisplays[i] = arguments[i].Display; + } + + builder.Append(')'); + + var format = pooledBuilder.ToStringAndFree(); + return FormattableStringFactory.Create(format, argumentDisplays); + } + } + } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 897d78ae38b36..f4ece7e919b28 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -462,7 +462,7 @@ Operator '{0}' cannot be applied to operand of type '{1}' - + Operator '{0}' cannot be applied to operand '{1}' @@ -489,8 +489,8 @@ Operator '{0}' is ambiguous on operands of type '{1}' and '{2}' - - Operator '{0}' is ambiguous on operands 'default' and 'default' + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' Operator '{0}' is ambiguous on an operand of type '{1}' @@ -2519,7 +2519,7 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep Invalid expression term '{0}' - A new expression requires (), [], or {} after type + A new expression requires an argument list or (), [], or {} after type Elements defined in a namespace cannot be explicitly declared as private, protected, protected internal, or private protected @@ -6007,4 +6007,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Invocation of implicit Range Indexer cannot name the argument. + + The type '{0}' may not be used as the target type of new() + + + Use of new() is not valid in this context + + + There is no target type for '{0}' + + + target-typed object creation + diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index e78020d61b8c3..a5add47bb6010 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1490,12 +1490,12 @@ internal enum ErrorCode ERR_NoRefOutWhenRefOnly = 8308, ERR_NoNetModuleOutputWhenRefOutOrRefOnly = 8309, - ERR_BadOpOnNullOrDefault = 8310, + ERR_BadOpOnNullOrDefaultOrNew = 8310, // ERR_BadDynamicMethodArgDefaultLiteral = 8311, ERR_DefaultLiteralNotValid = 8312, // ERR_DefaultInSwitch = 8313, ERR_PatternWrongGenericTypeInVersion = 8314, - ERR_AmbigBinaryOpsOnDefault = 8315, + ERR_AmbigBinaryOpsOnDefaultOrNew = 8315, #endregion diagnostics introduced for C# 7.1 @@ -1741,6 +1741,10 @@ internal enum ErrorCode ERR_InternalError = 8751, + ERR_TypelessNewIllegalTargetType = 8752, + ERR_TypelessNewNotValid = 8753, + ERR_TypelessNewNoTargetType = 8754, + ERR_ExternEventInitializer = 8760, ERR_AmbigBinaryOpsOnUnconstrainedDefault = 8761, WRN_ParameterConditionallyDisallowsNull = 8762, diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index eb8cf5953bbb3..cd957fe3613b4 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -189,6 +189,7 @@ internal enum MessageID IDS_FeatureLambdaDiscardParameters = MessageBase + 12765, IDS_FeatureLocalFunctionAttributes = MessageBase + 12766, IDS_FeatureExternLocalFunctions = MessageBase + 12767, + IDS_FeatureTargetTypedObjectCreation = MessageBase + 12768, } // Message IDs may refer to strings that need to be localized. @@ -299,6 +300,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureLambdaDiscardParameters: // semantic check case MessageID.IDS_FeatureLocalFunctionAttributes: // syntax check case MessageID.IDS_FeatureExternLocalFunctions: // syntax check + case MessageID.IDS_FeatureTargetTypedObjectCreation: // syntax check return LanguageVersion.Preview; // C# 8.0 features. diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs index a8d86273904ee..ab6170870aad3 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs @@ -2738,6 +2738,11 @@ public override BoundNode VisitDefaultExpression(BoundDefaultExpression node) return null; } + public override BoundNode VisitUnconvertedObjectCreationExpression(BoundUnconvertedObjectCreationExpression node) + { + throw ExceptionUtilities.Unreachable; + } + public override BoundNode VisitTypeOfOperator(BoundTypeOfOperator node) { VisitTypeExpression(node.SourceType); diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index 4c8d65e9193aa..48c9f942f6c04 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -2232,6 +2232,16 @@ public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpre return null; } + public override BoundNode VisitUnconvertedObjectCreationExpression(BoundUnconvertedObjectCreationExpression node) + { + var discardedDiagnostics = new DiagnosticBag(); + var expr = _binder.BindObjectCreationForErrorRecovery(node, discardedDiagnostics); + discardedDiagnostics.Free(); + Visit(expr); + SetResultType(node, TypeWithState.Create(expr.Type, NullableFlowState.NotNull)); + return null; + } + #nullable enable private void VisitObjectOrDynamicObjectCreation( BoundExpression node, @@ -4864,6 +4874,7 @@ private static NullableAnnotation GetNullableAnnotation(BoundExpression expr) return ((BoundExpressionWithNullability)expr).NullableAnnotation; case BoundKind.MethodGroup: case BoundKind.UnboundLambda: + case BoundKind.UnconvertedObjectCreationExpression: return NullableAnnotation.NotAnnotated; default: Debug.Assert(false); // unexpected value @@ -5714,6 +5725,7 @@ private TypeWithState VisitConversion( resultState = NullableFlowState.NotNull; break; + case ConversionKind.ObjectCreation: case ConversionKind.SwitchExpression: // The switch expression conversion is not represented as a separate conversion in the bound tree. throw ExceptionUtilities.UnexpectedValue(conversion.Kind); diff --git a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs index 62408fe4ec778..19695bb5e35d2 100644 --- a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs @@ -159,6 +159,7 @@ internal enum BoundKind: byte Call, EventAssignmentOperator, Attribute, + UnconvertedObjectCreationExpression, ObjectCreationExpression, TupleLiteral, ConvertedTupleLiteral, @@ -5480,9 +5481,48 @@ public BoundAttribute Update(MethodSymbol? constructor, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, InitializerExpressionSyntax? initializerOpt, bool hasErrors = false) + : base(BoundKind.UnconvertedObjectCreationExpression, syntax, null, hasErrors || arguments.HasErrors()) + { + + RoslynDebug.Assert(!arguments.IsDefault, "Field 'arguments' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); + + this.Arguments = arguments; + this.ArgumentNamesOpt = argumentNamesOpt; + this.ArgumentRefKindsOpt = argumentRefKindsOpt; + this.InitializerOpt = initializerOpt; + } + + + public new TypeSymbol? Type => base.Type!; + + public ImmutableArray Arguments { get; } + + public ImmutableArray ArgumentNamesOpt { get; } + + public ImmutableArray ArgumentRefKindsOpt { get; } + + public InitializerExpressionSyntax? InitializerOpt { get; } + [DebuggerStepThrough] + public override BoundNode? Accept(BoundTreeVisitor visitor) => visitor.VisitUnconvertedObjectCreationExpression(this); + + public BoundUnconvertedObjectCreationExpression Update(ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, InitializerExpressionSyntax? initializerOpt) + { + if (arguments != this.Arguments || argumentNamesOpt != this.ArgumentNamesOpt || argumentRefKindsOpt != this.ArgumentRefKindsOpt || initializerOpt != this.InitializerOpt) + { + var result = new BoundUnconvertedObjectCreationExpression(this.Syntax, arguments, argumentNamesOpt, argumentRefKindsOpt, initializerOpt, this.HasErrors); + result.CopyAttributes(this); + return result; + } + return this; + } + } + internal sealed partial class BoundObjectCreationExpression : BoundExpression { - public BoundObjectCreationExpression(SyntaxNode syntax, MethodSymbol constructor, ImmutableArray constructorsGroup, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, bool expanded, ImmutableArray argsToParamsOpt, ConstantValue? constantValueOpt, BoundObjectInitializerExpressionBase? initializerExpressionOpt, Binder? binderOpt, TypeSymbol type, bool hasErrors = false) + public BoundObjectCreationExpression(SyntaxNode syntax, MethodSymbol constructor, ImmutableArray constructorsGroup, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, bool expanded, ImmutableArray argsToParamsOpt, ConstantValue? constantValueOpt, BoundObjectInitializerExpressionBase? initializerExpressionOpt, bool wasTargetTyped, Binder? binderOpt, TypeSymbol type, bool hasErrors = false) : base(BoundKind.ObjectCreationExpression, syntax, type, hasErrors || arguments.HasErrors() || initializerExpressionOpt.HasErrors()) { @@ -5500,6 +5540,7 @@ public BoundObjectCreationExpression(SyntaxNode syntax, MethodSymbol constructor this.ArgsToParamsOpt = argsToParamsOpt; this.ConstantValueOpt = constantValueOpt; this.InitializerExpressionOpt = initializerExpressionOpt; + this.WasTargetTyped = wasTargetTyped; this.BinderOpt = binderOpt; } @@ -5524,15 +5565,17 @@ public BoundObjectCreationExpression(SyntaxNode syntax, MethodSymbol constructor public BoundObjectInitializerExpressionBase? InitializerExpressionOpt { get; } + public bool WasTargetTyped { get; } + public Binder? BinderOpt { get; } [DebuggerStepThrough] public override BoundNode? Accept(BoundTreeVisitor visitor) => visitor.VisitObjectCreationExpression(this); - public BoundObjectCreationExpression Update(MethodSymbol constructor, ImmutableArray constructorsGroup, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, bool expanded, ImmutableArray argsToParamsOpt, ConstantValue? constantValueOpt, BoundObjectInitializerExpressionBase? initializerExpressionOpt, Binder? binderOpt, TypeSymbol type) + public BoundObjectCreationExpression Update(MethodSymbol constructor, ImmutableArray constructorsGroup, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, bool expanded, ImmutableArray argsToParamsOpt, ConstantValue? constantValueOpt, BoundObjectInitializerExpressionBase? initializerExpressionOpt, bool wasTargetTyped, Binder? binderOpt, TypeSymbol type) { - if (!Symbols.SymbolEqualityComparer.ConsiderEverything.Equals(constructor, this.Constructor) || constructorsGroup != this.ConstructorsGroup || arguments != this.Arguments || argumentNamesOpt != this.ArgumentNamesOpt || argumentRefKindsOpt != this.ArgumentRefKindsOpt || expanded != this.Expanded || argsToParamsOpt != this.ArgsToParamsOpt || constantValueOpt != this.ConstantValueOpt || initializerExpressionOpt != this.InitializerExpressionOpt || binderOpt != this.BinderOpt || !TypeSymbol.Equals(type, this.Type, TypeCompareKind.ConsiderEverything)) + if (!Symbols.SymbolEqualityComparer.ConsiderEverything.Equals(constructor, this.Constructor) || constructorsGroup != this.ConstructorsGroup || arguments != this.Arguments || argumentNamesOpt != this.ArgumentNamesOpt || argumentRefKindsOpt != this.ArgumentRefKindsOpt || expanded != this.Expanded || argsToParamsOpt != this.ArgsToParamsOpt || constantValueOpt != this.ConstantValueOpt || initializerExpressionOpt != this.InitializerExpressionOpt || wasTargetTyped != this.WasTargetTyped || binderOpt != this.BinderOpt || !TypeSymbol.Equals(type, this.Type, TypeCompareKind.ConsiderEverything)) { - var result = new BoundObjectCreationExpression(this.Syntax, constructor, constructorsGroup, arguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, constantValueOpt, initializerExpressionOpt, binderOpt, type, this.HasErrors); + var result = new BoundObjectCreationExpression(this.Syntax, constructor, constructorsGroup, arguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, constantValueOpt, initializerExpressionOpt, wasTargetTyped, binderOpt, type, this.HasErrors); result.CopyAttributes(this); return result; } @@ -7681,6 +7724,8 @@ internal R VisitInternal(BoundNode node, A arg) return VisitEventAssignmentOperator((BoundEventAssignmentOperator)node, arg); case BoundKind.Attribute: return VisitAttribute((BoundAttribute)node, arg); + case BoundKind.UnconvertedObjectCreationExpression: + return VisitUnconvertedObjectCreationExpression((BoundUnconvertedObjectCreationExpression)node, arg); case BoundKind.ObjectCreationExpression: return VisitObjectCreationExpression((BoundObjectCreationExpression)node, arg); case BoundKind.TupleLiteral: @@ -7925,6 +7970,7 @@ internal abstract partial class BoundTreeVisitor public virtual R VisitCall(BoundCall node, A arg) => this.DefaultVisit(node, arg); public virtual R VisitEventAssignmentOperator(BoundEventAssignmentOperator node, A arg) => this.DefaultVisit(node, arg); public virtual R VisitAttribute(BoundAttribute node, A arg) => this.DefaultVisit(node, arg); + public virtual R VisitUnconvertedObjectCreationExpression(BoundUnconvertedObjectCreationExpression node, A arg) => this.DefaultVisit(node, arg); public virtual R VisitObjectCreationExpression(BoundObjectCreationExpression node, A arg) => this.DefaultVisit(node, arg); public virtual R VisitTupleLiteral(BoundTupleLiteral node, A arg) => this.DefaultVisit(node, arg); public virtual R VisitConvertedTupleLiteral(BoundConvertedTupleLiteral node, A arg) => this.DefaultVisit(node, arg); @@ -8116,6 +8162,7 @@ internal abstract partial class BoundTreeVisitor public virtual BoundNode? VisitCall(BoundCall node) => this.DefaultVisit(node); public virtual BoundNode? VisitEventAssignmentOperator(BoundEventAssignmentOperator node) => this.DefaultVisit(node); public virtual BoundNode? VisitAttribute(BoundAttribute node) => this.DefaultVisit(node); + public virtual BoundNode? VisitUnconvertedObjectCreationExpression(BoundUnconvertedObjectCreationExpression node) => this.DefaultVisit(node); public virtual BoundNode? VisitObjectCreationExpression(BoundObjectCreationExpression node) => this.DefaultVisit(node); public virtual BoundNode? VisitTupleLiteral(BoundTupleLiteral node) => this.DefaultVisit(node); public virtual BoundNode? VisitConvertedTupleLiteral(BoundConvertedTupleLiteral node) => this.DefaultVisit(node); @@ -8783,6 +8830,11 @@ internal abstract partial class BoundTreeWalker: BoundTreeVisitor this.VisitList(node.NamedArguments); return null; } + public override BoundNode? VisitUnconvertedObjectCreationExpression(BoundUnconvertedObjectCreationExpression node) + { + this.VisitList(node.Arguments); + return null; + } public override BoundNode? VisitObjectCreationExpression(BoundObjectCreationExpression node) { this.VisitList(node.Arguments); @@ -9812,12 +9864,18 @@ internal abstract partial class BoundTreeRewriter : BoundTreeVisitor TypeSymbol type = this.VisitType(node.Type); return node.Update(node.Constructor, constructorArguments, node.ConstructorArgumentNamesOpt, node.ConstructorArgumentsToParamsOpt, node.ConstructorExpanded, namedArguments, node.ResultKind, type); } + public override BoundNode? VisitUnconvertedObjectCreationExpression(BoundUnconvertedObjectCreationExpression node) + { + ImmutableArray arguments = this.VisitList(node.Arguments); + TypeSymbol type = this.VisitType(node.Type); + return node.Update(arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.InitializerOpt); + } public override BoundNode? VisitObjectCreationExpression(BoundObjectCreationExpression node) { ImmutableArray arguments = this.VisitList(node.Arguments); BoundObjectInitializerExpressionBase? initializerExpressionOpt = (BoundObjectInitializerExpressionBase?)this.Visit(node.InitializerExpressionOpt); TypeSymbol type = this.VisitType(node.Type); - return node.Update(node.Constructor, node.ConstructorsGroup, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.Expanded, node.ArgsToParamsOpt, node.ConstantValueOpt, initializerExpressionOpt, node.BinderOpt, type); + return node.Update(node.Constructor, node.ConstructorsGroup, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.Expanded, node.ArgsToParamsOpt, node.ConstantValueOpt, initializerExpressionOpt, node.WasTargetTyped, node.BinderOpt, type); } public override BoundNode? VisitTupleLiteral(BoundTupleLiteral node) { @@ -11593,6 +11651,23 @@ public NullabilityRewriter(ImmutableDictionary arguments = this.VisitList(node.Arguments); + BoundUnconvertedObjectCreationExpression updatedNode; + + if (_updatedNullabilities.TryGetValue(node, out (NullabilityInfo Info, TypeSymbol Type) infoAndType)) + { + updatedNode = node.Update(arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.InitializerOpt); + updatedNode.TopLevelNullability = infoAndType.Info; + } + else + { + updatedNode = node.Update(arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.InitializerOpt); + } + return updatedNode; + } + public override BoundNode? VisitObjectCreationExpression(BoundObjectCreationExpression node) { MethodSymbol constructor = GetUpdatedSymbol(node, node.Constructor); @@ -11603,12 +11678,12 @@ public NullabilityRewriter(ImmutableDictionary new TreeDumperNode("unconvertedObjectCreationExpression", null, new TreeDumperNode[] + { + new TreeDumperNode("arguments", null, from x in node.Arguments select Visit(x, null)), + new TreeDumperNode("argumentNamesOpt", node.ArgumentNamesOpt, null), + new TreeDumperNode("argumentRefKindsOpt", node.ArgumentRefKindsOpt, null), + new TreeDumperNode("initializerOpt", node.InitializerOpt, null), + new TreeDumperNode("type", node.Type, null), + new TreeDumperNode("isSuppressed", node.IsSuppressed, null), + new TreeDumperNode("hasErrors", node.HasErrors, null) + } + ); public override TreeDumperNode VisitObjectCreationExpression(BoundObjectCreationExpression node, object? arg) => new TreeDumperNode("objectCreationExpression", null, new TreeDumperNode[] { new TreeDumperNode("constructor", node.Constructor, null), @@ -13599,6 +13685,7 @@ private BoundTreeDumperNodeProducer() new TreeDumperNode("argsToParamsOpt", node.ArgsToParamsOpt, null), new TreeDumperNode("constantValueOpt", node.ConstantValueOpt, null), new TreeDumperNode("initializerExpressionOpt", null, new TreeDumperNode[] { Visit(node.InitializerExpressionOpt, null) }), + new TreeDumperNode("wasTargetTyped", node.WasTargetTyped, null), new TreeDumperNode("binderOpt", node.BinderOpt, null), new TreeDumperNode("type", node.Type, null), new TreeDumperNode("isSuppressed", node.IsSuppressed, null), diff --git a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 index c7cbacb1a7f41..75272dfaed0b0 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 +++ b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 @@ -616,6 +616,7 @@ expression | array_creation_expression | assignment_expression | await_expression + | base_object_creation_expression | binary_expression | cast_expression | checked_expression @@ -637,7 +638,6 @@ expression | make_ref_expression | member_access_expression | member_binding_expression - | object_creation_expression | omitted_array_size_expression | parenthesized_expression | postfix_unary_expression @@ -702,6 +702,19 @@ await_expression : 'await' expression ; +base_object_creation_expression + : implicit_object_creation_expression + | object_creation_expression + ; + +implicit_object_creation_expression + : 'new' argument_list initializer_expression? + ; + +object_creation_expression + : 'new' type argument_list? initializer_expression? + ; + binary_expression : expression ('+' | '-' | '*' | '/' | '%' | '<<' | '>>' | '||' | '&&' | '|' | '&' | '^' | '==' | '!=' | '<' | '<=' | '>' | '>=' | 'is' | 'as' | '??') expression ; @@ -821,10 +834,6 @@ member_binding_expression : '.' simple_name ; -object_creation_expression - : 'new' type argument_list? initializer_expression? - ; - omitted_array_size_expression : /* epsilon */ ; diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs index 9e06f3bf594f4..251046621315d 100644 --- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs @@ -6235,8 +6235,164 @@ static InitializerExpressionSyntax() } } + internal abstract partial class BaseObjectCreationExpressionSyntax : ExpressionSyntax + { + internal BaseObjectCreationExpressionSyntax(SyntaxKind kind, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) + : base(kind, diagnostics, annotations) + { + } + + internal BaseObjectCreationExpressionSyntax(SyntaxKind kind) + : base(kind) + { + } + + protected BaseObjectCreationExpressionSyntax(ObjectReader reader) + : base(reader) + { + } + + /// SyntaxToken representing the new keyword. + public abstract SyntaxToken NewKeyword { get; } + + /// ArgumentListSyntax representing the list of arguments passed as part of the object creation expression. + public abstract ArgumentListSyntax? ArgumentList { get; } + + /// InitializerExpressionSyntax representing the initializer expression for the object being created. + public abstract InitializerExpressionSyntax? Initializer { get; } + } + + /// Class which represents the syntax node for implicit object creation expression. + internal sealed partial class ImplicitObjectCreationExpressionSyntax : BaseObjectCreationExpressionSyntax + { + internal readonly SyntaxToken newKeyword; + internal readonly ArgumentListSyntax argumentList; + internal readonly InitializerExpressionSyntax? initializer; + + internal ImplicitObjectCreationExpressionSyntax(SyntaxKind kind, SyntaxToken newKeyword, ArgumentListSyntax argumentList, InitializerExpressionSyntax? initializer, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) + : base(kind, diagnostics, annotations) + { + this.SlotCount = 3; + this.AdjustFlagsAndWidth(newKeyword); + this.newKeyword = newKeyword; + this.AdjustFlagsAndWidth(argumentList); + this.argumentList = argumentList; + if (initializer != null) + { + this.AdjustFlagsAndWidth(initializer); + this.initializer = initializer; + } + } + + internal ImplicitObjectCreationExpressionSyntax(SyntaxKind kind, SyntaxToken newKeyword, ArgumentListSyntax argumentList, InitializerExpressionSyntax? initializer, SyntaxFactoryContext context) + : base(kind) + { + this.SetFactoryContext(context); + this.SlotCount = 3; + this.AdjustFlagsAndWidth(newKeyword); + this.newKeyword = newKeyword; + this.AdjustFlagsAndWidth(argumentList); + this.argumentList = argumentList; + if (initializer != null) + { + this.AdjustFlagsAndWidth(initializer); + this.initializer = initializer; + } + } + + internal ImplicitObjectCreationExpressionSyntax(SyntaxKind kind, SyntaxToken newKeyword, ArgumentListSyntax argumentList, InitializerExpressionSyntax? initializer) + : base(kind) + { + this.SlotCount = 3; + this.AdjustFlagsAndWidth(newKeyword); + this.newKeyword = newKeyword; + this.AdjustFlagsAndWidth(argumentList); + this.argumentList = argumentList; + if (initializer != null) + { + this.AdjustFlagsAndWidth(initializer); + this.initializer = initializer; + } + } + + /// SyntaxToken representing the new keyword. + public override SyntaxToken NewKeyword => this.newKeyword; + /// ArgumentListSyntax representing the list of arguments passed as part of the object creation expression. + public override ArgumentListSyntax ArgumentList => this.argumentList; + /// InitializerExpressionSyntax representing the initializer expression for the object being created. + public override InitializerExpressionSyntax? Initializer => this.initializer; + + internal override GreenNode? GetSlot(int index) + => index switch + { + 0 => this.newKeyword, + 1 => this.argumentList, + 2 => this.initializer, + _ => null, + }; + + internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.ImplicitObjectCreationExpressionSyntax(this, parent, position); + + public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitImplicitObjectCreationExpression(this); + public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitImplicitObjectCreationExpression(this); + + public ImplicitObjectCreationExpressionSyntax Update(SyntaxToken newKeyword, ArgumentListSyntax argumentList, InitializerExpressionSyntax initializer) + { + if (newKeyword != this.NewKeyword || argumentList != this.ArgumentList || initializer != this.Initializer) + { + var newNode = SyntaxFactory.ImplicitObjectCreationExpression(newKeyword, argumentList, initializer); + var diags = GetDiagnostics(); + if (diags?.Length > 0) + newNode = newNode.WithDiagnosticsGreen(diags); + var annotations = GetAnnotations(); + if (annotations?.Length > 0) + newNode = newNode.WithAnnotationsGreen(annotations); + return newNode; + } + + return this; + } + + internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics) + => new ImplicitObjectCreationExpressionSyntax(this.Kind, this.newKeyword, this.argumentList, this.initializer, diagnostics, GetAnnotations()); + + internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations) + => new ImplicitObjectCreationExpressionSyntax(this.Kind, this.newKeyword, this.argumentList, this.initializer, GetDiagnostics(), annotations); + + internal ImplicitObjectCreationExpressionSyntax(ObjectReader reader) + : base(reader) + { + this.SlotCount = 3; + var newKeyword = (SyntaxToken)reader.ReadValue(); + AdjustFlagsAndWidth(newKeyword); + this.newKeyword = newKeyword; + var argumentList = (ArgumentListSyntax)reader.ReadValue(); + AdjustFlagsAndWidth(argumentList); + this.argumentList = argumentList; + var initializer = (InitializerExpressionSyntax?)reader.ReadValue(); + if (initializer != null) + { + AdjustFlagsAndWidth(initializer); + this.initializer = initializer; + } + } + + internal override void WriteTo(ObjectWriter writer) + { + base.WriteTo(writer); + writer.WriteValue(this.newKeyword); + writer.WriteValue(this.argumentList); + writer.WriteValue(this.initializer); + } + + static ImplicitObjectCreationExpressionSyntax() + { + ObjectBinder.RegisterTypeReader(typeof(ImplicitObjectCreationExpressionSyntax), r => new ImplicitObjectCreationExpressionSyntax(r)); + } + } + /// Class which represents the syntax node for object creation expression. - internal sealed partial class ObjectCreationExpressionSyntax : ExpressionSyntax + internal sealed partial class ObjectCreationExpressionSyntax : BaseObjectCreationExpressionSyntax { internal readonly SyntaxToken newKeyword; internal readonly TypeSyntax type; @@ -6305,13 +6461,13 @@ internal ObjectCreationExpressionSyntax(SyntaxKind kind, SyntaxToken newKeyword, } /// SyntaxToken representing the new keyword. - public SyntaxToken NewKeyword => this.newKeyword; + public override SyntaxToken NewKeyword => this.newKeyword; /// TypeSyntax representing the type of the object being created. public TypeSyntax Type => this.type; /// ArgumentListSyntax representing the list of arguments passed as part of the object creation expression. - public ArgumentListSyntax? ArgumentList => this.argumentList; + public override ArgumentListSyntax? ArgumentList => this.argumentList; /// InitializerExpressionSyntax representing the initializer expression for the object being created. - public InitializerExpressionSyntax? Initializer => this.initializer; + public override InitializerExpressionSyntax? Initializer => this.initializer; internal override GreenNode? GetSlot(int index) => index switch @@ -30907,6 +31063,7 @@ internal partial class CSharpSyntaxVisitor public virtual TResult VisitRefExpression(RefExpressionSyntax node) => this.DefaultVisit(node); public virtual TResult VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpressionSyntax node) => this.DefaultVisit(node); public virtual TResult VisitInitializerExpression(InitializerExpressionSyntax node) => this.DefaultVisit(node); + public virtual TResult VisitImplicitObjectCreationExpression(ImplicitObjectCreationExpressionSyntax node) => this.DefaultVisit(node); public virtual TResult VisitObjectCreationExpression(ObjectCreationExpressionSyntax node) => this.DefaultVisit(node); public virtual TResult VisitAnonymousObjectMemberDeclarator(AnonymousObjectMemberDeclaratorSyntax node) => this.DefaultVisit(node); public virtual TResult VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpressionSyntax node) => this.DefaultVisit(node); @@ -31126,6 +31283,7 @@ internal partial class CSharpSyntaxVisitor public virtual void VisitRefExpression(RefExpressionSyntax node) => this.DefaultVisit(node); public virtual void VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpressionSyntax node) => this.DefaultVisit(node); public virtual void VisitInitializerExpression(InitializerExpressionSyntax node) => this.DefaultVisit(node); + public virtual void VisitImplicitObjectCreationExpression(ImplicitObjectCreationExpressionSyntax node) => this.DefaultVisit(node); public virtual void VisitObjectCreationExpression(ObjectCreationExpressionSyntax node) => this.DefaultVisit(node); public virtual void VisitAnonymousObjectMemberDeclarator(AnonymousObjectMemberDeclaratorSyntax node) => this.DefaultVisit(node); public virtual void VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpressionSyntax node) => this.DefaultVisit(node); @@ -31447,6 +31605,9 @@ public override CSharpSyntaxNode VisitParenthesizedLambdaExpression(Parenthesize public override CSharpSyntaxNode VisitInitializerExpression(InitializerExpressionSyntax node) => node.Update((SyntaxToken)Visit(node.OpenBraceToken), VisitList(node.Expressions), (SyntaxToken)Visit(node.CloseBraceToken)); + public override CSharpSyntaxNode VisitImplicitObjectCreationExpression(ImplicitObjectCreationExpressionSyntax node) + => node.Update((SyntaxToken)Visit(node.NewKeyword), (ArgumentListSyntax)Visit(node.ArgumentList), (InitializerExpressionSyntax)Visit(node.Initializer)); + public override CSharpSyntaxNode VisitObjectCreationExpression(ObjectCreationExpressionSyntax node) => node.Update((SyntaxToken)Visit(node.NewKeyword), (TypeSyntax)Visit(node.Type), (ArgumentListSyntax)Visit(node.ArgumentList), (InitializerExpressionSyntax)Visit(node.Initializer)); @@ -33182,6 +33343,27 @@ public InitializerExpressionSyntax InitializerExpression(SyntaxKind kind, Syntax return result; } + public ImplicitObjectCreationExpressionSyntax ImplicitObjectCreationExpression(SyntaxToken newKeyword, ArgumentListSyntax argumentList, InitializerExpressionSyntax? initializer) + { + #if DEBUG + if (newKeyword == null) throw new ArgumentNullException(nameof(newKeyword)); + if (newKeyword.Kind != SyntaxKind.NewKeyword) throw new ArgumentException(nameof(newKeyword)); + if (argumentList == null) throw new ArgumentNullException(nameof(argumentList)); + #endif + + int hash; + var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.ImplicitObjectCreationExpression, newKeyword, argumentList, initializer, this.context, out hash); + if (cached != null) return (ImplicitObjectCreationExpressionSyntax)cached; + + var result = new ImplicitObjectCreationExpressionSyntax(SyntaxKind.ImplicitObjectCreationExpression, newKeyword, argumentList, initializer, this.context); + if (hash >= 0) + { + SyntaxNodeCache.AddNode(result, hash); + } + + return result; + } + public ObjectCreationExpressionSyntax ObjectCreationExpression(SyntaxToken newKeyword, TypeSyntax type, ArgumentListSyntax? argumentList, InitializerExpressionSyntax? initializer) { #if DEBUG @@ -37706,6 +37888,27 @@ public static InitializerExpressionSyntax InitializerExpression(SyntaxKind kind, return result; } + public static ImplicitObjectCreationExpressionSyntax ImplicitObjectCreationExpression(SyntaxToken newKeyword, ArgumentListSyntax argumentList, InitializerExpressionSyntax? initializer) + { + #if DEBUG + if (newKeyword == null) throw new ArgumentNullException(nameof(newKeyword)); + if (newKeyword.Kind != SyntaxKind.NewKeyword) throw new ArgumentException(nameof(newKeyword)); + if (argumentList == null) throw new ArgumentNullException(nameof(argumentList)); + #endif + + int hash; + var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.ImplicitObjectCreationExpression, newKeyword, argumentList, initializer, out hash); + if (cached != null) return (ImplicitObjectCreationExpressionSyntax)cached; + + var result = new ImplicitObjectCreationExpressionSyntax(SyntaxKind.ImplicitObjectCreationExpression, newKeyword, argumentList, initializer); + if (hash >= 0) + { + SyntaxNodeCache.AddNode(result, hash); + } + + return result; + } + public static ObjectCreationExpressionSyntax ObjectCreationExpression(SyntaxToken newKeyword, TypeSyntax type, ArgumentListSyntax? argumentList, InitializerExpressionSyntax? initializer) { #if DEBUG @@ -41046,6 +41249,7 @@ internal static IEnumerable GetNodeTypes() typeof(RefExpressionSyntax), typeof(ParenthesizedLambdaExpressionSyntax), typeof(InitializerExpressionSyntax), + typeof(ImplicitObjectCreationExpressionSyntax), typeof(ObjectCreationExpressionSyntax), typeof(AnonymousObjectMemberDeclaratorSyntax), typeof(AnonymousObjectCreationExpressionSyntax), diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs index 1c846158a828f..ac7127776b223 100644 --- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs @@ -166,6 +166,9 @@ public partial class CSharpSyntaxVisitor /// Called when the visitor visits a InitializerExpressionSyntax node. public virtual TResult VisitInitializerExpression(InitializerExpressionSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a ImplicitObjectCreationExpressionSyntax node. + public virtual TResult VisitImplicitObjectCreationExpression(ImplicitObjectCreationExpressionSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a ObjectCreationExpressionSyntax node. public virtual TResult VisitObjectCreationExpression(ObjectCreationExpressionSyntax node) => this.DefaultVisit(node); @@ -814,6 +817,9 @@ public partial class CSharpSyntaxVisitor /// Called when the visitor visits a InitializerExpressionSyntax node. public virtual void VisitInitializerExpression(InitializerExpressionSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a ImplicitObjectCreationExpressionSyntax node. + public virtual void VisitImplicitObjectCreationExpression(ImplicitObjectCreationExpressionSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a ObjectCreationExpressionSyntax node. public virtual void VisitObjectCreationExpression(ObjectCreationExpressionSyntax node) => this.DefaultVisit(node); @@ -1462,6 +1468,9 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor public override SyntaxNode? VisitInitializerExpression(InitializerExpressionSyntax node) => node.Update(VisitToken(node.OpenBraceToken), VisitList(node.Expressions), VisitToken(node.CloseBraceToken)); + public override SyntaxNode? VisitImplicitObjectCreationExpression(ImplicitObjectCreationExpressionSyntax node) + => node.Update(VisitToken(node.NewKeyword), (ArgumentListSyntax?)Visit(node.ArgumentList) ?? throw new ArgumentNullException("argumentList"), (InitializerExpressionSyntax?)Visit(node.Initializer)); + public override SyntaxNode? VisitObjectCreationExpression(ObjectCreationExpressionSyntax node) => node.Update(VisitToken(node.NewKeyword), (TypeSyntax?)Visit(node.Type) ?? throw new ArgumentNullException("type"), (ArgumentListSyntax?)Visit(node.ArgumentList), (InitializerExpressionSyntax?)Visit(node.Initializer)); @@ -2925,6 +2934,22 @@ public static InitializerExpressionSyntax InitializerExpression(SyntaxKind kind, public static InitializerExpressionSyntax InitializerExpression(SyntaxKind kind, SeparatedSyntaxList expressions = default) => SyntaxFactory.InitializerExpression(kind, SyntaxFactory.Token(SyntaxKind.OpenBraceToken), expressions, SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); + /// Creates a new ImplicitObjectCreationExpressionSyntax instance. + public static ImplicitObjectCreationExpressionSyntax ImplicitObjectCreationExpression(SyntaxToken newKeyword, ArgumentListSyntax argumentList, InitializerExpressionSyntax? initializer) + { + if (newKeyword.Kind() != SyntaxKind.NewKeyword) throw new ArgumentException(nameof(newKeyword)); + if (argumentList == null) throw new ArgumentNullException(nameof(argumentList)); + return (ImplicitObjectCreationExpressionSyntax)Syntax.InternalSyntax.SyntaxFactory.ImplicitObjectCreationExpression((Syntax.InternalSyntax.SyntaxToken)newKeyword.Node!, (Syntax.InternalSyntax.ArgumentListSyntax)argumentList.Green, initializer == null ? null : (Syntax.InternalSyntax.InitializerExpressionSyntax)initializer.Green).CreateRed(); + } + + /// Creates a new ImplicitObjectCreationExpressionSyntax instance. + public static ImplicitObjectCreationExpressionSyntax ImplicitObjectCreationExpression(ArgumentListSyntax argumentList, InitializerExpressionSyntax? initializer) + => SyntaxFactory.ImplicitObjectCreationExpression(SyntaxFactory.Token(SyntaxKind.NewKeyword), argumentList, initializer); + + /// Creates a new ImplicitObjectCreationExpressionSyntax instance. + public static ImplicitObjectCreationExpressionSyntax ImplicitObjectCreationExpression() + => SyntaxFactory.ImplicitObjectCreationExpression(SyntaxFactory.Token(SyntaxKind.NewKeyword), SyntaxFactory.ArgumentList(), default); + /// Creates a new ObjectCreationExpressionSyntax instance. public static ObjectCreationExpressionSyntax ObjectCreationExpression(SyntaxToken newKeyword, TypeSyntax type, ArgumentListSyntax? argumentList, InitializerExpressionSyntax? initializer) { diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs index 7f72f18b5741c..81986fa205bd3 100644 --- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs @@ -2693,8 +2693,96 @@ public InitializerExpressionSyntax Update(SyntaxToken openBraceToken, SeparatedS public InitializerExpressionSyntax AddExpressions(params ExpressionSyntax[] items) => WithExpressions(this.Expressions.AddRange(items)); } + public abstract partial class BaseObjectCreationExpressionSyntax : ExpressionSyntax + { + internal BaseObjectCreationExpressionSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position) + : base(green, parent, position) + { + } + + /// SyntaxToken representing the new keyword. + public abstract SyntaxToken NewKeyword { get; } + public BaseObjectCreationExpressionSyntax WithNewKeyword(SyntaxToken newKeyword) => WithNewKeywordCore(newKeyword); + internal abstract BaseObjectCreationExpressionSyntax WithNewKeywordCore(SyntaxToken newKeyword); + + /// ArgumentListSyntax representing the list of arguments passed as part of the object creation expression. + public abstract ArgumentListSyntax? ArgumentList { get; } + public BaseObjectCreationExpressionSyntax WithArgumentList(ArgumentListSyntax? argumentList) => WithArgumentListCore(argumentList); + internal abstract BaseObjectCreationExpressionSyntax WithArgumentListCore(ArgumentListSyntax? argumentList); + + public BaseObjectCreationExpressionSyntax AddArgumentListArguments(params ArgumentSyntax[] items) => AddArgumentListArgumentsCore(items); + internal abstract BaseObjectCreationExpressionSyntax AddArgumentListArgumentsCore(params ArgumentSyntax[] items); + + /// InitializerExpressionSyntax representing the initializer expression for the object being created. + public abstract InitializerExpressionSyntax? Initializer { get; } + public BaseObjectCreationExpressionSyntax WithInitializer(InitializerExpressionSyntax? initializer) => WithInitializerCore(initializer); + internal abstract BaseObjectCreationExpressionSyntax WithInitializerCore(InitializerExpressionSyntax? initializer); + } + + /// Class which represents the syntax node for implicit object creation expression. + public sealed partial class ImplicitObjectCreationExpressionSyntax : BaseObjectCreationExpressionSyntax + { + private ArgumentListSyntax? argumentList; + private InitializerExpressionSyntax? initializer; + + internal ImplicitObjectCreationExpressionSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position) + : base(green, parent, position) + { + } + + /// SyntaxToken representing the new keyword. + public override SyntaxToken NewKeyword => new SyntaxToken(this, ((Syntax.InternalSyntax.ImplicitObjectCreationExpressionSyntax)this.Green).newKeyword, Position, 0); + + /// ArgumentListSyntax representing the list of arguments passed as part of the object creation expression. + public override ArgumentListSyntax ArgumentList => GetRed(ref this.argumentList, 1)!; + + /// InitializerExpressionSyntax representing the initializer expression for the object being created. + public override InitializerExpressionSyntax? Initializer => GetRed(ref this.initializer, 2); + + internal override SyntaxNode? GetNodeSlot(int index) + => index switch + { + 1 => GetRed(ref this.argumentList, 1)!, + 2 => GetRed(ref this.initializer, 2), + _ => null, + }; + + internal override SyntaxNode? GetCachedSlot(int index) + => index switch + { + 1 => this.argumentList, + 2 => this.initializer, + _ => null, + }; + + public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitImplicitObjectCreationExpression(this); + public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitImplicitObjectCreationExpression(this); + + public ImplicitObjectCreationExpressionSyntax Update(SyntaxToken newKeyword, ArgumentListSyntax argumentList, InitializerExpressionSyntax? initializer) + { + if (newKeyword != this.NewKeyword || argumentList != this.ArgumentList || initializer != this.Initializer) + { + var newNode = SyntaxFactory.ImplicitObjectCreationExpression(newKeyword, argumentList, initializer); + var annotations = GetAnnotations(); + return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode; + } + + return this; + } + + internal override BaseObjectCreationExpressionSyntax WithNewKeywordCore(SyntaxToken newKeyword) => WithNewKeyword(newKeyword); + public new ImplicitObjectCreationExpressionSyntax WithNewKeyword(SyntaxToken newKeyword) => Update(newKeyword, this.ArgumentList, this.Initializer); + internal override BaseObjectCreationExpressionSyntax WithArgumentListCore(ArgumentListSyntax? argumentList) => WithArgumentList(argumentList ?? throw new ArgumentNullException(nameof(argumentList))); + public new ImplicitObjectCreationExpressionSyntax WithArgumentList(ArgumentListSyntax argumentList) => Update(this.NewKeyword, argumentList, this.Initializer); + internal override BaseObjectCreationExpressionSyntax WithInitializerCore(InitializerExpressionSyntax? initializer) => WithInitializer(initializer); + public new ImplicitObjectCreationExpressionSyntax WithInitializer(InitializerExpressionSyntax? initializer) => Update(this.NewKeyword, this.ArgumentList, initializer); + + internal override BaseObjectCreationExpressionSyntax AddArgumentListArgumentsCore(params ArgumentSyntax[] items) => AddArgumentListArguments(items); + public new ImplicitObjectCreationExpressionSyntax AddArgumentListArguments(params ArgumentSyntax[] items) => WithArgumentList(this.ArgumentList.WithArguments(this.ArgumentList.Arguments.AddRange(items))); + } + /// Class which represents the syntax node for object creation expression. - public sealed partial class ObjectCreationExpressionSyntax : ExpressionSyntax + public sealed partial class ObjectCreationExpressionSyntax : BaseObjectCreationExpressionSyntax { private TypeSyntax? type; private ArgumentListSyntax? argumentList; @@ -2706,16 +2794,16 @@ internal ObjectCreationExpressionSyntax(InternalSyntax.CSharpSyntaxNode green, S } /// SyntaxToken representing the new keyword. - public SyntaxToken NewKeyword => new SyntaxToken(this, ((Syntax.InternalSyntax.ObjectCreationExpressionSyntax)this.Green).newKeyword, Position, 0); + public override SyntaxToken NewKeyword => new SyntaxToken(this, ((Syntax.InternalSyntax.ObjectCreationExpressionSyntax)this.Green).newKeyword, Position, 0); /// TypeSyntax representing the type of the object being created. public TypeSyntax Type => GetRed(ref this.type, 1)!; /// ArgumentListSyntax representing the list of arguments passed as part of the object creation expression. - public ArgumentListSyntax? ArgumentList => GetRed(ref this.argumentList, 2); + public override ArgumentListSyntax? ArgumentList => GetRed(ref this.argumentList, 2); /// InitializerExpressionSyntax representing the initializer expression for the object being created. - public InitializerExpressionSyntax? Initializer => GetRed(ref this.initializer, 3); + public override InitializerExpressionSyntax? Initializer => GetRed(ref this.initializer, 3); internal override SyntaxNode? GetNodeSlot(int index) => index switch @@ -2750,12 +2838,16 @@ public ObjectCreationExpressionSyntax Update(SyntaxToken newKeyword, TypeSyntax return this; } - public ObjectCreationExpressionSyntax WithNewKeyword(SyntaxToken newKeyword) => Update(newKeyword, this.Type, this.ArgumentList, this.Initializer); + internal override BaseObjectCreationExpressionSyntax WithNewKeywordCore(SyntaxToken newKeyword) => WithNewKeyword(newKeyword); + public new ObjectCreationExpressionSyntax WithNewKeyword(SyntaxToken newKeyword) => Update(newKeyword, this.Type, this.ArgumentList, this.Initializer); public ObjectCreationExpressionSyntax WithType(TypeSyntax type) => Update(this.NewKeyword, type, this.ArgumentList, this.Initializer); - public ObjectCreationExpressionSyntax WithArgumentList(ArgumentListSyntax? argumentList) => Update(this.NewKeyword, this.Type, argumentList, this.Initializer); - public ObjectCreationExpressionSyntax WithInitializer(InitializerExpressionSyntax? initializer) => Update(this.NewKeyword, this.Type, this.ArgumentList, initializer); + internal override BaseObjectCreationExpressionSyntax WithArgumentListCore(ArgumentListSyntax? argumentList) => WithArgumentList(argumentList); + public new ObjectCreationExpressionSyntax WithArgumentList(ArgumentListSyntax? argumentList) => Update(this.NewKeyword, this.Type, argumentList, this.Initializer); + internal override BaseObjectCreationExpressionSyntax WithInitializerCore(InitializerExpressionSyntax? initializer) => WithInitializer(initializer); + public new ObjectCreationExpressionSyntax WithInitializer(InitializerExpressionSyntax? initializer) => Update(this.NewKeyword, this.Type, this.ArgumentList, initializer); - public ObjectCreationExpressionSyntax AddArgumentListArguments(params ArgumentSyntax[] items) + internal override BaseObjectCreationExpressionSyntax AddArgumentListArgumentsCore(params ArgumentSyntax[] items) => AddArgumentListArguments(items); + public new ObjectCreationExpressionSyntax AddArgumentListArguments(params ArgumentSyntax[] items) { var argumentList = this.ArgumentList ?? SyntaxFactory.ArgumentList(); return WithArgumentList(argumentList.WithArguments(argumentList.Arguments.AddRange(items))); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs index b54a5797ddce6..53b057ad2f0ed 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs @@ -336,6 +336,11 @@ public override BoundNode VisitDefaultLiteral(BoundDefaultLiteral node) throw ExceptionUtilities.Unreachable; } + public override BoundNode VisitUnconvertedObjectCreationExpression(BoundUnconvertedObjectCreationExpression node) + { + throw ExceptionUtilities.Unreachable; + } + public override BoundNode VisitDeconstructValuePlaceholder(BoundDeconstructValuePlaceholder node) { return PlaceholderReplacement(node); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleBinaryOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleBinaryOperator.cs index 1d32550c927d0..8a2d8dd3063f1 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleBinaryOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_TupleBinaryOperator.cs @@ -226,6 +226,7 @@ bool conversionMustBePerformedOnOriginalExpression(BoundConversion expr, Convers case ConversionKind.SwitchExpression: // a switch expression must have its arms converted case ConversionKind.StackAllocToPointerType: // a stack alloc is not well-defined without an enclosing conversion case ConversionKind.StackAllocToSpanType: + case ConversionKind.ObjectCreation: return true; default: return false; diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 8cb298ee8cbd0..fb1fd35cdf75c 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -5890,6 +5890,7 @@ private enum ParseTypeMode AfterIs, DefinitePattern, AfterOut, + AfterRef, AfterTupleComma, AsExpression, NewExpression, @@ -5910,7 +5911,7 @@ private TypeSyntax ParseType(ParseTypeMode mode = ParseTypeMode.Normal) readonlyKeyword = this.CheckFeatureAvailability(readonlyKeyword, MessageID.IDS_FeatureReadOnlyReferences); } - var type = ParseTypeCore(mode); + var type = ParseTypeCore(ParseTypeMode.AfterRef); return _syntaxFactory.RefType(refKeyword, readonlyKeyword, type); } @@ -5941,13 +5942,14 @@ private TypeSyntax ParseTypeCore(ParseTypeMode mode) case ParseTypeMode.AsExpression: case ParseTypeMode.Normal: case ParseTypeMode.Parameter: + case ParseTypeMode.AfterRef: nameOptions = NameOptions.None; break; default: throw ExceptionUtilities.UnexpectedValue(mode); } - var type = this.ParseUnderlyingType(parentIsParameter: mode == ParseTypeMode.Parameter, options: nameOptions); + var type = this.ParseUnderlyingType(mode, options: nameOptions); Debug.Assert(type != null); int lastTokenPosition = -1; @@ -5997,6 +5999,7 @@ bool canBeNullableType() case ParseTypeMode.Normal: case ParseTypeMode.Parameter: case ParseTypeMode.AfterOut: + case ParseTypeMode.AfterRef: case ParseTypeMode.AsExpression: case ParseTypeMode.NewExpression: type = this.ParsePointerTypeMods(type); @@ -6233,7 +6236,7 @@ private PostSkipAction SkipBadArrayRankSpecifierTokens(ref SyntaxToken openBrack expected); } - private TypeSyntax ParseUnderlyingType(bool parentIsParameter, NameOptions options = NameOptions.None) + private TypeSyntax ParseUnderlyingType(ParseTypeMode mode, NameOptions options = NameOptions.None) { if (IsPredefinedType(this.CurrentToken.Kind)) { @@ -6241,24 +6244,29 @@ private TypeSyntax ParseUnderlyingType(bool parentIsParameter, NameOptions optio var token = this.EatToken(); if (token.Kind == SyntaxKind.VoidKeyword && this.CurrentToken.Kind != SyntaxKind.AsteriskToken) { - token = this.AddError(token, parentIsParameter ? ErrorCode.ERR_NoVoidParameter : ErrorCode.ERR_NoVoidHere); + token = this.AddError(token, mode == ParseTypeMode.Parameter ? ErrorCode.ERR_NoVoidParameter : ErrorCode.ERR_NoVoidHere); } return _syntaxFactory.PredefinedType(token); } - else if (IsTrueIdentifier()) + + if (IsTrueIdentifier()) { return this.ParseQualifiedName(options); } - else if (this.CurrentToken.Kind == SyntaxKind.OpenParenToken) + + if (this.CurrentToken.Kind == SyntaxKind.OpenParenToken) { return this.ParseTupleType(); } - else + + var name = this.CreateMissingIdentifierName(); + if (mode != ParseTypeMode.NewExpression) { - var name = this.CreateMissingIdentifierName(); return this.AddError(name, ErrorCode.ERR_TypeExpected); } + + return name; } private TypeSyntax ParsePointerTypeMods(TypeSyntax type) @@ -8824,6 +8832,7 @@ private static Precedence GetPrecedence(SyntaxKind op) case SyntaxKind.IdentifierName: case SyntaxKind.ImplicitArrayCreationExpression: case SyntaxKind.ImplicitStackAllocArrayCreationExpression: + case SyntaxKind.ImplicitObjectCreationExpression: case SyntaxKind.InterpolatedStringExpression: case SyntaxKind.InvocationExpression: case SyntaxKind.NullLiteralExpression: @@ -10439,43 +10448,83 @@ private bool IsDictionaryInitializer() private ExpressionSyntax ParseArrayOrObjectCreationExpression() { SyntaxToken @new = this.EatToken(SyntaxKind.NewKeyword); - var type = this.ParseType(ParseTypeMode.NewExpression); - if (type.Kind == SyntaxKind.ArrayType) - { - // Check for an initializer. - InitializerExpressionSyntax initializer = null; - if (this.CurrentToken.Kind == SyntaxKind.OpenBraceToken) - { - initializer = this.ParseArrayInitializer(); - } + TypeSyntax type = null; + InitializerExpressionSyntax initializer = null; - return _syntaxFactory.ArrayCreationExpression(@new, (ArrayTypeSyntax)type, initializer); + if (IsTargetTypedObjectCreation()) + { + @new = CheckFeatureAvailability(@new, MessageID.IDS_FeatureTargetTypedObjectCreation); } else { - ArgumentListSyntax argumentList = null; - if (this.CurrentToken.Kind == SyntaxKind.OpenParenToken) + type = this.ParseType(ParseTypeMode.NewExpression); + if (type.Kind == SyntaxKind.ArrayType) { - argumentList = this.ParseParenthesizedArgumentList(); - } + // Check for an initializer. + if (this.CurrentToken.Kind == SyntaxKind.OpenBraceToken) + { + initializer = this.ParseArrayInitializer(); + } - InitializerExpressionSyntax initializer = null; - if (this.CurrentToken.Kind == SyntaxKind.OpenBraceToken) - { - initializer = this.ParseObjectOrCollectionInitializer(); + return _syntaxFactory.ArrayCreationExpression(@new, (ArrayTypeSyntax)type, initializer); } + } + + ArgumentListSyntax argumentList = null; + if (this.CurrentToken.Kind == SyntaxKind.OpenParenToken) + { + argumentList = this.ParseParenthesizedArgumentList(); + } + + if (this.CurrentToken.Kind == SyntaxKind.OpenBraceToken) + { + initializer = this.ParseObjectOrCollectionInitializer(); + } + + // we need one or the other + if (argumentList == null && initializer == null) + { + argumentList = _syntaxFactory.ArgumentList( + this.EatToken(SyntaxKind.OpenParenToken, ErrorCode.ERR_BadNewExpr), + default(SeparatedSyntaxList), + SyntaxFactory.MissingToken(SyntaxKind.CloseParenToken)); + } + + return type is null + ? (ExpressionSyntax)_syntaxFactory.ImplicitObjectCreationExpression(@new, argumentList, initializer) + : (ExpressionSyntax)_syntaxFactory.ObjectCreationExpression(@new, type, argumentList, initializer); + } - // we need one or the other - if (argumentList == null && initializer == null) + private bool IsTargetTypedObjectCreation() + { + // The caller is expected to have consumed the new keyword. + if (this.CurrentToken.Kind != SyntaxKind.OpenParenToken) + { + return false; + } + + var point = this.GetResetPoint(); + try + { + this.EatToken(); // open paren + ScanTypeFlags scanTypeFlags = ScanTupleType(out _); + if (scanTypeFlags != ScanTypeFlags.NotType) { - argumentList = _syntaxFactory.ArgumentList( - this.EatToken(SyntaxKind.OpenParenToken, ErrorCode.ERR_BadNewExpr), - default(SeparatedSyntaxList), - SyntaxFactory.MissingToken(SyntaxKind.CloseParenToken)); + switch (this.CurrentToken.Kind) + { + case SyntaxKind.QuestionToken: // e.g. `new(a, b)?()` + case SyntaxKind.OpenBracketToken: // e.g. `new(a, b)[]` + case SyntaxKind.OpenParenToken: // e.g. `new(a, b)()` for better error recovery + return false; + } } - - return _syntaxFactory.ObjectCreationExpression(@new, type, argumentList, initializer); + return true; + } + finally + { + this.Reset(ref point); + this.Release(ref point); } } diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 746832ef9350f..3e7d2473ba621 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -8,6 +8,12 @@ *REMOVED*static Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(string text, Microsoft.CodeAnalysis.CSharp.CSharpParseOptions options = null, string path = "", System.Text.Encoding encoding = null, System.Collections.Immutable.ImmutableDictionary diagnosticOptions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.SyntaxTree *REMOVED*static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParseSyntaxTree(Microsoft.CodeAnalysis.Text.SourceText text, Microsoft.CodeAnalysis.ParseOptions options = null, string path = "", System.Collections.Immutable.ImmutableDictionary diagnosticOptions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.SyntaxTree *REMOVED*static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParseSyntaxTree(string text, Microsoft.CodeAnalysis.ParseOptions options = null, string path = "", System.Text.Encoding encoding = null, System.Collections.Immutable.ImmutableDictionary diagnosticOptions = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.SyntaxTree +*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax +*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.Initializer.get -> Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax +*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.NewKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken +*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax +*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.Initializer.get -> Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax +*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.NewKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken Microsoft.CodeAnalysis.CSharp.Conversion.IsDefaultLiteral.get -> bool Microsoft.CodeAnalysis.CSharp.ForEachStatementInfo.IsAsynchronous.get -> bool Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax.AddBodyAttributeLists(params Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax @@ -20,6 +26,11 @@ Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.AddBlockAtt Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.SyntaxToken delegateKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.WithExpressionBody(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.BaseMethodDeclarationSyntax.AddBodyAttributeLists(params Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseMethodDeclarationSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.AddArgumentListArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.WithArgumentList(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.WithInitializer(Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax initializer) -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.WithNewKeyword(Microsoft.CodeAnalysis.SyntaxToken newKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax.AddAttributeLists(params Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken openBraceToken, Microsoft.CodeAnalysis.SyntaxList statements, Microsoft.CodeAnalysis.SyntaxToken closeBraceToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax.WithAttributeLists(Microsoft.CodeAnalysis.SyntaxList attributeLists) -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax @@ -67,6 +78,12 @@ Microsoft.CodeAnalysis.CSharp.Syntax.GotoStatementSyntax.WithAttributeLists(Micr Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax.AddAttributeLists(params Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken ifKeyword, Microsoft.CodeAnalysis.SyntaxToken openParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax condition, Microsoft.CodeAnalysis.SyntaxToken closeParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax statement, Microsoft.CodeAnalysis.CSharp.Syntax.ElseClauseSyntax else) -> Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax.WithAttributeLists(Microsoft.CodeAnalysis.SyntaxList attributeLists) -> Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.AddArgumentListArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken newKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList, Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax initializer) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.WithArgumentList(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.WithInitializer(Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax initializer) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.WithNewKeyword(Microsoft.CodeAnalysis.SyntaxToken newKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.LabeledStatementSyntax.AddAttributeLists(params Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.LabeledStatementSyntax Microsoft.CodeAnalysis.CSharp.Syntax.LabeledStatementSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.SyntaxToken colonToken, Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax statement) -> Microsoft.CodeAnalysis.CSharp.Syntax.LabeledStatementSyntax Microsoft.CodeAnalysis.CSharp.Syntax.LabeledStatementSyntax.WithAttributeLists(Microsoft.CodeAnalysis.SyntaxList attributeLists) -> Microsoft.CodeAnalysis.CSharp.Syntax.LabeledStatementSyntax @@ -124,9 +141,14 @@ Microsoft.CodeAnalysis.CSharp.Syntax.WhileStatementSyntax.WithAttributeLists(Mic Microsoft.CodeAnalysis.CSharp.Syntax.YieldStatementSyntax.AddAttributeLists(params Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.YieldStatementSyntax Microsoft.CodeAnalysis.CSharp.Syntax.YieldStatementSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken yieldKeyword, Microsoft.CodeAnalysis.SyntaxToken returnOrBreakKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.YieldStatementSyntax Microsoft.CodeAnalysis.CSharp.Syntax.YieldStatementSyntax.WithAttributeLists(Microsoft.CodeAnalysis.SyntaxList attributeLists) -> Microsoft.CodeAnalysis.CSharp.Syntax.YieldStatementSyntax +Microsoft.CodeAnalysis.CSharp.SyntaxKind.ImplicitObjectCreationExpression = 8659 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind abstract Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.Block.get -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax abstract Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.ExpressionBody.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax +abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax +abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.Initializer.get -> Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax +abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.NewKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken abstract Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList +override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitImplicitObjectCreationExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode override Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.Block.get -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax override Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.ExpressionBody.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax override Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList @@ -142,10 +164,18 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.ForEachVariableStatementSyntax.Att override Microsoft.CodeAnalysis.CSharp.Syntax.ForStatementSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList override Microsoft.CodeAnalysis.CSharp.Syntax.GotoStatementSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList override Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList +override Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void +override Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult +override Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax +override Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.Initializer.get -> Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax +override Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax.NewKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken override Microsoft.CodeAnalysis.CSharp.Syntax.LabeledStatementSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList override Microsoft.CodeAnalysis.CSharp.Syntax.LocalDeclarationStatementSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList override Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList override Microsoft.CodeAnalysis.CSharp.Syntax.LockStatementSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList +override Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax +override Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.Initializer.get -> Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax +override Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.NewKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken override Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.Block.get -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax override Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.ExpressionBody.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax override Microsoft.CodeAnalysis.CSharp.Syntax.ReturnStatementSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList @@ -191,6 +221,9 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.GotoStatement(Microsoft.CodeA static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.GotoStatement(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken gotoKeyword, Microsoft.CodeAnalysis.SyntaxToken caseOrDefaultKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.GotoStatementSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.IfStatement(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax condition, Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax statement, Microsoft.CodeAnalysis.CSharp.Syntax.ElseClauseSyntax else) -> Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.IfStatement(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken ifKeyword, Microsoft.CodeAnalysis.SyntaxToken openParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax condition, Microsoft.CodeAnalysis.SyntaxToken closeParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax statement, Microsoft.CodeAnalysis.CSharp.Syntax.ElseClauseSyntax else) -> Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ImplicitObjectCreationExpression() -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ImplicitObjectCreationExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList, Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax initializer) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ImplicitObjectCreationExpression(Microsoft.CodeAnalysis.SyntaxToken newKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList, Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax initializer) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LabeledStatement(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax statement) -> Microsoft.CodeAnalysis.CSharp.Syntax.LabeledStatementSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LabeledStatement(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.SyntaxToken colonToken, Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax statement) -> Microsoft.CodeAnalysis.CSharp.Syntax.LabeledStatementSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LocalDeclarationStatement(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken awaitKeyword, Microsoft.CodeAnalysis.SyntaxToken usingKeyword, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.VariableDeclarationSyntax declaration, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalDeclarationStatementSyntax @@ -224,3 +257,5 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WhileStatement(Microsoft.Code static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WhileStatement(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken whileKeyword, Microsoft.CodeAnalysis.SyntaxToken openParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax condition, Microsoft.CodeAnalysis.SyntaxToken closeParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax statement) -> Microsoft.CodeAnalysis.CSharp.Syntax.WhileStatementSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.YieldStatement(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.YieldStatementSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.YieldStatement(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxToken yieldKeyword, Microsoft.CodeAnalysis.SyntaxToken returnOrBreakKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.YieldStatementSyntax +virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitImplicitObjectCreationExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax node) -> void +virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitImplicitObjectCreationExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax node) -> TResult diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs index 3fe63e93f82b5..a987ec95449b8 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs @@ -356,6 +356,7 @@ internal static bool ReportDefaultParameterErrors( ParameterSyntax parameterSyntax, SourceParameterSymbol parameter, BoundExpression defaultExpression, + BoundExpression convertedExpression, DiagnosticBag diagnostics) { bool hasErrors = false; @@ -411,7 +412,7 @@ internal static bool ReportDefaultParameterErrors( hasErrors = true; } } - else if (!defaultExpression.HasAnyErrors && !IsValidDefaultValue(defaultExpression)) + else if (!defaultExpression.HasAnyErrors && !IsValidDefaultValue(defaultExpression.IsTypelessNew() ? convertedExpression : defaultExpression)) { // error CS1736: Default parameter value for '{0}' must be a compile-time constant diagnostics.Add(ErrorCode.ERR_DefaultValueMustBeConstant, parameterSyntax.Default.Value.Location, parameterSyntax.Identifier.ValueText); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index 8f0b049b68fa5..aa06402894348 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -259,7 +259,7 @@ protected ConstantValue MakeDefaultExpression(DiagnosticBag diagnostics, Binder return ConstantValue.Bad; } - bool hasErrors = ParameterHelpers.ReportDefaultParameterErrors(binder, ContainingSymbol, parameterSyntax, this, valueBeforeConversion, diagnostics); + bool hasErrors = ParameterHelpers.ReportDefaultParameterErrors(binder, ContainingSymbol, parameterSyntax, this, valueBeforeConversion, convertedExpression, diagnostics); if (hasErrors) { return ConstantValue.Bad; diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index 3226af76846c6..9eec0189ed36a 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -1429,9 +1429,53 @@ Creates an InitializerExpressionSyntax node. - + + + + + + SyntaxToken representing the new keyword. + + + + + ArgumentListSyntax representing the list of arguments passed as part of the object creation expression. + + + + + InitializerExpressionSyntax representing the initializer expression for the object being created. + + + + + + + + + SyntaxToken representing the new keyword. + + + + + ArgumentListSyntax representing the list of arguments passed as part of the object creation expression. + + + + + InitializerExpressionSyntax representing the initializer expression for the object being created. + + + + Class which represents the syntax node for implicit object creation expression. + + + Creates an ImplicitObjectCreationExpressionSyntax node. + + + - + SyntaxToken representing the new keyword. @@ -1442,12 +1486,12 @@ TypeSyntax representing the type of the object being created. - + ArgumentListSyntax representing the list of arguments passed as part of the object creation expression. - + InitializerExpressionSyntax representing the initializer expression for the object being created. diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index 69df5ed9d5874..51cbde503f712 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -349,6 +349,7 @@ public enum SyntaxKind : ushort ImplicitElementAccess = 8656, IsPatternExpression = 8657, RangeExpression = 8658, + ImplicitObjectCreationExpression = 8659, // binary expressions AddExpression = 8668, diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index ce47fc9d76900..029233bbe33a8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -22,6 +22,11 @@ Pokud chcete pro interpolovaný doslovný řetězec použít @$ místo $@, použijte verzi jazyka {0} nebo vyšší. + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Operator '{0}' cannot be applied to 'default' and operand of type '{1}' because it is a type parameter that is not known to be a reference type Operátor {0} nejde použít pro default a operand typu {1}, protože se jedná o parametr typu, který není znám jako odkazový typ. @@ -82,6 +87,11 @@ Operátor typeof nejde použít na typ odkazů s možnou hodnotou null. + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. Neplatný operand pro porovnávací vzorek. Vyžaduje se hodnota, ale nalezeno: {0}. @@ -482,6 +492,21 @@ Typy řazené kolekce členů, které se používají jako operandy operátoru == nebo !=, musí mít odpovídající kardinality. U tohoto operátoru je ale kardinalita typů řazené kolekce členů vlevo {0} a vpravo {1}. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint {0}: Nejde zadat třídu omezení a zároveň omezení unmanaged. @@ -979,6 +1004,11 @@ <výraz přepínače> + + target-typed object creation + target-typed object creation + + tuple equality rovnost řazené kolekce členů @@ -2119,11 +2149,6 @@ Operátor {0} nejde použít na operand typu {1}. - - Operator '{0}' cannot be applied to operand '{1}' - Operátor {0} nejde použít pro operand {1}. - - Keyword 'this' is not valid in a static property, static method, or static field initializer Klíčové slovo this není platné ve statické vlastnosti, ve statické metodě ani ve statickém inicializátoru pole. @@ -2164,11 +2189,6 @@ Operátor {0} je nejednoznačný na operandech typu {1} a {2}. - - Operator '{0}' is ambiguous on operands 'default' and 'default' - Operátor {0} je nejednoznačný při použití s operandy default a default. - - Operator '{0}' is ambiguous on an operand of type '{1}' Operátor {0} je nejednoznačný na operandu typu {1}. @@ -5493,8 +5513,8 @@ Blok catch() po bloku catch (System.Exception e) může zachytit výjimky, kter - A new expression requires (), [], or {} after type - Výraz new vyžaduje za typem použití znaků (), [] nebo {} + A new expression requires an argument list or (), [], or {} after type + Výraz new vyžaduje za typem použití znaků (), [] nebo {} diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 58143615b438f..be54f32877ef5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -22,6 +22,11 @@ Um für eine interpolierte ausführliche Zeichenfolge "@$" anstelle von "$@" zu verwenden, benötigen Sie Sprachversion {0} oder höher. + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Operator '{0}' cannot be applied to 'default' and operand of type '{1}' because it is a type parameter that is not known to be a reference type Der Operator "{0}" kann nicht auf "default" und den Operanden vom Typ "{1}" angewendet werden, weil es sich um einen Typparameter handelt, der nicht als Verweistyp bekannt ist. @@ -82,6 +87,11 @@ Der typeof-Operator kann nicht für einen Verweistyp verwendet werden, der NULL-Werte zulässt. + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. Ungültiger Operand für die Musterübereinstimmung. Ein Wert ist erforderlich, gefunden wurde aber "{0}". @@ -482,6 +492,21 @@ Tupeltypen, die als Operanden eines ==- oder !=-Operators verwendet werden, müssen übereinstimmende Kardinalitäten aufweisen. Dieser Operator enthält jedoch Tupeltypen der Kardinalität "{0}" auf der linken und "{1}" auf der rechten Seite. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint "{0}": Eine Einschränkungsklasse kann nicht gleichzeitig mit einer unmanaged-Einschränkung angegeben werden. @@ -979,6 +1004,11 @@ <switch-Ausdruck> + + target-typed object creation + target-typed object creation + + tuple equality Tupelgleichheit @@ -2119,11 +2149,6 @@ Der {0}-Operator kann nicht auf einen Operanden vom Typ "{1}" angewendet werden. - - Operator '{0}' cannot be applied to operand '{1}' - Der Operator "{0}" kann nicht auf den Operanden "{1}" angewendet werden. - - Keyword 'this' is not valid in a static property, static method, or static field initializer Das this-Schlüsselwort ist in einer statischen Eigenschaft/Methode oder einem statischen Feldinitialisierer nicht gültig. @@ -2164,11 +2189,6 @@ Der {0}-Operator ist bei Operanden vom Typ "{1}" und "{2}" mehrdeutig. - - Operator '{0}' is ambiguous on operands 'default' and 'default' - Der Operator "{0}" ist mehrdeutig bei den Operanden "default" und "default". - - Operator '{0}' is ambiguous on an operand of type '{1}' Der {0}-Operator ist für einen Operanden vom Typ "{1}" mehrdeutig. @@ -5493,8 +5513,8 @@ Ein catch()-Block nach einem catch (System.Exception e)-Block kann nicht-CLS-Aus - A new expression requires (), [], or {} after type - Für einen new-Ausdruck ist nach type (), [] oder {} erforderlich. + A new expression requires an argument list or (), [], or {} after type + Für einen new-Ausdruck ist nach type (), [] oder {} erforderlich. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 1e254da3eef91..daf86d1d19b31 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -22,6 +22,11 @@ Para usar "@$" en lugar de "$@" para una cadena textual interpolada, use la versión "{0}" del lenguaje o una posterior. + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Operator '{0}' cannot be applied to 'default' and operand of type '{1}' because it is a type parameter that is not known to be a reference type No se puede aplicar el operador "{0}" a "Predeterminado" y a un operando de tipo "{1}", ya que es un parámetro de tipo del que no se conoce que sea un tipo de referencia. @@ -82,6 +87,11 @@ El operador typeof no se puede usar en un tipo de referencia que acepta valores NULL + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. Operando no válido para la coincidencia de patrones. Se requería un valor, pero se encontró '{0}'. @@ -482,6 +492,21 @@ Los tipos de tupla utilizados como operandos de un operador == o != deben tener cardinalidades coincidentes. Pero este operador tiene tipos de tupla de cardinalidad {0} a la izquierda y {1} a la derecha. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint "{0}": no se puede especificar a la vez una clase de restricción y la restricción "unmanaged" @@ -979,6 +1004,11 @@ <expresión switch> + + target-typed object creation + target-typed object creation + + tuple equality igualdad de tupla @@ -2119,11 +2149,6 @@ El operador '{0}' no se puede aplicar al operando del tipo '{1}' - - Operator '{0}' cannot be applied to operand '{1}' - El operador "{0}" no se puede aplicar al operando del tipo "{1}" - - Keyword 'this' is not valid in a static property, static method, or static field initializer La palabra clave 'this' no es válida en una propiedad, método o inicializador de campo estáticos @@ -2164,11 +2189,6 @@ El operador '{0}' es ambiguo en operandos del tipo '{1}' y '{2}' - - Operator '{0}' is ambiguous on operands 'default' and 'default' - El operador "{0}" es ambiguo en los operandos "default" y "default" - - Operator '{0}' is ambiguous on an operand of type '{1}' El operador '{0}' es ambiguo en un operando del tipo '{1}' @@ -5493,8 +5513,8 @@ Un bloque catch() después de un bloque catch (System.Exception e) puede abarcar - A new expression requires (), [], or {} after type - Una expresión new requiere (), [] o {} después del tipo + A new expression requires an argument list or (), [], or {} after type + Una expresión new requiere (), [] o {} después del tipo diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index f428da20b2808..2ef1e447d9b63 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -22,6 +22,11 @@ Pour utiliser '@$' à la place de '$@' pour une chaîne verbatim interpolée, utilisez la version de langage '{0}' ou une version ultérieure. + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Operator '{0}' cannot be applied to 'default' and operand of type '{1}' because it is a type parameter that is not known to be a reference type L'opérateur '{0}' ne peut pas être appliqué à 'default' et à l'opérande de type '{1}', car il s'agit d'un paramètre de type qui n'est pas connu en tant que type référence @@ -82,6 +87,11 @@ Impossible d'utiliser l'opérateur typeof sur un type référence Nullable + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. Opérande non valide pour les critères spéciaux ; la valeur nécessaire n'est pas celle trouvée, '{0}'. @@ -482,6 +492,21 @@ Les types de tuple utilisés en tant qu'opérandes d'un opérateur == ou != doivent avoir des cardinalités correspondantes. Toutefois, cet opérateur a des types de tuple de cardinalité {0} à gauche et {1} à droite. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint '{0}' : impossible de spécifier à la fois une classe de contrainte et la contrainte 'unmanaged' @@ -979,6 +1004,11 @@ <expression switch> + + target-typed object creation + target-typed object creation + + tuple equality égalité de tuple @@ -2119,11 +2149,6 @@ Impossible d'appliquer l'opérateur '{0}' à un opérande de type '{1}' - - Operator '{0}' cannot be applied to operand '{1}' - Impossible d'appliquer l'opérateur '{0}' à un opérande '{1}' - - Keyword 'this' is not valid in a static property, static method, or static field initializer Le mot clé 'this' n'est pas valide dans un initialiseur de propriété statique, de méthode statique ou de champ statique @@ -2164,11 +2189,6 @@ L'opérateur '{0}' est ambigu pour des opérandes de type '{1}' et '{2}' - - Operator '{0}' is ambiguous on operands 'default' and 'default' - L'opérateur '{0}' est ambigu sur les opérandes 'default' et 'default' - - Operator '{0}' is ambiguous on an operand of type '{1}' L'opérateur '{0}' est ambigu pour un opérande de type '{1}' @@ -5493,8 +5513,8 @@ Un bloc catch() après un bloc catch (System.Exception e) peut intercepter des e - A new expression requires (), [], or {} after type - Une expression new exige que type soit suivi de (), [] ou {} + A new expression requires an argument list or (), [], or {} after type + Une expression new exige que type soit suivi de (), [] ou {} diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 1e8ded4c777f9..c6219199c0a84 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -22,6 +22,11 @@ Per usare '@$' invece di '$@' per una stringa verbatim interpolata, usare la versione '{0}' o versioni successive del linguaggio. + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Operator '{0}' cannot be applied to 'default' and operand of type '{1}' because it is a type parameter that is not known to be a reference type Non è possibile applicare l'operatore '{0}' a 'default ' e all'operando di tipo '{1}' perché è un parametro di tipo non noto come tipo riferimento @@ -82,6 +87,11 @@ Non è possibile usare l'operatore typeof nel tipo riferimento nullable + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. L'operando non è valido per i criteri di ricerca. È richiesto un valore ma è stato trovato '{0}'. @@ -482,6 +492,21 @@ Le cardinalità dei tipi di tupla usati come operandi di un operatore == o != devono essere uguali, ma questo operatore presenta tipi di tupla con cardinalità {0} sulla sinistra e {1} sulla destra. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint '{0}': non è possibile specificare sia una classe constraint che il vincolo 'unmanaged' @@ -979,6 +1004,11 @@ <espressione switch> + + target-typed object creation + target-typed object creation + + tuple equality uguaglianza tuple @@ -2119,11 +2149,6 @@ Non è possibile applicare l'operatore '{0}' all'operando di tipo '{1}' - - Operator '{0}' cannot be applied to operand '{1}' - Non è possibile applicare l'operatore '{0}' all'operando '{1}' - - Keyword 'this' is not valid in a static property, static method, or static field initializer La parola chiave 'this' non può essere utilizzata in una proprietà statica, in un metodo statico o nell'inizializzatore di un campo statico @@ -2164,11 +2189,6 @@ L'operatore '{0}' è ambiguo su operandi di tipo '{1}' e '{2}'. - - Operator '{0}' is ambiguous on operands 'default' and 'default' - L'operatore '{0}' è ambiguo sugli operandi 'default' e 'default' - - Operator '{0}' is ambiguous on an operand of type '{1}' L'operatore '{0}' è ambiguo su un operando di tipo '{1}' @@ -5493,8 +5513,8 @@ Un blocco catch() dopo un blocco catch (System.Exception e) può rilevare eccezi - A new expression requires (), [], or {} after type - Un'espressione new richiede (), [] o {} dopo il tipo + A new expression requires an argument list or (), [], or {} after type + Un'espressione new richiede (), [] o {} dopo il tipo diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 926874553e3ef..0bc79d3cb2891 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -27,6 +27,11 @@ 演算子 '{0}' は、参照型として認識されていない型パラメーターであるため、型 '{1}' の 'default' およびオペランドに適用できません + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Cannot use a nullable reference type in object creation. オブジェクト作成では Null 許容参照型を使用できません。 @@ -82,6 +87,11 @@ NULL 許容参照型では typeof 演算子を使用できません + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. パターン マッチには使用できないオペランドです。値が必要ですが、'{0}' が見つかりました。 @@ -482,6 +492,21 @@ 演算子 == または != のオペランドとして使用するタプルの型は、カーディナリティが一致している必要があります。しかし、この演算子は、左辺のタプルの型のカーディナリティが {0} で、右辺が {1} です。 + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint '{0}': 制約クラスと 'unmanaged' 制約の両方を指定することはできません @@ -979,6 +1004,11 @@ <switch 式> + + target-typed object creation + target-typed object creation + + tuple equality タプルの等値性 @@ -2119,11 +2149,6 @@ 演算子 '{0}' は '{1}' 型のオペランドに適用できません - - Operator '{0}' cannot be applied to operand '{1}' - 演算子 '{0}' はオペランド '{1}' に適用できません - - Keyword 'this' is not valid in a static property, static method, or static field initializer キーワード 'this' は、静的プロパティ、静的メソッド、または静的フィールド初期化子では無効です @@ -2164,11 +2189,6 @@ 型 '{1}' および '{2}' のオペランドの演算子 '{0}' があいまいです - - Operator '{0}' is ambiguous on operands 'default' and 'default' - 演算子 '{0}' は、オペランド 'default' および 'default' であいまいです - - Operator '{0}' is ambiguous on an operand of type '{1}' 演算子 '{0}' は型 '{1}' のオペランドに対してあいまいです @@ -5493,8 +5513,8 @@ AssemblyInfo.cs ファイルで RuntimeCompatibilityAttribute が false に設 - A new expression requires (), [], or {} after type - new 式は型の後に丸かっこ ()、角かっこ []、または 波かっこ {} を必要とします。 + A new expression requires an argument list or (), [], or {} after type + new 式は型の後に丸かっこ ()、角かっこ []、または 波かっこ {} を必要とします。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 87f6184435e3f..62bdc54413913 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -27,6 +27,11 @@ '{0}' 연산자는 참조 형식인 것으로 알려지지 않은 형식 매개 변수이므로 'default' 및 '{1}' 형식의 피연산자에 적용할 수 없습니다. + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Cannot use a nullable reference type in object creation. nullable 참조 형식은 개체를 만드는 데 사용할 수 없습니다. @@ -82,6 +87,11 @@ typeof 연산자는 nullable 참조 형식에 사용할 수 없습니다. + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. 패턴 일치에 대한 피연산자가 잘못되었습니다. 값이 필요하지만 '{0}'을(를) 찾았습니다. @@ -482,6 +492,21 @@ == 또는 != 연산자의 피연산자로 사용되는 튜플 형식에는 일치하는 카디널리티가 있어야 합니다. 하지만 이 연산자는 왼쪽에 {0}, 오른쪽에 {1} 카디널리티 형식의 튜플이 있습니다. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint '{0}': constraint 클래스와 'unmanaged' 제약 조건을 둘 다 지정할 수는 없습니다. @@ -979,6 +1004,11 @@ <switch 식> + + target-typed object creation + target-typed object creation + + tuple equality 튜플 같음 @@ -2119,11 +2149,6 @@ {0}' 연산자는 '{1}' 형식의 피연산자에 적용할 수 없습니다. - - Operator '{0}' cannot be applied to operand '{1}' - {0}' 연산자는 '{1}' 피연산자에 적용할 수 없습니다. - - Keyword 'this' is not valid in a static property, static method, or static field initializer 정적 속성, 정적 메서드 또는 정적 필드 이니셜라이저에는 'this' 키워드를 사용할 수 없습니다. @@ -2164,11 +2189,6 @@ {0}' 연산자가 모호하여 '{1}' 및 '{2}' 형식의 피연산자에 사용할 수 없습니다. - - Operator '{0}' is ambiguous on operands 'default' and 'default' - {0}' 연산자가 모호하여 'default' 및 'default' 피연산자에 사용할 수 없습니다. - - Operator '{0}' is ambiguous on an operand of type '{1}' {0}' 연산자가 모호하여 '{1}' 형식의 피연산자에 사용할 수 없습니다. @@ -5493,8 +5513,8 @@ catch (System.Exception e) 블록 뒤의 catch() 블록은 RuntimeCompatibilityA - A new expression requires (), [], or {} after type - new 식은 형식 뒤에 (), [], 또는 {}가 필요합니다. + A new expression requires an argument list or (), [], or {} after type + new 식은 형식 뒤에 (), [], 또는 {}가 필요합니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 8eae9d29c8ff3..aa310e231386c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -22,6 +22,11 @@ Aby użyć elementu „@$” zamiast elementu „$@” w interpolowanym ciągu dosłownym, użyj wersji języka „{0}” lub nowszej. + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Operator '{0}' cannot be applied to 'default' and operand of type '{1}' because it is a type parameter that is not known to be a reference type Nie można zastosować operatora „{0}” do elementu „default” i operandu typu „{1}”, ponieważ jest to parametr typu, który nie jest znany jako typ referencyjny @@ -82,6 +87,11 @@ Nie można użyć operatora typeof w przypadku typu referencyjnego dopuszczającego wartość null + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. Nieprawidłowy operand dla dopasowania wzorca; wymagana jest wartość, a znaleziono „{0}”. @@ -482,6 +492,21 @@ Typy krotek używane jako operandy operatorów == lub != muszą mieć zgodne kardynalności. Ten operator zawiera natomiast typy krotek o kardynalności {0} z lewej strony i {1} z prawej strony. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint „{0}”: nie można jednocześnie określić klasy ograniczenia i ograniczenia „unmanaged” @@ -979,6 +1004,11 @@ <wyrażenie przełącznika> + + target-typed object creation + target-typed object creation + + tuple equality równość krotki @@ -2119,11 +2149,6 @@ Nie można zastosować operatora „{0}” do argumentu operacji typu „{1}”. - - Operator '{0}' cannot be applied to operand '{1}' - Nie można zastosować operatora „{0}” do operandu „{1}” - - Keyword 'this' is not valid in a static property, static method, or static field initializer W przypadku statycznej właściwości, statycznej metody lub statycznego inicjatora pola użycie słowa kluczowego „this” jest nieprawidłowe @@ -2164,11 +2189,6 @@ Operator „{0}” jest niejednoznaczny dla operandów typu „{1}” i „{2}” - - Operator '{0}' is ambiguous on operands 'default' and 'default' - Operator „{0}” jest niejednoznaczny dla operandów „default” i „default” - - Operator '{0}' is ambiguous on an operand of type '{1}' Dla argumentu operacji typu „{0}” operator „{1}” jest niejednoznaczny. @@ -5493,8 +5513,8 @@ Blok catch() po bloku catch (System.Exception e) może przechwytywać wyjątki n - A new expression requires (), [], or {} after type - Wyrażenie new wymaga znaków (), [] lub {} po typie. + A new expression requires an argument list or (), [], or {} after type + Wyrażenie new wymaga znaków (), [] lub {} po typie. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 1e0020ca2a0a1..ddae4d73d4a4a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -27,6 +27,11 @@ O operador '{0}' não pode ser aplicado a 'default' e ao operando do tipo '{1}' porque é um parâmetro de tipo que não é conhecido como um tipo de referência + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Cannot use a nullable reference type in object creation. Não é possível usar um tipo de referência que permite valor nulo na criação do objeto. @@ -82,6 +87,11 @@ O operador typeof não pode ser usado em um tipo de referência anulável + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. Operando inválido para correspondência de padrão. Um valor era obrigatório, mas '{0}' foi encontrado. @@ -482,6 +492,21 @@ Os tipos de tupla usados como operandos de um operador == ou != precisam ter cardinalidades correspondentes. No entanto, este operador tem tipos de tupla de cardinalidade {0} na esquerda e {1} na direita. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint '{0}': não é possível especificar uma classe de restrição e a restrição 'unmanaged' @@ -977,6 +1002,11 @@ <expressão switch> + + target-typed object creation + target-typed object creation + + tuple equality igualdade de tupla @@ -2117,11 +2147,6 @@ O operador "{0}" não pode ser aplicado ao operando do tipo "{1}" - - Operator '{0}' cannot be applied to operand '{1}' - O operador '{0}' não pode ser aplicado ao operando '{1}' - - Keyword 'this' is not valid in a static property, static method, or static field initializer A palavra-chave 'this' não é válida em uma propriedade, um método ou um inicializador de campo estático @@ -2162,11 +2187,6 @@ O operador "{0}" é ambíguo em operandos dos tipos "{1}" e "{2}" - - Operator '{0}' is ambiguous on operands 'default' and 'default' - O operador '{0}' é ambíguo nos operandos 'default' e 'default' - - Operator '{0}' is ambiguous on an operand of type '{1}' O operador "{0}" é ambíguo em um operando do tipo "{1}" @@ -5491,8 +5511,8 @@ Um bloco catch() depois de um bloco catch (System.Exception e) poderá capturar - A new expression requires (), [], or {} after type - Uma expressão new requer (), [] ou {} após o tipo + A new expression requires an argument list or (), [], or {} after type + Uma expressão new requer (), [] ou {} após o tipo diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index d20ae75fe590a..7e3f0e5e55957 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -27,6 +27,11 @@ Оператор "{0}" не может быть применен к "default" и операнду типа "{1}", так как это параметр типа, который не является ссылочным типом. + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Cannot use a nullable reference type in object creation. При создании объекта невозможно использовать ссылочный тип, допускающий значения NULL. @@ -82,6 +87,11 @@ Оператор typeof невозможно использовать для ссылочного типа, допускающего значения NULL. + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. Недопустимый операнд для сопоставления с шаблоном. Требуется значение, но найдено "{0}". @@ -482,6 +492,21 @@ Типы кортежей, используемые в качестве операндов оператора == или !=, должны иметь соответствующие кратности. Однако этот оператор имеет типы кортежей с кратностью {0} слева и {1} справа. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint "{0}": невозможно одновременно задать класс ограничения и ограничение "unmanaged" @@ -979,6 +1004,11 @@ <выражения для выбора вариантов> + + target-typed object creation + target-typed object creation + + tuple equality равенство кортежей @@ -2119,11 +2149,6 @@ Оператор "{0}" невозможно применить к операнду типа "{1}". - - Operator '{0}' cannot be applied to operand '{1}' - Оператор "{0}" невозможно применить к операнду "{1}". - - Keyword 'this' is not valid in a static property, static method, or static field initializer Ключевое слово "this" не может использоваться в инициализаторах статических свойств, методов или полей. @@ -2164,11 +2189,6 @@ Оператор "{0}" для операнда типа "{1}" и "{2}" является неоднозначным. - - Operator '{0}' is ambiguous on operands 'default' and 'default' - Оператор "{0}" для операндов "по умолчанию" и "по умолчанию" является неоднозначным. - - Operator '{0}' is ambiguous on an operand of type '{1}' Оператор "{0}" для операнда типа "{1}" является неоднозначным. @@ -5493,8 +5513,8 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep - A new expression requires (), [], or {} after type - В выражении new после типа требуется "()", []" или "{}". + A new expression requires an argument list or (), [], or {} after type + В выражении new после типа требуется "()", []" или "{}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 6624139a138e3..8facf078455d5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -22,6 +22,11 @@ İlişkilendirilmiş tam bir dize için '$@' yerine '@$' kullanmak amacıyla lütfen '{0}' veya daha yüksek bir dil sürümü kullanın. + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Operator '{0}' cannot be applied to 'default' and operand of type '{1}' because it is a type parameter that is not known to be a reference type '{0}' işleci, başvuru türü olduğu bilinmeyen bir tür parametresi olduğundan 'default' öğesine ve '{1}' türünde işlenene uygulanamıyor @@ -82,6 +87,11 @@ Boş değer atanabilir tür üzerinde typeof işleci kullanılamaz + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. Desen eşleşmesi için işlenen geçersiz. Değer gerekiyordu ancak '{0}' bulundu. @@ -482,6 +492,21 @@ == veya != işlecinin işleneni olarak kullanılan demet türlerinin kardinalitesi eşleşmelidir. Ancak bu işleç, solda {0} ve sağda {1} demet kardinalite türlerine sahip olmalıdır. + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint '{0}': hem bir kısıtlama sınıfı hem de 'unmanaged' kısıtlaması belirtilemez @@ -979,6 +1004,11 @@ <switch expression> + + target-typed object creation + target-typed object creation + + tuple equality demet eşitliği @@ -2119,11 +2149,6 @@ {0}' işleci '{1}' türündeki işlenene uygulanamaz - - Operator '{0}' cannot be applied to operand '{1}' - {0}' işleci '{1}' türündeki işlenene uygulanamaz - - Keyword 'this' is not valid in a static property, static method, or static field initializer this' anahtar sözcüğü statik özellikte, statik yöntemde veya statik alan başlatıcısında geçerli değildir @@ -2164,11 +2189,6 @@ {0}' işleci, '{1}' ve '{2}' türündeki işlenenler üzerinde belirsizdir - - Operator '{0}' is ambiguous on operands 'default' and 'default' - {0}' işleci 'default' ve 'default' işlenenlerinde belirsiz - - Operator '{0}' is ambiguous on an operand of type '{1}' {0}' işleci, '{1}' türündeki bir işlenen üzerinde belirsizdir @@ -5493,8 +5513,8 @@ RuntimeCompatibilityAttribute AssemblyInfo.cs dosyasında false olarak ayarlanm - A new expression requires (), [], or {} after type - Bir new ifadesinde türden sonra (), [] veya {} gerekir + A new expression requires an argument list or (), [], or {} after type + Bir new ifadesinde türden sonra (), [] veya {} gerekir diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 8dbac7d9c181e..7e480dbf68d23 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -22,6 +22,11 @@ 若要对内插逐字字符串使用 "@$" 而不是 "$@",请使用语言版本 {0} 或更高版本。 + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Operator '{0}' cannot be applied to 'default' and operand of type '{1}' because it is a type parameter that is not known to be a reference type 运算符“{0}”不能应用于“默认值”和类型为“{1}”的操作数,因为它是一个类型参数,而系统不知道该参数是引用类型 @@ -82,6 +87,11 @@ 不能在可为 null 的引用类型上使用 typeof 运算符 + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. 用于模式匹配的操作数无效;需要值,但找到的是“{0}”。 @@ -482,6 +492,21 @@ 用作 == 或 != 运算符的操作数的元组类型必须具有匹配的基数。但此运算符的基数的元组类型左侧为 {0},右侧为 {1}。 + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint “{0}”: 不能既指定约束类又指定 “unmanaged” 约束 @@ -979,6 +1004,11 @@ <switch expression> + + target-typed object creation + target-typed object creation + + tuple equality 元组相等 @@ -2119,11 +2149,6 @@ 运算符“{0}”无法应用于“{1}”类型的操作数 - - Operator '{0}' cannot be applied to operand '{1}' - 运算符“{0}”无法应用于操作数“{1}” - - Keyword 'this' is not valid in a static property, static method, or static field initializer 关键字 "this" 在静态属性、静态方法或静态字段初始值设定项中无效 @@ -2164,11 +2189,6 @@ 运算符“{0}”对于“{1}”和“{2}”类型的操作数具有二义性 - - Operator '{0}' is ambiguous on operands 'default' and 'default' - 运算符“{0}”在操作数 "default" 和 "default" 上不明确 - - Operator '{0}' is ambiguous on an operand of type '{1}' 运算符“{0}”对于“{1}”类型的操作数具有二义性 @@ -5493,8 +5513,8 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep - A new expression requires (), [], or {} after type - new 表达式要求在类型后有 ()、[] 或 {} + A new expression requires an argument list or (), [], or {} after type + new 表达式要求在类型后有 ()、[] 或 {} diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index c79e89369d7bd..87fd501860d10 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -22,6 +22,11 @@ 若要在插入的逐字字串使用 '@$' 而不是 '$@',請使用 '{0}' 或更高的語言版本。 + + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + Operator '{0}' is ambiguous on operands '{1}' and '{2}' + + Operator '{0}' cannot be applied to 'default' and operand of type '{1}' because it is a type parameter that is not known to be a reference type 無法將運算子 '{0}' 套用至 'default' 和類型為 '{1}' 的運算元,原因是其為未知參考型別的型別參數 @@ -82,6 +87,11 @@ typeof 運算子不得用於可為 Null 的參考型別上 + + Operator '{0}' cannot be applied to operand '{1}' + Operator '{0}' cannot be applied to operand '{1}' + + Invalid operand for pattern match; value required, but found '{0}'. 模式比對運算元無效; 需要值,但找到 '{0}'。 @@ -482,6 +492,21 @@ 作為 == 或 != 運算子之運算元使用的元組類型,必須具有相符的基數。但此運算子在左側的元組類型為基數 {0},在右側則為 {1}。 + + The type '{0}' may not be used as the target type of new() + The type '{0}' may not be used as the target type of new() + + + + There is no target type for '{0}' + There is no target type for '{0}' + + + + Use of new() is not valid in this context + Use of new() is not valid in this context + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint '{0}': 不可在指定條件約束類型的同時,又指定 'unmanaged' 條件約束 @@ -979,6 +1004,11 @@ <切換運算式> + + target-typed object creation + target-typed object creation + + tuple equality 元組相等 @@ -2119,11 +2149,6 @@ 運算子 '{0}' 不可套用至類型為 '{1}' 的運算元 - - Operator '{0}' cannot be applied to operand '{1}' - 運算子 '{0}' 不可套用至運算元 '{1}' - - Keyword 'this' is not valid in a static property, static method, or static field initializer 關鍵字 'this' 在靜態屬性、靜態方法或靜態欄位初始設定式中無效。 @@ -2164,11 +2189,6 @@ 運算子 '{0}' 在類型為 '{1}' 和 '{2}' 的運算元上模稜兩可 - - Operator '{0}' is ambiguous on operands 'default' and 'default' - 運算子 '{0}' 在運算元 'default' 和 'default' 不明確 - - Operator '{0}' is ambiguous on an operand of type '{1}' 運算子 '{0}' 在類型為 '{1}' 的運算元上模稜兩可 @@ -5493,8 +5513,8 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep - A new expression requires (), [], or {} after type - new 運算式在類型後需要有 ()、[] 或 {} + A new expression requires an argument list or (), [], or {} after type + new 運算式在類型後需要有 ()、[] 或 {} diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs index 2d061347128e4..60a2b9487177b 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs @@ -1254,10 +1254,10 @@ static void Main() comp.VerifyDiagnostics( // (6,30): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // System.Console.Write((default, default) == (default, default)); - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "(default, default) == (default, default)").WithArguments("==").WithLocation(6, 30), + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "(default, default) == (default, default)").WithArguments("==", "default", "default").WithLocation(6, 30), // (6,30): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // System.Console.Write((default, default) == (default, default)); - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "(default, default) == (default, default)").WithArguments("==").WithLocation(6, 30), + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "(default, default) == (default, default)").WithArguments("==", "default", "default").WithLocation(6, 30), // (7,30): error CS0034: Operator '==' is ambiguous on operands of type 'default' and '(default, default)' // System.Console.Write(default == (default, default)); Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "default == (default, default)").WithArguments("==", "default", "(default, default)").WithLocation(7, 30) @@ -1301,10 +1301,10 @@ static void Main() comp.VerifyDiagnostics( // (6,30): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // System.Console.Write((null, (default, default)) == (null, (default, default))); - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "(null, (default, default)) == (null, (default, default))").WithArguments("==").WithLocation(6, 30), + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "(null, (default, default)) == (null, (default, default))").WithArguments("==", "default", "default").WithLocation(6, 30), // (6,30): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // System.Console.Write((null, (default, default)) == (null, (default, default))); - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "(null, (default, default)) == (null, (default, default))").WithArguments("==").WithLocation(6, 30) + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "(null, (default, default)) == (null, (default, default))").WithArguments("==", "default", "default").WithLocation(6, 30) ); } diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IConversionExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IConversionExpression.cs index a2b7c86c71aa1..b1bb95a0cc0ca 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IConversionExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IConversionExpression.cs @@ -947,9 +947,6 @@ static void Main(string[] args) Children(0) "; var expectedDiagnostics = new DiagnosticDescription[] { - // CS1031: Type expected - // C1 /**/c1 = new/**/; - Diagnostic(ErrorCode.ERR_TypeExpected, ";").WithLocation(8, 41), // CS1526: A new expression requires (), [], or {} after type // C1 /**/c1 = new/**/; Diagnostic(ErrorCode.ERR_BadNewExpr, ";").WithLocation(8, 41) diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs index 31e53c44685de..d97b7091d858f 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -11,6 +12,1496 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public partial class IOperationTests : SemanticModelTestBase { + private static readonly CSharpParseOptions ImplicitObjectCreationOptions = TestOptions.RegularPreview; + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithArguments() + { + string source = @" +class C +{ + public C(byte i, long j) + { + } + void M() + /**/{ + C x1 = new(3, 4); + C x2 = new(j: 3, i: 4); + C x3 = new(3, j: 4); + C x4 = new(i: 3, 4); + }/**/ +} +"; + var expectedDiagnostics = DiagnosticDescription.None; + + string expectedOperationTree = @" +IBlockOperation (4 statements, 4 locals) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + Locals: Local_1: C x1 + Local_2: C x2 + Local_3: C x3 + Local_4: C x4 + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'C x1 = new(3, 4);') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'C x1 = new(3, 4)') + Declarators: + IVariableDeclaratorOperation (Symbol: C x1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x1 = new(3, 4)') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new(3, 4)') + IObjectCreationOperation (Constructor: C..ctor(System.Byte i, System.Int64 j)) (OperationKind.ObjectCreation, Type: C) (Syntax: 'new(3, 4)') + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: '3') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Byte, Constant: 3, IsImplicit) (Syntax: '3') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3) (Syntax: '3') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: j) (OperationKind.Argument, Type: null) (Syntax: '4') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int64, Constant: 4, IsImplicit) (Syntax: '4') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 4) (Syntax: '4') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Initializer: + null + Initializer: + null + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'C x2 = new(j: 3, i: 4);') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'C x2 = new(j: 3, i: 4)') + Declarators: + IVariableDeclaratorOperation (Symbol: C x2) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x2 = new(j: 3, i: 4)') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new(j: 3, i: 4)') + IObjectCreationOperation (Constructor: C..ctor(System.Byte i, System.Int64 j)) (OperationKind.ObjectCreation, Type: C) (Syntax: 'new(j: 3, i: 4)') + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: j) (OperationKind.Argument, Type: null) (Syntax: 'j: 3') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int64, Constant: 3, IsImplicit) (Syntax: '3') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3) (Syntax: '3') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: 'i: 4') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Byte, Constant: 4, IsImplicit) (Syntax: '4') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 4) (Syntax: '4') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Initializer: + null + Initializer: + null + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'C x3 = new(3, j: 4);') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'C x3 = new(3, j: 4)') + Declarators: + IVariableDeclaratorOperation (Symbol: C x3) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x3 = new(3, j: 4)') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new(3, j: 4)') + IObjectCreationOperation (Constructor: C..ctor(System.Byte i, System.Int64 j)) (OperationKind.ObjectCreation, Type: C) (Syntax: 'new(3, j: 4)') + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: '3') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Byte, Constant: 3, IsImplicit) (Syntax: '3') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3) (Syntax: '3') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: j) (OperationKind.Argument, Type: null) (Syntax: 'j: 4') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int64, Constant: 4, IsImplicit) (Syntax: '4') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 4) (Syntax: '4') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Initializer: + null + Initializer: + null + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'C x4 = new(i: 3, 4);') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'C x4 = new(i: 3, 4)') + Declarators: + IVariableDeclaratorOperation (Symbol: C x4) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x4 = new(i: 3, 4)') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new(i: 3, 4)') + IObjectCreationOperation (Constructor: C..ctor(System.Byte i, System.Int64 j)) (OperationKind.ObjectCreation, Type: C) (Syntax: 'new(i: 3, 4)') + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: 'i: 3') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Byte, Constant: 3, IsImplicit) (Syntax: '3') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3) (Syntax: '3') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: j) (OperationKind.Argument, Type: null) (Syntax: '4') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int64, Constant: 4, IsImplicit) (Syntax: '4') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 4) (Syntax: '4') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Initializer: + null + Initializer: + null +"; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithMemberInitializers() + { + string source = @" +struct B +{ + public bool Field; +} +class F +{ + public int Field; + public string Property1 { set; get; } + public B Property2 { set; get; } +} +class C +{ + public void M1() + /**/{ + F x1 = new(); + F x2 = new() { Field = 2 }; + F x3 = new() { Property1 = """" }; + F x4 = new() { Property1 = """", Field = 2 }; + F x5 = new() { Property2 = new B { Field = true } }; + F e1 = new() { Property2 = 1 }; + F e2 = new() { """" }; + }/**/ +} +"; + string expectedOperationTree = @" +IBlockOperation (7 statements, 7 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ ... }') + Locals: Local_1: F x1 + Local_2: F x2 + Local_3: F x3 + Local_4: F x4 + Local_5: F x5 + Local_6: F e1 + Local_7: F e2 + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'F x1 = new();') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'F x1 = new()') + Declarators: + IVariableDeclaratorOperation (Symbol: F x1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x1 = new()') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new()') + IObjectCreationOperation (Constructor: F..ctor()) (OperationKind.ObjectCreation, Type: F) (Syntax: 'new()') + Arguments(0) + Initializer: + null + Initializer: + null + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'F x2 = new( ... ield = 2 };') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'F x2 = new( ... Field = 2 }') + Declarators: + IVariableDeclaratorOperation (Symbol: F x2) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x2 = new() { Field = 2 }') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new() { Field = 2 }') + IObjectCreationOperation (Constructor: F..ctor()) (OperationKind.ObjectCreation, Type: F) (Syntax: 'new() { Field = 2 }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: F) (Syntax: '{ Field = 2 }') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'Field = 2') + Left: + IFieldReferenceOperation: System.Int32 F.Field (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'Field') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: F, IsImplicit) (Syntax: 'Field') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') + Initializer: + null + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'F x3 = new( ... ty1 = """" };') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'F x3 = new( ... rty1 = """" }') + Declarators: + IVariableDeclaratorOperation (Symbol: F x3) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x3 = new() ... rty1 = """" }') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new() { P ... rty1 = """" }') + IObjectCreationOperation (Constructor: F..ctor()) (OperationKind.ObjectCreation, Type: F) (Syntax: 'new() { Property1 = """" }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: F) (Syntax: '{ Property1 = """" }') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.String) (Syntax: 'Property1 = """"') + Left: + IPropertyReferenceOperation: System.String F.Property1 { get; set; } (OperationKind.PropertyReference, Type: System.String) (Syntax: 'Property1') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: F, IsImplicit) (Syntax: 'Property1') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: """") (Syntax: '""""') + Initializer: + null + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'F x4 = new( ... ield = 2 };') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'F x4 = new( ... Field = 2 }') + Declarators: + IVariableDeclaratorOperation (Symbol: F x4) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x4 = new() ... Field = 2 }') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new() { P ... Field = 2 }') + IObjectCreationOperation (Constructor: F..ctor()) (OperationKind.ObjectCreation, Type: F) (Syntax: 'new() { Pro ... Field = 2 }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: F) (Syntax: '{ Property1 ... Field = 2 }') + Initializers(2): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.String) (Syntax: 'Property1 = """"') + Left: + IPropertyReferenceOperation: System.String F.Property1 { get; set; } (OperationKind.PropertyReference, Type: System.String) (Syntax: 'Property1') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: F, IsImplicit) (Syntax: 'Property1') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: """") (Syntax: '""""') + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'Field = 2') + Left: + IFieldReferenceOperation: System.Int32 F.Field (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'Field') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: F, IsImplicit) (Syntax: 'Field') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') + Initializer: + null + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'F x5 = new( ... = true } };') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'F x5 = new( ... = true } }') + Declarators: + IVariableDeclaratorOperation (Symbol: F x5) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x5 = new() ... = true } }') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= new() { P ... = true } }') + IObjectCreationOperation (Constructor: F..ctor()) (OperationKind.ObjectCreation, Type: F) (Syntax: 'new() { Pro ... = true } }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: F) (Syntax: '{ Property2 ... = true } }') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: B) (Syntax: 'Property2 = ... ld = true }') + Left: + IPropertyReferenceOperation: B F.Property2 { get; set; } (OperationKind.PropertyReference, Type: B) (Syntax: 'Property2') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: F, IsImplicit) (Syntax: 'Property2') + Right: + IObjectCreationOperation (Constructor: B..ctor()) (OperationKind.ObjectCreation, Type: B) (Syntax: 'new B { Field = true }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: B) (Syntax: '{ Field = true }') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'Field = true') + Left: + IFieldReferenceOperation: System.Boolean B.Field (OperationKind.FieldReference, Type: System.Boolean) (Syntax: 'Field') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: B, IsImplicit) (Syntax: 'Field') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true') + Initializer: + null + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'F e1 = new( ... rty2 = 1 };') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'F e1 = new( ... erty2 = 1 }') + Declarators: + IVariableDeclaratorOperation (Symbol: F e1) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: 'e1 = new() ... erty2 = 1 }') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null, IsInvalid) (Syntax: '= new() { P ... erty2 = 1 }') + IObjectCreationOperation (Constructor: F..ctor()) (OperationKind.ObjectCreation, Type: F, IsInvalid) (Syntax: 'new() { Property2 = 1 }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: F, IsInvalid) (Syntax: '{ Property2 = 1 }') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: B, IsInvalid) (Syntax: 'Property2 = 1') + Left: + IPropertyReferenceOperation: B F.Property2 { get; set; } (OperationKind.PropertyReference, Type: B) (Syntax: 'Property2') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: F, IsImplicit) (Syntax: 'Property2') + Right: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: B, IsInvalid, IsImplicit) (Syntax: '1') + Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') + Initializer: + null + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'F e2 = new() { """" };') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'F e2 = new() { """" }') + Declarators: + IVariableDeclaratorOperation (Symbol: F e2) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: 'e2 = new() { """" }') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null, IsInvalid) (Syntax: '= new() { """" }') + IObjectCreationOperation (Constructor: F..ctor()) (OperationKind.ObjectCreation, Type: F, IsInvalid) (Syntax: 'new() { """" }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: F, IsInvalid) (Syntax: '{ """" }') + Initializers(1): + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: '""""') + Children(1): + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: """", IsInvalid) (Syntax: '""""') + Initializer: + null +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // file.cs(21,36): error CS0029: Cannot implicitly convert type 'int' to 'B' + // F e1 = new() { Property2 = 1 }; + Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "B").WithLocation(21, 36), + // file.cs(22,22): error CS1922: Cannot initialize type 'F' with a collection initializer because it does not implement 'System.Collections.IEnumerable' + // F e2 = new() { "" }; + Diagnostic(ErrorCode.ERR_CollectionInitRequiresIEnumerable, @"{ """" }").WithArguments("F").WithLocation(22, 22) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithCollectionInitializer() + { + string source = @" +using System.Collections.Generic; +class C +{ + private readonly int field; + public void M1(int x) + { + int y = 0; + List x1 = /**/new() { x, y, field }/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationOperation (Constructor: System.Collections.Generic.List..ctor()) (OperationKind.ObjectCreation, Type: System.Collections.Generic.List) (Syntax: 'new() { x, y, field }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: System.Collections.Generic.List) (Syntax: '{ x, y, field }') + Initializers(3): + IInvocationOperation ( void System.Collections.Generic.List.Add(System.Int32 item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'x') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List, IsImplicit) (Syntax: 'new() { x, y, field }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'x') + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IInvocationOperation ( void System.Collections.Generic.List.Add(System.Int32 item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'y') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List, IsImplicit) (Syntax: 'new() { x, y, field }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'y') + ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IInvocationOperation ( void System.Collections.Generic.List.Add(System.Int32 item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'field') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List, IsImplicit) (Syntax: 'new() { x, y, field }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'field') + IFieldReferenceOperation: System.Int32 C.field (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'field') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'field') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // file.cs(5,23): warning CS0649: Field 'C.field' is never assigned to, and will always have its default value 0 + // private readonly int field; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("C.field", "0").WithLocation(5, 26) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithNestedCollectionInitializer() + { + string source = @" +using System.Collections.Generic; +using System.Linq; +class C +{ + private readonly int field = 0; + public void M1(int x) + { + int y = 0; + List> x1 = /**/new() { + new[] { x, y }.ToList(), + new() { field } + }/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationOperation (Constructor: System.Collections.Generic.List>..ctor()) (OperationKind.ObjectCreation, Type: System.Collections.Generic.List>) (Syntax: 'new() { ... }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: System.Collections.Generic.List>) (Syntax: '{ ... }') + Initializers(2): + IInvocationOperation ( void System.Collections.Generic.List>.Add(System.Collections.Generic.List item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'new[] { x, y }.ToList()') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List>, IsImplicit) (Syntax: 'new() { ... }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'new[] { x, y }.ToList()') + IInvocationOperation (System.Collections.Generic.List System.Linq.Enumerable.ToList(this System.Collections.Generic.IEnumerable source)) (OperationKind.Invocation, Type: System.Collections.Generic.List) (Syntax: 'new[] { x, y }.ToList()') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: source) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'new[] { x, y }') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Collections.Generic.IEnumerable, IsImplicit) (Syntax: 'new[] { x, y }') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + Operand: + IArrayCreationOperation (OperationKind.ArrayCreation, Type: System.Int32[]) (Syntax: 'new[] { x, y }') + Dimension Sizes(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: 'new[] { x, y }') + Initializer: + IArrayInitializerOperation (2 elements) (OperationKind.ArrayInitializer, Type: null) (Syntax: '{ x, y }') + Element Values(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x') + ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IInvocationOperation ( void System.Collections.Generic.List>.Add(System.Collections.Generic.List item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'new() { field }') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List>, IsImplicit) (Syntax: 'new() { ... }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'new() { field }') + IObjectCreationOperation (Constructor: System.Collections.Generic.List..ctor()) (OperationKind.ObjectCreation, Type: System.Collections.Generic.List) (Syntax: 'new() { field }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: System.Collections.Generic.List) (Syntax: '{ field }') + Initializers(1): + IInvocationOperation ( void System.Collections.Generic.List.Add(System.Int32 item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'field') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List, IsImplicit) (Syntax: 'new() { field }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'field') + IFieldReferenceOperation: System.Int32 C.field (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'field') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'field') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithMemberAndCollectionInitializers() + { + string source = @" +using System.Collections.Generic; +internal class Class +{ + public int X { get; set; } + public List Y { get; set; } + public Dictionary Z { get; set; } + public Class C { get; set; } + private readonly int field = 0; + public void M(int x) + { + int y = 0; + Class c = /**/new() { + X = x, + Y = { x, y, 3 }, + Z = { { x, y } }, + C = { X = field } + }/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationOperation (Constructor: Class..ctor()) (OperationKind.ObjectCreation, Type: Class) (Syntax: 'new() { ... }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: Class) (Syntax: '{ ... }') + Initializers(4): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'X = x') + Left: + IPropertyReferenceOperation: System.Int32 Class.X { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'X') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'X') + Right: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x') + IMemberInitializerOperation (OperationKind.MemberInitializer, Type: System.Collections.Generic.List) (Syntax: 'Y = { x, y, 3 }') + InitializedMember: + IPropertyReferenceOperation: System.Collections.Generic.List Class.Y { get; set; } (OperationKind.PropertyReference, Type: System.Collections.Generic.List) (Syntax: 'Y') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'Y') + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: System.Collections.Generic.List) (Syntax: '{ x, y, 3 }') + Initializers(3): + IInvocationOperation ( void System.Collections.Generic.List.Add(System.Int32 item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'x') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List, IsImplicit) (Syntax: 'Y') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'x') + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IInvocationOperation ( void System.Collections.Generic.List.Add(System.Int32 item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'y') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List, IsImplicit) (Syntax: 'Y') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'y') + ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IInvocationOperation ( void System.Collections.Generic.List.Add(System.Int32 item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: '3') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List, IsImplicit) (Syntax: 'Y') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '3') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3) (Syntax: '3') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IMemberInitializerOperation (OperationKind.MemberInitializer, Type: System.Collections.Generic.Dictionary) (Syntax: 'Z = { { x, y } }') + InitializedMember: + IPropertyReferenceOperation: System.Collections.Generic.Dictionary Class.Z { get; set; } (OperationKind.PropertyReference, Type: System.Collections.Generic.Dictionary) (Syntax: 'Z') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'Z') + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: System.Collections.Generic.Dictionary) (Syntax: '{ { x, y } }') + Initializers(1): + IInvocationOperation ( void System.Collections.Generic.Dictionary.Add(System.Int32 key, System.Int32 value)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: '{ x, y }') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.Dictionary, IsImplicit) (Syntax: 'Z') + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: key) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'x') + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'y') + ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IMemberInitializerOperation (OperationKind.MemberInitializer, Type: Class) (Syntax: 'C = { X = field }') + InitializedMember: + IPropertyReferenceOperation: Class Class.C { get; set; } (OperationKind.PropertyReference, Type: Class) (Syntax: 'C') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'C') + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: Class) (Syntax: '{ X = field }') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'X = field') + Left: + IPropertyReferenceOperation: System.Int32 Class.X { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'X') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'X') + Right: + IFieldReferenceOperation: System.Int32 Class.field (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'field') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'field') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithArrayInitializer() + { + string source = @" +class C +{ + int[] a; + static void Main() + { + C a = /**/new() { a = { [0] = 1, [1] = 2 } }/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationOperation (Constructor: C..ctor()) (OperationKind.ObjectCreation, Type: C) (Syntax: 'new() { a = ... [1] = 2 } }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C) (Syntax: '{ a = { [0] ... [1] = 2 } }') + Initializers(1): + IMemberInitializerOperation (OperationKind.MemberInitializer, Type: System.Int32[]) (Syntax: 'a = { [0] = 1, [1] = 2 }') + InitializedMember: + IFieldReferenceOperation: System.Int32[] C.a (OperationKind.FieldReference, Type: System.Int32[]) (Syntax: 'a') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'a') + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: System.Int32[]) (Syntax: '{ [0] = 1, [1] = 2 }') + Initializers(2): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: '[0] = 1') + Left: + IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: '[0]') + Array reference: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Int32[], IsImplicit) (Syntax: 'a') + Indices(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: '[1] = 2') + Left: + IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: '[1]') + Array reference: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Int32[], IsImplicit) (Syntax: 'a') + Indices(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') +"; + var expectedDiagnostics = new DiagnosticDescription[] + { + // warning CS0414: The field 'C.a' is assigned but its value is never used + // int[] a; + Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "a").WithArguments("C.a").WithLocation(4, 11) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithInvalidInitializer() + { + string source = @" +class C +{ + public void M1() + { + C x1 = /**/new() { MissingMember = 1 }/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationOperation (Constructor: C..ctor()) (OperationKind.ObjectCreation, Type: C, IsInvalid) (Syntax: 'new() { Mis ... ember = 1 }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C, IsInvalid) (Syntax: '{ MissingMember = 1 }') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: 'MissingMember = 1') + Left: + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: 'MissingMember') + Children(1): + IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'MissingMember') + Children(1): + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'new() { Mis ... ember = 1 }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // file.cs(6,34): error CS0117: 'C' does not contain a definition for 'MissingMember' + // C x1 = /**/new() { MissingMember = 1 }/**/; + Diagnostic(ErrorCode.ERR_NoSuchMember, "MissingMember").WithArguments("C", "MissingMember").WithLocation(6, 34) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithInvalidMemberInitializer() + { + string source = @" +class C +{ + public void M1() + { + C x1 = /**/new(){ MissingField = { x = 1 } }/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationOperation (Constructor: C..ctor()) (OperationKind.ObjectCreation, Type: C, IsInvalid) (Syntax: 'new(){ Miss ... { x = 1 } }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C, IsInvalid) (Syntax: '{ MissingFi ... { x = 1 } }') + Initializers(1): + IMemberInitializerOperation (OperationKind.MemberInitializer, Type: ?, IsInvalid) (Syntax: 'MissingField = { x = 1 }') + InitializedMember: + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: 'MissingField') + Children(1): + IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'MissingField') + Children(1): + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'new(){ Miss ... { x = 1 } }') + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: ?) (Syntax: '{ x = 1 }') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?) (Syntax: 'x = 1') + Left: + IInvalidOperation (OperationKind.Invalid, Type: ?, IsImplicit) (Syntax: 'x') + Children(1): + IOperation: (OperationKind.None, Type: null) (Syntax: 'x') + Children(1): + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: ?, IsInvalid, IsImplicit) (Syntax: 'MissingField') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // file.cs(6,33): error CS0117: 'C' does not contain a definition for 'MissingField' + // C x1 = /**/new(){ MissingField = { x = 1 } }/**/; + Diagnostic(ErrorCode.ERR_NoSuchMember, "MissingField").WithArguments("C", "MissingField").WithLocation(6, 33) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithInvalidCollectionInitializer() + { + string source = @" +using System.Collections.Generic; +class C +{ + public void M1() + { + C x1 = /**/new(){ MissingField = new List() { 1 }}/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationOperation (Constructor: C..ctor()) (OperationKind.ObjectCreation, Type: C, IsInvalid) (Syntax: 'new(){ Miss ... t>() { 1 }}') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C, IsInvalid) (Syntax: '{ MissingFi ... t>() { 1 }}') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: 'MissingFiel ... nt>() { 1 }') + Left: + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: 'MissingField') + Children(1): + IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'MissingField') + Children(1): + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'new(){ Miss ... t>() { 1 }}') + Right: + IObjectCreationOperation (Constructor: System.Collections.Generic.List..ctor()) (OperationKind.ObjectCreation, Type: System.Collections.Generic.List) (Syntax: 'new List() { 1 }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: System.Collections.Generic.List) (Syntax: '{ 1 }') + Initializers(1): + IInvocationOperation ( void System.Collections.Generic.List.Add(System.Int32 item)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: '1') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: System.Collections.Generic.List, IsImplicit) (Syntax: 'List') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: item) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '1') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // file.cs(7,33): error CS0117: 'C' does not contain a definition for 'MissingField' + // C x1 = /**/new(){ MissingField = new List() { 1 }}/**/; + Diagnostic(ErrorCode.ERR_NoSuchMember, "MissingField").WithArguments("C", "MissingField").WithLocation(7, 33) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithDynamicMemberInitializer_01() + { + string source = @" +#pragma warning disable 0169 +class A +{ + dynamic this[int x, int y] + { + get + { + return new A(); + } + } + dynamic this[string x, string y] + { + get + { + throw null; + } + } + int X, Y, Z; + static void Main() + { + dynamic x = 1; + A _ = new() {/**/[y: x, x: x] = { X = 1, Y = 1, Z = 1 }/**/ }; + } +} +"; + string expectedOperationTree = @" +IMemberInitializerOperation (OperationKind.MemberInitializer, Type: dynamic) (Syntax: '[y: x, x: x ... 1, Z = 1 }') + InitializedMember: + IDynamicIndexerAccessOperation (OperationKind.DynamicIndexerAccess, Type: dynamic) (Syntax: '[y: x, x: x]') + Expression: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: A, IsImplicit) (Syntax: '[y: x, x: x]') + Arguments(2): + ILocalReferenceOperation: x (OperationKind.LocalReference, Type: dynamic) (Syntax: 'x') + ILocalReferenceOperation: x (OperationKind.LocalReference, Type: dynamic) (Syntax: 'x') + ArgumentNames(2): + ""y"" + ""x"" + ArgumentRefKinds(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: dynamic) (Syntax: '{ X = 1, Y = 1, Z = 1 }') + Initializers(3): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: dynamic) (Syntax: 'X = 1') + Left: + IDynamicMemberReferenceOperation (Member Name: ""X"", Containing Type: dynamic) (OperationKind.DynamicMemberReference, Type: dynamic) (Syntax: 'X') + Type Arguments(0) + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: dynamic, IsImplicit) (Syntax: 'X') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: dynamic) (Syntax: 'Y = 1') + Left: + IDynamicMemberReferenceOperation (Member Name: ""Y"", Containing Type: dynamic) (OperationKind.DynamicMemberReference, Type: dynamic) (Syntax: 'Y') + Type Arguments(0) + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: dynamic, IsImplicit) (Syntax: 'Y') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: dynamic) (Syntax: 'Z = 1') + Left: + IDynamicMemberReferenceOperation (Member Name: ""Z"", Containing Type: dynamic) (OperationKind.DynamicMemberReference, Type: dynamic) (Syntax: 'Z') + Type Arguments(0) + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: dynamic, IsImplicit) (Syntax: 'Z') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithDynamicMemberInitializer_02() + { + string source = @" +#pragma warning disable 0169 +class A +{ + dynamic this[int x, int y] + { + get + { + return new A(); + } + } + dynamic this[string x, string y] + { + get + { + throw null; + } + } + int X, Y, Z; + static void Main() + { + dynamic x = 1; + A _ = new() {/**/[y: x, x: x] = { }/**/ }; + } +} +"; + string expectedOperationTree = @" +IMemberInitializerOperation (OperationKind.MemberInitializer, Type: dynamic) (Syntax: '[y: x, x: x] = { }') + InitializedMember: + IDynamicIndexerAccessOperation (OperationKind.DynamicIndexerAccess, Type: dynamic) (Syntax: '[y: x, x: x]') + Expression: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: A, IsImplicit) (Syntax: '[y: x, x: x]') + Arguments(2): + ILocalReferenceOperation: x (OperationKind.LocalReference, Type: dynamic) (Syntax: 'x') + ILocalReferenceOperation: x (OperationKind.LocalReference, Type: dynamic) (Syntax: 'x') + ArgumentNames(2): + ""y"" + ""x"" + ArgumentRefKinds(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: dynamic) (Syntax: '{ }') + Initializers(0) +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationWithDynamicMemberInitializer_03() + { + string source = @" +#pragma warning disable 0169 +class A +{ + dynamic this[int x, int y] + { + get + { + return new A(); + } + } + dynamic this[string x, string y] + { + get + { + throw null; + } + } + int X, Y, Z; + static void Main() + { + dynamic x = 1; + A _ = new() {/**/[y: x, x: x]/**/ = { } }; + } +} +"; + string expectedOperationTree = @" +IDynamicIndexerAccessOperation (OperationKind.DynamicIndexerAccess, Type: dynamic) (Syntax: '[y: x, x: x]') + Expression: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: A, IsImplicit) (Syntax: '[y: x, x: x]') + Arguments(2): + ILocalReferenceOperation: x (OperationKind.LocalReference, Type: dynamic) (Syntax: 'x') + ILocalReferenceOperation: x (OperationKind.LocalReference, Type: dynamic) (Syntax: 'x') + ArgumentNames(2): + ""y"" + ""x"" + ArgumentRefKinds(0) +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationDynamicCollectionInitializer() + { + string source = @" +using System.Collections; +using System.Collections.Generic; +class C1 : IEnumerable +{ + public static void M(C1 c, dynamic d1) + { + c = /**/new() { d1 }/**/; + } + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + public void Add(int c2) { } +} +"; + var expectedDiagnostics = DiagnosticDescription.None; + + string expectedOperationTree = @" +IObjectCreationOperation (Constructor: C1..ctor()) (OperationKind.ObjectCreation, Type: C1) (Syntax: 'new() { d1 }') + Arguments(0) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C1) (Syntax: '{ d1 }') + Initializers(1): + IDynamicInvocationOperation (OperationKind.DynamicInvocation, Type: dynamic, IsImplicit) (Syntax: 'd1') + Expression: + IDynamicMemberReferenceOperation (Member Name: ""Add"", Containing Type: null) (OperationKind.DynamicMemberReference, Type: null, IsImplicit) (Syntax: 'new() { d1 }') + Type Arguments(0) + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C1, IsImplicit) (Syntax: 'new() { d1 }') + Arguments(1): + IParameterReferenceOperation: d1 (OperationKind.ParameterReference, Type: dynamic) (Syntax: 'd1') + ArgumentNames(0) + ArgumentRefKinds(0) +"; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationCollectionInitializerWithRefAddMethod() + { + string source = @" +using System; +using System.Collections; +using System.Collections.Generic; +class C : IEnumerable +{ + public static void M() + { + C c = new() /**/{ 1, 2, 3 }/**/; + } + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + public void Add(ref int i) + { + } +} +"; + string expectedOperationTree = @" +IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C, IsInvalid) (Syntax: '{ 1, 2, 3 }') + Initializers(3): + IInvalidOperation (OperationKind.Invalid, Type: System.Void, IsInvalid, IsImplicit) (Syntax: '1') + Children(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') + IInvalidOperation (OperationKind.Invalid, Type: System.Void, IsInvalid, IsImplicit) (Syntax: '2') + Children(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2') + IInvalidOperation (OperationKind.Invalid, Type: System.Void, IsInvalid, IsImplicit) (Syntax: '3') + Children(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3, IsInvalid) (Syntax: '3') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // file.cs(9,33): error CS1954: The best overloaded method match 'C.Add(ref int)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // C c = new() /**/{ 1, 2, 3 }/**/; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "1").WithArguments("C.Add(ref int)").WithLocation(9, 33), + // file.cs(9,36): error CS1954: The best overloaded method match 'C.Add(ref int)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // C c = new() /**/{ 1, 2, 3 }/**/; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "2").WithArguments("C.Add(ref int)").WithLocation(9, 36), + // file.cs(9,39): error CS1954: The best overloaded method match 'C.Add(ref int)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // C c = new() /**/{ 1, 2, 3 }/**/; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "3").WithArguments("C.Add(ref int)").WithLocation(9, 39) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationCollectionInitializerWithDefaultParameterAddMethod() + { + string source = @" +using System; +using System.Collections; +using System.Collections.Generic; +class C : IEnumerable +{ + public static void M() + { + C c = new() /**/{ 1, 2, 3 }/**/; + } + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + public void Add(int i, object o = null) + { + } +} +"; + string expectedOperationTree = @" +IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C) (Syntax: '{ 1, 2, 3 }') + Initializers(3): + IInvocationOperation ( void C.Add(System.Int32 i, [System.Object o = null])) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: '1') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'new() /*(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationCollectionInitializerWithParamsAddMethod() + { + string source = @" +using System.Collections; +using System.Collections.Generic; +class C : IEnumerable +{ + void M(C c) + { + c = new() /**/{ 1, 2, 3 }/**/; + } + public void Add(params int[] ints) + { + } + public IEnumerator GetEnumerator() + { + throw new System.NotImplementedException(); + } + IEnumerator IEnumerable.GetEnumerator() + { + throw new System.NotImplementedException(); + } +} +"; + var expectedDiagnostics = DiagnosticDescription.None; + + string expectedOperationTree = @" +IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C) (Syntax: '{ 1, 2, 3 }') + Initializers(3): + IInvocationOperation ( void C.Add(params System.Int32[] ints)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: '1') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'new() /*(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationCollectionInitializerExtensionAddMethod() + { + string source = @" +using System.Collections; +using System.Collections.Generic; +class C : IEnumerable +{ + void M(C c) + { + c = new() /**/{ 1, 2, 3 }/**/; + } + public IEnumerator GetEnumerator() + { + throw new System.NotImplementedException(); + } + IEnumerator IEnumerable.GetEnumerator() + { + throw new System.NotImplementedException(); + } +} +static class CExtensions +{ + public static void Add(this C c, int i) + { + } +} +"; + var expectedDiagnostics = DiagnosticDescription.None; + + string expectedOperationTree = @" +IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C) (Syntax: '{ 1, 2, 3 }') + Initializers(3): + IInvocationOperation (void CExtensions.Add(this C c, System.Int32 i)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: '1') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: c) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'new() /*(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationCollectionInitializerStaticAddMethod() + { + string source = @" +using System; +using System.Collections; +using System.Collections.Generic; +class C : IEnumerable +{ + public static void M() + { + C c = new() /**/{ 1, 2, 3 }/**/; + } + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + public static void Add(int i) + { + } +} +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // file.cs(9,33): error CS1921: The best overloaded method match for 'C.Add(int)' has wrong signature for the initializer element. The initializable Add must be an accessible instance method. + // C c = new() /**/{ 1, 2, 3 }/**/; + Diagnostic(ErrorCode.ERR_InitializerAddHasWrongSignature, "1").WithArguments("C.Add(int)").WithLocation(9, 33), + // file.cs(9,36): error CS1921: The best overloaded method match for 'C.Add(int)' has wrong signature for the initializer element. The initializable Add must be an accessible instance method. + // C c = new() /**/{ 1, 2, 3 }/**/; + Diagnostic(ErrorCode.ERR_InitializerAddHasWrongSignature, "2").WithArguments("C.Add(int)").WithLocation(9, 36), + // file.cs(9,39): error CS1921: The best overloaded method match for 'C.Add(int)' has wrong signature for the initializer element. The initializable Add must be an accessible instance method. + // C c = new() /**/{ 1, 2, 3 }/**/; + Diagnostic(ErrorCode.ERR_InitializerAddHasWrongSignature, "3").WithArguments("C.Add(int)").WithLocation(9, 39) + }; + + string expectedOperationTree = @" +IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C, IsInvalid) (Syntax: '{ 1, 2, 3 }') + Initializers(3): + IInvalidOperation (OperationKind.Invalid, Type: System.Void, IsInvalid, IsImplicit) (Syntax: '1') + Children(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') + IInvalidOperation (OperationKind.Invalid, Type: System.Void, IsInvalid, IsImplicit) (Syntax: '2') + Children(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2') + IInvalidOperation (OperationKind.Invalid, Type: System.Void, IsInvalid, IsImplicit) (Syntax: '3') + Children(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3, IsInvalid) (Syntax: '3') +"; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationCollectionInitializerAddMethodOnInterface() + { + string source = @" +using System.Collections.Generic; +using System.Runtime.InteropServices; +[ComImport()] +[CoClass(typeof(CoClassImplementation))] +[Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58257"")] +public interface IInterface : IEnumerable +{ + void Add(int i); +} +public class CoClassImplementation +{ +} +class C +{ + void M() + { + IInterface iinterface = new() /**/{ 1, 2, 3 }/**/; + } +} +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // file.cs(18,33): error CS0144: Cannot create an instance of the abstract class or interface 'IInterface' + // IInterface iinterface = new() /**/{ 1, 2, 3 }/**/; + Diagnostic(ErrorCode.ERR_NoNewAbstract, "new() /**/{ 1, 2, 3 }").WithArguments("IInterface").WithLocation(18, 33) + }; + + string expectedOperationTree = @" +IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: IInterface, IsInvalid) (Syntax: '{ 1, 2, 3 }') + Initializers(3): + IInvocationOperation (virtual void IInterface.Add(System.Int32 i)) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: '1') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: IInterface, IsInvalid, IsImplicit) (Syntax: 'new() /*(source, expectedOperationTree, expectedDiagnostics, parseOptions: TestOptions.RegularPreview); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationNestedObjectInitializerNoSet() + { + string source = @" +class C1 +{ + void M(C1 c1) + { + c1 = new() /**/{ [1] = { A = 1 } }/**/; + } + C2 this[int i] { get => null; } +} +class C2 +{ + public int A { get; set; } +} +"; + var expectedDiagnostics = DiagnosticDescription.None; + + string expectedOperationTree = @" +IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C1) (Syntax: '{ [1] = { A = 1 } }') + Initializers(1): + IMemberInitializerOperation (OperationKind.MemberInitializer, Type: C2) (Syntax: '[1] = { A = 1 }') + InitializedMember: + IPropertyReferenceOperation: C2 C1.this[System.Int32 i] { get; } (OperationKind.PropertyReference, Type: C2) (Syntax: '[1]') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C1, IsImplicit) (Syntax: '[1]') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: '1') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C2) (Syntax: '{ A = 1 }') + Initializers(1): + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'A = 1') + Left: + IPropertyReferenceOperation: System.Int32 C2.A { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'A') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C2, IsImplicit) (Syntax: 'A') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') +"; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ImplicitObjectCreationNestedCollectionInitializerNoSet() + { + string source = @" +using System.Collections; +using System.Collections.Generic; +class C1 +{ + void M(C1 c1) + { + c1 = new() /**/{ [1] = { 1 } }/**/; + } + C2 this[int i] { get => null; } +} +class C2 : IEnumerable +{ + public IEnumerator GetEnumerator() => throw new System.NotImplementedException(); + IEnumerator IEnumerable.GetEnumerator() => throw new System.NotImplementedException(); + public void Add(int i) { } +} +"; + var expectedDiagnostics = DiagnosticDescription.None; + + string expectedOperationTree = @" +IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C1) (Syntax: '{ [1] = { 1 } }') + Initializers(1): + IMemberInitializerOperation (OperationKind.MemberInitializer, Type: C2) (Syntax: '[1] = { 1 }') + InitializedMember: + IPropertyReferenceOperation: C2 C1.this[System.Int32 i] { get; } (OperationKind.PropertyReference, Type: C2) (Syntax: '[1]') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C1, IsImplicit) (Syntax: '[1]') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: '1') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Initializer: + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C2) (Syntax: '{ 1 }') + Initializers(1): + IInvocationOperation ( void C2.Add(System.Int32 i)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: '1') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: C2, IsImplicit) (Syntax: '[1]') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '1') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); + } + [CompilerTrait(CompilerFeature.IOperation)] [Fact, WorkItem(17588, "https://github.com/dotnet/roslyn/issues/17588")] public void ObjectCreationWithMemberInitializers() @@ -223,12 +1714,12 @@ public void ObjectCreationWithCollectionInitializer() class C { - private readonly int field; - public void M1(int x) - { - int y = 0; - var x1 = /**/new List { x, y, field }/**/; - } + private readonly int field; + public void M1(int x) + { + int y = 0; + var x1 = /**/new List { x, y, field }/**/; + } } "; string expectedOperationTree = @" @@ -266,8 +1757,8 @@ public void M1(int x) "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0649: Field 'C.field' is never assigned to, and will always have its default value 0 - // private readonly int field; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("C.field", "0").WithLocation(6, 23) + // private readonly int field; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("C.field", "0").WithLocation(6, 26) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index dbdd589c00658..45e3da8a73c91 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -1568,9 +1568,9 @@ public override void M() // (8,17): error CS0023: Operator '.' cannot be applied to operand of type '' // _ = null!.field; // 1 Diagnostic(ErrorCode.ERR_BadUnaryOp, "null!.field").WithArguments(".", "").WithLocation(8, 17), - // (9,25): error CS0023: Operator '.' cannot be applied to operand of type 'default' + // (9,25): error CS8310: Operator '.' cannot be applied to operand 'default' // _ = default!.field; // 2 - Diagnostic(ErrorCode.ERR_BadUnaryOp, ".").WithArguments(".", "default").WithLocation(9, 25), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, ".").WithArguments(".", "default").WithLocation(9, 25), // (10,17): error CS8598: The suppression operator is not allowed in this context // _ = NS!.C.field; // 3 Diagnostic(ErrorCode.ERR_IllegalSuppression, "NS").WithLocation(10, 17), @@ -3706,10 +3706,10 @@ void M(object o, int? i) Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "null").WithLocation(17, 10), // (18,13): error CS8310: Operator '!' cannot be applied to operand '' // _ = !null; // 11 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "!null").WithArguments("!", "").WithLocation(18, 13), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "!null").WithArguments("!", "").WithLocation(18, 13), // (19,13): error CS8310: Operator '!' cannot be applied to operand '' // _ = !(null!); // 12 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "!(null!)").WithArguments("!", "").WithLocation(19, 13), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "!(null!)").WithArguments("!", "").WithLocation(19, 13), // (20,58): error CS0845: An expression tree lambda may not contain a coalescing operator with a null or default literal left-hand side // Expression> testExpr = () => null! ?? "hello"; // 13 Diagnostic(ErrorCode.ERR_ExpressionTreeContainsBadCoalesce, "null").WithLocation(20, 58) @@ -3752,13 +3752,13 @@ void M2(object o) Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(5, 36), // (6,13): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // _ = default == default!; // 2 - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default == default!").WithArguments("==").WithLocation(6, 13), + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "default == default!").WithArguments("==", "default", "default").WithLocation(6, 13), // (7,13): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // _ = default! == default!; // 3 - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default! == default!").WithArguments("==").WithLocation(7, 13), + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "default! == default!").WithArguments("==", "default", "default").WithLocation(7, 13), // (8,13): error CS8310: Operator '+' cannot be applied to operand 'default' // _ = 1 + default!; // 4 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 + default!").WithArguments("+", "default").WithLocation(8, 13), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 + default!").WithArguments("+", "default").WithLocation(8, 13), // (9,13): error CS8716: There is no target type for the default literal. // _ = default ?? d; // 5 Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(9, 13), @@ -65554,9 +65554,10 @@ static void F() }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (5,33): error CS0023: Operator '.' cannot be applied to operand of type 'default' + // (5,33): error CS8310: Operator '.' cannot be applied to operand 'default' // _ = default/*T:!*/.ToString(); - Diagnostic(ErrorCode.ERR_BadUnaryOp, ".").WithArguments(".", "default").WithLocation(5, 33)); + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, ".").WithArguments(".", "default").WithLocation(5, 33) + ); comp.VerifyTypes(); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index 0331865500944..6ca6c170747cb 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -1068,13 +1068,13 @@ object M() Diagnostic(ErrorCode.ERR_BadUnaryOp, "!q").WithArguments("!", "object").WithLocation(9, 17), // (12,26): error CS8310: Operator '-' cannot be applied to operand '' // object obj = -null; // CS0023 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "-null").WithArguments("-", "").WithLocation(12, 26), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "-null").WithArguments("-", "").WithLocation(12, 26), // (13,19): error CS8310: Operator '!' cannot be applied to operand '' // obj = !null; // CS0023 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "!null").WithArguments("!", "").WithLocation(13, 19), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "!null").WithArguments("!", "").WithLocation(13, 19), // (14,19): error CS8310: Operator '~' cannot be applied to operand '' // obj = ~null; // CS0023 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "~null").WithArguments("~", "").WithLocation(14, 19), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "~null").WithArguments("~", "").WithLocation(14, 19), // (16,13): error CS0023: Operator '++' cannot be applied to operand of type 'object' // obj++; // CS0023 Diagnostic(ErrorCode.ERR_BadUnaryOp, "obj++").WithArguments("++", "object").WithLocation(16, 13), @@ -1083,7 +1083,7 @@ object M() Diagnostic(ErrorCode.ERR_BadUnaryOp, "--obj").WithArguments("--", "object").WithLocation(17, 13), // (18,20): error CS8310: Operator '+' cannot be applied to operand '' // return +null; // CS0023 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "+null").WithArguments("+", "").WithLocation(18, 20) + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "+null").WithArguments("+", "").WithLocation(18, 20) ); } @@ -1111,16 +1111,16 @@ public static void Main() CreateCompilation(text).VerifyDiagnostics( // (6,19): error CS8310: Operator '!' cannot be applied to operand '' // bool? b = !null; // CS0023 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "!null").WithArguments("!", "").WithLocation(6, 19), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "!null").WithArguments("!", "").WithLocation(6, 19), // (7,18): error CS8310: Operator '~' cannot be applied to operand '' // int? n = ~null; // CS0023 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "~null").WithArguments("~", "").WithLocation(7, 18), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "~null").WithArguments("~", "").WithLocation(7, 18), // (8,20): error CS8310: Operator '+' cannot be applied to operand '' // float? f = +null; // CS0023 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "+null").WithArguments("+", "").WithLocation(8, 20), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "+null").WithArguments("+", "").WithLocation(8, 20), // (9,19): error CS8310: Operator '-' cannot be applied to operand '' // long? u = -null; // CS0023 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "-null").WithArguments("-", "").WithLocation(9, 19) + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "-null").WithArguments("-", "").WithLocation(9, 19) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedDefaultTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedDefaultTests.cs index a1333ecbc6c20..c8eb8ea6dd321 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedDefaultTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedDefaultTests.cs @@ -952,9 +952,9 @@ void M2() "; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_1); comp.VerifyDiagnostics( - // (6,16): error CS0023: Operator '.' cannot be applied to operand of type 'default' + // (6,16): error CS8310: Operator '.' cannot be applied to operand 'default' // default.ToString(); - Diagnostic(ErrorCode.ERR_BadUnaryOp, ".").WithArguments(".", "default").WithLocation(6, 16), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, ".").WithArguments(".", "default").WithLocation(6, 16), // (7,9): error CS8716: There is no target type for the default literal. // default[0].ToString(); Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(7, 9), @@ -974,9 +974,9 @@ void M2() // (6,9): error CS8107: Feature 'default literal' is not available in C# 7.0. Please use language version 7.1 or greater. // default.ToString(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "default").WithArguments("default literal", "7.1").WithLocation(6, 9), - // (6,16): error CS0023: Operator '.' cannot be applied to operand of type 'default' + // (6,16): error CS8310: Operator '.' cannot be applied to operand 'default' // default.ToString(); - Diagnostic(ErrorCode.ERR_BadUnaryOp, ".").WithArguments(".", "default").WithLocation(6, 16), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, ".").WithArguments(".", "default").WithLocation(6, 16), // (7,9): error CS8107: Feature 'default literal' is not available in C# 7.0. Please use language version 7.1 or greater. // default[0].ToString(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "default").WithArguments("default literal", "7.1").WithLocation(7, 9), @@ -1204,7 +1204,7 @@ static void Main() comp.VerifyDiagnostics( // (6,25): error CS8310: Operator '+' cannot be applied to operand 'default' // int j = checked(default + 4); - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default + 4").WithArguments("+", "default").WithLocation(6, 25) + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default + 4").WithArguments("+", "default").WithLocation(6, 25) ); var tree = comp.SyntaxTrees.First(); @@ -1249,52 +1249,52 @@ static void Main() { // (6,17): error CS8310: Operator '+' cannot be applied to operand 'default' // var a = default + default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default + default").WithArguments("+", "default").WithLocation(6, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default + default").WithArguments("+", "default").WithLocation(6, 17), // (7,17): error CS8310: Operator '-' cannot be applied to operand 'default' // var b = default - default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default - default").WithArguments("-", "default").WithLocation(7, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default - default").WithArguments("-", "default").WithLocation(7, 17), // (8,17): error CS8310: Operator '&' cannot be applied to operand 'default' // var c = default & default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default & default").WithArguments("&", "default").WithLocation(8, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default & default").WithArguments("&", "default").WithLocation(8, 17), // (9,17): error CS8310: Operator '|' cannot be applied to operand 'default' // var d = default | default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default | default").WithArguments("|", "default").WithLocation(9, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default | default").WithArguments("|", "default").WithLocation(9, 17), // (10,17): error CS8310: Operator '^' cannot be applied to operand 'default' // var e = default ^ default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default ^ default").WithArguments("^", "default").WithLocation(10, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default ^ default").WithArguments("^", "default").WithLocation(10, 17), // (11,17): error CS8310: Operator '*' cannot be applied to operand 'default' // var f = default * default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default * default").WithArguments("*", "default").WithLocation(11, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default * default").WithArguments("*", "default").WithLocation(11, 17), // (12,17): error CS8310: Operator '/' cannot be applied to operand 'default' // var g = default / default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default / default").WithArguments("/", "default").WithLocation(12, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default / default").WithArguments("/", "default").WithLocation(12, 17), // (13,17): error CS8310: Operator '%' cannot be applied to operand 'default' // var h = default % default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default % default").WithArguments("%", "default").WithLocation(13, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default % default").WithArguments("%", "default").WithLocation(13, 17), // (14,17): error CS8310: Operator '>>' cannot be applied to operand 'default' // var i = default >> default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default >> default").WithArguments(">>", "default").WithLocation(14, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default >> default").WithArguments(">>", "default").WithLocation(14, 17), // (15,17): error CS8310: Operator '<<' cannot be applied to operand 'default' // var j = default << default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default << default").WithArguments("<<", "default").WithLocation(15, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default << default").WithArguments("<<", "default").WithLocation(15, 17), // (16,17): error CS8310: Operator '>' cannot be applied to operand 'default' // var k = default > default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default > default").WithArguments(">", "default").WithLocation(16, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default > default").WithArguments(">", "default").WithLocation(16, 17), // (17,17): error CS8310: Operator '<' cannot be applied to operand 'default' // var l = default < default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default < default").WithArguments("<", "default").WithLocation(17, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default < default").WithArguments("<", "default").WithLocation(17, 17), // (18,17): error CS8310: Operator '>=' cannot be applied to operand 'default' // var m = default >= default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default >= default").WithArguments(">=", "default").WithLocation(18, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default >= default").WithArguments(">=", "default").WithLocation(18, 17), // (19,17): error CS8310: Operator '<=' cannot be applied to operand 'default' // var n = default <= default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default <= default").WithArguments("<=", "default").WithLocation(19, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default <= default").WithArguments("<=", "default").WithLocation(19, 17), // (20,17): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // var o = default == default; // ambiguous - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default == default").WithArguments("==").WithLocation(20, 17), + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "default == default").WithArguments("==", "default", "default").WithLocation(20, 17), // (21,17): error CS8315: Operator '!=' is ambiguous on operands 'default' and 'default' // var p = default != default; // ambiguous - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default != default").WithArguments("!=").WithLocation(21, 17), + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "default != default").WithArguments("!=", "default", "default").WithLocation(21, 17), // (22,17): error CS8716: There is no target type for the default literal. // var q = default && default; Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(22, 17), @@ -1354,46 +1354,46 @@ static void Main() { // (6,17): error CS8310: Operator '+' cannot be applied to operand 'default' // var a = default + 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default + 1").WithArguments("+", "default").WithLocation(6, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default + 1").WithArguments("+", "default").WithLocation(6, 17), // (7,17): error CS8310: Operator '-' cannot be applied to operand 'default' // var b = default - 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default - 1").WithArguments("-", "default").WithLocation(7, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default - 1").WithArguments("-", "default").WithLocation(7, 17), // (8,17): error CS8310: Operator '&' cannot be applied to operand 'default' // var c = default & 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default & 1").WithArguments("&", "default").WithLocation(8, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default & 1").WithArguments("&", "default").WithLocation(8, 17), // (9,17): error CS8310: Operator '|' cannot be applied to operand 'default' // var d = default | 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default | 1").WithArguments("|", "default").WithLocation(9, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default | 1").WithArguments("|", "default").WithLocation(9, 17), // (10,17): error CS8310: Operator '^' cannot be applied to operand 'default' // var e = default ^ 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default ^ 1").WithArguments("^", "default").WithLocation(10, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default ^ 1").WithArguments("^", "default").WithLocation(10, 17), // (11,17): error CS8310: Operator '*' cannot be applied to operand 'default' // var f = default * 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default * 1").WithArguments("*", "default").WithLocation(11, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default * 1").WithArguments("*", "default").WithLocation(11, 17), // (12,17): error CS8310: Operator '/' cannot be applied to operand 'default' // var g = default / 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default / 1").WithArguments("/", "default").WithLocation(12, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default / 1").WithArguments("/", "default").WithLocation(12, 17), // (13,17): error CS8310: Operator '%' cannot be applied to operand 'default' // var h = default % 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default % 1").WithArguments("%", "default").WithLocation(13, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default % 1").WithArguments("%", "default").WithLocation(13, 17), // (14,17): error CS8310: Operator '>>' cannot be applied to operand 'default' // var i = default >> 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default >> 1").WithArguments(">>", "default").WithLocation(14, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default >> 1").WithArguments(">>", "default").WithLocation(14, 17), // (15,17): error CS8310: Operator '<<' cannot be applied to operand 'default' // var j = default << 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default << 1").WithArguments("<<", "default").WithLocation(15, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default << 1").WithArguments("<<", "default").WithLocation(15, 17), // (16,17): error CS8310: Operator '>' cannot be applied to operand 'default' // var k = default > 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default > 1").WithArguments(">", "default").WithLocation(16, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default > 1").WithArguments(">", "default").WithLocation(16, 17), // (17,17): error CS8310: Operator '<' cannot be applied to operand 'default' // var l = default < 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default < 1").WithArguments("<", "default").WithLocation(17, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default < 1").WithArguments("<", "default").WithLocation(17, 17), // (18,17): error CS8310: Operator '>=' cannot be applied to operand 'default' // var m = default >= 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default >= 1").WithArguments(">=", "default").WithLocation(18, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default >= 1").WithArguments(">=", "default").WithLocation(18, 17), // (19,17): error CS8310: Operator '<=' cannot be applied to operand 'default' // var n = default <= 1; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default <= 1").WithArguments("<=", "default").WithLocation(19, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default <= 1").WithArguments("<=", "default").WithLocation(19, 17), // (22,17): error CS8716: There is no target type for the default literal. // var q = default && 1; Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(22, 17), @@ -1456,46 +1456,46 @@ static void Main() { // (6,17): error CS8310: Operator '+' cannot be applied to operand 'default' // var a = 1 + default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 + default").WithArguments("+", "default").WithLocation(6, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 + default").WithArguments("+", "default").WithLocation(6, 17), // (7,17): error CS8310: Operator '-' cannot be applied to operand 'default' // var b = 1 - default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 - default").WithArguments("-", "default").WithLocation(7, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 - default").WithArguments("-", "default").WithLocation(7, 17), // (8,17): error CS8310: Operator '&' cannot be applied to operand 'default' // var c = 1 & default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 & default").WithArguments("&", "default").WithLocation(8, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 & default").WithArguments("&", "default").WithLocation(8, 17), // (9,17): error CS8310: Operator '|' cannot be applied to operand 'default' // var d = 1 | default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 | default").WithArguments("|", "default").WithLocation(9, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 | default").WithArguments("|", "default").WithLocation(9, 17), // (10,17): error CS8310: Operator '^' cannot be applied to operand 'default' // var e = 1 ^ default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 ^ default").WithArguments("^", "default").WithLocation(10, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 ^ default").WithArguments("^", "default").WithLocation(10, 17), // (11,17): error CS8310: Operator '*' cannot be applied to operand 'default' // var f = 1 * default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 * default").WithArguments("*", "default").WithLocation(11, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 * default").WithArguments("*", "default").WithLocation(11, 17), // (12,17): error CS8310: Operator '/' cannot be applied to operand 'default' // var g = 1 / default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 / default").WithArguments("/", "default").WithLocation(12, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 / default").WithArguments("/", "default").WithLocation(12, 17), // (13,17): error CS8310: Operator '%' cannot be applied to operand 'default' // var h = 1 % default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 % default").WithArguments("%", "default").WithLocation(13, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 % default").WithArguments("%", "default").WithLocation(13, 17), // (14,17): error CS8310: Operator '>>' cannot be applied to operand 'default' // var i = 1 >> default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 >> default").WithArguments(">>", "default").WithLocation(14, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 >> default").WithArguments(">>", "default").WithLocation(14, 17), // (15,17): error CS8310: Operator '<<' cannot be applied to operand 'default' // var j = 1 << default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 << default").WithArguments("<<", "default").WithLocation(15, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 << default").WithArguments("<<", "default").WithLocation(15, 17), // (16,17): error CS8310: Operator '>' cannot be applied to operand 'default' // var k = 1 > default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 > default").WithArguments(">", "default").WithLocation(16, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 > default").WithArguments(">", "default").WithLocation(16, 17), // (17,17): error CS8310: Operator '<' cannot be applied to operand 'default' // var l = 1 < default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 < default").WithArguments("<", "default").WithLocation(17, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 < default").WithArguments("<", "default").WithLocation(17, 17), // (18,17): error CS8310: Operator '>=' cannot be applied to operand 'default' // var m = 1 >= default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 >= default").WithArguments(">=", "default").WithLocation(18, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 >= default").WithArguments(">=", "default").WithLocation(18, 17), // (19,17): error CS8310: Operator '<=' cannot be applied to operand 'default' // var n = 1 <= default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 <= default").WithArguments("<=", "default").WithLocation(19, 17), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 <= default").WithArguments("<=", "default").WithLocation(19, 17), // (22,22): error CS8716: There is no target type for the default literal. // var q = 1 && default; Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(22, 22), @@ -1560,7 +1560,7 @@ static void Main() { // (8,9): error CS8310: Operator '+=' cannot be applied to operand 'default' // s += default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "s += default").WithArguments("+=", "default").WithLocation(8, 9) + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "s += default").WithArguments("+=", "default").WithLocation(8, 9) }; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_1, options: TestOptions.DebugExe); @@ -1914,13 +1914,13 @@ static void Main() comp.VerifyDiagnostics( // (9,13): error CS8310: Operator '+=' cannot be applied to operand 'default' // i += default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "i += default").WithArguments("+=", "default").WithLocation(9, 13), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "i += default").WithArguments("+=", "default").WithLocation(9, 13), // (11,13): error CS8310: Operator '&=' cannot be applied to operand 'default' // b &= default; - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "b &= default").WithArguments("&=", "default").WithLocation(11, 13), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "b &= default").WithArguments("&=", "default").WithLocation(11, 13), // (12,37): error CS8310: Operator '|' cannot be applied to operand 'default' // System.Console.Write($"{true | default} {i} {b}"); - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "true | default").WithArguments("|", "default").WithLocation(12, 37), + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "true | default").WithArguments("|", "default").WithLocation(12, 37), // (15,40): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block // catch (System.Exception) when (default) Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "default").WithLocation(15, 40), @@ -2057,7 +2057,7 @@ static void Main() Diagnostic(ErrorCode.ERR_BadUnaryOp, "!Main").WithArguments("!", "method group").WithLocation(6, 13), // (6,22): error CS8310: Operator '!' cannot be applied to operand '' // if (!Main || !null) - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "!null").WithArguments("!", "").WithLocation(6, 22) + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "!null").WithArguments("!", "").WithLocation(6, 22) ); } @@ -2470,7 +2470,7 @@ static void Main() comp.VerifyDiagnostics( // (5,16): error CS8310: Operator '+' cannot be applied to operand 'default' // OneEntry = default + 1 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default + 1").WithArguments("+", "default").WithLocation(5, 16) + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default + 1").WithArguments("+", "default").WithLocation(5, 16) ); } @@ -2495,7 +2495,7 @@ static void Main() comp.VerifyDiagnostics( // (5,16): error CS8310: Operator '+' cannot be applied to operand 'default' // OneEntry = default + 1 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default + 1").WithArguments("+", "default").WithLocation(5, 16) + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default + 1").WithArguments("+", "default").WithLocation(5, 16) ); } @@ -2617,10 +2617,10 @@ static void Main() comp.VerifyDiagnostics( // (6,33): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // System.Console.Write($"{default == default} {default != default}"); - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default == default").WithArguments("==").WithLocation(6, 33), + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "default == default").WithArguments("==", "default", "default").WithLocation(6, 33), // (6,54): error CS8315: Operator '!=' is ambiguous on operands 'default' and 'default' // System.Console.Write($"{default == default} {default != default}"); - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default != default").WithArguments("!=").WithLocation(6, 54) + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "default != default").WithArguments("!=", "default", "default").WithLocation(6, 54) ); } @@ -2642,10 +2642,10 @@ static void Main() comp.VerifyDiagnostics( // (6,33): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // System.Console.Write($"{default == default} {default != default}"); - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default == default").WithArguments("==").WithLocation(6, 33), + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "default == default").WithArguments("==", "default", "default").WithLocation(6, 33), // (6,54): error CS8315: Operator '!=' is ambiguous on operands 'default' and 'default' // System.Console.Write($"{default == default} {default != default}"); - Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default != default").WithArguments("!=").WithLocation(6, 54) + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "default != default").WithArguments("!=", "default", "default").WithLocation(6, 54) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedObjectCreationTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedObjectCreationTests.cs new file mode 100644 index 0000000000000..5c559f272c4f5 --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedObjectCreationTests.cs @@ -0,0 +1,3964 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics +{ + public class TargetTypedObjectCreationTests : CSharpTestBase + { + private static readonly CSharpParseOptions TargetTypedObjectCreationTestOptions = TestOptions.RegularPreview; + + private static CSharpCompilation CreateCompilation(string source, CSharpCompilationOptions options = null, IEnumerable references = null) + { + return CSharpTestBase.CreateCompilation(source, options: options, parseOptions: TargetTypedObjectCreationTestOptions, references: references); + } + + [Fact] + public void TestInLocal() + { + var source = @" +using System; + +struct S +{ +} + +class C +{ + public static void Main() + { + C v1 = new(); + S v2 = new(); + S? v3 = new(); + Console.Write(v1); + Console.Write(v2); + Console.Write(v3); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "CSS"); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes().OfType().ToArray(); + + assert(0, type: "C", convertedType: "C", symbol: "C..ctor()", ConversionKind.Identity); + assert(1, type: "S", convertedType: "S", symbol: "S..ctor()", ConversionKind.Identity); + assert(2, type: "S", convertedType: "S?", symbol: "S..ctor()", ConversionKind.ImplicitNullable); + + void assert(int index, string type, string convertedType, string symbol, ConversionKind conversionKind) + { + var @new = nodes[index]; + Assert.Equal(type, model.GetTypeInfo(@new).Type.ToTestDisplayString()); + Assert.Equal(convertedType, model.GetTypeInfo(@new).ConvertedType.ToTestDisplayString()); + Assert.Equal(symbol, model.GetSymbolInfo(@new).Symbol.ToTestDisplayString()); + Assert.Equal(conversionKind, model.GetConversion(@new).Kind); + } + } + + [Fact] + public void TestInExpressionTree() + { + var source = @" +using System; +using System.Linq.Expressions; + +struct S +{ +} + +class C +{ + public static void Main() + { + Expression> expr1 = () => new(); + Expression> expr2 = () => new(); + Expression> expr3 = () => new(); + Console.Write(expr1.Compile()()); + Console.Write(expr2.Compile()()); + Console.Write(expr3.Compile()()); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "CSS"); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes().OfType().ToArray(); + + assert(0, type: "C", convertedType: "C", symbol: "C..ctor()", ConversionKind.Identity); + assert(1, type: "S", convertedType: "S", symbol: "S..ctor()", ConversionKind.Identity); + assert(2, type: "S", convertedType: "S?", symbol: "S..ctor()", ConversionKind.ImplicitNullable); + + void assert(int index, string type, string convertedType, string symbol, ConversionKind conversionKind) + { + var @new = nodes[index]; + Assert.Equal(type, model.GetTypeInfo(@new).Type.ToTestDisplayString()); + Assert.Equal(convertedType, model.GetTypeInfo(@new).ConvertedType.ToTestDisplayString()); + Assert.Equal(symbol, model.GetSymbolInfo(@new).Symbol.ToTestDisplayString()); + Assert.Equal(conversionKind, model.GetConversion(@new).Kind); + } + } + + [Fact] + public void TestInParameterDefaultValue() + { + var source = @" +struct S +{ +} + +class C +{ + void M( + C p1 = new(), + S p2 = new(), // ok + S? p3 = new(), + int p4 = new(), // ok + bool? p5 = new() // ok + ) + { + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (9,16): error CS1736: Default parameter value for 'p1' must be a compile-time constant + // C p1 = new(), + Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "new()").WithArguments("p1").WithLocation(9, 16), + // (11,17): error CS1736: Default parameter value for 'p3' must be a compile-time constant + // S? p3 = new() + Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "new()").WithArguments("p3").WithLocation(11, 17) + ); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes().OfType().ToArray(); + + assert(0, type: "C", convertedType: "C", symbol: "C..ctor()", constant: null, ConversionKind.Identity); + assert(1, type: "S", convertedType: "S", symbol: "S..ctor()", constant: null, ConversionKind.Identity); + assert(2, type: "S", convertedType: "S?", symbol: "S..ctor()", constant: null, ConversionKind.ImplicitNullable); + assert(3, type: "System.Int32", convertedType: "System.Int32", symbol: "System.Int32..ctor()", constant: "0", ConversionKind.Identity); + assert(4, type: "System.Boolean", convertedType: "System.Boolean?", symbol: "System.Boolean..ctor()", constant: "False", ConversionKind.ImplicitNullable); + + void assert(int index, string type, string convertedType, string symbol, string constant, ConversionKind conversionKind) + { + var @new = nodes[index]; + Assert.Equal(type, model.GetTypeInfo(@new).Type.ToTestDisplayString()); + Assert.Equal(convertedType, model.GetTypeInfo(@new).ConvertedType.ToTestDisplayString()); + Assert.Equal(symbol, model.GetSymbolInfo(@new).Symbol.ToTestDisplayString()); + Assert.Equal(conversionKind, model.GetConversion(@new).Kind); + Assert.Equal(constant, model.GetConstantValue(@new).Value?.ToString()); + } + } + + [Fact] + public void TestArguments_Out() + { + var source = @" +using System; + +class C +{ + public int j; + public C(out int i) + { + i = 2; + } + + public static void Main() + { + C c = new(out var i) { j = i }; + Console.Write(c.j); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "2"); + } + + [Fact] + public void TestArguments_Params() + { + var source = @" +using System; + +class C +{ + public C(params int[] p) + { + foreach (var item in p) + { + Console.Write(item); + } + } + + public static void Main() + { + C c = new(1, 2, 3); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "123"); + } + + [Fact] + public void TestArguments_NonTrailingNamedArgs() + { + var source = @" +using System; + +class C +{ + public C(object c, object o) => Console.Write(1); + public C(int i, object o) => Console.Write(2); + + public static void Main() + { + C c = new(c: new(), 2); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "1"); + } + + [Fact] + public void TestArguments_DynamicArgs() + { + var source = @" +using System; + +class C +{ + readonly int field; + + public C(int field) + { + this.field = field; + } + + public C(dynamic c) + { + Console.Write(c.field); + } + + public static void Main() + { + dynamic d = 5; + C c = new(new C(d)); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe, references: new[] { CSharpRef }); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "5"); + } + + [Fact] + public void TestInDynamicInvocation() + { + var source = @" +class C +{ + public void M(int i) {} + + public static void Main() + { + dynamic d = new C(); + d.M(new()); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe, references: new[] { CSharpRef }); + comp.VerifyDiagnostics( + // (9,13): error CS8754: There is no target type for 'new()' + // d.M(new()); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(9, 13) + ); + } + + [Fact] + public void TestInAsOperator() + { + var source = @" +using System; + +struct S +{ +} + +class C +{ + public void M() + where TClass : class + where TNew : new() + { + Console.Write(new() as C); + Console.Write(new() as S?); + Console.Write(new() as TClass); + Console.Write(new() as TNew); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugDll); + comp.VerifyDiagnostics( + // (14,23): error CS8754: There is no target type for 'new()' + // Console.Write(new() as C); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(14, 23), + // (15,23): error CS8754: There is no target type for 'new()' + // Console.Write(new() as S?); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(15, 23), + // (16,23): error CS8754: There is no target type for 'new()' + // Console.Write(new() as TClass); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(16, 23), + // (17,23): error CS8754: There is no target type for 'new()' + // Console.Write(new() as TNew); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(17, 23) + ); + } + + [Fact] + public void TestInTupleElement() + { + var source = @" +using System; + +class C +{ + static void M((T a, T b) t, T c) => Console.Write(t); + + public static void Main() + { + M((new(), new()), new C()); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "(C, C)"); + } + + [Fact] + public void TestTargetType_Var() + { + var source = @" +class C +{ + void M() + { + var x = new(2, 3); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,17): error CS8754: There is no target type for 'new(int, int)' + // var x = new(5); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new(2, 3)").WithArguments("new(int, int)").WithLocation(6, 17) + ); + } + + [Fact] + public void TestTargetType_Discard() + { + var source = @" +class C +{ + void M() + { + _ = new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,13): error CS8754: There is no target type for 'new()' + // _ = new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 13) + ); + } + + [Fact] + public void TestTargetType_Delegate() + { + var source = @" +delegate void D(); +class C +{ + void M() + { + D x0 = new(); + D x1 = new(M); // ok + var x2 = (D)new(); + var x3 = (D)new(M); // ok + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (7,16): error CS1729: 'D' does not contain a constructor that takes 0 arguments + // D x0 = new(); + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "new()").WithArguments("D", "0").WithLocation(7, 16), + // (9,21): error CS1729: 'D' does not contain a constructor that takes 0 arguments + // var x2 = (D)new(); + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "new()").WithArguments("D", "0").WithLocation(9, 21) + ); + } + + [Fact] + public void TestTargetType_Static() + { + var source = @" +public static class C { + static void M(object c) { + _ = (C)(new()); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (4,13): error CS0716: Cannot convert to static type 'C' + // _ = (C)(new()); + Diagnostic(ErrorCode.ERR_ConvertToStaticClass, "(C)(new())").WithArguments("C").WithLocation(4, 13), + // (4,17): error CS1729: 'C' does not contain a constructor that takes 0 arguments + // _ = (C)(new()); + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "new()").WithArguments("C", "0").WithLocation(4, 17) + ); + } + + [Fact] + public void TestTargetType_Abstract() + { + var source = @" +abstract class C +{ + void M() + { + C x0 = new(); + var x1 = (C)new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,16): error CS0144: Cannot create an instance of the abstract class or interface 'C' + // C x0 = new(); + Diagnostic(ErrorCode.ERR_NoNewAbstract, "new()").WithArguments("C").WithLocation(6, 16), + // (7,21): error CS0144: Cannot create an instance of the abstract class or interface 'C' + // var x1 = (C)new(); + Diagnostic(ErrorCode.ERR_NoNewAbstract, "new()").WithArguments("C").WithLocation(7, 21) + ); + } + + [Fact] + public void TestTargetType_Interface() + { + var source = @" +interface I {} +class C +{ + void M() + { + I x0 = new(); + var x1 = (I)new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (7,16): error CS0144: Cannot create an instance of the abstract class or interface 'I' + // I x0 = new(); + Diagnostic(ErrorCode.ERR_NoNewAbstract, "new()").WithArguments("I").WithLocation(7, 16), + // (8,21): error CS0144: Cannot create an instance of the abstract class or interface 'I' + // var x1 = (I)new(); + Diagnostic(ErrorCode.ERR_NoNewAbstract, "new()").WithArguments("I").WithLocation(8, 21) + ); + } + + [Fact] + public void TestTargetType_Enum() + { + var source = @" +enum E {} +class C +{ + void M() + { + E x0 = new(); + var x1 = (E)new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (7,16): error CS8752: The type 'E' may not be used as the target-type of 'new()' + // E x0 = new(); + Diagnostic(ErrorCode.ERR_TypelessNewIllegalTargetType, "new()").WithArguments("E").WithLocation(7, 16), + // (8,21): error CS8752: The type 'E' may not be used as the target-type of 'new()' + // var x1 = (E)new(); + Diagnostic(ErrorCode.ERR_TypelessNewIllegalTargetType, "new()").WithArguments("E").WithLocation(8, 21) + ); + } + + [Fact] + public void TestTargetType_Primitive() + { + var source = @" +class C +{ + void M() + { + int x0 = new(); + var x1 = (int)new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,13): warning CS0219: The variable 'x0' is assigned but its value is never used + // int x0 = new(); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x0").WithArguments("x0").WithLocation(6, 13), + // (7,13): warning CS0219: The variable 'x1' is assigned but its value is never used + // var x1 = (int)new(); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x1").WithArguments("x1").WithLocation(7, 13) + ); + } + + [Fact] + public void TestTargetType_TupleType() + { + var source = @" +#pragma warning disable 0219 +class C +{ + void M() + { + (int, int) x0 = new(); + var x1 = ((int, int))new(); + (int, C) x2 = new(); + var x3 = ((int, C))new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics(); + } + + [Fact] + public void TestTargetType_ValueTuple() + { + var source = @" +using System; +class C +{ + void M() + { + ValueTuple x0 = new(); + ValueTuple x1 = new(2, 3); + var x2 = (ValueTuple)new(); + var x3 = (ValueTuple)new(2, 3); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (7,30): warning CS0219: The variable 'x0' is assigned but its value is never used + // ValueTuple x0 = new(); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x0").WithArguments("x0").WithLocation(7, 30), + // (9,13): warning CS0219: The variable 'x2' is assigned but its value is never used + // var x2 = (ValueTuple)new(); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x2").WithArguments("x2").WithLocation(9, 13) + ); + } + + [Fact] + public void TestTypeParameter() + { + var source = @" +using System; + +struct S +{ + static void M1() where T : struct + { + Console.Write((T)new()); + } + static void M2() where T : new() + { + Console.Write((T)new()); + } + + public static void Main() + { + M1(); + M2(); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "SS"); + } + + [Fact] + public void TestTypeParameter_ErrorCases() + { + var source = @" +class C +{ + void M() + where TClass : class + where TStruct : struct + where TNew : new() + { + { + T x0 = new(); + var x1 = (T)new(); + } + { + TClass x0 = new(); + var x1 = (TClass)new(); + } + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (10,20): error CS0304: Cannot create an instance of the variable type 'T' because it does not have the new() constraint + // T x0 = new(); + Diagnostic(ErrorCode.ERR_NoNewTyvar, "new()").WithArguments("T").WithLocation(10, 20), + // (11,25): error CS0304: Cannot create an instance of the variable type 'T' because it does not have the new() constraint + // var x1 = (T)new(); + Diagnostic(ErrorCode.ERR_NoNewTyvar, "new()").WithArguments("T").WithLocation(11, 25), + // (14,25): error CS0304: Cannot create an instance of the variable type 'TClass' because it does not have the new() constraint + // TClass x0 = new(); + Diagnostic(ErrorCode.ERR_NoNewTyvar, "new()").WithArguments("TClass").WithLocation(14, 25), + // (15,30): error CS0304: Cannot create an instance of the variable type 'TClass' because it does not have the new() constraint + // var x1 = (TClass)new(); + Diagnostic(ErrorCode.ERR_NoNewTyvar, "new()").WithArguments("TClass").WithLocation(15, 30) + ); + } + + [Fact] + public void TestTargetType_ErrorType() + { + var source = @" +class C +{ + void M() + { + Missing x0 = new(); + var x1 = (Missing)new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,9): error CS0246: The type or namespace name 'Missing' could not be found (are you missing a using directive or an assembly reference?) + // Missing x0 = new(); + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Missing").WithArguments("Missing").WithLocation(6, 9), + // (7,19): error CS0246: The type or namespace name 'Missing' could not be found (are you missing a using directive or an assembly reference?) + // var x1 = (Missing)new(); + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Missing").WithArguments("Missing").WithLocation(7, 19) + ); + } + + [Fact] + public void TestTargetType_Pointer() + { + var source = @" +class C +{ + unsafe void M() + { + int* x0 = new(); + var x1 = (int*)new(); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseDll); + comp.VerifyDiagnostics( + // (6,19): error CS1919: Unsafe type 'int*' cannot be used in object creation + // int* x0 = new(); + Diagnostic(ErrorCode.ERR_UnsafeTypeInObjectCreation, "new()").WithArguments("int*").WithLocation(6, 19), + // (7,24): error CS1919: Unsafe type 'int*' cannot be used in object creation + // var x1 = (int*)new(); + Diagnostic(ErrorCode.ERR_UnsafeTypeInObjectCreation, "new()").WithArguments("int*").WithLocation(7, 24) + ); + } + + [Fact] + public void TestTargetType_AnonymousType() + { + var source = @" +class C +{ + void M() + { + var x0 = new { }; + x0 = new(); + var x1 = new { X = 1 }; + x1 = new(2); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (7,14): error CS8752: The type '' may not be used as the target-type of 'new()' + // x0 = new(); + Diagnostic(ErrorCode.ERR_TypelessNewIllegalTargetType, "new()").WithArguments("").WithLocation(7, 14), + // (9,14): error CS8752: The type '' may not be used as the target-type of 'new()' + // x1 = new(2); + Diagnostic(ErrorCode.ERR_TypelessNewIllegalTargetType, "new(2)").WithArguments("").WithLocation(9, 14)); + } + + [Fact] + public void TestAmbiguousCall() + { + var source = @" +class C { + + public C(object a, C b) {} + public C(C a, object b) {} + + public static void Main() + { + C c = new(new(), new()); + } +} +"; + + var comp = CreateCompilation(source).VerifyDiagnostics( + // (9,15): error CS0121: The call is ambiguous between the following methods or properties: 'C.C(object, C)' and 'C.C(C, object)' + // C c = new(new(), new()); + Diagnostic(ErrorCode.ERR_AmbigCall, "new(new(), new())").WithArguments("C.C(object, C)", "C.C(C, object)").WithLocation(9, 15) + ); + } + + [Fact] + public void TestObjectAndCollectionInitializer() + { + var source = @" +using System; +using System.Collections.Generic; + +class C +{ + public C field; + public int i; + + public C(int i) => this.i = i; + public C() {} + + public static void Main() + { + Dictionary> dict1 = new() { { new() { field = new(1) }, new() { 1, 2, 3 } } }; + Dictionary> dict2 = new() { [new() { field = new(2) }] = new() { 4, 5, 6 } }; + Dump(dict1); + Dump(dict2); + } + + static void Dump(Dictionary> dict) + { + foreach (C key in dict.Keys) + { + Console.Write($""C({key.field.i}): ""); + } + + foreach (List value in dict.Values) + { + Console.WriteLine(string.Join("", "", value)); + } + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: +@"C(1): 1, 2, 3 +C(2): 4, 5, 6"); + } + + [Fact] + public void TestInClassInitializer() + { + var source = @" +using System; + +class D +{ +} + +class C +{ + public D field = new(); + public D Property1 { get; } = new(); + public D Property2 { get; set; } = new(); + + public static void Main() + { + C c = new(); + Console.Write(c.field); + Console.Write(c.Property1); + Console.Write(c.Property2); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "DDD"); + } + + [Fact] + public void TestDataFlow() + { + var source = @" +using System; + +class C +{ + public int field; + + public static void Main() + { + int i; + C c = new() { field = (i = 42) }; + Console.Write(i); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "42"); + } + + [Fact] + public void TestDotOff() + { + var source = @" +class C +{ + public static void Main() + { + _ = (new()).field; + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (8,20): error CS0117: 'new()' does not contain a definition for 'field' + // _ = (new()).field; + Diagnostic(ErrorCode.ERR_NoSuchMember, "field").WithArguments("new()", "field").WithLocation(6, 20) + ); + } + + [Fact] + public void TestConditionalAccess() + { + var source = @" +using System; +class C +{ + public static void Main() + { + Console.Write(((int?)new())?.ToString()); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "0"); + } + + [Fact] + public void TestInaccessibleConstructor() + { + var source = @" +class D +{ + private D() {} +} + +class C +{ + public static void Main() + { + D d = new(); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (11,15): error CS0122: 'D.D()' is inaccessible due to its protection level + // D d = new(); + Diagnostic(ErrorCode.ERR_BadAccess, "new()").WithArguments("D.D()").WithLocation(11, 15) + ); + } + + [Fact] + public void TestBadArgs() + { + var source = @" +class C +{ + public static void Main() + { + C c = new(1); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,15): error CS1729: 'C' does not contain a constructor that takes 1 arguments + // C c = new(1); + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "new(1)").WithArguments("C", "1").WithLocation(6, 15) + ); + } + + [Fact] + public void TestNested() + { + var source = @" +using System; + +class C +{ + public C(C a, C b) => Console.Write(3); + public C(int i) => Console.Write(i); + + public static void Main() + { + C x = new(new(1), new(2)); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "123"); + } + + [Fact] + public void TestDeconstruction() + { + var source = @" +class C +{ + public static void Main() + { + var (_, _) = new(); + (var _, var _) = new(); + (C _, C _) = new(); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,22): error CS8754: There is no target type for 'new()' + // var (_, _) = new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 22), + // (6,22): error CS8131: Deconstruct assignment requires an expression with a type on the right-hand-side. + // var (_, _) = new(); + Diagnostic(ErrorCode.ERR_DeconstructRequiresExpression, "new()").WithLocation(6, 22), + // (6,14): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable '_'. + // var (_, _) = new(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "_").WithArguments("_").WithLocation(6, 14), + // (6,14): error CS8183: Cannot infer the type of implicitly-typed discard. + // var (_, _) = new(); + Diagnostic(ErrorCode.ERR_DiscardTypeInferenceFailed, "_").WithLocation(6, 14), + // (6,17): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable '_'. + // var (_, _) = new(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "_").WithArguments("_").WithLocation(6, 17), + // (6,17): error CS8183: Cannot infer the type of implicitly-typed discard. + // var (_, _) = new(); + Diagnostic(ErrorCode.ERR_DiscardTypeInferenceFailed, "_").WithLocation(6, 17), + // (7,26): error CS8754: There is no target type for 'new()' + // (var _, var _) = new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(7, 26), + // (7,26): error CS8131: Deconstruct assignment requires an expression with a type on the right-hand-side. + // (var _, var _) = new(); + Diagnostic(ErrorCode.ERR_DeconstructRequiresExpression, "new()").WithLocation(7, 26), + // (7,10): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable '_'. + // (var _, var _) = new(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "var _").WithArguments("_").WithLocation(7, 10), + // (7,10): error CS8183: Cannot infer the type of implicitly-typed discard. + // (var _, var _) = new(); + Diagnostic(ErrorCode.ERR_DiscardTypeInferenceFailed, "var _").WithLocation(7, 10), + // (7,17): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable '_'. + // (var _, var _) = new(); + Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "var _").WithArguments("_").WithLocation(7, 17), + // (7,17): error CS8183: Cannot infer the type of implicitly-typed discard. + // (var _, var _) = new(); + Diagnostic(ErrorCode.ERR_DiscardTypeInferenceFailed, "var _").WithLocation(7, 17), + // (8,22): error CS8754: There is no target type for 'new()' + // (C _, C _) = new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(8, 22), + // (8,22): error CS8131: Deconstruct assignment requires an expression with a type on the right-hand-side. + // (C _, C _) = new(); + Diagnostic(ErrorCode.ERR_DeconstructRequiresExpression, "new()").WithLocation(8, 22) + ); + } + + [Fact] + public void TestBestType_NullCoalescing() + { + var source = @" +using System; + +class C +{ + public static void Main() + { + C c = null; + Console.Write(c ?? new()); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "C"); + } + + [Fact] + public void TestBestType_Lambda() + { + var source = @" +using System; + +class C +{ + public static void M(Func f) + { + Console.Write(f(true)); + Console.Write(f(false)); + } + public static void Main() + { + M(b => { if (b) return new C(); else return new(); }); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "CC"); + } + + [Fact] + public void TestBestType_SwitchExpression() + { + var source = @" +using System; + +class C +{ + public static void Main() + { + var b = false; + Console.Write((int)(b switch { true => 1, false => new() })); + b = true; + Console.Write((int)(b switch { true => 1, false => new() })); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "01"); + } + + [Fact] + public void TestInSwitchExpression() + { + var source = @" +using System; + +class C +{ + public static void Main() + { + C x = 0 switch { _ => new() }; + Console.Write(x); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "C"); + } + + [Fact] + public void TestInNullCoalescingAssignment() + { + var source = @" +using System; + +class C +{ + public static void Main() + { + C x = null; + x ??= new(); + Console.Write(x); + int? i = null; + i ??= new(); + Console.Write(i); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "C0"); + } + + [Fact] + public void TestInNullCoalescingAssignment_ErrorCase() + { + var source = @" +class C +{ + public static void Main() + { + new() ??= new C(); + new() ??= new(); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (6,9): error CS0131: The left-hand side of an assignment must be a variable, property or indexer + // new() ??= new C(); + Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "new()").WithLocation(6, 9), + // (7,9): error CS0131: The left-hand side of an assignment must be a variable, property or indexer + // new() ??= new(); + Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "new()").WithLocation(7, 9) + ); + } + + [Fact] + public void TestBestType_Lambda_ErrorCase() + { + var source = @" +using System; + +class C +{ + public static void M(Func f) + { + } + + public static void Main() + { + M(b => { if (b) return new(); else return new(); }); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (12,9): error CS0411: The type arguments for method 'C.M(Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M(b => { if (b) return new(); else return new(); }); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M").WithArguments("C.M(System.Func)").WithLocation(12, 9) + ); + } + + [Fact] + public void TestBadTypeParameter() + { + var source = @" +class C +{ + static void M() + where A : struct + where B : new() + { + A v1 = new(1); + B v2 = new(2); + C v3 = new(); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.ReleaseDll).VerifyDiagnostics( + // (8,16): error CS0417: 'A': cannot provide arguments when creating an instance of a variable type + // A v1 = new(1); + Diagnostic(ErrorCode.ERR_NewTyvarWithArgs, "new(1)").WithArguments("A").WithLocation(8, 16), + // (9,16): error CS0417: 'B': cannot provide arguments when creating an instance of a variable type + // B v2 = new(2); + Diagnostic(ErrorCode.ERR_NewTyvarWithArgs, "new(2)").WithArguments("B").WithLocation(9, 16), + // (10,16): error CS0304: Cannot create an instance of the variable type 'C' because it does not have the new() constraint + // C v3 = new(); + Diagnostic(ErrorCode.ERR_NoNewTyvar, "new()").WithArguments("C").WithLocation(10, 16) + ); + } + + [Fact] + public void TestTypeParameterInitializer() + { + var source = @" +using System; + +class C +{ + public int field; + + static void M1() where T : C, new() + { + Console.Write(((T)new(){ field = 42 }).field); + } + + public static void Main() + { + M1(); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "42"); + } + + [Fact] + public void TestInitializer_ErrorCase() + { + var source = @" +class C +{ + public static void Main() + { + string x = new() { Length = 5 }; + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (8,28): error CS0200: Property or indexer 'string.Length' cannot be assigned to -- it is read only + // string x = new() { Length = 5 }; + Diagnostic(ErrorCode.ERR_AssgReadonlyProp, "Length").WithArguments("string.Length").WithLocation(6, 28), + // (8,20): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // string x = new() { Length = 5 }; + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "new() { Length = 5 }").WithArguments("string", "0").WithLocation(6, 20) + ); + } + + [Fact] + public void TestImplicitConversion() + { + var source = @" +public class Dog +{ + public Dog() {} +} +public class Animal +{ + public Animal() {} + public static implicit operator Animal(Dog dog) => throw null; +} + +public class Program +{ + public static void M(Animal a) => System.Console.Write(a); + public static void Main() + { + M(new()); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + ); + CompileAndVerify(comp, expectedOutput: "Animal"); + } + + [ConditionalFact(typeof(DesktopOnly), Reason = ConditionalSkipReason.RestrictedTypesNeedDesktop)] + public void ArgList() + { + var source = @" +using System; + +class C +{ + static void Main() + { + C x = new(__arglist(2, 3, true)); + } + + public C(__arglist) + { + DumpArgs(new(__arglist)); + } + + static void DumpArgs(ArgIterator args) + { + while(args.GetRemainingCount() > 0) + { + TypedReference tr = args.GetNextArg(); + object arg = TypedReference.ToObject(tr); + Console.Write(arg); + } + } +}"; + + var comp = CreateCompilation(source, options: TestOptions.ReleaseExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "23True"); + } + + [Fact] + public void TestOverloadResolution01() + { + var source = @" +class C +{ + public C(int i) {} +} + +class D +{ +} + +class Program +{ + static void M(C c, object o) {} + static void M(D d, int i) {} + + public static void Main() + { + M(new(1), 1); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (18,11): error CS1729: 'D' does not contain a constructor that takes 1 arguments + // M(new(1), 1); + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "new(1)").WithArguments("D", "1").WithLocation(18, 11) + ); + } + + [Fact] + public void TestOverloadResolution02() + { + var source = @" +using System; +class A +{ + public A(int i) {} +} +class B : A +{ + public B(int i) : base(i) {} +} + +class Program +{ + static void M(A a) => Console.Write(""A""); + static void M(B a) => Console.Write(""B""); + + public static void Main() + { + M(new(43)); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + + CompileAndVerify(comp, expectedOutput: "B"); + } + + [Fact] + public void TestOverloadResolution03() + { + var source = @" +class A +{ + public A(int i) {} +} +class B : A +{ + public B(int i) : base(i) {} +} + +class Program +{ + static void M(A a) {} + static void M(B a) {} + + public static void Main() + { + M(new(Missing())); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (18,15): error CS0103: The name 'Missing' does not exist in the current context + // M(new(Missing())); + Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(18, 15) + ); + } + + [Fact] + public void TestOverloadResolution04() + { + var source = @" +class A +{ + public A(int i) {} +} +class B : A +{ + public B(int i) : base(i) {} +} + +class Program +{ + public static void Main() + { + Missing(new(1)); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (15,9): error CS0103: The name 'Missing' does not exist in the current context + // Missing(new(1)); + Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(15, 9) + ); + } + + [Fact] + public void TestOverloadResolution05() + { + var source = @" +class A +{ + public A(int i) {} +} +class B : A +{ + public B(int i) : base(i) {} +} + +class Program +{ + static void M(A a, int i) {} + static void M(B a, object i) {} + + public static void Main() + { + M(new(), 1); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (18,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.M(A, int)' and 'Program.M(B, object)' + // M(new(), 1); + Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("Program.M(A, int)", "Program.M(B, object)").WithLocation(18, 9) + ); + } + + [Fact] + public void TestOverloadResolution06() + { + var source = @" +class C +{ + public C(object a, C b) {} + public C(C a, int b) {} + + public static void Main() + { + C c = new(new(), new()); + } +} +"; + + var comp = CreateCompilation(source).VerifyDiagnostics( + // (9,19): error CS1729: 'C' does not contain a constructor that takes 0 arguments + // C c = new(new(), new()); + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "new()").WithArguments("C", "0").WithLocation(9, 19) + ); + } + + [Fact] + public void TestSymbols() + { + var source = @" +class C +{ + static C N(int i) => null; + + static void M(C c) {} + + public static void Main() + { + Missing(new() { X = N(1) }); + M(new() { X = N(2) }); + + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (10,9): error CS0103: The name 'Missing' does not exist in the current context + // Missing(new() { X = N(1) }); + Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(10, 9), + // (11,19): error CS0117: 'C' does not contain a definition for 'X' + // M(new() { X = N(2) }); + Diagnostic(ErrorCode.ERR_NoSuchMember, "X").WithArguments("C", "X").WithLocation(11, 19) + ); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes().OfType().ToArray(); + + assert(1, "N(1)", type: "C", convertedType: "C", symbol: "C C.N(System.Int32 i)", ConversionKind.Identity); + assert(3, "N(2)", type: "C", convertedType: "C", symbol: "C C.N(System.Int32 i)", ConversionKind.Identity); + + void assert(int index, string expression, string type, string convertedType, string symbol, ConversionKind conversionKind) + { + var invocation = nodes[index]; + Assert.Equal(expression, invocation.ToString()); + Assert.Equal(type, model.GetTypeInfo(invocation).Type.ToTestDisplayString()); + Assert.Equal(convertedType, model.GetTypeInfo(invocation).ConvertedType.ToTestDisplayString()); + Assert.Equal(symbol, model.GetSymbolInfo(invocation).Symbol.ToTestDisplayString()); + Assert.Equal(conversionKind, model.GetConversion(invocation).Kind); + } + } + + [Fact] + public void TestAssignment() + { + var source = @" +class Program +{ + public static void Main() + { + new() = 5; + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (6,9): error CS0131: The left-hand side of an assignment must be a variable, property or indexer + // new() = 5; + Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "new()").WithLocation(6, 9) + ); + } + + [Fact] + public void TestNullableType01() + { + var source = @" +using System; + +struct S +{ + public S(int i) + { + Console.Write(i); + } + + public static void Main() + { + S? s = new(43); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "43"); + } + + [Fact] + public void TestNullableType02() + { + var source = @" +using System; +struct S +{ + public static T? M() where T : struct + { + return new(); + } + + public static void Main() + { + Console.Write(M()); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + + CompileAndVerify(comp, expectedOutput: "S"); + } + + [Fact] + public void TestInStatement() + { + var source = @" +struct S +{ + public static void Main() + { + new(a) { x }; + new() { x }; + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( + // (6,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement + // new(a) { x }; + Diagnostic(ErrorCode.ERR_IllegalStatement, "new(a) { x }").WithLocation(6, 9), + // (6,13): error CS0103: The name 'a' does not exist in the current context + // new(a) { x }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 13), + // (7,9): error CS8754: There is no target type for 'new()' + // new() { x }; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new() { x }").WithArguments("new()").WithLocation(7, 9), + // (7,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement + // new() { x }; + Diagnostic(ErrorCode.ERR_IllegalStatement, "new() { x }").WithLocation(7, 9), + // (7,17): error CS0103: The name 'x' does not exist in the current context + // new() { x }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(7, 17) + ); + } + + [Fact] + public void TestLangVersion_CSharp7() + { + string source = @" +class C +{ + static void Main() + { + C x = new(); + } +} +"; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7); + comp.VerifyDiagnostics( + // (6,15): error CS8652: The feature 'target-typed object creation' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // C x = new(); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "new").WithArguments("target-typed object creation").WithLocation(6, 15) + ); + } + + [Fact] + public void TestAssignmentToClass() + { + string source = @" +class C +{ + static void Main() + { + C x = new(); + System.Console.Write(x); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "C"); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); + + var def = nodes.OfType().Single(); + Assert.Equal("C", model.GetTypeInfo(def).Type.ToTestDisplayString()); + Assert.Equal("C", model.GetTypeInfo(def).ConvertedType.ToTestDisplayString()); + Assert.Equal("C..ctor()", model.GetSymbolInfo(def).Symbol.ToTestDisplayString()); + Assert.False(model.GetConstantValue(def).HasValue); + Assert.True(model.GetConversion(def).IsIdentity); + } + + [Fact] + public void TestAssignmentToStruct() + { + string source = @" +struct S +{ + public S(int i) {} + static void Main() + { + S x = new(43); + System.Console.Write(x); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "S"); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); + + var def = nodes.OfType().Single(); + Assert.Equal("S", model.GetTypeInfo(def).Type.ToTestDisplayString()); + Assert.Equal("S", model.GetTypeInfo(def).ConvertedType.ToTestDisplayString()); + Assert.Equal("S..ctor(System.Int32 i)", model.GetSymbolInfo(def).Symbol.ToTestDisplayString()); + Assert.False(model.GetConstantValue(def).HasValue); + Assert.True(model.GetConversion(def).IsIdentity); + } + + [Fact] + public void AssignmentToNullableStruct() + { + string source = @" +struct S +{ + public S(int i) {} + static void Main() + { + S? x = new(43); + System.Console.Write(x); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "S"); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); + + var def = nodes.OfType().Single(); + Assert.Equal("S", model.GetTypeInfo(def).Type.ToTestDisplayString()); + Assert.Equal("S?", model.GetTypeInfo(def).ConvertedType.ToTestDisplayString()); + Assert.Equal("S..ctor(System.Int32 i)", model.GetSymbolInfo(def).Symbol.ToTestDisplayString()); + Assert.False(model.GetConstantValue(def).HasValue); + Assert.True(model.GetConversion(def).IsNullable); + Assert.True(model.GetConversion(def).IsImplicit); + } + + [Fact] + public void AssignmentToThisOnRefType() + { + string source = @" +public class C +{ + public int field; + public C() => this = new(); + public static void Main() + { + new C(); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (5,19): error CS1604: Cannot assign to 'this' because it is read-only + // public C() => this = new(); + Diagnostic(ErrorCode.ERR_AssgReadonlyLocal, "this").WithArguments("this").WithLocation(5, 19) + ); + } + + [Fact] + public void AssignmentToThisOnStructType() + { + string source = @" +public struct S +{ + public int field; + public S(int x) => this = new(x); + public static void Main() + { + new S(1); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); + + var def = nodes.OfType().ElementAt(0); + Assert.Equal("new(x)", def.ToString()); + Assert.Equal("S", model.GetTypeInfo(def).Type.ToTestDisplayString()); + Assert.Equal("S", model.GetTypeInfo(def).ConvertedType.ToTestDisplayString()); + } + + [Fact] + public void InAttributeParameter() + { + string source = @" +[Custom(z: new(), y: new(), x: new())] +class C +{ + [Custom(new(1), new('s', 2))] + void M() + { + } +} +public class CustomAttribute : System.Attribute +{ + public CustomAttribute(int x, string y, byte z = 0) { } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (2,22): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // [Custom(z: new(), y: new(), x: new())] + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "new()").WithArguments("string", "0").WithLocation(2, 22), + // (5,13): error CS1729: 'int' does not contain a constructor that takes 1 arguments + // [Custom(new(1), new('s', 2))] + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "new(1)").WithArguments("int", "1").WithLocation(5, 13), + // (5,21): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type + // [Custom(new(1), new('s', 2))] + Diagnostic(ErrorCode.ERR_BadAttributeArgument, "new('s', 2)").WithLocation(5, 21) + ); + } + + [Fact] + public void InStringInterpolation() + { + string source = @" +class C +{ + static void Main() + { + System.Console.Write($""({new()}) ({new object()})""); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "(System.Object) (System.Object)"); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); + + var @new = nodes.OfType().Single(); + Assert.Equal("new()", @new.ToString()); + Assert.Equal("System.Object", model.GetTypeInfo(@new).Type.ToTestDisplayString()); + Assert.Equal("System.Object", model.GetTypeInfo(@new).ConvertedType.ToTestDisplayString()); + Assert.Equal("System.Object..ctor()", model.GetSymbolInfo(@new).Symbol?.ToTestDisplayString()); + Assert.False(model.GetConstantValue(@new).HasValue); + + var newObject = nodes.OfType().Single(); + Assert.Equal("new object()", newObject.ToString()); + Assert.Equal("System.Object", model.GetTypeInfo(newObject).Type.ToTestDisplayString()); + Assert.Equal("System.Object", model.GetTypeInfo(newObject).ConvertedType.ToTestDisplayString()); + Assert.Equal("System.Object..ctor()", model.GetSymbolInfo(newObject).Symbol?.ToTestDisplayString()); + } + + [Fact] + public void InUsing01() + { + string source = @" +class C +{ + static void Main() + { + using (new()) + { + } + + using (var x = new()) + { + } + + using (System.IDisposable x = new()) + { + } + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,16): error CS8754: There is no target type for 'new()' + // using (new()) + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 16), + // (10,24): error CS8754: There is no target type for 'new()' + // using (var x = new()) + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(10, 24), + // (14,39): error CS0144: Cannot create an instance of the abstract class or interface 'IDisposable' + // using (System.IDisposable x = new()) + Diagnostic(ErrorCode.ERR_NoNewAbstract, "new()").WithArguments("System.IDisposable").WithLocation(14, 39) + ); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes().OfType().ToArray(); + + assert(0, type: "?", convertedType: "?", ConversionKind.Identity); + assert(1, type: "?", convertedType: "?", ConversionKind.Identity); + assert(2, type: "System.IDisposable", convertedType: "System.IDisposable", ConversionKind.Identity); + + void assert(int index, string type, string convertedType, ConversionKind conversionKind) + { + var @new = nodes[index]; + Assert.Equal(type, model.GetTypeInfo(@new).Type.ToTestDisplayString()); + Assert.Equal(convertedType, model.GetTypeInfo(@new).ConvertedType.ToTestDisplayString()); + Assert.Null(model.GetSymbolInfo(@new).Symbol); + Assert.Equal(conversionKind, model.GetConversion(@new).Kind); + } + } + + [Fact] + public void InUsing02() + { + string source = @" +using System; + +class C : IDisposable +{ + public void Dispose() + { + Console.Write(""C.Dispose""); + } + + static void Main() + { + using (C c = new()) + { + } + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "C.Dispose"); + } + + [Fact] + public void TestInAwait() + { + string source = @" +class C +{ + async System.Threading.Tasks.Task M1() + { + await new(); + } + + async System.Threading.Tasks.Task M2() + { + await new(a); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,15): error CS8754: There is no target type for 'new()' + // await new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 15), + // (11,19): error CS0103: The name 'a' does not exist in the current context + // await new(a); + Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(11, 19) + ); + } + + [Fact] + public void ReturningFromAsyncMethod() + { + string source = @" +using System.Threading.Tasks; +class C +{ + async Task M2() where T : new() + { + await Task.Delay(0); + return new(); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); + + var def = nodes.OfType().ElementAt(0); + Assert.Equal("new()", def.ToString()); + Assert.Equal("T", model.GetTypeInfo(def).Type.ToTestDisplayString()); + Assert.Equal("T", model.GetTypeInfo(def).ConvertedType.ToTestDisplayString()); + Assert.Null(model.GetSymbolInfo(def).Symbol); + Assert.False(model.GetConstantValue(def).HasValue); + Assert.True(model.GetConversion(def).IsIdentity); + } + + [Fact] + public void TestInAsyncLambda_01() + { + string source = @" +class C +{ + static void F(System.Threading.Tasks.Task t) { } + + static void M() + { + F(async () => await new()); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (8,9): error CS0411: The type arguments for method 'C.F(Task)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // F(async () => await new()); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F").WithArguments("C.F(System.Threading.Tasks.Task)").WithLocation(8, 9) + ); + } + + [Fact] + public void TestInAsyncLambda_02() + { + string source = @" +class C +{ + static void F(System.Threading.Tasks.Task t) { } + + static void M() + { + F(async () => new()); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (8,9): error CS0411: The type arguments for method 'C.F(Task)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // F(async () => new()); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F").WithArguments("C.F(System.Threading.Tasks.Task)").WithLocation(8, 9), + // (8,20): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. + // F(async () => new()); + Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(8, 20) + ); + } + + [Fact] + public void RefReturnValue1() + { + string source = @" +class C +{ + ref int M() + { + return new(); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,9): error CS8150: By-value returns may only be used in methods that return by value + // return new(); + Diagnostic(ErrorCode.ERR_MustHaveRefReturn, "return").WithLocation(6, 9) + ); + } + + [Fact] + public void RefReturnValue2() + { + string source = @" +class C +{ + ref C M() + { + return ref new(); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,20): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference + // return ref new(); + Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "new()").WithLocation(6, 20) + ); + } + + [Fact] + public void InAnonType() + { + string source = @" +class C +{ + static void M() + { + var x = new { Prop = new() }; + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,30): error CS8754: There is no target type for 'new()' + // var x = new { Prop = new() }; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 30) + ); + } + + [Fact] + public void BadUnaryOperator() + { + string source = @" +class C +{ + static void M() + { + C v1 = +new(); + C v2 = -new(); + C v3 = ~new(); + C v4 = !new(); + C v5 = ++new(); + C v6 = --new(); + C v7 = new()++; + C v8 = new()--; + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,17): error CS8754: There is no target type for 'new()' + // C v1 = +new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 17), + // (7,17): error CS8754: There is no target type for 'new()' + // C v2 = -new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(7, 17), + // (8,17): error CS8754: There is no target type for 'new()' + // C v3 = ~new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(8, 17), + // (9,17): error CS8754: There is no target type for 'new()' + // C v4 = !new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(9, 17), + // (10,18): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer + // C v5 = ++new(); + Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "new()").WithLocation(10, 18), + // (11,18): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer + // C v6 = --new(); + Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "new()").WithLocation(11, 18), + // (12,16): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer + // C v7 = new()++; + Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "new()").WithLocation(12, 16), + // (13,16): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer + // C v8 = new()--; + Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "new()").WithLocation(13, 16) + ); + } + + [Fact] + public void AmbiguousMethod() + { + string source = @" +class C +{ + static void Main() + { + M(new()); + } + static void M(int x) { } + static void M(string x) { } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,9): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(int)' and 'C.M(string)' + // M(new()); + Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(int)", "C.M(string)").WithLocation(6, 9) + ); + } + + [Fact] + public void MethodWithNullableParameters() + { + string source = @" +struct S +{ + public S(int i) {} + + static void Main() + { + M(new(43)); + } + + static void M(S? x) => System.Console.Write(x); +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "S"); + } + + [Fact] + public void CannotInferTypeArg() + { + string source = @" +class C +{ + static void Main() + { + M(new()); + } + static void M(T x) { } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,9): error CS0411: The type arguments for method 'C.M(T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M(new()); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M").WithArguments("C.M(T)").WithLocation(6, 9) + ); + } + + [Fact] + public void CannotInferTypeArg2() + { + string source = @" +class C +{ + static void Main() + { + M(new(), null); + } + static void M(T x, T y) where T : class { } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,9): error CS0411: The type arguments for method 'C.M(T, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M(new(), null); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M").WithArguments("C.M(T, T)").WithLocation(6, 9) + ); + } + + [Fact] + public void Invocation() + { + string source = @" +class C +{ + static void Main() + { + new().ToString(); + new()[0].ToString(); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,15): error CS0117: 'new()' does not contain a definition for 'ToString' + // new().ToString(); + Diagnostic(ErrorCode.ERR_NoSuchMember, "ToString").WithArguments("new()", "ToString").WithLocation(6, 15), + // (7,9): error CS8754: There is no target type for 'new()' + // new()[0].ToString(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(7, 9) + ); + } + + [Fact] + public void InThrow() + { + string source = @" +class C +{ + static void Main() + { + throw new(""message""); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); + + var def = nodes.OfType().First(); + Assert.Equal("System.Exception", model.GetTypeInfo(def).Type.ToTestDisplayString()); + Assert.Equal("System.Exception", model.GetTypeInfo(def).ConvertedType.ToTestDisplayString()); + Assert.Equal("System.Exception..ctor(System.String message)", model.GetSymbolInfo(def).Symbol.ToTestDisplayString()); + } + + [Fact] + public void TestConst() + { + string source = @" +class C +{ + static void M() + { + const object x = new(); + const int y = new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,26): error CS0133: The expression being assigned to 'x' must be constant + // const object x = new(); + Diagnostic(ErrorCode.ERR_NotConstantExpression, "new()").WithArguments("x").WithLocation(6, 26), + // (7,19): warning CS0219: The variable 'y' is assigned but its value is never used + // const int y = new(); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y").WithLocation(7, 19) + ); + } + + [Fact] + public void ImplicitlyTypedArray() + { + string source = @" +class C +{ + static void Main() + { + var t = new[] { new C(), new() }; + System.Console.Write(t[1]); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "C"); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); + + var def = nodes.OfType().First(); + Assert.Equal("new()", def.ToString()); + Assert.Equal("C", model.GetTypeInfo(def).Type.ToTestDisplayString()); + Assert.Equal("C", model.GetTypeInfo(def).ConvertedType.ToTestDisplayString()); + Assert.Equal("C..ctor()", model.GetSymbolInfo(def).Symbol.ToTestDisplayString()); + Assert.False(model.GetConstantValue(def).HasValue); + } + + [Fact] + public void InSwitch1() + { + string source = @" +class C +{ + static void Main() + { + switch (new()) + { + case new() when new(): + case (new()) when (new()): + break; + } + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,17): error CS8754: There is no target type for 'new()' + // switch (new()) + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 17), + // (10,17): warning CS0162: Unreachable code detected + // break; + Diagnostic(ErrorCode.WRN_UnreachableCode, "break").WithLocation(10, 17) + ); + } + + [Fact] + public void InSwitch2() + { + string source = @" +class C +{ + static void Main() + { + switch (new C()) + { + case new(): + case (new()): + break; + } + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (8,18): error CS0150: A constant value is expected + // case new(): + Diagnostic(ErrorCode.ERR_ConstantExpected, "new()").WithLocation(8, 18), + // (9,18): error CS0150: A constant value is expected + // case (new()): + Diagnostic(ErrorCode.ERR_ConstantExpected, "(new())").WithLocation(9, 18) + ); + } + + [Fact] + public void InSwitch3() + { + string source = @" +class C +{ + static void Main() + { + int i = 0; + bool b = true; + switch (i) + { + case new() when b: + System.Console.Write(0); + break; + } + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.ReleaseExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "0"); + } + + [Fact] + public void InGoToCase() + { + string source = @" +using System; +class C +{ + static int Get(int i) + { + switch (i) + { + case new(): + return 1; + case 1: + goto case new(); + default: + return 2; + } + } + static void Main() + { + Console.Write(Get(0)); + Console.Write(Get(1)); + Console.Write(Get(2)); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "112"); + } + + [Fact] + public void InCatchFilter() + { + string source = @" +class C +{ + static void Main() + { + try + { + } + catch when (new()) + { + } + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (9,21): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block + // catch when (new()) + Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "new()").WithLocation(9, 21) + ); + } + + [Fact] + public void InLock() + { + string source = @" +class C +{ + static void Main() + { + lock (new()) + { + } + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,15): error CS8754: There is no target type for 'new()' + // lock (new()) + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 15) + ); + } + + [Fact] + public void InMakeRef() + { + string source = @" +class C +{ + static void Main() + { + System.TypedReference tr = __makeref(new()); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,46): error CS1510: A ref or out value must be an assignable variable + // System.TypedReference tr = __makeref(new()); + Diagnostic(ErrorCode.ERR_RefLvalueExpected, "new()").WithLocation(6, 46) + ); + } + + [Fact] + public void InNameOf() + { + string source = @" +class C +{ + static void Main() + { + _ = nameof(new()); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,20): error CS8081: Expression does not have a name. + // _ = nameof(new()); + Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "new()").WithLocation(6, 20) + ); + } + + [Fact] + public void InOutArgument() + { + string source = @" +class C +{ + static void M(out int i) + { + i = 0; + M(out new()); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugDll); + comp.VerifyDiagnostics( + // (7,15): error CS1510: A ref or out value must be an assignable variable + // M(out new()); + Diagnostic(ErrorCode.ERR_RefLvalueExpected, "new()").WithLocation(7, 15) + ); + } + + [Fact] + public void InSizeOf() + { + string source = @" +class C +{ + static void Main() + { + _ = sizeof(new()); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,20): error CS1031: Type expected + // _ = sizeof(new()); + Diagnostic(ErrorCode.ERR_TypeExpected, "new").WithLocation(6, 20), + // (6,20): error CS1026: ) expected + // _ = sizeof(new()); + Diagnostic(ErrorCode.ERR_CloseParenExpected, "new").WithLocation(6, 20), + // (6,20): error CS1002: ; expected + // _ = sizeof(new()); + Diagnostic(ErrorCode.ERR_SemicolonExpected, "new").WithLocation(6, 20), + // (6,25): error CS1002: ; expected + // _ = sizeof(new()); + Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(6, 25), + // (6,25): error CS1513: } expected + // _ = sizeof(new()); + Diagnostic(ErrorCode.ERR_RbraceExpected, ")").WithLocation(6, 25), + // (6,13): error CS0233: '?' does not have a predefined size, therefore sizeof can only be used in an unsafe context + // _ = sizeof(new()); + Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(").WithArguments("?").WithLocation(6, 13), + // (6,20): error CS8754: There is no target type for 'new()' + // _ = sizeof(new()); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 20) + ); + } + + [Fact] + public void InTypeOf() + { + string source = @" +class C +{ + static void Main() + { + _ = typeof(new()); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,20): error CS1031: Type expected + // _ = typeof(new()); + Diagnostic(ErrorCode.ERR_TypeExpected, "new").WithLocation(6, 20), + // (6,20): error CS1026: ) expected + // _ = typeof(new()); + Diagnostic(ErrorCode.ERR_CloseParenExpected, "new").WithLocation(6, 20), + // (6,20): error CS1002: ; expected + // _ = typeof(new()); + Diagnostic(ErrorCode.ERR_SemicolonExpected, "new").WithLocation(6, 20), + // (6,20): error CS8754: There is no target type for 'new()' + // _ = typeof(new()); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 20), + // (6,25): error CS1002: ; expected + // _ = typeof(new()); + Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(6, 25), + // (6,25): error CS1513: } expected + // _ = typeof(new()); + Diagnostic(ErrorCode.ERR_RbraceExpected, ")").WithLocation(6, 25) + ); + } + + [Fact] + public void InChecked() + { + string source = @" +class C +{ + static void Main() + { + int i = checked(new(a)); + int j = checked(new()); // ok + C k = unchecked(new()); // ok + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,29): error CS0103: The name 'a' does not exist in the current context + // int i = checked(new(a)); + Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 29), + // (7,13): warning CS0219: The variable 'j' is assigned but its value is never used + // int j = checked(new()); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "j").WithArguments("j").WithLocation(7, 13) + ); + } + + [Fact] + public void InRange() + { + string source = @" +using System; +class C +{ + static void Main() + { + Range x0 = new()..new(); + Range x1 = 1..new(); + Range x2 = new()..1; + Console.WriteLine($""{x0.Start.Value}..{x0.End.Value}""); + Console.WriteLine($""{x1.Start.Value}..{x1.End.Value}""); + Console.WriteLine($""{x2.Start.Value}..{x2.End.Value}""); + } +} +"; + var comp = CreateCompilationWithIndexAndRange(source, options: TestOptions.DebugExe, parseOptions: TargetTypedObjectCreationTestOptions); + comp.VerifyDiagnostics(); + + var expectedOutput = +@"0..0 +1..0 +0..1"; + CompileAndVerify(comp, expectedOutput: expectedOutput); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes().OfType().ToArray(); + + assert(0, type: "System.Index", convertedType: "System.Index", symbol: "System.Index..ctor()", ConversionKind.Identity); + assert(1, type: "System.Index", convertedType: "System.Index", symbol: "System.Index..ctor()", ConversionKind.Identity); + assert(2, type: "System.Index", convertedType: "System.Index", symbol: "System.Index..ctor()", ConversionKind.Identity); + assert(3, type: "System.Index", convertedType: "System.Index", symbol: "System.Index..ctor()", ConversionKind.Identity); + + void assert(int index, string type, string convertedType, string symbol, ConversionKind conversionKind) + { + var @new = nodes[index]; + Assert.Equal(type, model.GetTypeInfo(@new).Type.ToTestDisplayString()); + Assert.Equal(convertedType, model.GetTypeInfo(@new).ConvertedType.ToTestDisplayString()); + Assert.Equal(symbol, model.GetSymbolInfo(@new).Symbol.ToTestDisplayString()); + Assert.Equal(conversionKind, model.GetConversion(@new).Kind); + } + } + + [Fact] + public void RefTypeAndValue() + { + string source = @" +class C +{ + static void Main() + { + var t = __reftype(new()); + int rv = __refvalue(new(), int); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + } + + [Fact] + public void ConditionalOnNew() + { + string source = @" +class C +{ + static void Main() + { + if (new()) + { + System.Console.Write(""if""); + } + + while (new()) + { + System.Console.Write(""while""); + } + + for (int i = 0; new(); i++) + { + System.Console.Write(""for""); + } + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (8,13): warning CS0162: Unreachable code detected + // System.Console.Write("if"); + Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(8, 13), + // (13,13): warning CS0162: Unreachable code detected + // System.Console.Write("while"); + Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(13, 13), + // (18,13): warning CS0162: Unreachable code detected + // System.Console.Write("for"); + Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(18, 13)); + } + + [Fact] + public void InFixed() + { + string source = @" +class C +{ + static unsafe void Main() + { + fixed (byte* p = new()) + { + } + fixed (byte* p = &new()) + { + } + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe.WithAllowUnsafe(true)); + comp.VerifyDiagnostics( + // (6,26): error CS9385: The given expression cannot be used in a fixed statement + // fixed (byte* p = new()) + Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "new()").WithLocation(6, 26), + // (9,27): error CS0211: Cannot take the address of the given expression + // fixed (byte* p = &new()) + Diagnostic(ErrorCode.ERR_InvalidAddrOp, "new()").WithLocation(9, 27) + ); + } + + [Fact] + public void Dereference() + { + string source = @" +class C +{ + static void M() + { + var p = *new(); + var q = new()->F; + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,18): error CS8754: There is no target type for 'new()' + // var p = *new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 18), + // (7,17): error CS8754: There is no target type for 'new()' + // var q = new()->F; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(7, 17) + ); + } + + [Fact] + public void FailedImplicitlyTypedArray() + { + string source = @" +class C +{ + static void Main() + { + var t = new[] { new(), new() }; + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,17): error CS0826: No best type found for implicitly-typed array + // var t = new[] { new(), new() }; + Diagnostic(ErrorCode.ERR_ImplicitlyTypedArrayNoBestType, "new[] { new(), new() }").WithLocation(6, 17) + ); + } + + [Fact] + public void ArrayConstruction() + { + string source = @" +class C +{ + static void Main() + { + var t = new object[new()]; + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics(); + } + + [Fact] + public void Tuple() + { + string source = @" +class C +{ + static void Main() + { + (int, C) t = (1, new()); + System.Console.Write(t.Item2); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "C"); + } + + [Fact] + public void TypeInferenceSucceeds() + { + string source = @" +class C +{ + static void Main() + { + M(new(), new C()); + } + static void M(T x, T y) { System.Console.Write(x); } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "C"); + } + + [Fact] + public void ArrayTypeInferredFromParams() + { + string source = @" +class C +{ + static void Main() + { + M(new()); + } + + static void M(params object[] x) { } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,11): error CS9366: The type 'object[]' may not be used as the target-type of 'new()' + // M(new()); + Diagnostic(ErrorCode.ERR_TypelessNewIllegalTargetType, "new()").WithArguments("object[]").WithLocation(6, 11) + ); + } + + [Fact] + public void ParamsAmbiguity01() + { + string source = @" +class C +{ + static void Main() + { + M(new()); + } + static void M(params object[] x) { } + static void M(params int[] x) { } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,9): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(params object[])' and 'C.M(params int[])' + // M(new()); + Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(params object[])", "C.M(params int[])").WithLocation(6, 9) + ); + } + + [Fact] + public void ParamsAmbiguity02() + { + string source = @" +class C +{ + static void Main() + { + M(new()); + } + static void M(params object[] x) { } + static void M(C x) { } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,9): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(params object[])' and 'C.M(C)' + // M(new()); + Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(params object[])", "C.M(C)").WithLocation(6, 9) + ); + } + + [Fact] + public void ParamsAmbiguity03() + { + string source = @" +class C +{ + static void Main() + { + object o = null; + C c = new(); + M(o, new()); + M(new(), o); + M(c, new()); + M(new(), c); + } + static void M(T x, params T[] y) { } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (8,14): error CS9366: The type 'object[]' may not be used as the target-type of 'new'. + // M(o, new()); + Diagnostic(ErrorCode.ERR_TypelessNewIllegalTargetType, "new()").WithArguments("object[]").WithLocation(8, 14), + // (10,14): error CS9366: The type 'C[]' may not be used as the target-type of 'new'. + // M(c, new()); + Diagnostic(ErrorCode.ERR_TypelessNewIllegalTargetType, "new()").WithArguments("C[]").WithLocation(10, 14) + ); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes(); + + var first = nodes.OfType().ElementAt(1); + Assert.Equal("(o, new())", first.Parent.Parent.ToString()); + Assert.Equal("System.Object[]", model.GetTypeInfo(first).Type.ToTestDisplayString()); + + var second = nodes.OfType().ElementAt(2); + Assert.Equal("(new(), o)", second.Parent.Parent.ToString()); + Assert.Equal("System.Object", model.GetTypeInfo(second).Type.ToTestDisplayString()); + + var third = nodes.OfType().ElementAt(3); + Assert.Equal("(c, new())", third.Parent.Parent.ToString()); + Assert.Equal("C[]", model.GetTypeInfo(third).Type.ToTestDisplayString()); + + var fourth = nodes.OfType().ElementAt(4); + Assert.Equal("(new(), c)", fourth.Parent.Parent.ToString()); + Assert.Equal("C", model.GetTypeInfo(fourth).Type.ToTestDisplayString()); + } + + [Fact] + public void NewIdentifier() + { + string source = @" +class C +{ + static void Main() + { + int @new = 2; + C x = new(); + System.Console.Write($""{x} {@new}""); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "C 2"); + } + + [Fact] + public void Return() + { + string source = @" +class C +{ + static C M() + { + return new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics(); + } + + [Fact] + public void NewInEnum() + { + string source = @" +enum E : byte +{ + A = new(), + B = new() + 1 +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics(); + } + + [Fact] + public void YieldReturn() + { + string source = @" +using System.Collections; +using System.Collections.Generic; +class C +{ + static IEnumerable M() + { + yield return new(); + } + static IEnumerable M2() + { + yield return new(); + } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics(); + } + + [Fact] + public void InvocationOnDynamic() + { + string source = @" +class C +{ + static void M1() + { + dynamic d = null; + d.M2(new()); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (7,14): error CS8754: There is no target type for 'new()' + // d.M2(new()); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(7, 14) + ); + } + + [Fact] + public void DynamicInvocation() + { + string source = @" +class C +{ + static void Main() + { + F(new()); + } + static void F(dynamic x) + { + System.Console.Write(x == null); + } +} +"; + + var comp = CreateCompilation(source, references: new[] { CSharpRef }, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,11): error CS0143: The type 'dynamic' has no constructors defined + // F(new()); + Diagnostic(ErrorCode.ERR_NoConstructors, "new()").WithArguments("dynamic").WithLocation(6, 11) + ); + } + + [Fact] + public void TestBinaryOperators01() + { + string source = @" +class C +{ + static void Main() + { + var a = new() + new(); + var b = new() - new(); + var c = new() & new(); + var d = new() | new(); + var e = new() ^ new(); + var f = new() * new(); + var g = new() / new(); + var h = new() % new(); + var i = new() >> new(); + var j = new() << new(); + var k = new() > new(); + var l = new() < new(); + var m = new() >= new(); + var n = new() <= new(); + var o = new() == new(); // void ImplicitObjectCreation + var p = new() != new(); // void ImplicitObjectCreation + var q = new() && new(); + var r = new() || new(); + var s = new() ?? new(); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (6,17): error CS8315: Operator '+' is ambiguous on operands 'new()' and 'new()' + // var a = new() + new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() + new()").WithArguments("+", "new()", "new()").WithLocation(6, 17), + // (7,17): error CS8315: Operator '-' is ambiguous on operands 'new()' and 'new()' + // var b = new() - new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() - new()").WithArguments("-", "new()", "new()").WithLocation(7, 17), + // (8,17): error CS8315: Operator '&' is ambiguous on operands 'new()' and 'new()' + // var c = new() & new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() & new()").WithArguments("&", "new()", "new()").WithLocation(8, 17), + // (9,17): error CS8315: Operator '|' is ambiguous on operands 'new()' and 'new()' + // var d = new() | new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() | new()").WithArguments("|", "new()", "new()").WithLocation(9, 17), + // (10,17): error CS8315: Operator '^' is ambiguous on operands 'new()' and 'new()' + // var e = new() ^ new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() ^ new()").WithArguments("^", "new()", "new()").WithLocation(10, 17), + // (11,17): error CS8315: Operator '*' is ambiguous on operands 'new()' and 'new()' + // var f = new() * new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() * new()").WithArguments("*", "new()", "new()").WithLocation(11, 17), + // (12,17): error CS8315: Operator '/' is ambiguous on operands 'new()' and 'new()' + // var g = new() / new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() / new()").WithArguments("/", "new()", "new()").WithLocation(12, 17), + // (13,17): error CS8315: Operator '%' is ambiguous on operands 'new()' and 'new()' + // var h = new() % new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() % new()").WithArguments("%", "new()", "new()").WithLocation(13, 17), + // (14,17): error CS8315: Operator '>>' is ambiguous on operands 'new()' and 'new()' + // var i = new() >> new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() >> new()").WithArguments(">>", "new()", "new()").WithLocation(14, 17), + // (15,17): error CS8315: Operator '<<' is ambiguous on operands 'new()' and 'new()' + // var j = new() << new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() << new()").WithArguments("<<", "new()", "new()").WithLocation(15, 17), + // (16,17): error CS8315: Operator '>' is ambiguous on operands 'new()' and 'new()' + // var k = new() > new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() > new()").WithArguments(">", "new()", "new()").WithLocation(16, 17), + // (17,17): error CS8315: Operator '<' is ambiguous on operands 'new()' and 'new()' + // var l = new() < new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() < new()").WithArguments("<", "new()", "new()").WithLocation(17, 17), + // (18,17): error CS8315: Operator '>=' is ambiguous on operands 'new()' and 'new()' + // var m = new() >= new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() >= new()").WithArguments(">=", "new()", "new()").WithLocation(18, 17), + // (19,17): error CS8315: Operator '<=' is ambiguous on operands 'new()' and 'new()' + // var n = new() <= new(); + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() <= new()").WithArguments("<=", "new()", "new()").WithLocation(19, 17), + // (20,17): error CS8315: Operator '==' is ambiguous on operands 'new()' and 'new()' + // var o = new() == new(); // void ImplicitObjectCreation + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() == new()").WithArguments("==", "new()", "new()").WithLocation(20, 17), + // (21,17): error CS8315: Operator '!=' is ambiguous on operands 'new()' and 'new()' + // var p = new() != new(); // void ImplicitObjectCreation + Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefaultOrNew, "new() != new()").WithArguments("!=", "new()", "new()").WithLocation(21, 17), + // (22,17): error CS8754: There is no target type for 'new()' + // var q = new() && new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(22, 17), + // (22,26): error CS8754: There is no target type for 'new()' + // var q = new() && new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(22, 26), + // (23,17): error CS8754: There is no target type for 'new()' + // var r = new() || new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(23, 17), + // (23,26): error CS8754: There is no target type for 'new()' + // var r = new() || new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(23, 26), + // (24,17): error CS8754: There is no target type for 'new()' + // var s = new() ?? new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(24, 17) + ); + } + + [Fact] + public void TestBinaryOperators02() + { + string source = @" +class C +{ + static void Main() + { + _ = new() + 1; + _ = new() - 1; + _ = new() & 1; + _ = new() | 1; + _ = new() ^ 1; + _ = new() * 1; + _ = new() / 1; + _ = new() % 1; + _ = new() >> 1; + _ = new() << 1; + _ = new() > 1; + _ = new() < 1; + _ = new() >= 1; + _ = new() <= 1; + _ = new() == 1; // ok + _ = new() != 1; // ok + _ = new() && 1; + _ = new() || 1; + _ = new() ?? 1; + _ = new() ?? default(int?); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (22,13): error CS8754: There is no target type for 'new()' + // _ = new() && 1; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(22, 13), + // (23,13): error CS8754: There is no target type for 'new()' + // _ = new() || 1; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(23, 13), + // (24,13): error CS8754: There is no target type for 'new()' + // _ = new() ?? 1; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(24, 13), + // (25,13): error CS8754: There is no target type for 'new()' + // _ = new() ?? default(int?); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(25, 13) + ); + } + + [Fact] + public void TestBinaryOperators03() + { + string source = @" +class C +{ + static void Main() + { + _ = 1 + new(); + _ = 1 - new(); + _ = 1 & new(); + _ = 1 | new(); + _ = 1 ^ new(); + _ = 1 * new(); + _ = 1 / new(); + _ = 1 % new(); + _ = 1 >> new(); + _ = 1 << new(); + _ = 1 > new(); + _ = 1 < new(); + _ = 1 >= new(); + _ = 1 <= new(); + _ = 1 == new(); + _ = 1 != new(); + _ = 1 && new(); + _ = 1 || new(); + _ = new object() ?? new(); // ok + _ = 1 ?? new(); + } +} +"; + + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (12,13): error CS0020: Division by constant zero + // _ = 1 / new(); + Diagnostic(ErrorCode.ERR_IntDivByZero, "1 / new()").WithLocation(12, 13), + // (13,13): error CS0020: Division by constant zero + // _ = 1 % new(); + Diagnostic(ErrorCode.ERR_IntDivByZero, "1 % new()").WithLocation(13, 13), + // (22,18): error CS8754: There is no target type for 'new()' + // _ = 1 && new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(22, 18), + // (23,18): error CS8754: There is no target type for 'new()' + // _ = 1 || new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(23, 18), + // (25,13): error CS0019: Operator '??' cannot be applied to operands of type 'int' and 'new()' + // _ = 1 ?? new(); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "1 ?? new()").WithArguments("??", "int", "new()").WithLocation(25, 13) + ); + } + + [Fact] + public void InForeach() + { + var text = @" +class C +{ + static void Main() + { + foreach (int x in new()) { } + } +}"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,27): error CS8754: There is no target type for 'new()' + // foreach (int x in new()) { } + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 27) + ); + } + + [Fact] + public void Query() + { + string source = +@"using System.Linq; +static class C +{ + static void Main() + { + var q = from x in new() select x; + var p = from x in new int[] { 1 } select new(); + } +} +"; + var compilation = CreateCompilation(source, options: TestOptions.DebugExe); + compilation.VerifyDiagnostics( + // (6,27): error CS8754: There is no target type for 'new()' + // var q = from x in new() select x; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 27), + // (7,43): error CS1942: The type of the expression in the select clause is incorrect. Type inference failed in the call to 'Select'. + // var p = from x in new int[] { 1 } select new(); + Diagnostic(ErrorCode.ERR_QueryTypeInferenceFailed, "select").WithArguments("select", "Select").WithLocation(7, 43) + ); + } + + [Fact] + public void InIsOperator() + { + var text = @" +class C +{ + void M() + { + bool v1 = new() is long; + bool v2 = new() is string; + bool v3 = new() is new(); + bool v4 = v1 is new(); + bool v5 = this is new(); + } +}"; + + var comp = CreateCompilation(text, options: TestOptions.DebugDll); + comp.VerifyDiagnostics( + // (6,19): error CS8754: There is no target type for 'new()' + // bool v1 = new() is long; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(6, 19), + // (7,19): error CS8754: There is no target type for 'new()' + // bool v2 = new() is string; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(7, 19), + // (8,19): error CS8754: There is no target type for 'new()' + // bool v3 = new() is new(); + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(8, 19), + // (10,27): error CS0150: A constant value is expected + // bool v5 = this is new(); + Diagnostic(ErrorCode.ERR_ConstantExpected, "new()").WithLocation(10, 27) + ); + } + + [Fact] + public void InNullCoalescing() + { + var text = +@"using System; + +class Program +{ + static void Main() + { + Func f = () => new() ?? ""hello""; + } +}"; + + var comp = CreateCompilation(text).VerifyDiagnostics( + // (7,32): error CS8754: There is no target type for 'new()' + // Func f = () => new() ?? "hello"; + Diagnostic(ErrorCode.ERR_TypelessNewNoTargetType, "new()").WithArguments("new()").WithLocation(7, 32) + ); + } + + [Fact] + public void Lambda() + { + string source = @" +class C +{ + static void Main() + { + System.Console.Write(M()()); + } + static System.Func M() + { + return () => new(); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "C"); + } + + [Fact] + public void TestTupleEquality01() + { + string source = @" +using System; +class C +{ + public static void Main() + { + Console.Write(new() == (1, 2L) ? 1 : 0); + Console.Write(new() != (1, 2L) ? 1 : 0); + Console.Write((1, 2L) == new() ? 1 : 0); + Console.Write((1, 2L) != new() ? 1 : 0); + Console.Write('-'); + Console.Write(new(1, 2L) == (1, 2L) ? 1 : 0); + Console.Write(new(1, 2L) != (1, 2L) ? 1 : 0); + Console.Write((1, 2L) == new(1, 2L) ? 1 : 0); + Console.Write((1, 2L) != new(1, 2L) ? 1 : 0); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "0101-1010"); + } + + [Fact] + public void TestTupleEquality02() + { + string source = @" +using System; + +class C +{ + public static void Main() + { + Console.Write((new(), new()) == (1, 2L) ? 1 : 0); + Console.Write((new(), new()) != (1, 2L) ? 1 : 0); + Console.Write((1, 2L) == (new(), new()) ? 1 : 0); + Console.Write((1, 2L) != (new(), new()) ? 1 : 0); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.ReleaseExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "0101"); + } + + [Fact] + public void TestEquality_Class() + { + string source = @" +using System; + +class C +{ + static void Main() + { + Console.Write(new C() == new() ? 1 : 0); + Console.Write(new C() != new() ? 1 : 0); + Console.Write(new() == new C() ? 1 : 0); + Console.Write(new() != new C() ? 1 : 0); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: "0101"); + } + + [Fact] + public void TestEquality_Class_UserDefinedOperator() + { + string source = @" +using System; + +class C +{ + public static bool operator ==(C o1, C o2) + { + Console.WriteLine(""operator==""); + return (object)o1 == (object)o2; + } + public static bool operator !=(C o1, C o2) + { + Console.WriteLine(""operator!=""); + return (object)o1 != (object)o2; + } + + static void Main() + { + Console.WriteLine(new C() == new() ? 1 : 0); + Console.WriteLine(new() == new C() ? 1 : 0); + Console.WriteLine(new C() != new() ? 1 : 0); + Console.WriteLine(new() != new C() ? 1 : 0); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe.WithWarningLevel(0)); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: @" +operator== +0 +operator== +0 +operator!= +1 +operator!= +1"); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var nodes = tree.GetCompilationUnitRoot().DescendantNodes().OfType().ToArray(); + + assert(0, type: "C", convertedType: "C", symbol: "C..ctor()", @operator: "System.Boolean C.op_Equality(C o1, C o2)", ConversionKind.Identity); + assert(1, type: "C", convertedType: "C", symbol: "C..ctor()", @operator: "System.Boolean C.op_Equality(C o1, C o2)", ConversionKind.Identity); + assert(2, type: "C", convertedType: "C", symbol: "C..ctor()", @operator: "System.Boolean C.op_Inequality(C o1, C o2)", ConversionKind.Identity); + assert(3, type: "C", convertedType: "C", symbol: "C..ctor()", @operator: "System.Boolean C.op_Inequality(C o1, C o2)", ConversionKind.Identity); + + void assert(int index, string type, string convertedType, string symbol, string @operator, ConversionKind conversionKind) + { + var @new = nodes[index]; + Assert.Equal(type, model.GetTypeInfo(@new).Type.ToTestDisplayString()); + Assert.Equal(convertedType, model.GetTypeInfo(@new).ConvertedType.ToTestDisplayString()); + Assert.Equal(symbol, model.GetSymbolInfo(@new).Symbol.ToTestDisplayString()); + Assert.Equal(conversionKind, model.GetConversion(@new).Kind); + Assert.Equal(@operator, model.GetSymbolInfo(@new.Parent).Symbol.ToTestDisplayString()); + } + } + + [Fact] + public void TestEquality_Class_UserDefinedOperator_ErrorCases() + { + string source = @" +using System; + +class D +{ +} + +class C +{ + public extern static bool operator ==(C o1, C o2); + public extern static bool operator !=(C o1, C o2); + public extern static bool operator ==(C o1, D o2); + public extern static bool operator !=(C o1, D o2); + + static void Main() + { + Console.WriteLine(new C() == new()); + Console.WriteLine(new() == new C()); // ok + Console.WriteLine(new C() != new()); + Console.WriteLine(new() != new C()); // ok + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe.WithWarningLevel(0)); + comp.VerifyDiagnostics( + // (17,27): error CS0034: Operator '==' is ambiguous on operands of type 'C' and 'new()' + // Console.WriteLine(new C() == new()); + Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "new C() == new()").WithArguments("==", "C", "new()").WithLocation(17, 27), + // (19,27): error CS0034: Operator '!=' is ambiguous on operands of type 'C' and 'new()' + // Console.WriteLine(new C() != new()); + Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "new C() != new()").WithArguments("!=", "C", "new()").WithLocation(19, 27) + ); + } + + [Fact] + public void TestEquality_Struct_ErrorCases() + { + string source = @" +using System; + +struct S +{ + static void Main() + { + Console.WriteLine(new S() == new()); + Console.WriteLine(new() == new S()); + Console.WriteLine(new S() != new()); + Console.WriteLine(new() != new S()); + + Console.WriteLine(new S?() == new()); + Console.WriteLine(new() == new S?()); + Console.WriteLine(new S?() != new()); + Console.WriteLine(new() != new S?()); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (8,27): error CS0019: Operator '==' cannot be applied to operands of type 'S' and 'new()' + // Console.WriteLine(new S() == new()); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "new S() == new()").WithArguments("==", "S", "new()").WithLocation(8, 27), + // (9,27): error CS0019: Operator '==' cannot be applied to operands of type 'new()' and 'S' + // Console.WriteLine(new() == new S()); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "new() == new S()").WithArguments("==", "new()", "S").WithLocation(9, 27), + // (10,27): error CS0019: Operator '!=' cannot be applied to operands of type 'S' and 'new()' + // Console.WriteLine(new S() != new()); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "new S() != new()").WithArguments("!=", "S", "new()").WithLocation(10, 27), + // (11,27): error CS0019: Operator '!=' cannot be applied to operands of type 'new()' and 'S' + // Console.WriteLine(new() != new S()); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "new() != new S()").WithArguments("!=", "new()", "S").WithLocation(11, 27), + // (13,27): error CS0019: Operator '==' cannot be applied to operands of type 'S?' and 'new()' + // Console.WriteLine(new S?() == new()); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "new S?() == new()").WithArguments("==", "S?", "new()").WithLocation(13, 27), + // (14,27): error CS0019: Operator '==' cannot be applied to operands of type 'new()' and 'S?' + // Console.WriteLine(new() == new S?()); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "new() == new S?()").WithArguments("==", "new()", "S?").WithLocation(14, 27), + // (15,27): error CS0019: Operator '!=' cannot be applied to operands of type 'S?' and 'new()' + // Console.WriteLine(new S?() != new()); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "new S?() != new()").WithArguments("!=", "S?", "new()").WithLocation(15, 27), + // (16,27): error CS0019: Operator '!=' cannot be applied to operands of type 'new()' and 'S?' + // Console.WriteLine(new() != new S?()); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "new() != new S?()").WithArguments("!=", "new()", "S?").WithLocation(16, 27)); + } + + [Fact] + public void TestEquality_Struct_UserDefinedOperator_ErrorCases() + { + string source = @" +using System; + +struct S +{ + public S(int i) {} + + public static bool operator ==(S o1, S o2) + { + Console.WriteLine(""operator ==""); + return false; + } + + public static bool operator !=(S o1, S o2) + { + Console.WriteLine(""operator !=""); + return true; + } + + public override int GetHashCode() => throw null; + public override bool Equals(object o) => throw null; + + static void Main() + { + _ = (new S() == new()); + _ = (new() == new S()); + _ = (new S() != new()); + _ = (new() != new S()); + + Console.WriteLine(new S?() == new()); + Console.WriteLine(new() == new S?()); + Console.WriteLine(new S?() != new()); + Console.WriteLine(new() != new S?()); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: +@"operator == +operator == +operator != +operator != +False +False +True +True"); + } + + [Fact] + public void TestEquality_Struct_UserDefinedOperator() + { + string source = @" +using System; + +struct S +{ + private readonly int field; + + public S(int i) + { + this.field = i; + } + + public static bool operator ==(S o1, S o2) => o1.field == o2.field; + public static bool operator !=(S o1, S o2) => o1.field != o2.field; + + static void Main() + { + Console.WriteLine(new S(42) == new(42)); + Console.WriteLine(new(42) == new S(42)); + Console.WriteLine(new S(42) != new(42)); + Console.WriteLine(new(42) != new S(42)); + + Console.WriteLine(new S?(new(42)) == new(42)); + Console.WriteLine(new(42) == new S?(new(42))); + Console.WriteLine(new S?(new(42)) != new(42)); + Console.WriteLine(new(42) != new S?(new(42))); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe.WithWarningLevel(0)); + comp.VerifyDiagnostics(); + + CompileAndVerify(comp, expectedOutput: @" +True +True +False +False +True +True +False +False"); + } + + [Fact] + public void ArraySize() + { + string source = @" +class C +{ + static void Main() + { + var a = new int[new()]; + System.Console.Write(a.Length); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "0"); + } + + [Fact] + public void TernaryOperator01() + { + string source = @" +class C +{ + static void Main() + { + bool flag = true; + var x = flag ? new() : 1; + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + } + + [Fact] + public void TernaryOperator02() + { + string source = @" +class C +{ + static void Main() + { + bool flag = true; + System.Console.Write(flag ? new() : new C()); + System.Console.Write(flag ? new C() : new()); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "CC"); + } + + [Fact] + public void TernaryOperator03() + { + string source = @" +class C +{ + static void Main() + { + bool flag = true; + System.Console.Write(flag ? new() : new()); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (7,30): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'new()' and 'new()' + // System.Console.Write(flag ? new() : new()); + Diagnostic(ErrorCode.ERR_InvalidQM, "flag ? new() : new()").WithArguments("new()", "new()").WithLocation(7, 30) + ); + } + + [Fact] + public void NotAType() + { + string source = @" +class C +{ + static void Main() + { + ((System)new()).ToString(); + } +} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (6,11): error CS0118: 'System' is a namespace but is used like a type + // ((System)new()).ToString(); + Diagnostic(ErrorCode.ERR_BadSKknown, "System").WithArguments("System", "namespace", "type").WithLocation(6, 11) + ); + } + + [Fact] + public void TestSpeculativeModel01() + { + string source = @" +class C +{ + static void Main() + { + int i = 2; + } +} +"; + var comp = CreateCompilation(source, parseOptions: TargetTypedObjectCreationTestOptions); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var node = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single(); + int nodeLocation = node.Location.SourceSpan.Start; + + var newExpression = SyntaxFactory.ParseExpression("new()"); + var typeInfo = model.GetSpeculativeTypeInfo(nodeLocation, newExpression, SpeculativeBindingOption.BindAsExpression); + Assert.Null(typeInfo.Type); + var symbolInfo = model.GetSpeculativeSymbolInfo(nodeLocation, newExpression, SpeculativeBindingOption.BindAsExpression); + Assert.True(symbolInfo.IsEmpty); + } + + [Fact] + public void TestSpeculativeModel02() + { + string source = @" +class C +{ + static void M(int i) {} + static void Main() + { + M(42); + } +} +"; + var comp = CreateCompilation(source, parseOptions: TargetTypedObjectCreationTestOptions); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var node = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single(); + int nodeLocation = node.Location.SourceSpan.Start; + + var modifiedNode = (ExpressionStatementSyntax)SyntaxFactory.ParseStatement("M(new());"); + Assert.True(model.TryGetSpeculativeSemanticModel(nodeLocation, modifiedNode, out var speculativeModel)); + + var newExpression = ((InvocationExpressionSyntax)modifiedNode.Expression).ArgumentList.Arguments[0].Expression; + var symbolInfo = speculativeModel.GetSymbolInfo(newExpression); + Assert.True(symbolInfo.IsEmpty); + var typeInfo = speculativeModel.GetTypeInfo(newExpression); + Assert.True(typeInfo.ConvertedType.IsErrorType()); + Assert.True(typeInfo.Type.IsErrorType()); + } + } +} diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs index 553d52cfc19e5..ac23339faf342 100644 --- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs +++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs @@ -163,6 +163,9 @@ private static Syntax.InternalSyntax.ParenthesizedLambdaExpressionSyntax Generat private static Syntax.InternalSyntax.InitializerExpressionSyntax GenerateInitializerExpression() => InternalSyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, InternalSyntaxFactory.Token(SyntaxKind.OpenBraceToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.CloseBraceToken)); + private static Syntax.InternalSyntax.ImplicitObjectCreationExpressionSyntax GenerateImplicitObjectCreationExpression() + => InternalSyntaxFactory.ImplicitObjectCreationExpression(InternalSyntaxFactory.Token(SyntaxKind.NewKeyword), GenerateArgumentList(), null); + private static Syntax.InternalSyntax.ObjectCreationExpressionSyntax GenerateObjectCreationExpression() => InternalSyntaxFactory.ObjectCreationExpression(InternalSyntaxFactory.Token(SyntaxKind.NewKeyword), GenerateIdentifierName(), null, null); @@ -1257,6 +1260,18 @@ public void TestInitializerExpressionFactoryAndProperties() AttachAndCheckDiagnostics(node); } + [Fact] + public void TestImplicitObjectCreationExpressionFactoryAndProperties() + { + var node = GenerateImplicitObjectCreationExpression(); + + Assert.Equal(SyntaxKind.NewKeyword, node.NewKeyword.Kind); + Assert.NotNull(node.ArgumentList); + Assert.Null(node.Initializer); + + AttachAndCheckDiagnostics(node); + } + [Fact] public void TestObjectCreationExpressionFactoryAndProperties() { @@ -4748,6 +4763,32 @@ public void TestInitializerExpressionIdentityRewriter() Assert.Same(oldNode, newNode); } + [Fact] + public void TestImplicitObjectCreationExpressionTokenDeleteRewriter() + { + var oldNode = GenerateImplicitObjectCreationExpression(); + var rewriter = new TokenDeleteRewriter(); + var newNode = rewriter.Visit(oldNode); + + if(!oldNode.IsMissing) + { + Assert.NotEqual(oldNode, newNode); + } + + Assert.NotNull(newNode); + Assert.True(newNode.IsMissing, "No tokens => missing"); + } + + [Fact] + public void TestImplicitObjectCreationExpressionIdentityRewriter() + { + var oldNode = GenerateImplicitObjectCreationExpression(); + var rewriter = new IdentityRewriter(); + var newNode = rewriter.Visit(oldNode); + + Assert.Same(oldNode, newNode); + } + [Fact] public void TestObjectCreationExpressionTokenDeleteRewriter() { @@ -9170,6 +9211,9 @@ private static ParenthesizedLambdaExpressionSyntax GenerateParenthesizedLambdaEx private static InitializerExpressionSyntax GenerateInitializerExpression() => SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, SyntaxFactory.Token(SyntaxKind.OpenBraceToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); + private static ImplicitObjectCreationExpressionSyntax GenerateImplicitObjectCreationExpression() + => SyntaxFactory.ImplicitObjectCreationExpression(SyntaxFactory.Token(SyntaxKind.NewKeyword), GenerateArgumentList(), default(InitializerExpressionSyntax)); + private static ObjectCreationExpressionSyntax GenerateObjectCreationExpression() => SyntaxFactory.ObjectCreationExpression(SyntaxFactory.Token(SyntaxKind.NewKeyword), GenerateIdentifierName(), default(ArgumentListSyntax), default(InitializerExpressionSyntax)); @@ -10264,6 +10308,18 @@ public void TestInitializerExpressionFactoryAndProperties() Assert.Equal(node, newNode); } + [Fact] + public void TestImplicitObjectCreationExpressionFactoryAndProperties() + { + var node = GenerateImplicitObjectCreationExpression(); + + Assert.Equal(SyntaxKind.NewKeyword, node.NewKeyword.Kind()); + Assert.NotNull(node.ArgumentList); + Assert.Null(node.Initializer); + var newNode = node.WithNewKeyword(node.NewKeyword).WithArgumentList(node.ArgumentList).WithInitializer(node.Initializer); + Assert.Equal(node, newNode); + } + [Fact] public void TestObjectCreationExpressionFactoryAndProperties() { @@ -13755,6 +13811,32 @@ public void TestInitializerExpressionIdentityRewriter() Assert.Same(oldNode, newNode); } + [Fact] + public void TestImplicitObjectCreationExpressionTokenDeleteRewriter() + { + var oldNode = GenerateImplicitObjectCreationExpression(); + var rewriter = new TokenDeleteRewriter(); + var newNode = rewriter.Visit(oldNode); + + if(!oldNode.IsMissing) + { + Assert.NotEqual(oldNode, newNode); + } + + Assert.NotNull(newNode); + Assert.True(newNode.IsMissing, "No tokens => missing"); + } + + [Fact] + public void TestImplicitObjectCreationExpressionIdentityRewriter() + { + var oldNode = GenerateImplicitObjectCreationExpression(); + var rewriter = new IdentityRewriter(); + var newNode = rewriter.Visit(oldNode); + + Assert.Same(oldNode, newNode); + } + [Fact] public void TestObjectCreationExpressionTokenDeleteRewriter() { diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs index 9661ac4fa3008..ddd5082664677 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs @@ -2695,19 +2695,13 @@ public static void Main() "; ParseAndValidate(text, TestOptions.Regular, - // (7,21): error CS1031: Type expected - // e = new base; // CS1031, not a type - Diagnostic(ErrorCode.ERR_TypeExpected, "base").WithLocation(7, 21), - // (7,21): error CS1526: A new expression requires (), [], or {} after type + // (7,21): error CS1526: A new expression requires an argument list or (), [], or {} after type // e = new base; // CS1031, not a type Diagnostic(ErrorCode.ERR_BadNewExpr, "base").WithLocation(7, 21), // (7,21): error CS1002: ; expected // e = new base; // CS1031, not a type Diagnostic(ErrorCode.ERR_SemicolonExpected, "base").WithLocation(7, 21), - // (8,21): error CS1031: Type expected - // e = new this; // CS1031, not a type - Diagnostic(ErrorCode.ERR_TypeExpected, "this").WithLocation(8, 21), - // (8,21): error CS1526: A new expression requires (), [], or {} after type + // (8,21): error CS1526: A new expression requires an argument list or (), [], or {} after type // e = new this; // CS1031, not a type Diagnostic(ErrorCode.ERR_BadNewExpr, "this").WithLocation(8, 21), // (8,21): error CS1002: ; expected @@ -2731,18 +2725,9 @@ public static void Main() "; CreateCompilationWithMscorlib46(text).VerifyDiagnostics( - // (7,26): error CS8124: Tuple must contain at least two elements. - // var e = new (); - Diagnostic(ErrorCode.ERR_TupleTooFewElements, ")").WithLocation(7, 26), - // (7,27): error CS1526: A new expression requires (), [], or {} after type - // var e = new (); - Diagnostic(ErrorCode.ERR_BadNewExpr, ";").WithLocation(7, 27), - // (7,25): error CS8181: 'new' cannot be used with tuple type. Use a tuple literal expression instead. + // (7,21): error CS8652: The feature 'target-typed object creation' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var e = new (); - Diagnostic(ErrorCode.ERR_NewWithTupleTypeSyntax, "()").WithLocation(7, 25), - // (7,25): error CS8179: Predefined type 'System.ValueTuple`2' is not defined or imported - // var e = new (); - Diagnostic(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, "()").WithArguments("System.ValueTuple`2").WithLocation(7, 25)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "new").WithArguments("target-typed object creation").WithLocation(7, 21)); } [Fact] @@ -2762,19 +2747,13 @@ public static void Main() "; // TODO: this appears to be a severe regression from Dev10, which neatly reported 3 errors. ParseAndValidate(text, TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6), - // (7,21): error CS1031: Type expected - // e = new base; // CS1031, not a type - Diagnostic(ErrorCode.ERR_TypeExpected, "base").WithLocation(7, 21), - // (7,21): error CS1526: A new expression requires (), [], or {} after type + // (7,21): error CS1526: A new expression requires an argument list or (), [], or {} after type // e = new base; // CS1031, not a type Diagnostic(ErrorCode.ERR_BadNewExpr, "base").WithLocation(7, 21), // (7,21): error CS1002: ; expected // e = new base; // CS1031, not a type Diagnostic(ErrorCode.ERR_SemicolonExpected, "base").WithLocation(7, 21), - // (8,21): error CS1031: Type expected - // e = new this; // CS1031, not a type - Diagnostic(ErrorCode.ERR_TypeExpected, "this").WithLocation(8, 21), - // (8,21): error CS1526: A new expression requires (), [], or {} after type + // (8,21): error CS1526: A new expression requires an argument list or (), [], or {} after type // e = new this; // CS1031, not a type Diagnostic(ErrorCode.ERR_BadNewExpr, "this").WithLocation(8, 21), // (8,21): error CS1002: ; expected @@ -2797,21 +2776,9 @@ public static void Main() } "; CreateCompilationWithMscorlib46(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)).VerifyDiagnostics( - // (7,25): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7.0 or greater. + // (7,21): error CS8652: The feature 'target-typed object creation' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var e = new (); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "()").WithArguments("tuples", "7.0").WithLocation(7, 25), - // (7,26): error CS8124: Tuple must contain at least two elements. - // var e = new (); - Diagnostic(ErrorCode.ERR_TupleTooFewElements, ")").WithLocation(7, 26), - // (7,27): error CS1526: A new expression requires (), [], or {} after type - // var e = new (); - Diagnostic(ErrorCode.ERR_BadNewExpr, ";").WithLocation(7, 27), - // (7,25): error CS8181: 'new' cannot be used with tuple type. Use a tuple literal expression instead. - // var e = new (); - Diagnostic(ErrorCode.ERR_NewWithTupleTypeSyntax, "()").WithLocation(7, 25), - // (7,25): error CS8179: Predefined type 'System.ValueTuple`2' is not defined or imported - // var e = new (); - Diagnostic(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, "()").WithArguments("System.ValueTuple`2").WithLocation(7, 25)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "new").WithArguments("target-typed object creation").WithLocation(7, 21)); } [Fact] @@ -2829,18 +2796,9 @@ public static void Main() } "; CreateCompilationWithMscorlib46(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)).VerifyDiagnostics( - // (7,26): error CS8124: Tuple must contain at least two elements. - // var e = new (); - Diagnostic(ErrorCode.ERR_TupleTooFewElements, ")"), - // (7,27): error CS1526: A new expression requires (), [], or {} after type - // var e = new (); - Diagnostic(ErrorCode.ERR_BadNewExpr, ";"), - // (7,25): error CS8179: Predefined type 'System.ValueTuple`2' is not defined or imported - // var e = new (); - Diagnostic(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, "()").WithArguments("System.ValueTuple`2"), - // (7,25): error CS8181: 'new' cannot be used with tuple type. Use a tuple literal expression instead. + // (7,21): error CS8652: The feature 'target-typed object creation' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var e = new (); - Diagnostic(ErrorCode.ERR_NewWithTupleTypeSyntax, "()")); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "new").WithArguments("target-typed object creation").WithLocation(7, 21)); } [WorkItem(541347, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541347")] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs index ea3fe8e1d0bf0..c73994b3eea0f 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs @@ -495,7 +495,7 @@ public void TestNewRefArray() // (1,8): error CS1031: Type expected // new ref[]; Diagnostic(ErrorCode.ERR_TypeExpected, "[").WithLocation(1, 8), - // (1,10): error CS1526: A new expression requires (), [], or {} after type + // (1,10): error CS1526: A new expression requires an argument list or (), [], or {} after type // new ref[]; Diagnostic(ErrorCode.ERR_BadNewExpr, ";").WithLocation(1, 10) ); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs index 3d521c7caa95a..2d5bb34053bda 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs @@ -84,15 +84,43 @@ public void Error_NewKeywordUsedAsOperator() var test = @" new in "; - // (2,5): error CS1526: A new expression requires (), [], or {} after type - // (2,5): error CS1031: Type expected - // (2,5): error CS1002: ; expected - // (2,5): error CS7017: Member definition, statement, or end-of-file expected - ParseAndValidate(test, - new ErrorDescription { Code = (int)ErrorCode.ERR_BadNewExpr, Line = 2, Column = 5 }, - new ErrorDescription { Code = (int)ErrorCode.ERR_TypeExpected, Line = 2, Column = 5 }, - new ErrorDescription { Code = (int)ErrorCode.ERR_SemicolonExpected, Line = 2, Column = 5 }, - new ErrorDescription { Code = (int)ErrorCode.ERR_GlobalDefinitionOrStatementExpected, Line = 2, Column = 5 }); + + UsingTree(test).GetDiagnostics().Verify( + // (2,5): error CS1526: A new expression requires an argument list or (), [], or {} after type + // new in + Diagnostic(ErrorCode.ERR_BadNewExpr, "in").WithLocation(2, 5), + // (2,5): error CS1002: ; expected + // new in + Diagnostic(ErrorCode.ERR_SemicolonExpected, "in").WithLocation(2, 5), + // (2,5): error CS7017: Member definition, statement, or end-of-file expected + // new in + Diagnostic(ErrorCode.ERR_GlobalDefinitionOrStatementExpected, "in").WithLocation(2, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.ArgumentList); + { + M(SyntaxKind.OpenParenToken); + M(SyntaxKind.CloseParenToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); } #region Method Declarations diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/TargetTypedObjectCreationParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/TargetTypedObjectCreationParsingTests.cs new file mode 100644 index 0000000000000..bd5baff53521e --- /dev/null +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/TargetTypedObjectCreationParsingTests.cs @@ -0,0 +1,599 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public class TargetTypedObjectCreationParsingTests : ParsingTests + { + private static readonly CSharpParseOptions DefaultParseOptions = TestOptions.RegularPreview; + + public TargetTypedObjectCreationParsingTests(ITestOutputHelper output) : base(output) { } + + [Fact] + public void TestNoRegressionOnNew() + { + UsingExpression("new", DefaultParseOptions, + // (1,4): error CS1526: A new expression requires (), [], or {} after type + // new + Diagnostic(ErrorCode.ERR_BadNewExpr, "").WithLocation(1, 4) + ); + + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.ArgumentList); + { + M(SyntaxKind.OpenParenToken); + M(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void TestNoRegressionOnNullableTuple() + { + UsingExpression("new(Int32,Int32)?()", DefaultParseOptions); + + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.NullableType); + { + N(SyntaxKind.TupleType); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Int32"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Int32"); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void TestNoRegressionOnImplicitArrayCreation() + { + UsingExpression("new[]", DefaultParseOptions, + // (1,6): error CS1514: { expected + // new[] + Diagnostic(ErrorCode.ERR_LbraceExpected, "").WithLocation(1, 6), + // (1,6): error CS1513: } expected + // new[] + Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(1, 6) + ); + + N(SyntaxKind.ImplicitArrayCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.CloseBracketToken); + M(SyntaxKind.ArrayInitializerExpression); + { + M(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void TestNoRegressionOnAnonymousObjectCreation() + { + UsingExpression("new{}", DefaultParseOptions + ); + + N(SyntaxKind.AnonymousObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact] + public void TestNoRegressionOnConditional() + { + UsingExpression("new (a, b) ? x : y", + // (1,12): error CS1526: A new expression requires (), [], or {} after type + // new (a, b) ? x : y + Diagnostic(ErrorCode.ERR_BadNewExpr, "?").WithLocation(1, 12)); + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.TupleType); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.ArgumentList); + { + M(SyntaxKind.OpenParenToken); + M(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + EOF(); + } + + [Fact] + public void TestNoRegressionOnTupleArrayCreation() + { + UsingExpression("new(x,y)[0]", DefaultParseOptions); + N(SyntaxKind.ArrayCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.TupleType); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void TestInvalidTupleCreation() + { + UsingExpression("new(int,int)()", DefaultParseOptions); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.TupleType); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void TestInvalidTupleArrayCreation() + { + UsingExpression("new()[0]", DefaultParseOptions); + N(SyntaxKind.ElementAccessExpression); + { + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + EOF(); + } + + [Theory] + [InlineData(SyntaxKind.AddExpression, SyntaxKind.PlusToken)] + [InlineData(SyntaxKind.SubtractExpression, SyntaxKind.MinusToken)] + [InlineData(SyntaxKind.MultiplyExpression, SyntaxKind.AsteriskToken)] + [InlineData(SyntaxKind.DivideExpression, SyntaxKind.SlashToken)] + [InlineData(SyntaxKind.ModuloExpression, SyntaxKind.PercentToken)] + [InlineData(SyntaxKind.LeftShiftExpression, SyntaxKind.LessThanLessThanToken)] + [InlineData(SyntaxKind.RightShiftExpression, SyntaxKind.GreaterThanGreaterThanToken)] + [InlineData(SyntaxKind.LogicalOrExpression, SyntaxKind.BarBarToken)] + [InlineData(SyntaxKind.LogicalAndExpression, SyntaxKind.AmpersandAmpersandToken)] + [InlineData(SyntaxKind.BitwiseOrExpression, SyntaxKind.BarToken)] + [InlineData(SyntaxKind.BitwiseAndExpression, SyntaxKind.AmpersandToken)] + [InlineData(SyntaxKind.ExclusiveOrExpression, SyntaxKind.CaretToken)] + [InlineData(SyntaxKind.EqualsExpression, SyntaxKind.EqualsEqualsToken)] + [InlineData(SyntaxKind.NotEqualsExpression, SyntaxKind.ExclamationEqualsToken)] + [InlineData(SyntaxKind.LessThanExpression, SyntaxKind.LessThanToken)] + [InlineData(SyntaxKind.LessThanOrEqualExpression, SyntaxKind.LessThanEqualsToken)] + [InlineData(SyntaxKind.GreaterThanExpression, SyntaxKind.GreaterThanToken)] + [InlineData(SyntaxKind.GreaterThanOrEqualExpression, SyntaxKind.GreaterThanEqualsToken)] + public void TestBinaryOperators(SyntaxKind expressionKind, SyntaxKind tokenKind) + { + UsingExpression($"new(Int32,Int32){SyntaxFacts.GetText(tokenKind),2}", DefaultParseOptions, + // (1,18): error CS1733: Expected expression + // new(Int32,Int32) + + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 19)); + + N(expressionKind); + { + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Int32"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Int32"); + } + } + N(SyntaxKind.CloseParenToken); + } + } + N(tokenKind); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + + UsingExpression($"new(Int32,Int32){SyntaxFacts.GetText(tokenKind),2}e", DefaultParseOptions); + + N(expressionKind); + { + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Int32"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Int32"); + } + } + N(SyntaxKind.CloseParenToken); + } + } + N(tokenKind); + N(SyntaxKind.IdentifierName, "e"); + { + N(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void TestEmptyArgList() + { + UsingExpression("new()", DefaultParseOptions); + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void TestEmptyArgList_LangVersion() + { + UsingExpression("new()", options: TestOptions.Regular8, + // (1,1): error CS8652: The feature 'target-typed object creation' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // new() + Diagnostic(ErrorCode.ERR_FeatureInPreview, "new").WithArguments("target-typed object creation").WithLocation(1, 1) + ); + + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void TestEmptyObjectInitializer() + { + UsingExpression("new(){}", DefaultParseOptions); + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ObjectInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void TestEmptyObjectInitializer_LangVersion() + { + UsingExpression("new(){}", options: TestOptions.Regular8, + // (1,1): error CS8652: The feature 'target-typed object creation' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // new(){} + Diagnostic(ErrorCode.ERR_FeatureInPreview, "new").WithArguments("target-typed object creation").WithLocation(1, 1) + ); + + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ObjectInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void TestObjectInitializer() + { + UsingExpression("new(1,2){x=y}", DefaultParseOptions); + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "2"); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ObjectInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void TestObjectInitializer_LangVersion() + { + UsingExpression("new(a,b){x=y}", options: TestOptions.Regular8, + // (1,1): error CS8652: The feature 'target-typed object creation' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // new(1,2){x=y} + Diagnostic(ErrorCode.ERR_FeatureInPreview, "new").WithArguments("target-typed object creation").WithLocation(1, 1) + ); + + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ObjectInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void TestCollectionInitializer() + { + UsingExpression("new(1){2}", DefaultParseOptions); + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.CollectionInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "2"); + } + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + } +} diff --git a/src/Test/Utilities/Portable/TestResource.resx b/src/Test/Utilities/Portable/TestResource.resx index 87ecd4185a136..6695a9b76daf3 100644 --- a/src/Test/Utilities/Portable/TestResource.resx +++ b/src/Test/Utilities/Portable/TestResource.resx @@ -316,6 +316,7 @@ namespace My C = 0 }; var o5 = new { A = 0 }; + object o6 = new(); var dictionaryInitializer = new Dictionary<int, string> { {1, ""}, diff --git a/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs b/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs index b62578c24dce3..55df46ffef00f 100644 --- a/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs +++ b/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs @@ -4910,7 +4910,7 @@ void bar() { void bar() { - (string a, string b)[] ab = new ( + (string a, string b)[] ab = new( } }";