diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 571816c086a2a..6efec7573fa21 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6078,6 +6078,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Nullable value type is null-checked and will throw if null. + Type '{0}' cannot be embedded because it has a re-abstraction of a member from base interface. Consider setting the 'Embed Interop Types' property to false. diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs index b39db544fa391..f40f80e8731dd 100644 --- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs +++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs @@ -1232,7 +1232,7 @@ private void CompileMethod( // Iterators handled in IteratorRewriter.cs if (!methodSymbol.IsIterator) { - var boundStatementsWithNullCheck = LocalRewriter.ConstructNullCheckedStatementList(methodSymbol.Parameters, boundStatements, factory); + var boundStatementsWithNullCheck = LocalRewriter.TryConstructNullCheckedStatementList(methodSymbol.Parameters, boundStatements, factory); if (!boundStatementsWithNullCheck.IsDefault) { @@ -1249,8 +1249,6 @@ private void CompileMethod( } if (!(methodSymbol is SynthesizedStaticConstructor cctor) || cctor.ShouldEmit(processedInitializers.BoundInitializers)) { - CSharpSyntaxNode syntax = methodSymbol.GetNonNullSyntaxNode(); - var boundBody = BoundStatementList.Synthesized(syntax, boundStatements); var emittedBody = GenerateMethodBody( diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index f97a0765fa9a6..b70bd92b96564 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1738,12 +1738,6 @@ internal enum ErrorCode ERR_ReAbstractionInNoPIAType = 8750, - ERR_NeedSpaceBetweenExclamationAndEquals = 8716, - ERR_MustNullCheckInImplementation = 8717, - ERR_NonNullableValueTypeIsNullChecked = 8718, - WRN_NullCheckedHasDefaultNull = 8719, - ERR_NullCheckingOnByRefParameter = 8720, - WRN_NullCheckingOnNullableValueType = 8721, #endregion diagnostics introduced for C# 8.0 #region diagnostics introduced in C# 9.0 @@ -1874,7 +1868,15 @@ internal enum ErrorCode ERR_CopyConstructorWrongAccessibility = 8878, ERR_NonPrivateAPIInRecord = 8879, + ERR_NeedSpaceBetweenExclamationAndEquals = 8890, + ERR_MustNullCheckInImplementation = 8891, + ERR_NonNullableValueTypeIsNullChecked = 8892, + WRN_NullCheckedHasDefaultNull = 8893, + ERR_NullCheckingOnByRefParameter = 8894, + WRN_NullCheckingOnNullableValueType = 8895, + #endregion diagnostics introduced for C# 9.0 + // Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd) } } diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index fde67b2a4aaa1..2c92866da0b44 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -187,7 +187,6 @@ internal enum MessageID IDS_OverrideWithConstraints = MessageBase + 12761, IDS_FeatureNestedStackalloc = MessageBase + 12762, IDS_FeatureSwitchExpression = MessageBase + 12763, - IDS_ParameterNullChecking = MessageBase + 12764, IDS_FeatureAsyncUsing = MessageBase + 12764, IDS_FeatureLambdaDiscardParameters = MessageBase + 12765, IDS_FeatureLocalFunctionAttributes = MessageBase + 12766, @@ -211,6 +210,8 @@ internal enum MessageID IDS_FeatureNullPointerConstantPattern = MessageBase + 12783, IDS_FeatureModuleInitializers = MessageBase + 12784, IDS_FeatureTargetTypedConditional = MessageBase + 12785, + + IDS_ParameterNullChecking = MessageBase + 12786, } // Message IDs may refer to strings that need to be localized. diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs index 02fffc4aaba9f..e885b09608f2e 100644 --- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs @@ -227,8 +227,6 @@ public static bool IsWarning(ErrorCode code) case ErrorCode.WRN_MissingNonNullTypesContextForAnnotationInGeneratedCode: case ErrorCode.WRN_NullReferenceInitializer: case ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint: - case ErrorCode.WRN_NullCheckedHasDefaultNull: - case ErrorCode.WRN_NullCheckingOnNullableValueType: case ErrorCode.WRN_ParameterConditionallyDisallowsNull: case ErrorCode.WRN_ShouldNotReturn: case ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride: @@ -248,6 +246,8 @@ public static bool IsWarning(ErrorCode code) case ErrorCode.WRN_GivenExpressionAlwaysMatchesPattern: case ErrorCode.WRN_IsPatternAlways: case ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial: + case ErrorCode.WRN_NullCheckedHasDefaultNull: + case ErrorCode.WRN_NullCheckingOnNullableValueType: return true; default: return false; diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs index 840500bea13cd..a58cac6837109 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs @@ -254,7 +254,8 @@ public override BoundNode VisitLambda(BoundLambda node) try { _factory.CurrentFunction = node.Symbol; - var visited = (BoundLambda)base.VisitLambda(node); + var visited = (BoundLambda)base.VisitLambda(node)!; + if (RewriteNullChecking(visited.Body) is BoundBlock newBody) { visited = visited.Update(visited.UnboundLambda, visited.Symbol, newBody, visited.Diagnostics, visited.Binder, visited.Type); @@ -314,7 +315,8 @@ static bool hasReturnTypeOrParameter(LocalFunctionSymbol localFunction, Func ConstructNullCheckedStatementList(ImmutableArray parameters, + internal static ImmutableArray TryConstructNullCheckedStatementList(ImmutableArray parameters, ImmutableArray existingStatements, SyntheticBoundNodeFactory factory) { diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs index 9732f0c41f774..ad2354f139a4c 100644 --- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs @@ -316,12 +316,9 @@ protected BoundStatement GenerateParameterStorage(LocalSymbol stateMachineVariab } } - bodyBuilder.Add(GenerateStateMachineCreation(stateMachineVariable, frameType)); var builtBody = bodyBuilder.ToImmutableAndFree(); - ImmutableArray newBody = LocalRewriter.ConstructNullCheckedStatementList(method.Parameters, builtBody, F); - return F.Block( - ImmutableArray.Create(stateMachineVariable), - newBody.IsDefault ? builtBody : newBody); + ImmutableArray newBody = LocalRewriter.TryConstructNullCheckedStatementList(method.Parameters, builtBody, F); + return newBody.IsDefault ? F.Block(builtBody) : F.Block(ImmutableArray.Create(stateMachineVariable), newBody); } protected SynthesizedImplementationMethod OpenMethodImplementation( diff --git a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs index daace1cc43853..5da3a9cac1f99 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs @@ -1487,6 +1487,7 @@ internal ImmutableArray MakeTempsForDiscardArguments(ImmutableA return arguments; } +#nullable disable internal BoundExpression MakeNullCheck(SyntaxNode syntax, BoundExpression rewrittenExpr, BinaryOperatorKind operatorKind) { Debug.Assert((operatorKind == BinaryOperatorKind.Equal) || (operatorKind == BinaryOperatorKind.NotEqual) || @@ -1531,7 +1532,7 @@ internal BoundExpression MakeNullCheck(SyntaxNode syntax, BoundExpression rewrit } if (operatorKind == BinaryOperatorKind.NullableNullEqual || operatorKind == BinaryOperatorKind.NullableNullNotEqual) { - return RewriteNullableNullEquality(syntax, operatorKind, rewrittenExpr, Literal(ConstantValue.Null, objectType), boolType); + return RewriteNullableNullEquality(syntax, operatorKind, rewrittenExpr, Literal(ConstantValue.Null, objectType), boolType); } else { @@ -1615,5 +1616,7 @@ internal BoundExpression RewriteNullableNullEquality( return result; } + // PROTOTYPE(BangBang): Re-enable annotations +#nullable enable } } diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 5f8dcfd7c2cd9..4c5ec5a9c9621 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -6923,7 +6923,7 @@ private FunctionPointerTypeSyntax ParseFunctionPointerTypeSyntax() var lessThanTokenError = WithAdditionalDiagnostics(SyntaxFactory.MissingToken(SyntaxKind.LessThanToken), GetExpectedTokenError(SyntaxKind.LessThanToken, SyntaxKind.None)); var missingTypes = _pool.AllocateSeparated(); var missingTypeName = CreateMissingIdentifierName(); - var missingType = SyntaxFactory.Parameter(attributeLists: default, modifiers: default, missingTypeName, identifier: CreateMissingIdentifierToken(), @default: null); + var missingType = SyntaxFactory.Parameter(attributeLists: default, modifiers: default, missingTypeName, identifier: CreateMissingIdentifierToken(), exclamationToken: null, @default: null); missingTypes.Add(missingType); // Handle the simple case of delegate*>. We don't try to deal with any variation of delegate*invalid>, as // we don't know for sure that the expression isn't a relational with something else. @@ -6949,7 +6949,7 @@ private FunctionPointerTypeSyntax ParseFunctionPointerTypeSyntax() ParseParameterModifiers(modifiers, isFunctionPointerParameter: true); var parameterType = ParseTypeOrVoid(); - types.Add(SyntaxFactory.Parameter(attributeLists: default, modifiers, parameterType, identifier: CreateMissingIdentifierToken(), @default: null)); + types.Add(SyntaxFactory.Parameter(attributeLists: default, modifiers, parameterType, identifier: CreateMissingIdentifierToken(), exclamationToken: null, @default: null)); if (skipBadFunctionPointerParameterListTokens() == PostSkipAction.Abort) { @@ -10413,26 +10413,6 @@ private bool IsPossibleAnonymousMethodExpression() tokenIndex++; } - if (precedence <= Precedence.Lambda) - { - SyntaxKind token1 = this.PeekToken(1).Kind; - if (token1 == SyntaxKind.EqualsGreaterThanToken) - { - return true; - } - - if (token1 == SyntaxKind.ExclamationToken && this.PeekToken(2).Kind == SyntaxKind.EqualsGreaterThanToken) - { - return true; - } - - // Broken case but error will be added in lambda function. - if (token1 == SyntaxKind.ExclamationEqualsToken && this.PeekToken(2).Kind == SyntaxKind.GreaterThanToken) - { - return true; - } - } - return this.PeekToken(tokenIndex).Kind == SyntaxKind.DelegateKeyword; } @@ -11261,6 +11241,22 @@ private bool IsPossibleLambdaExpression(Precedence precedence) return false; } + SyntaxKind token1 = this.PeekToken(1).Kind; + if (token1 == SyntaxKind.EqualsGreaterThanToken) + { + return true; + } + if (token1 == SyntaxKind.ExclamationToken && this.PeekToken(2).Kind == SyntaxKind.EqualsGreaterThanToken) + { + return true; + } + + // Broken case but error will be added in lambda function. + if (token1 == SyntaxKind.ExclamationEqualsToken && this.PeekToken(2).Kind == SyntaxKind.GreaterThanToken) + { + return true; + } + // If we start with `static` or `async static` then just jump past those and do the // analysis after that point. Note, we don't just blindly consume `async` in `static // async` because that `async` may not be a modifier (it may just be an identifier) and diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index e07f767c5f9e7..f5be02f64a306 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -5,6 +5,9 @@ Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.AddModifier Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxTokenList modifiers, 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.WithModifiers(Microsoft.CodeAnalysis.SyntaxTokenList modifiers) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.DefaultConstraintSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax.ExclamationToken.get -> Microsoft.CodeAnalysis.SyntaxToken +Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.SyntaxToken exclamationToken, Microsoft.CodeAnalysis.CSharp.Syntax.EqualsValueClauseSyntax default) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax.WithExclamationToken(Microsoft.CodeAnalysis.SyntaxToken exclamationToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax Microsoft.CodeAnalysis.CSharp.Syntax.DefaultConstraintSyntax.DefaultKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken Microsoft.CodeAnalysis.CSharp.Syntax.DefaultConstraintSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken defaultKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.DefaultConstraintSyntax Microsoft.CodeAnalysis.CSharp.Syntax.DefaultConstraintSyntax.WithDefaultKeyword(Microsoft.CodeAnalysis.SyntaxToken defaultKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.DefaultConstraintSyntax @@ -16,6 +19,7 @@ Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.WithMod Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.AddModifiers(params Microsoft.CodeAnalysis.SyntaxToken[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax parameter, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.WithModifiers(Microsoft.CodeAnalysis.SyntaxTokenList modifiers) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Parameter(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.SyntaxToken exclamationToken, Microsoft.CodeAnalysis.CSharp.Syntax.EqualsValueClauseSyntax default) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax Microsoft.CodeAnalysis.CSharp.SyntaxKind.DefaultConstraint = 9057 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind abstract Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.Modifiers.get -> Microsoft.CodeAnalysis.SyntaxTokenList override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitDefaultConstraint(Microsoft.CodeAnalysis.CSharp.Syntax.DefaultConstraintSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode diff --git a/src/Compilers/CSharp/Portable/Symbols/FunctionPointers/FunctionPointerParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/FunctionPointers/FunctionPointerParameterSymbol.cs index c2aebe52064fa..c4872ddd7574b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/FunctionPointers/FunctionPointerParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/FunctionPointers/FunctionPointerParameterSymbol.cs @@ -67,6 +67,7 @@ internal int MethodHashCode() public override bool IsDiscard => false; public override bool IsParams => false; public override bool IsImplicitlyDeclared => true; + public override bool IsNullChecked => false; internal override MarshalPseudoCustomAttributeData? MarshallingInformation => null; internal override bool IsMetadataOptional => false; internal override bool IsMetadataIn => RefKind == RefKind.In; diff --git a/src/Compilers/CSharp/Portable/Symbols/PublicModel/ParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PublicModel/ParameterSymbol.cs index e0cfc28079648..dbcea4a4b2d03 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PublicModel/ParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PublicModel/ParameterSymbol.cs @@ -60,6 +60,8 @@ IParameterSymbol IParameterSymbol.OriginalDefinition bool IParameterSymbol.IsParams => _underlying.IsParams; + bool IParameterSymbol.IsNullChecked => _underlying.IsNullChecked; + bool IParameterSymbol.IsOptional => _underlying.IsOptional; bool IParameterSymbol.IsThis => _underlying.IsThis; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs index f5588c408cab7..0259140149509 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs @@ -194,18 +194,7 @@ private static ImmutableArray MakeParameters ConditionallyCreateInModifiers(RefKind refKind, bool addRefReadOnlyModifier, Binder binder, DiagnosticBag diagnostics, SyntaxNode syntax) { if (addRefReadOnlyModifier && refKind == RefKind.In) @@ -791,6 +778,5 @@ private static ImmutableArray CreateModifiers(WellKnownType modi var modifierType = binder.GetWellKnownType(modifier, diagnostics, syntax); return ImmutableArray.Create(CSharpCustomModifier.CreateRequired(modifierType)); } ->>>>>>> origin/master } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs index d5573595f4cf6..047a00ad68b0d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs @@ -271,8 +271,9 @@ public SynthesizedComplexParameterSymbol( RefKind refKind, string name, ImmutableArray refCustomModifiers, - SourceComplexParameterSymbol? baseParameterForAttributes) - : base(container, type, ordinal, refKind, name) + SourceComplexParameterSymbol? baseParameterForAttributes, + bool isNullChecked) + : base(container, type, ordinal, refKind, name, isNullChecked) { Debug.Assert(!refCustomModifiers.IsDefault); Debug.Assert(!refCustomModifiers.IsEmpty || baseParameterForAttributes is object); diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 2d72ca040048e..9e92067b054a5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -537,6 +537,16 @@ Seznam parametrů může mít jenom částečná deklarace jednoho záznamu. + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Omezení new() nejde používat s omezením unmanaged. @@ -567,6 +577,11 @@ Typ příjemce {0} není platný typ záznamu. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' Očekávala se hodnota enable, disable nebo restore. @@ -1506,6 +1526,11 @@ omezení pro metody přepsání a explicitní implementace rozhraní + + parameter null-checking + parameter null-checking + + <throw expression> <výraz throw> @@ -2096,6 +2121,26 @@ Literál null nejde převést na odkazový typ, který nemůže mít hodnotu null. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. V parametru {0} v {1} může být argument s odkazem null. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 24b7bfd937b38..400acce3f52ca 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -537,6 +537,16 @@ Nur eine partielle Deklaration eines einzelnen Datensatzes darf eine Parameterliste aufweisen. + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Die new()-Einschränkung kann nicht mit der unmanaged-Einschränkung verwendet werden. @@ -567,6 +577,11 @@ Der Empfängertyp "{0}" ist kein gültiger Datensatztyp. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' "enable", "disable" oder "restore" erwartet. @@ -1506,6 +1526,11 @@ Einschränkungen für Außerkraftsetzung und explizite Schnittstellenimplementierungsmethoden + + parameter null-checking + parameter null-checking + + <throw expression> throw-Ausdruck @@ -2096,6 +2121,26 @@ Ein NULL-Literal kann nicht in einen Non-Nullable-Verweistyp konvertiert werden. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. Mögliches Nullverweisargument für den Parameter "{0}" in "{1}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 468c9875f8442..9f7899dfeff16 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -537,6 +537,16 @@ Solo una declaración parcial de un registro puede tener una lista de parámetros + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint La restricción "new()" no se puede utilizar con la restricción "unmanaged" @@ -567,6 +577,11 @@ El tipo de receptor "{0}" no es un tipo de registro válido. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' Se esperaba "enable", "disable" o "restore". @@ -1506,6 +1526,11 @@ restricciones para métodos de implementación de interfaz explícita e invalidación + + parameter null-checking + parameter null-checking + + <throw expression> <expresión throw> @@ -2096,6 +2121,26 @@ No se puede convertir un literal NULL en un tipo de referencia que no acepta valores NULL. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. Posible argumento de referencia nulo para el parámetro "{0}" en "{1}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 7fad19657ce32..a8ce979a1e5e0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -537,6 +537,16 @@ Seule une déclaration partielle d'un seul enregistrement peut avoir une liste de paramètres + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint La contrainte 'new()' ne peut pas être utilisée avec la contrainte 'unmanaged' @@ -567,6 +577,11 @@ Le récepteur de type '{0}' n'est pas un type d'enregistrement valide. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' 'enable', 'disable' ou 'restore' attendu @@ -1506,6 +1526,11 @@ contraintes des méthodes d'implémentation d'interface par remplacement et explicites + + parameter null-checking + parameter null-checking + + <throw expression> <expression throw> @@ -2096,6 +2121,26 @@ Impossible de convertir un littéral ayant une valeur null en type référence non-nullable. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. Existence possible d'un argument de référence null pour le paramètre '{0}' dans '{1}'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 28c3739cf1ac9..e7aad044cd71b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -537,6 +537,16 @@ Solo una dichiarazione parziale di singolo record può includere un elenco di parametri + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Non è possibile usare il vincolo 'new()' con il vincolo 'unmanaged' @@ -567,6 +577,11 @@ Il tipo di ricevitore '{0}' non è un tipo di record valido. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' È previsto 'enable', 'disable' o 'restore' @@ -1506,6 +1526,11 @@ vincoli per i metodi di override e di implementazione esplicita dell'interfaccia + + parameter null-checking + parameter null-checking + + <throw expression> <espressione throw> @@ -2096,6 +2121,26 @@ Non è possibile convertire il valore letterale Null in tipo riferimento che non ammette i valori Null. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. Possibile argomento di riferimento Null per il parametro '{0}' in '{1}'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index f6080b15f0976..13bbe6eb71f18 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -537,6 +537,16 @@ 1 つのレコードの部分宣言のみがパラメーター リストを持つことができます + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 制約は 'unmanaged' 制約と一緒には使用できません @@ -567,6 +577,11 @@ レシーバーの種類 '{0}' は有効なレコードの種類ではありません。 + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' 'enable'、'disable'、'restore' のいずれかが必要でした @@ -1506,6 +1526,11 @@ オーバーライドおよび明示的なインターフェイスの実装メソッドの制約 + + parameter null-checking + parameter null-checking + + <throw expression> <スロー式> @@ -2096,6 +2121,26 @@ null リテラルを null 非許容参照型に変換できません。 + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. '{1}' 内のパラメーター '{0}' に Null 参照引数がある可能性があります。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 427cbbdf0451c..9da7174302751 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -537,6 +537,16 @@ 단일 레코드 partial 선언에만 매개 변수 목록을 사용할 수 있습니다. + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 제약 조건은 'unmanaged' 제약 조건과 함께 사용할 수 없습니다. @@ -567,6 +577,11 @@ 수신기 형식 '{0}'이(가) 유효한 레코드 형식이 아닙니다. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' 'enable', 'disable' 또는 'restore'가 필요합니다. @@ -1506,6 +1526,11 @@ 재정의 및 명시적 인터페이스 구현 메서드에 대한 제약 조건 + + parameter null-checking + parameter null-checking + + <throw expression> <Throw 식> @@ -2096,6 +2121,26 @@ Null 리터럴을 null을 허용하지 않는 참조 형식으로 변환할 수 없습니다. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. '{1}'의 매개 변수 '{0}'에 대한 가능한 null 참조 인수입니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 535fbddfc7158..971df013a5f6f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -537,6 +537,16 @@ Tylko pojedyncza częściowa deklaracja rekordu może mieć listę parametrów + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Ograniczenie „new()” nie może być używane z ograniczeniem „unmanaged” @@ -567,6 +577,11 @@ Typ odbiorcy „{0}” nie jest prawidłowym typem rekordu. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' Oczekiwano opcji „enable”, „disable” lub „restore” @@ -1506,6 +1526,11 @@ ograniczenia dla przesłonięć i jawnych metod implementacji interfejsu + + parameter null-checking + parameter null-checking + + <throw expression> <wyrażenie throw> @@ -2096,6 +2121,26 @@ Nie można przekonwertować literału o wartości null na nienullowalny typ referencyjny. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. Możliwy argument odwołania o wartości null dla parametru „{0}” w „{1}”. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 0340587a59fd5..b6d018e91683a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -537,6 +537,16 @@ Apenas uma declaração parcial de registro único pode ter uma lista de parâmetros + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint A restrição 'new()' não pode ser usada com a restrição 'unmanaged' @@ -567,6 +577,11 @@ O tipo de receptor '{0}' não é um tipo de registro válido. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' Esperava-se 'enable', 'disable' ou 'restore' @@ -1505,6 +1525,11 @@ restrições para métodos de substituição e de implementação explícita da interface + + parameter null-checking + parameter null-checking + + <throw expression> <expressão throw> @@ -2095,6 +2120,26 @@ Não é possível converter um literal nulo em um tipo de referência não anulável. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. Possível argumento de referência nula para o parâmetro '{0}' em '{1}'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 60f46d0f4b3cb..2f454e5eb1acf 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -537,6 +537,16 @@ Только частичное объявление отдельной записи может иметь список параметров. + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Ограничение "new()" невозможно использовать вместе с ограничением "unmanaged" @@ -567,6 +577,11 @@ Тип получателя "{0}" не является допустимым типом записи. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' Ожидается "enable", "disable" или "restore" @@ -1506,6 +1526,11 @@ ограничения для методов переопределения и явной реализации интерфейса + + parameter null-checking + parameter null-checking + + <throw expression> <выражение throw> @@ -2096,6 +2121,26 @@ Литерал, равный NULL, не может быть преобразован в ссылочный тип, не допускающий значение NULL. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. Возможно, аргумент-ссылка, допускающий значение NULL, для параметра "{0}" в "{1}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index d7535fdf13d7d..04c531aab5748 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -537,6 +537,16 @@ Yalnızca tek kaydın kısmi bildiriminde parametre listesi olabilir + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint 'new()' kısıtlaması, 'unmanaged' kısıtlamasıyla kullanılamaz @@ -567,6 +577,11 @@ '{0}' alıcı türü geçerli bir kayıt türü değil. + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' 'enable', 'disable' veya 'restore' bekleniyor @@ -1506,6 +1526,11 @@ geçersiz kılma ve açık arabirim uygulama yöntemleri için kısıtlamalar + + parameter null-checking + parameter null-checking + + <throw expression> <throw ifadesi> @@ -2096,6 +2121,26 @@ Null sabit değer, boş değer atanamayan başvuru türüne dönüştürülemiyor. + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. '{1}' içindeki '{0}' parametresi için olası null başvuru bağımsız değişkeni. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 40db8f961e779..16a2938e2b00e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -537,6 +537,16 @@ 只有一个记录分部声明可以具有参数列表 + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint "new()" 约束不能与 "unmanaged" 约束一起使用 @@ -567,6 +577,11 @@ 指定的接收器类型“{0}”不是有效的记录类型。 + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' 应为 "enable"、"disable" 或 "restore" @@ -1506,6 +1526,11 @@ 重写和显式接口实现方法的约束 + + parameter null-checking + parameter null-checking + + <throw expression> <throw 表达式> @@ -2096,6 +2121,26 @@ 无法将 null 文本转换为不可为 null 的引用类型。 + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. “{1}”中“{0}”形参的可能的 null 引用实参。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index e617fc714b865..9b1b2f09c857a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -537,6 +537,16 @@ 只有一筆記錄可以在部分宣告中包含參數清單 + + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + Parameter '{0}' can only have exclamation-point null checking in implementation methods. + + + + Space required between '!' and '=' here. + Space required between '!' and '=' here. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 條件約束不能和 'unmanaged' 條件約束一起使用 @@ -567,6 +577,11 @@ 接收器類型 '{0}' 不是有效的記錄類型。 + + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + Parameter '{0}' is a non-nullable value type and cannot be null-checked. + + Record member '{0}' must be private. Record member '{0}' must be private. @@ -587,6 +602,11 @@ '{0}' must allow overriding because the containing record is not sealed. + + By-reference parameter '{0}' cannot be null-checked. + By-reference parameter '{0}' cannot be null-checked. + + Expected 'enable', 'disable', or 'restore' 應為 'enable'、'disable' 或 'restore' @@ -1506,6 +1526,11 @@ 適用於覆寫和明確介面實作方法的條件約束 + + parameter null-checking + parameter null-checking + + <throw expression> <throw 運算式> @@ -2096,6 +2121,26 @@ 無法將 null 常值轉換成不可為 Null 的參考型別。 + + Parameter '{0}' is null-checked but is null by default. + Parameter '{0}' is null-checked but is null by default. + + + + Parameter is null-checked but is null by default. + Parameter is null-checked but is null by default. + + + + Nullable value type '{0}' is null-checked and will throw if null. + Nullable value type '{0}' is null-checked and will throw if null. + + + + Nullable value type is null-checked and will throw if null. + Nullable value type is null-checked and will throw if null. + + Possible null reference argument for parameter '{0}' in '{1}'. '{1}' 中的參數 '{0}' 可能有 Null 參考引數。 diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenNullCheckedParameterTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenNullCheckedParameterTests.cs index 0c3e0513a48d8..733ca39e17606 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenNullCheckedParameterTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenNullCheckedParameterTests.cs @@ -1,4 +1,6 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Emit; @@ -1206,13 +1208,13 @@ public static void Main() { // Code size 29 (0x1d) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brtrue.s IL_000e - IL_0003: ldstr ""s"" - IL_0008: newobj ""System.ArgumentNullException..ctor(string)"" - IL_000d: throw - IL_000e: ldc.i4.s -2 - IL_0010: newobj ""C.d__0..ctor(int)"" + IL_0000: ldc.i4.s -2 + IL_0002: newobj ""C.d__0..ctor(int)"" + IL_0007: ldarg.1 + IL_0008: brtrue.s IL_0015 + IL_000a: ldstr ""s"" + IL_000f: newobj ""System.ArgumentNullException..ctor(string)"" + IL_0014: throw IL_0015: dup IL_0016: ldarg.1 IL_0017: stfld ""string C.d__0.<>3__s"" @@ -1245,13 +1247,13 @@ IEnumerable GetChars(string s!) { // Code size 29 (0x1d) .maxstack 3 - IL_0000: ldarg.0 - IL_0001: brtrue.s IL_000e - IL_0003: ldstr ""s"" - IL_0008: newobj ""System.ArgumentNullException..ctor(string)"" - IL_000d: throw - IL_000e: ldc.i4.s -2 - IL_0010: newobj ""Iterators.<g__GetChars|0_0>d..ctor(int)"" + IL_0000: ldc.i4.s -2 + IL_0002: newobj ""Iterators.<g__GetChars|0_0>d..ctor(int)"" + IL_0007: ldarg.0 + IL_0008: brtrue.s IL_0015 + IL_000a: ldstr ""s"" + IL_000f: newobj ""System.ArgumentNullException..ctor(string)"" + IL_0014: throw IL_0015: dup IL_0016: ldarg.0 IL_0017: stfld ""string Iterators.<g__GetChars|0_0>d.<>3__s"" @@ -1284,17 +1286,17 @@ IEnumerator GetChars(string s!) { // Code size 28 (0x1c) .maxstack 3 - IL_0000: ldarg.0 - IL_0001: brtrue.s IL_000e - IL_0003: ldstr ""s"" - IL_0008: newobj ""System.ArgumentNullException..ctor(string)"" - IL_000d: throw - IL_000e: ldc.i4.0 - IL_000f: newobj ""Iterators.<g__GetChars|0_0>d..ctor(int)"" + IL_0000: ldc.i4.0 + IL_0001: newobj ""Iterators.<g__GetChars|0_0>d..ctor(int)"" + IL_0006: ldarg.0 + IL_0007: brtrue.s IL_0014 + IL_0009: ldstr ""s"" + IL_000e: newobj ""System.ArgumentNullException..ctor(string)"" + IL_0013: throw IL_0014: dup IL_0015: ldarg.0 IL_0016: stfld ""string Iterators.<g__GetChars|0_0>d.s"" - IL_001b: ret + IL_001b: ret }"); } @@ -1403,14 +1405,14 @@ static IEnumerable GetChars(string s!) CompileAndVerify(source, parseOptions: TestOptions.RegularPreview).VerifyIL("C.GetChars(string)", @" { // Code size 22 (0x16) - .maxstack 1 - IL_0000: ldarg.0 - IL_0001: brtrue.s IL_000e - IL_0003: ldstr ""s"" - IL_0008: newobj ""System.ArgumentNullException..ctor(string)"" - IL_000d: throw - IL_000e: ldc.i4.s -2 - IL_0010: newobj ""C.d__1..ctor(int)"" + .maxstack 2 + IL_0000: ldc.i4.s -2 + IL_0002: newobj ""C.d__1..ctor(int)"" + IL_0007: ldarg.0 + IL_0008: brtrue.s IL_0015 + IL_000a: ldstr ""s"" + IL_000f: newobj ""System.ArgumentNullException..ctor(string)"" + IL_0014: throw IL_0015: ret }"); } @@ -1431,14 +1433,14 @@ static IEnumerator GetChars(string s!) CompileAndVerify(source, parseOptions: TestOptions.RegularPreview).VerifyIL("C.GetChars(string)", @" { // Code size 21 (0x15) - .maxstack 1 - IL_0000: ldarg.0 - IL_0001: brtrue.s IL_000e - IL_0003: ldstr ""s"" - IL_0008: newobj ""System.ArgumentNullException..ctor(string)"" - IL_000d: throw - IL_000e: ldc.i4.0 - IL_000f: newobj ""C.d__1..ctor(int)"" + .maxstack 2 + IL_0000: ldc.i4.0 + IL_0001: newobj ""C.d__1..ctor(int)"" + IL_0006: ldarg.0 + IL_0007: brtrue.s IL_0014 + IL_0009: ldstr ""s"" + IL_000e: newobj ""System.ArgumentNullException..ctor(string)"" + IL_0013: throw IL_0014: ret }"); } diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTest_INullCheckedParameters.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTest_INullCheckedParameters.cs deleted file mode 100644 index 9ffbbd67ac852..0000000000000 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTest_INullCheckedParameters.cs +++ /dev/null @@ -1,2603 +0,0 @@ -// 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.Linq; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.CSharp.Test.Utilities; -using Microsoft.CodeAnalysis.FlowAnalysis; -using Microsoft.CodeAnalysis.Operations; -using Microsoft.CodeAnalysis.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.CSharp.UnitTests -{ - public partial class IOperationTests : SemanticModelTestBase - { - [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)] - [Fact] - public void NullCheckedMethodDeclarationIOp() - { - var source = @" -public class C -{ - public void M(string input!) { } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... input!) { }') - BlockBody: - IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... input!) { }') - Left: - IParameterReferenceOperation: input (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public void ... input!) { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public void ... input!) { }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... input!) { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... input!) { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""input"", IsImplicit) (Syntax: 'public void ... input!) { }') - 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 - Block[B3] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_OneNullCheckedManyParams() - { - var source = @" -public class C -{ - public void M(string x, string y!) { } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... ing y!) { }') - BlockBody: - IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... ing y!) { }') - Left: - IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public void ... ing y!) { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public void ... ing y!) { }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... ing y!) { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... ing y!) { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""y"", IsImplicit) (Syntax: 'public void ... ing 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) - Initializer: - null - Block[B3] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_OneNullCheckedParamWithStringOpt() - { - var source = @" -public class C -{ - public void M(string name! = ""rose"") { } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... ""rose"") { }') - BlockBody: - IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" -Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... ""rose"") { }') - Left: - IParameterReferenceOperation: name (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public void ... ""rose"") { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public void ... ""rose"") { }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... ""rose"") { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... ""rose"") { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""name"", IsImplicit) (Syntax: 'public void ... ""rose"") { }') - 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 - Block[B3] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedOperator() - { - var source = @" -public class Box -{ - public static int operator+ (Box b!, Box c) - { - return 2; - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public stat ... }') - BlockBody: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IReturnOperation (OperationKind.Return, Type: null) (Syntax: 'return 2;') - ReturnedValue: - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public stat ... }') - Left: - IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: Box, IsImplicit) (Syntax: 'public stat ... }') - Right: - ILiteralOperation (OperationKind.Literal, Type: Box, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public stat ... }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public stat ... }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public stat ... }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""b"", IsImplicit) (Syntax: 'public stat ... }') - 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 - Block[B3] - Block - Predecessors: [B1] - Statements (0) - Next (Return) Block[B4] - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') - Block[B4] - Exit - Predecessors: [B3] - Statements (0)"); - } - - [Fact(Skip = "PROTOTYPE")] - public void TestIOp_NullCheckedIndexedProperty() - { - // PROTOTYPE - var source = @" -public class C -{ - public string this[string index!] => null; -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> null') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'null') - ReturnedValue: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, Constant: null, IsImplicit) (Syntax: 'null') - Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) - Operand: - ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @""); - } - - [Fact] - public void TestIOp_NullCheckedIndexedGetterSetter() - { - var source = @" -public class C -{ - private object[] items = {'h', ""hello""}; - public string this[object item!] - { - /**/get - { - return items[0].ToString(); - }/**/ - set - { - items[0] = value; - } - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'set ... }') - BlockBody: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'items[0] = value;') - Expression: - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Object) (Syntax: 'items[0] = value') - Left: - IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Object) (Syntax: 'items[0]') - Array reference: - IFieldReferenceOperation: System.Object[] C.items (OperationKind.FieldReference, Type: System.Object[]) (Syntax: 'items') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'items') - Indices(1): - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') - Right: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: 'value') - Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) - Operand: - IParameterReferenceOperation: value (OperationKind.ParameterReference, Type: System.String) (Syntax: 'value') - ExpressionBody: - null"); - var expected = @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'get ... }') - Left: - IParameterReferenceOperation: item (OperationKind.ParameterReference, Type: System.Object, IsImplicit) (Syntax: 'get ... }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.Object, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'get ... }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'get ... }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'get ... }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""item"", IsImplicit) (Syntax: 'get ... }') - 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 - Block[B3] - Block - Predecessors: [B1] - Statements (0) - Next (Return) Block[B4] - IInvocationOperation (virtual System.String System.Object.ToString()) (OperationKind.Invocation, Type: System.String) (Syntax: 'items[0].ToString()') - Instance Receiver: - IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Object) (Syntax: 'items[0]') - Array reference: - IFieldReferenceOperation: System.Object[] C.items (OperationKind.FieldReference, Type: System.Object[]) (Syntax: 'items') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'items') - Indices(1): - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') - Arguments(0) - Block[B4] - Exit - Predecessors: [B3] - Statements (0)"; - VerifyFlowGraphAndDiagnosticsForTest(source, expected, DiagnosticDescription.None, parseOptions: TestOptions.RegularPreview); - } - - [Fact] - public void TestIOp_NullCheckedIndexedGetterExpression() - { - var source = @" -public class C -{ - private object[] items = {'h', ""hello""}; - public string this[object item!] - { - /**/get => items[0].ToString();/**/ - set - { - items[0] = value; - } - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'set ... }') - BlockBody: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'items[0] = value;') - Expression: - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Object) (Syntax: 'items[0] = value') - Left: - IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Object) (Syntax: 'items[0]') - Array reference: - IFieldReferenceOperation: System.Object[] C.items (OperationKind.FieldReference, Type: System.Object[]) (Syntax: 'items') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'items') - Indices(1): - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') - Right: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: 'value') - Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) - Operand: - IParameterReferenceOperation: value (OperationKind.ParameterReference, Type: System.String) (Syntax: 'value') - ExpressionBody: - null"); - var expected = @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'get => item ... ToString();') - Left: - IParameterReferenceOperation: item (OperationKind.ParameterReference, Type: System.Object, IsImplicit) (Syntax: 'get => item ... ToString();') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.Object, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'get => item ... ToString();') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'get => item ... ToString();') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'get => item ... ToString();') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""item"", IsImplicit) (Syntax: 'get => item ... ToString();') - 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 - Block[B3] - Block - Predecessors: [B1] - Statements (0) - Next (Return) Block[B4] - IInvocationOperation (virtual System.String System.Object.ToString()) (OperationKind.Invocation, Type: System.String) (Syntax: 'items[0].ToString()') - Instance Receiver: - IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Object) (Syntax: 'items[0]') - Array reference: - IFieldReferenceOperation: System.Object[] C.items (OperationKind.FieldReference, Type: System.Object[]) (Syntax: 'items') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'items') - Indices(1): - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') - Arguments(0) - Block[B4] - Exit - Predecessors: [B3] - Statements (0) -"; - VerifyFlowGraphAndDiagnosticsForTest(source, expected, DiagnosticDescription.None, parseOptions: TestOptions.RegularPreview); - } - - [Fact] - public void TestIOp_NullCheckedIndexedSetter() - { - var source = @" -public class C -{ - public string this[object item!] { /**/set { }/**/ } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'set { }') - BlockBody: - IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - ExpressionBody: - null"); - var expected = @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'set { }') - Left: - IParameterReferenceOperation: item (OperationKind.ParameterReference, Type: System.Object, IsImplicit) (Syntax: 'set { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.Object, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'set { }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'set { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'set { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""item"", IsImplicit) (Syntax: 'set { }') - 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 - Block[B3] - Exit - Predecessors: [B1] - Statements (0)"; - VerifyFlowGraphAndDiagnosticsForTest(source, expected, DiagnosticDescription.None, parseOptions: TestOptions.RegularPreview); - } - - [Fact] - public void TestIOp_NullCheckedLambda() - { - var source = @" -using System; -class C -{ - public void M() - { - Func func1 = x! => x; - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... }') - BlockBody: - IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - Locals: Local_1: System.Func func1 - IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'Func x;') - IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'Func x') - Declarators: - IVariableDeclaratorOperation (Symbol: System.Func func1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'func1 = x! => x') - Initializer: - IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= x! => x') - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 'x! => x') - Target: - IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: 'x! => x') - IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'x') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'x') - ReturnedValue: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') - Initializer: - null - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" -Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Entering: {R1} -.locals {R1} -{ - Locals: [System.Func func1] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsImplicit) (Syntax: 'func1 = x! => x') - Left: - ILocalReferenceOperation: func1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Func, IsImplicit) (Syntax: 'func1 = x! => x') - Right: - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 'x! => x') - Target: - IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: 'x! => x') - { - Block[B0#A0] - Entry - Statements (0) - Next (Regular) Block[B1#A0] - Block[B1#A0] - Block - Predecessors: [B0#A0] - Statements (0) - Jump if False (Regular) to Block[B3#A0] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'x! => x') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'x! => x') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'x! => x') - Next (Regular) Block[B2#A0] - Block[B2#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'x! => x') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'x! => x') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'x! => 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) - Initializer: - null - Block[B3#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Return) Block[B4#A0] - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') - Block[B4#A0] - Exit - Predecessors: [B3#A0] - Statements (0) - } - Next (Regular) Block[B2] - Leaving: {R1} -} -Block[B2] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedInLambdaWithManyParameters() - { - var source = @" -using System; -class C -{ - public void M() - { - Func func1 = (x!, y) => x; - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... }') - BlockBody: - IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - Locals: Local_1: System.Func func1 - IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'Func x;') - IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'Func x') - Declarators: - IVariableDeclaratorOperation (Symbol: System.Func func1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'func1 = (x!, y) => x') - Initializer: - IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= (x!, y) => x') - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: '(x!, y) => x') - Target: - IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: '(x!, y) => x') - IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'x') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'x') - ReturnedValue: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') - Initializer: - null - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Entering: {R1} - .locals {R1} - { - Locals: [System.Func func1] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsImplicit) (Syntax: 'func1 = (x!, y) => x') - Left: - ILocalReferenceOperation: func1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Func, IsImplicit) (Syntax: 'func1 = (x!, y) => x') - Right: - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: '(x!, y) => x') - Target: - IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: '(x!, y) => x') - { - Block[B0#A0] - Entry - Statements (0) - Next (Regular) Block[B1#A0] - Block[B1#A0] - Block - Predecessors: [B0#A0] - Statements (0) - Jump if False (Regular) to Block[B3#A0] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: '(x!, y) => x') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: '(x!, y) => x') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: '(x!, y) => x') - Next (Regular) Block[B2#A0] - Block[B2#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: '(x!, y) => x') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '(x!, y) => x') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: '(x!, y) => 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) - Initializer: - null - Block[B3#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Return) Block[B4#A0] - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') - Block[B4#A0] - Exit - Predecessors: [B3#A0] - Statements (0) - } - Next (Regular) Block[B2] - Leaving: {R1} - } - Block[B2] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedUnnamedVariableInLambda() - { - var source = @" -using System; -class C -{ - public void M() - { - Func func1 = _! => null; - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... }') - BlockBody: - IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - Locals: Local_1: System.Func func1 - IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'Func null;') - IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'Func null') - Declarators: - IVariableDeclaratorOperation (Symbol: System.Func func1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'func1 = _! => null') - Initializer: - IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= _! => null') - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: '_! => null') - Target: - IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: '_! => null') - IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'null') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'null') - ReturnedValue: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, Constant: null, IsImplicit) (Syntax: 'null') - Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) - Operand: - ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') - Initializer: - null - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Entering: {R1} - .locals {R1} - { - Locals: [System.Func func1] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsImplicit) (Syntax: 'func1 = _! => null') - Left: - ILocalReferenceOperation: func1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Func, IsImplicit) (Syntax: 'func1 = _! => null') - Right: - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: '_! => null') - Target: - IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: '_! => null') - { - Block[B0#A0] - Entry - Statements (0) - Next (Regular) Block[B1#A0] - Block[B1#A0] - Block - Predecessors: [B0#A0] - Statements (0) - Jump if False (Regular) to Block[B3#A0] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: '_! => null') - Left: - IParameterReferenceOperation: _ (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: '_! => null') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: '_! => null') - Next (Regular) Block[B2#A0] - Block[B2#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: '_! => null') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '_! => null') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""_"", IsImplicit) (Syntax: '_! => 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) - Initializer: - null - Block[B3#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Return) Block[B4#A0] - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, Constant: null, IsImplicit) (Syntax: 'null') - Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) - (ImplicitReference) - Operand: - ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') - Block[B4#A0] - Exit - Predecessors: [B3#A0] - Statements (0) - } - Next (Regular) Block[B2] - Leaving: {R1} - } - Block[B2] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedTwoExpressionBodyLambdas() - { - var source = @" -using System; -class C -{ - public Func M(string s1!) => s2! => s2 + s1; -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public Func ... => s2 + s1;') - BlockBody: - null - ExpressionBody: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> s2! => s2 + s1') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 's2! => s2 + s1') - ReturnedValue: - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 's2! => s2 + s1') - Target: - IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: 's2! => s2 + s1') - IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 's2 + s1') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 's2 + s1') - ReturnedValue: - IBinaryOperation (BinaryOperatorKind.Add) (OperationKind.Binary, Type: System.String) (Syntax: 's2 + s1') - Left: - IParameterReferenceOperation: s2 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's2') - Right: - IParameterReferenceOperation: s1 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's1')"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public Func ... => s2 + s1;') - Left: - IParameterReferenceOperation: s1 (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public Func ... => s2 + s1;') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public Func ... => s2 + s1;') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public Func ... => s2 + s1;') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public Func ... => s2 + s1;') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s1"", IsImplicit) (Syntax: 'public Func ... => s2 + s1;') - 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 - Block[B3] - Block - Predecessors: [B1] - Statements (0) - Next (Return) Block[B4] - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 's2! => s2 + s1') - Target: - IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: 's2! => s2 + s1') - { - Block[B0#A0] - Entry - Statements (0) - Next (Regular) Block[B1#A0] - Block[B1#A0] - Block - Predecessors: [B0#A0] - Statements (0) - Jump if False (Regular) to Block[B3#A0] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 's2! => s2 + s1') - Left: - IParameterReferenceOperation: s2 (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 's2! => s2 + s1') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 's2! => s2 + s1') - Next (Regular) Block[B2#A0] - Block[B2#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 's2! => s2 + s1') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 's2! => s2 + s1') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s2"", IsImplicit) (Syntax: 's2! => s2 + s1') - 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 - Block[B3#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Return) Block[B4#A0] - IBinaryOperation (BinaryOperatorKind.Add) (OperationKind.Binary, Type: System.String) (Syntax: 's2 + s1') - Left: - IParameterReferenceOperation: s2 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's2') - Right: - IParameterReferenceOperation: s1 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's1') - Block[B4#A0] - Exit - Predecessors: [B3#A0] - Statements (0) - } - Block[B4] - Exit - Predecessors: [B3] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedLambdaInField() - { - var source = @" -using System; -class C -{ - Func func1 = x! => x; - public C() - { - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: 'x! => x') - IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'x') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'x') - ReturnedValue: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x')"); - - VerifyFlowGraph(compilation, node2, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsImplicit) (Syntax: '= x! => x') - Left: - IFieldReferenceOperation: System.Func C.func1 (OperationKind.FieldReference, Type: System.Func, IsImplicit) (Syntax: '= x! => x') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: '= x! => x') - Right: - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 'x! => x') - Target: - IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: 'x! => x') - { - Block[B0#A0] - Entry - Statements (0) - Next (Regular) Block[B1#A0] - Block[B1#A0] - Block - Predecessors: [B0#A0] - Statements (0) - Jump if False (Regular) to Block[B3#A0] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'x! => x') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'x! => x') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'x! => x') - Next (Regular) Block[B2#A0] - Block[B2#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'x! => x') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'x! => x') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'x! => 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) - Initializer: - null - Block[B3#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Return) Block[B4#A0] - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') - Block[B4#A0] - Exit - Predecessors: [B3#A0] - Statements (0) - } - Next (Regular) Block[B2] - Block[B2] - Exit - Predecessors: [B1] - Statements (0) -"); - } - - [Fact] - public void TestIOp_NullCheckedLocalFunction() - { - var source = @" -class C -{ - public void M() - { - InnerM(""hello world""); - void InnerM(string x!) { } - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - ILocalFunctionOperation (Symbol: void InnerM(System.String x)) (OperationKind.LocalFunction, Type: null) (Syntax: 'void InnerM ... ing x!) { }') - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') - ReturnedValue: - null"); - VerifyFlowGraph(compilation, node2, @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Entering: {R1} - .locals {R1} - { - Methods: [void InnerM(System.String x)] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hello world"");') - Expression: - IInvocationOperation (void InnerM(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hello world"")') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello world""') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello world"") (Syntax: '""hello world""') - 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) - Next (Regular) Block[B2] - Leaving: {R1} - - { void InnerM(System.String x) - - Block[B0#0R1] - Entry - Statements (0) - Next (Regular) Block[B1#0R1] - Block[B1#0R1] - Block - Predecessors: [B0#0R1] - Statements (0) - Jump if False (Regular) to Block[B3#0R1] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - Next (Regular) Block[B2#0R1] - Block[B2#0R1] - Block - Predecessors: [B1#0R1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'void InnerM ... ing 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) - Initializer: - null - Block[B3#0R1] - Exit - Predecessors: [B1#0R1] - Statements (0) - } - } - Block[B2] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedManyParamsInLocalFunction() - { - var source = @" -class C -{ - public void M() - { - InnerM(""hello"", ""world""); - void InnerM(string x!, string y!) { } - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - ILocalFunctionOperation (Symbol: void InnerM(System.String x, System.String y)) (OperationKind.LocalFunction, Type: null) (Syntax: 'void InnerM ... ing y!) { }') - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') - ReturnedValue: - null"); - - VerifyFlowGraph(compilation, node2, @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Entering: {R1} - .locals {R1} - { - Methods: [void InnerM(System.String x, System.String y)] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hel ... ""world"");') - Expression: - IInvocationOperation (void InnerM(System.String x, System.String y)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hel ... , ""world"")') - Instance Receiver: - null - Arguments(2): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello""') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') - 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: y) (OperationKind.Argument, Type: null) (Syntax: '""world""') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""world"") (Syntax: '""world""') - 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) - Next (Regular) Block[B2] - Leaving: {R1} - - { void InnerM(System.String x, System.String y) - - Block[B0#0R1] - Entry - Statements (0) - Next (Regular) Block[B1#0R1] - Block[B1#0R1] - Block - Predecessors: [B0#0R1] - Statements (0) - Jump if False (Regular) to Block[B3#0R1] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - Next (Regular) Block[B2#0R1] - Block[B2#0R1] - Block - Predecessors: [B1#0R1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'void InnerM ... ing 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) - Initializer: - null - Block[B3#0R1] - Block - Predecessors: [B1#0R1] - Statements (0) - Jump if False (Regular) to Block[B5#0R1] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - Left: - IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - Next (Regular) Block[B4#0R1] - Block[B4#0R1] - Block - Predecessors: [B3#0R1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""y"", IsImplicit) (Syntax: 'void InnerM ... ing 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) - Initializer: - null - Block[B5#0R1] - Exit - Predecessors: [B3#0R1] - Statements (0) - } - } - Block[B2] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_OuterNullCheckedShadowedParameter() - { - var source = @" -class C -{ - public void M(string x!) - { - InnerM(""hello""); - void InnerM(string x) { } - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... }') - BlockBody: - IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hello"");') - Expression: - IInvocationOperation (void InnerM(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hello"")') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello""') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') - 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) - ILocalFunctionOperation (Symbol: void InnerM(System.String x)) (OperationKind.LocalFunction, Type: null) (Syntax: 'void InnerM ... ring x) { }') - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') - ReturnedValue: - null - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... }') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public void ... }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public void ... }') - Entering: {R1} - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public void ... }') - 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 - .locals {R1} - { - Methods: [void InnerM(System.String x)] - Block[B3] - Block - Predecessors: [B1] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hello"");') - Expression: - IInvocationOperation (void InnerM(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hello"")') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello""') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') - 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) - Next (Regular) Block[B4] - Leaving: {R1} - - { void InnerM(System.String x) - - Block[B0#0R1] - Entry - Statements (0) - Next (Regular) Block[B1#0R1] - Block[B1#0R1] - Exit - Predecessors: [B0#0R1] - Statements (0) - } - } - Block[B4] - Exit - Predecessors: [B3] - Statements (0)"); - } - - [Fact] - public void TestIOp_InnerNullCheckedShadowedParameter() - { - var source = @" -class C -{ - public void M(string x) - { - InnerM(""hello""); - void InnerM(string x!) { } - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - ILocalFunctionOperation (Symbol: void InnerM(System.String x)) (OperationKind.LocalFunction, Type: null) (Syntax: 'void InnerM ... ing x!) { }') - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') - ReturnedValue: - null"); - VerifyFlowGraph(compilation, node2, @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Entering: {R1} - .locals {R1} - { - Methods: [void InnerM(System.String x)] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hello"");') - Expression: - IInvocationOperation (void InnerM(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hello"")') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello""') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') - 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) - Next (Regular) Block[B2] - Leaving: {R1} - - { void InnerM(System.String x) - - Block[B0#0R1] - Entry - Statements (0) - Next (Regular) Block[B1#0R1] - Block[B1#0R1] - Block - Predecessors: [B0#0R1] - Statements (0) - Jump if False (Regular) to Block[B3#0R1] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - Next (Regular) Block[B2#0R1] - Block[B2#0R1] - Block - Predecessors: [B1#0R1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'void InnerM ... ing 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) - Initializer: - null - Block[B3#0R1] - Exit - Predecessors: [B1#0R1] - Statements (0) - } - } - Block[B2] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedConstructor() - { - var source = @" -class C -{ - public C(string x!) { } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(string x!) { }') - Initializer: - null - BlockBody: - IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(string x!) { }') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(string x!) { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public C(string x!) { }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(string x!) { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(string x!) { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public C(string 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) - Initializer: - null - Block[B3] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedConstructorWithThisChain() - { - var source = @" -class C -{ - public C() { } - public C(string x!) : this() { } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(st ... this() { }') - Initializer: - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': this()') - Expression: - IInvocationOperation ( C..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': this()') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: ': this()') - Arguments(0) - BlockBody: - IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(st ... this() { }') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(st ... this() { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public C(st ... this() { }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(st ... this() { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(st ... this() { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public C(st ... this() { }') - 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 - Block[B3] - Block - Predecessors: [B1] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': this()') - Expression: - IInvocationOperation ( C..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': this()') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: ': this()') - Arguments(0) - Next (Regular) Block[B4] - Block[B4] - Exit - Predecessors: [B3] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedConstructorWithBaseChain() - { - var source = @" -class B -{ - public B(string y) { } -} -class C : B -{ - public C(string x!) : base(x) { } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(st ... base(x) { }') - Initializer: - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(x)') - Expression: - IInvocationOperation ( B..ctor(System.String y)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(x)') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: B, IsImplicit) (Syntax: ': base(x)') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: y) (OperationKind.Argument, Type: null) (Syntax: 'x') - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (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) - BlockBody: - IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(st ... base(x) { }') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(st ... base(x) { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public C(st ... base(x) { }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(st ... base(x) { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(st ... base(x) { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public C(st ... base(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) - Initializer: - null - Block[B3] - Block - Predecessors: [B1] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(x)') - Expression: - IInvocationOperation ( B..ctor(System.String y)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(x)') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: B, IsImplicit) (Syntax: ': base(x)') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: y) (OperationKind.Argument, Type: null) (Syntax: 'x') - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (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) - Next (Regular) Block[B4] - Block[B4] - Exit - Predecessors: [B3] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedConstructorWithFieldInitializers() - { - var source = @" -class C -{ - int y = 5; - public C(string x!) { y++; } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(st ... !) { y++; }') - Initializer: - null - BlockBody: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ y++; }') - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'y++;') - Expression: - IIncrementOrDecrementOperation (Postfix) (OperationKind.Increment, Type: System.Int32) (Syntax: 'y++') - Target: - IFieldReferenceOperation: System.Int32 C.y (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'y') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'y') - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(st ... !) { y++; }') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(st ... !) { y++; }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public C(st ... !) { y++; }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(st ... !) { y++; }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(st ... !) { y++; }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public C(st ... !) { 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) - Initializer: - null - Block[B3] - Block - Predecessors: [B1] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'y++;') - Expression: - IIncrementOrDecrementOperation (Postfix) (OperationKind.Increment, Type: System.Int32) (Syntax: 'y++') - Target: - IFieldReferenceOperation: System.Int32 C.y (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'y') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'y') - Next (Regular) Block[B4] - Block[B4] - Exit - Predecessors: [B3] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedExpressionBodyMethod() - { - var source = @" -class C -{ - object Local(object arg!) => arg; -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'object Loca ... g!) => arg;') - BlockBody: - null - ExpressionBody: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> arg') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'arg') - ReturnedValue: - IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'arg')"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'object Loca ... g!) => arg;') - Left: - IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Object, IsImplicit) (Syntax: 'object Loca ... g!) => arg;') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.Object, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'object Loca ... g!) => arg;') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'object Loca ... g!) => arg;') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'object Loca ... g!) => arg;') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""arg"", IsImplicit) (Syntax: 'object Loca ... g!) => arg;') - 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 - Block[B3] - Block - Predecessors: [B1] - Statements (0) - Next (Return) Block[B4] - IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'arg') - Block[B4] - Exit - Predecessors: [B3] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedIterator() - { - var source = @" -using System.Collections.Generic; -class C -{ - IEnumerable GetChars(string s!) - { - foreach (var c in s) - { - yield return c; - } - } - public static void Main() - { - C c = new C(); - IEnumerable e = c.GetChars(""hello""); - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(0); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'IEnumerable ... }') - BlockBody: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IForEachLoopOperation (LoopKind.ForEach, Continue Label Id: 0, Exit Label Id: 1) (OperationKind.Loop, Type: null) (Syntax: 'foreach (va ... }') - Locals: Local_1: System.Char c - LoopControlVariable: - IVariableDeclaratorOperation (Symbol: System.Char c) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'var') - Initializer: - null - Collection: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 's') - Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: - IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String) (Syntax: 's') - Body: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return c;') - ReturnedValue: - ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.Char) (Syntax: 'c') - NextVariables(0) - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'IEnumerable ... }') - Left: - IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'IEnumerable ... }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'IEnumerable ... }') - Entering: {R1} - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'IEnumerable ... }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'IEnumerable ... }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s"", IsImplicit) (Syntax: 'IEnumerable ... }') - 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 - .locals {R1} - { - CaptureIds: [0] - Block[B3] - Block - Predecessors: [B1] - Statements (1) - IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 's') - Value: - IInvocationOperation ( System.CharEnumerator System.String.GetEnumerator()) (OperationKind.Invocation, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - Instance Receiver: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 's') - Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - (Identity) - Operand: - IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String) (Syntax: 's') - Arguments(0) - Next (Regular) Block[B4] - Entering: {R2} {R3} - .try {R2, R3} - { - Block[B4] - Block - Predecessors: [B3] [B5] - Statements (0) - Jump if False (Regular) to Block[B9] - IInvocationOperation ( System.Boolean System.CharEnumerator.MoveNext()) (OperationKind.Invocation, Type: System.Boolean, IsImplicit) (Syntax: 's') - Instance Receiver: - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - Arguments(0) - Finalizing: {R5} - Leaving: {R3} {R2} {R1} - Next (Regular) Block[B5] - Entering: {R4} - .locals {R4} - { - Locals: [System.Char c] - Block[B5] - Block - Predecessors: [B4] - Statements (2) - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: null, IsImplicit) (Syntax: 'var') - Left: - ILocalReferenceOperation: c (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Char, IsImplicit) (Syntax: 'var') - Right: - IPropertyReferenceOperation: System.Char System.CharEnumerator.Current { get; } (OperationKind.PropertyReference, Type: System.Char, IsImplicit) (Syntax: 'var') - Instance Receiver: - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return c;') - ReturnedValue: - ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.Char) (Syntax: 'c') - Next (Regular) Block[B4] - Leaving: {R4} - } - } - .finally {R5} - { - Block[B6] - Block - Predecessors (0) - Statements (0) - Jump if True (Regular) to Block[B8] - IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 's') - Operand: - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - Next (Regular) Block[B7] - Block[B7] - Block - Predecessors: [B6] - Statements (1) - IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 's') - Instance Receiver: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsImplicit) (Syntax: 's') - Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) - (ImplicitReference) - Operand: - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - Arguments(0) - Next (Regular) Block[B8] - Block[B8] - Block - Predecessors: [B6] [B7] - Statements (0) - Next (StructuredExceptionHandling) Block[null] - } - } - Block[B9] - Exit - Predecessors: [B4] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedIteratorInLocalFunction() - { - var source = @" -using System.Collections.Generic; -class Iterators -{ - void Use() - { - IEnumerable e = GetChars(""hello""); - IEnumerable GetChars(string s!) - { - foreach (var c in s) - { - yield return c; - } - } - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - ILocalFunctionOperation (Symbol: System.Collections.Generic.IEnumerable GetChars(System.String s)) (OperationKind.LocalFunction, Type: null) (Syntax: 'IEnumerable ... }') - IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IForEachLoopOperation (LoopKind.ForEach, Continue Label Id: 0, Exit Label Id: 1) (OperationKind.Loop, Type: null) (Syntax: 'foreach (va ... }') - Locals: Local_1: System.Char c - LoopControlVariable: - IVariableDeclaratorOperation (Symbol: System.Char c) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'var') - Initializer: - null - Collection: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 's') - Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: - IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String) (Syntax: 's') - Body: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return c;') - ReturnedValue: - ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.Char) (Syntax: 'c') - NextVariables(0) - IReturnOperation (OperationKind.YieldBreak, Type: null, IsImplicit) (Syntax: '{ ... }') - ReturnedValue: - null"); - - VerifyFlowGraph(compilation, node2, @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Entering: {R1} - .locals {R1} - { - Locals: [System.Collections.Generic.IEnumerable e] - Methods: [System.Collections.Generic.IEnumerable GetChars(System.String s)] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Collections.Generic.IEnumerable, IsImplicit) (Syntax: 'e = GetChars(""hello"")') - Left: - ILocalReferenceOperation: e (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Collections.Generic.IEnumerable, IsImplicit) (Syntax: 'e = GetChars(""hello"")') - Right: - IInvocationOperation (System.Collections.Generic.IEnumerable GetChars(System.String s)) (OperationKind.Invocation, Type: System.Collections.Generic.IEnumerable) (Syntax: 'GetChars(""hello"")') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: s) (OperationKind.Argument, Type: null) (Syntax: '""hello""') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') - 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) - Next (Regular) Block[B2] - Leaving: {R1} - - { System.Collections.Generic.IEnumerable GetChars(System.String s) - - Block[B0#0R1] - Entry - Statements (0) - Next (Regular) Block[B1#0R1] - Block[B1#0R1] - Block - Predecessors: [B0#0R1] - Statements (0) - Jump if False (Regular) to Block[B3#0R1] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'IEnumerable ... }') - Left: - IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'IEnumerable ... }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'IEnumerable ... }') - Entering: {R1#0R1} - Next (Regular) Block[B2#0R1] - Block[B2#0R1] - Block - Predecessors: [B1#0R1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'IEnumerable ... }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'IEnumerable ... }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s"", IsImplicit) (Syntax: 'IEnumerable ... }') - 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 - .locals {R1#0R1} - { - CaptureIds: [0] - Block[B3#0R1] - Block - Predecessors: [B1#0R1] - Statements (1) - IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 's') - Value: - IInvocationOperation ( System.CharEnumerator System.String.GetEnumerator()) (OperationKind.Invocation, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - Instance Receiver: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 's') - Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - (Identity) - Operand: - IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String) (Syntax: 's') - Arguments(0) - Next (Regular) Block[B4#0R1] - Entering: {R2#0R1} {R3#0R1} - .try {R2#0R1, R3#0R1} - { - Block[B4#0R1] - Block - Predecessors: [B3#0R1] [B5#0R1] - Statements (0) - Jump if False (Regular) to Block[B9#0R1] - IInvocationOperation ( System.Boolean System.CharEnumerator.MoveNext()) (OperationKind.Invocation, Type: System.Boolean, IsImplicit) (Syntax: 's') - Instance Receiver: - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - Arguments(0) - Finalizing: {R5#0R1} - Leaving: {R3#0R1} {R2#0R1} {R1#0R1} - Next (Regular) Block[B5#0R1] - Entering: {R4#0R1} - .locals {R4#0R1} - { - Locals: [System.Char c] - Block[B5#0R1] - Block - Predecessors: [B4#0R1] - Statements (2) - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: null, IsImplicit) (Syntax: 'var') - Left: - ILocalReferenceOperation: c (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Char, IsImplicit) (Syntax: 'var') - Right: - IPropertyReferenceOperation: System.Char System.CharEnumerator.Current { get; } (OperationKind.PropertyReference, Type: System.Char, IsImplicit) (Syntax: 'var') - Instance Receiver: - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return c;') - ReturnedValue: - ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.Char) (Syntax: 'c') - Next (Regular) Block[B4#0R1] - Leaving: {R4#0R1} - } - } - .finally {R5#0R1} - { - Block[B6#0R1] - Block - Predecessors (0) - Statements (0) - Jump if True (Regular) to Block[B8#0R1] - IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 's') - Operand: - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - Next (Regular) Block[B7#0R1] - Block[B7#0R1] - Block - Predecessors: [B6#0R1] - Statements (1) - IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 's') - Instance Receiver: - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsImplicit) (Syntax: 's') - Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) - (ImplicitReference) - Operand: - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') - Arguments(0) - Next (Regular) Block[B8#0R1] - Block[B8#0R1] - Block - Predecessors: [B6#0R1] [B7#0R1] - Statements (0) - Next (StructuredExceptionHandling) Block[null] - } - } - Block[B9#0R1] - Exit - Predecessors: [B4#0R1] - Statements (0) - } - } - Block[B2] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedEmptyIterator() - { - var source = @" -using System.Collections.Generic; -class C -{ - public static void Main() { } - static IEnumerable GetChars(string s!) - { - yield break; - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'static IEnu ... }') - BlockBody: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IReturnOperation (OperationKind.YieldBreak, Type: null) (Syntax: 'yield break;') - ReturnedValue: - null - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'static IEnu ... }') - Left: - IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'static IEnu ... }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'static IEnu ... }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'static IEnu ... }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'static IEnu ... }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s"", IsImplicit) (Syntax: 'static IEnu ... }') - 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 - Block[B3] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestIOp_NullCheckedEmptyIteratorReturningIEnumerator() - { - var source = @" -using System.Collections.Generic; -class C -{ - public static void Main() { } - static IEnumerator GetChars(string s!) - { - yield break; - } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'static IEnu ... }') - BlockBody: - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') - IReturnOperation (OperationKind.YieldBreak, Type: null) (Syntax: 'yield break;') - ReturnedValue: - null - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'static IEnu ... }') - Left: - IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'static IEnu ... }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'static IEnu ... }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'static IEnu ... }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'static IEnu ... }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s"", IsImplicit) (Syntax: 'static IEnu ... }') - 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 - Block[B3] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestNullCheckedLambdaWithMissingType() - { - var source = -@" -using System; -class Program -{ - public static void Main() - { - Func func = x! => x; - } -} - -"; - var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - comp.MakeMemberMissing(WellKnownMember.System_ArgumentNullException__ctorString); - comp.MakeTypeMissing(WellKnownType.System_ArgumentNullException); - comp.VerifyDiagnostics( - // (7,37): error CS0656: Missing compiler required member 'System.ArgumentNullException..ctor' - // Func func = x! => x; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "x").WithArguments("System.ArgumentNullException", ".ctor").WithLocation(7, 37)); - var tree = comp.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - comp.VerifyOperationTree(node1, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null, IsInvalid) (Syntax: 'public stat ... }') - BlockBody: - IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ ... }') - Locals: Local_1: System.Func func - IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'Func x;') - IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'Func x') - Declarators: - IVariableDeclaratorOperation (Symbol: System.Func func) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: 'func = x! => x') - Initializer: - IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null, IsInvalid) (Syntax: '= x! => x') - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsInvalid, IsImplicit) (Syntax: 'x! => x') - Target: - IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null, IsInvalid) (Syntax: 'x! => x') - IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'x') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'x') - ReturnedValue: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') - Initializer: - null - ExpressionBody: - null"); - VerifyFlowGraph(comp, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Entering: {R1} - .locals {R1} - { - Locals: [System.Func func] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsInvalid, IsImplicit) (Syntax: 'func = x! => x') - Left: - ILocalReferenceOperation: func (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Func, IsInvalid, IsImplicit) (Syntax: 'func = x! => x') - Right: - IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsInvalid, IsImplicit) (Syntax: 'x! => x') - Target: - IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null, IsInvalid) (Syntax: 'x! => x') - { - Block[B0#A0] - Entry - Statements (0) - Next (Regular) Block[B1#A0] - Block[B1#A0] - Block - Predecessors: [B0#A0] - Statements (0) - Jump if False (Regular) to Block[B3#A0] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'x! => x') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsInvalid, IsImplicit) (Syntax: 'x! => x') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsInvalid, IsImplicit) (Syntax: 'x! => x') - Next (Regular) Block[B2#A0] - Block[B2#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Throw) Block[null] - IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'x! => x') - Children(1): - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsInvalid, IsImplicit) (Syntax: 'x! => x') - Block[B3#A0] - Block - Predecessors: [B1#A0] - Statements (0) - Next (Return) Block[B4#A0] - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') - Block[B4#A0] - Exit - Predecessors: [B3#A0] - Statements (0) - } - Next (Regular) Block[B2] - Leaving: {R1} - } - Block[B2] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestNullCheckedLocalFunctionWithMissingType() - { - var source = -@" -class Program -{ - public static void Main() - { - M(""ok""); - void M(string x!) { } - } -}"; - var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - comp.MakeMemberMissing(WellKnownMember.System_ArgumentNullException__ctorString); - comp.MakeTypeMissing(WellKnownType.System_ArgumentNullException); - comp.VerifyDiagnostics( - // (7,23): error CS0656: Missing compiler required member 'System.ArgumentNullException..ctor' - // void M(string x!) { } - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "x").WithArguments("System.ArgumentNullException", ".ctor").WithLocation(7, 23)); - var tree = comp.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); - comp.VerifyOperationTree(node1, expectedOperationTree: @" - ILocalFunctionOperation (Symbol: void M(System.String x)) (OperationKind.LocalFunction, Type: null, IsInvalid) (Syntax: 'void M(string x!) { }') - IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') - ReturnedValue: - null"); - VerifyFlowGraph(comp, node2, @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Entering: {R1} - .locals {R1} - { - Methods: [void M(System.String x)] - Block[B1] - Block - Predecessors: [B0] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'M(""ok"");') - Expression: - IInvocationOperation (void M(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'M(""ok"")') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""ok""') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""ok"") (Syntax: '""ok""') - 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) - Next (Regular) Block[B2] - Leaving: {R1} - - { void M(System.String x) - - Block[B0#0R1] - Entry - Statements (0) - Next (Regular) Block[B1#0R1] - Block[B1#0R1] - Block - Predecessors: [B0#0R1] - Statements (0) - Jump if False (Regular) to Block[B3#0R1] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') - Left: - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') - Next (Regular) Block[B2#0R1] - Block[B2#0R1] - Block - Predecessors: [B1#0R1] - Statements (0) - Next (Throw) Block[null] - IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') - Children(1): - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') - Block[B3#0R1] - Exit - Predecessors: [B1#0R1] - Statements (0) - } - } - Block[B2] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact] - public void TestNullCheckedMethodWithMissingHasValue() - { - var source = -@" -class Program -{ - public void Method(int? x!) { } -}"; - var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - comp.MakeMemberMissing(SpecialMember.System_Nullable_T_get_HasValue); - comp.VerifyDiagnostics( - // (4,29): warning CS8721: Nullable value type 'int?' is null-checked and will throw if null. - // public void Method(int? x!) { } - Diagnostic(ErrorCode.WRN_NullCheckingOnNullableValueType, "x").WithArguments("int?").WithLocation(4, 29)); - var tree = comp.SyntaxTrees.Single(); - var node = tree.GetRoot().DescendantNodes().OfType().Single(); - comp.VerifyOperationTree(node, expectedOperationTree: @" - IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... nt? x!) { }') - BlockBody: - IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - ExpressionBody: - null"); - VerifyFlowGraph(comp, node, @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if True (Regular) to Block[B3] - IInvalidOperation (OperationKind.Invalid, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... nt? x!) { }') - Children(1): - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32?, IsImplicit) (Syntax: 'public void ... nt? x!) { }') - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... nt? x!) { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... nt? x!) { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public void ... nt? 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) - Initializer: - null - Block[B3] - Exit - Predecessors: [B1] - Statements (0)"); - } - - [Fact(Skip = "PROTOTYPE")] - public void TestNoNullChecksInBlockOperation() - { - // PROTOTYPE - Nullchecks currently included when only BlockSyntax is bound. Falls into VisitMethodBody instead of VisitBlock. - var source = @" -public class C -{ - public void M(string input!) - /**/{ }/**/ -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); - - compilation.VerifyOperationTree(node1, expectedOperationTree: @" -IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') -"); - var output = @""; - VerifyFlowGraphAndDiagnosticsForTest(compilation, expectedFlowGraph: output, DiagnosticDescription.None); - } - - [Fact] - public void TestNullCheckedBaseCallOrdering() - { - var source = @" -public class B -{ - public B(string x) { } -} -public class C : B -{ - public C(string param!) : base(param ?? """") { } -}"; - var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); - - compilation.VerifyDiagnostics(); - - var tree = compilation.SyntaxTrees.Single(); - var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); - compilation.VerifyOperationTree(node1, expectedOperationTree: @" - IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(st ... ?? """") { }') - Initializer: - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(param ?? """")') - Expression: - IInvocationOperation ( B..ctor(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(param ?? """")') - Instance Receiver: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: B, IsImplicit) (Syntax: ': base(param ?? """")') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'param ?? """"') - ICoalesceOperation (OperationKind.Coalesce, Type: System.String) (Syntax: 'param ?? """"') - Expression: - IParameterReferenceOperation: param (OperationKind.ParameterReference, Type: System.String) (Syntax: 'param') - ValueConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - (Identity) - WhenNull: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: """") (Syntax: '""""') - 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) - BlockBody: - IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') - ExpressionBody: - null"); - - VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" - Block[B0] - Entry - Statements (0) - Next (Regular) Block[B1] - Block[B1] - Block - Predecessors: [B0] - Statements (0) - Jump if False (Regular) to Block[B3] - IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(st ... ?? """") { }') - Left: - IParameterReferenceOperation: param (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(st ... ?? """") { }') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ConstantValueNull(null: Null), IsImplicit) (Syntax: 'public C(st ... ?? """") { }') - Entering: {R1} - Next (Regular) Block[B2] - Block[B2] - Block - Predecessors: [B1] - Statements (0) - Next (Throw) Block[null] - IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(st ... ?? """") { }') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(st ... ?? """") { }') - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""param"", IsImplicit) (Syntax: 'public C(st ... ?? """") { }') - 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 - .locals {R1} - { - CaptureIds: [0] [2] - Block[B3] - Block - Predecessors: [B1] - Statements (1) - IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: ': base(param ?? """")') - Value: - IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: B, IsImplicit) (Syntax: ': base(param ?? """")') - Next (Regular) Block[B4] - Entering: {R2} - .locals {R2} - { - CaptureIds: [1] - Block[B4] - Block - Predecessors: [B3] - Statements (1) - IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'param') - Value: - IParameterReferenceOperation: param (OperationKind.ParameterReference, Type: System.String) (Syntax: 'param') - Jump if True (Regular) to Block[B6] - IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'param') - Operand: - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 'param') - Leaving: {R2} - Next (Regular) Block[B5] - Block[B5] - Block - Predecessors: [B4] - Statements (1) - IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'param') - Value: - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 'param') - Next (Regular) Block[B7] - Leaving: {R2} - } - Block[B6] - Block - Predecessors: [B4] - Statements (1) - IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: '""""') - Value: - ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: """") (Syntax: '""""') - Next (Regular) Block[B7] - Block[B7] - Block - Predecessors: [B5] [B6] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(param ?? """")') - Expression: - IInvocationOperation ( B..ctor(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(param ?? """")') - Instance Receiver: - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: B, IsImplicit) (Syntax: ': base(param ?? """")') - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'param ?? """"') - IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 'param ?? """"') - 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) - Next (Regular) Block[B8] - Leaving: {R1} - } - Block[B8] - Exit - Predecessors: [B7] - Statements (0)"); - } - } -} diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_INullCheckedParameters.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_INullCheckedParameters.cs new file mode 100644 index 0000000000000..49ffbeb216160 --- /dev/null +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_INullCheckedParameters.cs @@ -0,0 +1,2647 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.FlowAnalysis; +using Microsoft.CodeAnalysis.Operations; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)] + [Fact] + public void NullCheckedMethodDeclarationIOp() + { + var source = @" +public class C +{ + public void M(string input!) { } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: @" +IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... input!) { }') + BlockBody: + IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... input!) { }') + Left: + IParameterReferenceOperation: input (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public void ... input!) { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public void ... input!) { }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... input!) { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... input!) { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""input"", IsImplicit) (Syntax: 'public void ... input!) { }') + 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 +Block[B3] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_OneNullCheckedManyParams() + { + var source = @" +public class C +{ + public void M(string x, string y!) { } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... ing y!) { }') + BlockBody: + IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... ing y!) { }') + Left: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public void ... ing y!) { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public void ... ing y!) { }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... ing y!) { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... ing y!) { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""y"", IsImplicit) (Syntax: 'public void ... ing 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) + Initializer: + null +Block[B3] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_OneNullCheckedParamWithStringOpt() + { + var source = @" +public class C +{ + public void M(string name! = ""rose"") { } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... ""rose"") { }') + BlockBody: + IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... ""rose"") { }') + Left: + IParameterReferenceOperation: name (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public void ... ""rose"") { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public void ... ""rose"") { }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... ""rose"") { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... ""rose"") { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""name"", IsImplicit) (Syntax: 'public void ... ""rose"") { }') + 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 +Block[B3] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedOperator() + { + var source = @" +public class Box +{ + public static int operator+ (Box b!, Box c) + { + return 2; + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public stat ... }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IReturnOperation (OperationKind.Return, Type: null) (Syntax: 'return 2;') + ReturnedValue: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public stat ... }') + Left: + IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: Box, IsImplicit) (Syntax: 'public stat ... }') + Right: + ILiteralOperation (OperationKind.Literal, Type: Box, Constant: null, IsImplicit) (Syntax: 'public stat ... }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public stat ... }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public stat ... }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""b"", IsImplicit) (Syntax: 'public stat ... }') + 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 +Block[B3] - Block + Predecessors: [B1] + Statements (0) + Next (Return) Block[B4] + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') +Block[B4] - Exit + Predecessors: [B3] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedIndexedProperty() + { + // PROTOTYPE + var source = @" +public class C +{ + public string this[string index!] => null; +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> null') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'null') + ReturnedValue: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, Constant: null, IsImplicit) (Syntax: 'null') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Next (Return) Block[B2] + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, Constant: null, IsImplicit) (Syntax: 'null') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + (ImplicitReference) + Operand: + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedIndexedGetterSetter() + { + var source = @" +public class C +{ + private object[] items = {'h', ""hello""}; + public string this[object item!] + { + /**/get + { + return items[0].ToString(); + }/**/ + set + { + items[0] = value; + } + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'set ... }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'items[0] = value;') + Expression: + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Object) (Syntax: 'items[0] = value') + Left: + IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Object) (Syntax: 'items[0]') + Array reference: + IFieldReferenceOperation: System.Object[] C.items (OperationKind.FieldReference, Type: System.Object[]) (Syntax: 'items') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'items') + Indices(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') + Right: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: 'value') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + Operand: + IParameterReferenceOperation: value (OperationKind.ParameterReference, Type: System.String) (Syntax: 'value') + ExpressionBody: + null"); + var expected = @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'get ... }') + Left: + IParameterReferenceOperation: item (OperationKind.ParameterReference, Type: System.Object, IsImplicit) (Syntax: 'get ... }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'get ... }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'get ... }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'get ... }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""item"", IsImplicit) (Syntax: 'get ... }') + 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 +Block[B3] - Block + Predecessors: [B1] + Statements (0) + Next (Return) Block[B4] + IInvocationOperation (virtual System.String System.Object.ToString()) (OperationKind.Invocation, Type: System.String) (Syntax: 'items[0].ToString()') + Instance Receiver: + IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Object) (Syntax: 'items[0]') + Array reference: + IFieldReferenceOperation: System.Object[] C.items (OperationKind.FieldReference, Type: System.Object[]) (Syntax: 'items') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'items') + Indices(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') + Arguments(0) +Block[B4] - Exit + Predecessors: [B3] + Statements (0)"; + VerifyFlowGraphAndDiagnosticsForTest(source, expected, DiagnosticDescription.None, parseOptions: TestOptions.RegularPreview); + } + + [Fact] + public void TestIOp_NullCheckedIndexedGetterExpression() + { + var source = @" +public class C +{ + private object[] items = {'h', ""hello""}; + public string this[object item!] + { + /**/get => items[0].ToString();/**/ + set + { + items[0] = value; + } + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'set ... }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'items[0] = value;') + Expression: + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Object) (Syntax: 'items[0] = value') + Left: + IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Object) (Syntax: 'items[0]') + Array reference: + IFieldReferenceOperation: System.Object[] C.items (OperationKind.FieldReference, Type: System.Object[]) (Syntax: 'items') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'items') + Indices(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') + Right: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: 'value') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + Operand: + IParameterReferenceOperation: value (OperationKind.ParameterReference, Type: System.String) (Syntax: 'value') + ExpressionBody: + null"); + var expected = @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'get => item ... ToString();') + Left: + IParameterReferenceOperation: item (OperationKind.ParameterReference, Type: System.Object, IsImplicit) (Syntax: 'get => item ... ToString();') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'get => item ... ToString();') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'get => item ... ToString();') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'get => item ... ToString();') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""item"", IsImplicit) (Syntax: 'get => item ... ToString();') + 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 +Block[B3] - Block + Predecessors: [B1] + Statements (0) + Next (Return) Block[B4] + IInvocationOperation (virtual System.String System.Object.ToString()) (OperationKind.Invocation, Type: System.String) (Syntax: 'items[0].ToString()') + Instance Receiver: + IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Object) (Syntax: 'items[0]') + Array reference: + IFieldReferenceOperation: System.Object[] C.items (OperationKind.FieldReference, Type: System.Object[]) (Syntax: 'items') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'items') + Indices(1): + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') + Arguments(0) +Block[B4] - Exit + Predecessors: [B3] + Statements (0)"; + + VerifyFlowGraphAndDiagnosticsForTest(source, expected, DiagnosticDescription.None, parseOptions: TestOptions.RegularPreview); + } + + [Fact] + public void TestIOp_NullCheckedIndexedSetter() + { + var source = @" +public class C +{ + public string this[object item!] { /**/set { }/**/ } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'set { }') + BlockBody: + IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + ExpressionBody: + null"); + var expected = @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'set { }') + Left: + IParameterReferenceOperation: item (OperationKind.ParameterReference, Type: System.Object, IsImplicit) (Syntax: 'set { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'set { }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'set { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'set { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""item"", IsImplicit) (Syntax: 'set { }') + 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 +Block[B3] - Exit + Predecessors: [B1] + Statements (0)"; + VerifyFlowGraphAndDiagnosticsForTest(source, expected, DiagnosticDescription.None, parseOptions: TestOptions.RegularPreview); + } + + [Fact] + public void TestIOp_NullCheckedLambda() + { + var source = @" +using System; +class C +{ + public void M() + { + Func func1 = x! => x; + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... }') + BlockBody: + IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + Locals: Local_1: System.Func func1 + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'Func x;') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'Func x') + Declarators: + IVariableDeclaratorOperation (Symbol: System.Func func1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'func1 = x! => x') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= x! => x') + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 'x! => x') + Target: + IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: 'x! => x') + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'x') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'x') + ReturnedValue: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') + Initializer: + null + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Locals: [System.Func func1] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsImplicit) (Syntax: 'func1 = x! => x') + Left: + ILocalReferenceOperation: func1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Func, IsImplicit) (Syntax: 'func1 = x! => x') + Right: + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 'x! => x') + Target: + IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: 'x! => x') + { + Block[B0#A0] - Entry + Statements (0) + Next (Regular) Block[B1#A0] + Block[B1#A0] - Block + Predecessors: [B0#A0] + Statements (0) + Jump if False (Regular) to Block[B3#A0] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'x! => x') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'x! => x') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'x! => x') + Next (Regular) Block[B2#A0] + Block[B2#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'x! => x') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'x! => x') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'x! => 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) + Initializer: + null + Block[B3#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Return) Block[B4#A0] + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') + Block[B4#A0] - Exit + Predecessors: [B3#A0] + Statements (0) + } + Next (Regular) Block[B2] + Leaving: {R1} +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedInLambdaWithManyParameters() + { + var source = @" +using System; +class C +{ + public void M() + { + Func func1 = (x!, y) => x; + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... }') + BlockBody: + IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + Locals: Local_1: System.Func func1 + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'Func x;') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'Func x') + Declarators: + IVariableDeclaratorOperation (Symbol: System.Func func1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'func1 = (x!, y) => x') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= (x!, y) => x') + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: '(x!, y) => x') + Target: + IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: '(x!, y) => x') + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'x') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'x') + ReturnedValue: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') + Initializer: + null + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Locals: [System.Func func1] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsImplicit) (Syntax: 'func1 = (x!, y) => x') + Left: + ILocalReferenceOperation: func1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Func, IsImplicit) (Syntax: 'func1 = (x!, y) => x') + Right: + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: '(x!, y) => x') + Target: + IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: '(x!, y) => x') + { + Block[B0#A0] - Entry + Statements (0) + Next (Regular) Block[B1#A0] + Block[B1#A0] - Block + Predecessors: [B0#A0] + Statements (0) + Jump if False (Regular) to Block[B3#A0] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: '(x!, y) => x') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: '(x!, y) => x') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: '(x!, y) => x') + Next (Regular) Block[B2#A0] + Block[B2#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: '(x!, y) => x') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '(x!, y) => x') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: '(x!, y) => 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) + Initializer: + null + Block[B3#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Return) Block[B4#A0] + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') + Block[B4#A0] - Exit + Predecessors: [B3#A0] + Statements (0) + } + Next (Regular) Block[B2] + Leaving: {R1} +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedUnnamedVariableInLambda() + { + var source = @" +using System; +class C +{ + public void M() + { + Func func1 = _! => null; + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... }') + BlockBody: + IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + Locals: Local_1: System.Func func1 + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'Func null;') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'Func null') + Declarators: + IVariableDeclaratorOperation (Symbol: System.Func func1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'func1 = _! => null') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= _! => null') + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: '_! => null') + Target: + IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: '_! => null') + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'null') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'null') + ReturnedValue: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, Constant: null, IsImplicit) (Syntax: 'null') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + Operand: + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') + Initializer: + null + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Locals: [System.Func func1] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsImplicit) (Syntax: 'func1 = _! => null') + Left: + ILocalReferenceOperation: func1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Func, IsImplicit) (Syntax: 'func1 = _! => null') + Right: + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: '_! => null') + Target: + IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: '_! => null') + { + Block[B0#A0] - Entry + Statements (0) + Next (Regular) Block[B1#A0] + Block[B1#A0] - Block + Predecessors: [B0#A0] + Statements (0) + Jump if False (Regular) to Block[B3#A0] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: '_! => null') + Left: + IParameterReferenceOperation: _ (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: '_! => null') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: '_! => null') + Next (Regular) Block[B2#A0] + Block[B2#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: '_! => null') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '_! => null') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""_"", IsImplicit) (Syntax: '_! => 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) + Initializer: + null + Block[B3#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Return) Block[B4#A0] + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, Constant: null, IsImplicit) (Syntax: 'null') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + (ImplicitReference) + Operand: + ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') + Block[B4#A0] - Exit + Predecessors: [B3#A0] + Statements (0) + } + Next (Regular) Block[B2] + Leaving: {R1} +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedTwoExpressionBodyLambdas() + { + var source = @" +using System; +class C +{ + public Func M(string s1!) => s2! => s2 + s1; +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public Func ... => s2 + s1;') + BlockBody: + null + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> s2! => s2 + s1') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 's2! => s2 + s1') + ReturnedValue: + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 's2! => s2 + s1') + Target: + IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: 's2! => s2 + s1') + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 's2 + s1') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 's2 + s1') + ReturnedValue: + IBinaryOperation (BinaryOperatorKind.Add) (OperationKind.Binary, Type: System.String) (Syntax: 's2 + s1') + Left: + IParameterReferenceOperation: s2 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's2') + Right: + IParameterReferenceOperation: s1 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's1')"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public Func ... => s2 + s1;') + Left: + IParameterReferenceOperation: s1 (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public Func ... => s2 + s1;') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public Func ... => s2 + s1;') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public Func ... => s2 + s1;') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public Func ... => s2 + s1;') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s1"", IsImplicit) (Syntax: 'public Func ... => s2 + s1;') + 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 +Block[B3] - Block + Predecessors: [B1] + Statements (0) + Next (Return) Block[B4] + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 's2! => s2 + s1') + Target: + IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: 's2! => s2 + s1') + { + Block[B0#A0] - Entry + Statements (0) + Next (Regular) Block[B1#A0] + Block[B1#A0] - Block + Predecessors: [B0#A0] + Statements (0) + Jump if False (Regular) to Block[B3#A0] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 's2! => s2 + s1') + Left: + IParameterReferenceOperation: s2 (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 's2! => s2 + s1') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 's2! => s2 + s1') + Next (Regular) Block[B2#A0] + Block[B2#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 's2! => s2 + s1') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 's2! => s2 + s1') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s2"", IsImplicit) (Syntax: 's2! => s2 + s1') + 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 + Block[B3#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Return) Block[B4#A0] + IBinaryOperation (BinaryOperatorKind.Add) (OperationKind.Binary, Type: System.String) (Syntax: 's2 + s1') + Left: + IParameterReferenceOperation: s2 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's2') + Right: + IParameterReferenceOperation: s1 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's1') + Block[B4#A0] - Exit + Predecessors: [B3#A0] + Statements (0) + } +Block[B4] - Exit + Predecessors: [B3] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedLambdaInField() + { + var source = @" +using System; +class C +{ + Func func1 = x! => x; + public C() + { + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null) (Syntax: 'x! => x') + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'x') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'x') + ReturnedValue: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x')"); + + VerifyFlowGraph(compilation, node2, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (1) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsImplicit) (Syntax: '= x! => x') + Left: + IFieldReferenceOperation: System.Func C.func1 (OperationKind.FieldReference, Type: System.Func, IsImplicit) (Syntax: '= x! => x') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: '= x! => x') + Right: + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsImplicit) (Syntax: 'x! => x') + Target: + IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null) (Syntax: 'x! => x') + { + Block[B0#A0] - Entry + Statements (0) + Next (Regular) Block[B1#A0] + Block[B1#A0] - Block + Predecessors: [B0#A0] + Statements (0) + Jump if False (Regular) to Block[B3#A0] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'x! => x') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'x! => x') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'x! => x') + Next (Regular) Block[B2#A0] + Block[B2#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'x! => x') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'x! => x') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'x! => 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) + Initializer: + null + Block[B3#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Return) Block[B4#A0] + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') + Block[B4#A0] - Exit + Predecessors: [B3#A0] + Statements (0) + } + Next (Regular) Block[B2] +Block[B2] - Exit + Predecessors: [B1] + Statements (0) +"); + } + + [Fact] + public void TestIOp_NullCheckedLocalFunction() + { + var source = @" +class C +{ + public void M() + { + InnerM(""hello world""); + void InnerM(string x!) { } + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + ILocalFunctionOperation (Symbol: void InnerM(System.String x)) (OperationKind.LocalFunction, Type: null) (Syntax: 'void InnerM ... ing x!) { }') + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') + ReturnedValue: + null"); + VerifyFlowGraph(compilation, node2, @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Methods: [void InnerM(System.String x)] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hello world"");') + Expression: + IInvocationOperation (void InnerM(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hello world"")') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello world""') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello world"") (Syntax: '""hello world""') + 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) + Next (Regular) Block[B2] + Leaving: {R1} + + { void InnerM(System.String x) + + Block[B0#0R1] - Entry + Statements (0) + Next (Regular) Block[B1#0R1] + Block[B1#0R1] - Block + Predecessors: [B0#0R1] + Statements (0) + Jump if False (Regular) to Block[B3#0R1] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + Next (Regular) Block[B2#0R1] + Block[B2#0R1] - Block + Predecessors: [B1#0R1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'void InnerM ... ing 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) + Initializer: + null + Block[B3#0R1] - Exit + Predecessors: [B1#0R1] + Statements (0) + } +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedManyParamsInLocalFunction() + { + var source = @" +class C +{ + public void M() + { + InnerM(""hello"", ""world""); + void InnerM(string x!, string y!) { } + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + ILocalFunctionOperation (Symbol: void InnerM(System.String x, System.String y)) (OperationKind.LocalFunction, Type: null) (Syntax: 'void InnerM ... ing y!) { }') + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') + ReturnedValue: + null"); + + VerifyFlowGraph(compilation, node2, @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Methods: [void InnerM(System.String x, System.String y)] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hel ... ""world"");') + Expression: + IInvocationOperation (void InnerM(System.String x, System.String y)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hel ... , ""world"")') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello""') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') + 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: y) (OperationKind.Argument, Type: null) (Syntax: '""world""') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""world"") (Syntax: '""world""') + 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) + Next (Regular) Block[B2] + Leaving: {R1} + + { void InnerM(System.String x, System.String y) + + Block[B0#0R1] - Entry + Statements (0) + Next (Regular) Block[B1#0R1] + Block[B1#0R1] - Block + Predecessors: [B0#0R1] + Statements (0) + Jump if False (Regular) to Block[B3#0R1] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + Next (Regular) Block[B2#0R1] + Block[B2#0R1] - Block + Predecessors: [B1#0R1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'void InnerM ... ing 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) + Initializer: + null + Block[B3#0R1] - Block + Predecessors: [B1#0R1] + Statements (0) + Jump if False (Regular) to Block[B5#0R1] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + Left: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + Next (Regular) Block[B4#0R1] + Block[B4#0R1] - Block + Predecessors: [B3#0R1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'void InnerM ... ing y!) { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""y"", IsImplicit) (Syntax: 'void InnerM ... ing 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) + Initializer: + null + Block[B5#0R1] - Exit + Predecessors: [B3#0R1] + Statements (0) + } +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_OuterNullCheckedShadowedParameter() + { + var source = @" +class C +{ + public void M(string x!) + { + InnerM(""hello""); + void InnerM(string x) { } + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... }') + BlockBody: + IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hello"");') + Expression: + IInvocationOperation (void InnerM(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hello"")') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello""') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') + 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) + ILocalFunctionOperation (Symbol: void InnerM(System.String x)) (OperationKind.LocalFunction, Type: null) (Syntax: 'void InnerM ... ring x) { }') + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') + ReturnedValue: + null + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... }') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public void ... }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public void ... }') + Entering: {R1} + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public void ... }') + 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 +.locals {R1} +{ + Methods: [void InnerM(System.String x)] + Block[B3] - Block + Predecessors: [B1] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hello"");') + Expression: + IInvocationOperation (void InnerM(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hello"")') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello""') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') + 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) + Next (Regular) Block[B4] + Leaving: {R1} + + { void InnerM(System.String x) + + Block[B0#0R1] - Entry + Statements (0) + Next (Regular) Block[B1#0R1] + Block[B1#0R1] - Exit + Predecessors: [B0#0R1] + Statements (0) + } +} +Block[B4] - Exit + Predecessors: [B3] + Statements (0)"); + } + + [Fact] + public void TestIOp_InnerNullCheckedShadowedParameter() + { + var source = @" +class C +{ + public void M(string x) + { + InnerM(""hello""); + void InnerM(string x!) { } + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + ILocalFunctionOperation (Symbol: void InnerM(System.String x)) (OperationKind.LocalFunction, Type: null) (Syntax: 'void InnerM ... ing x!) { }') + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') + ReturnedValue: + null"); + VerifyFlowGraph(compilation, node2, @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Methods: [void InnerM(System.String x)] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'InnerM(""hello"");') + Expression: + IInvocationOperation (void InnerM(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'InnerM(""hello"")') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""hello""') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') + 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) + Next (Regular) Block[B2] + Leaving: {R1} + + { void InnerM(System.String x) + + Block[B0#0R1] - Entry + Statements (0) + Next (Regular) Block[B1#0R1] + Block[B1#0R1] - Block + Predecessors: [B0#0R1] + Statements (0) + Jump if False (Regular) to Block[B3#0R1] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + Next (Regular) Block[B2#0R1] + Block[B2#0R1] - Block + Predecessors: [B1#0R1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'void InnerM ... ing x!) { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'void InnerM ... ing 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) + Initializer: + null + Block[B3#0R1] - Exit + Predecessors: [B1#0R1] + Statements (0) + } +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedConstructor() + { + var source = @" +class C +{ + public C(string x!) { } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(string x!) { }') + Initializer: + null + BlockBody: + IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(string x!) { }') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(string x!) { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public C(string x!) { }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(string x!) { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(string x!) { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public C(string 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) + Initializer: + null +Block[B3] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedConstructorWithThisChain() + { + var source = @" +class C +{ + public C() { } + public C(string x!) : this() { } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(st ... this() { }') + Initializer: + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': this()') + Expression: + IInvocationOperation ( C..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': this()') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: ': this()') + Arguments(0) + BlockBody: + IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(st ... this() { }') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(st ... this() { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public C(st ... this() { }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(st ... this() { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(st ... this() { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public C(st ... this() { }') + 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 +Block[B3] - Block + Predecessors: [B1] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': this()') + Expression: + IInvocationOperation ( C..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': this()') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: ': this()') + Arguments(0) + Next (Regular) Block[B4] +Block[B4] - Exit + Predecessors: [B3] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedConstructorWithBaseChain() + { + var source = @" +class B +{ + public B(string y) { } +} +class C : B +{ + public C(string x!) : base(x) { } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(st ... base(x) { }') + Initializer: + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(x)') + Expression: + IInvocationOperation ( B..ctor(System.String y)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(x)') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: B, IsImplicit) (Syntax: ': base(x)') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: y) (OperationKind.Argument, Type: null) (Syntax: 'x') + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (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) + BlockBody: + IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(st ... base(x) { }') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(st ... base(x) { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public C(st ... base(x) { }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(st ... base(x) { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(st ... base(x) { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public C(st ... base(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) + Initializer: + null +Block[B3] - Block + Predecessors: [B1] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(x)') + Expression: + IInvocationOperation ( B..ctor(System.String y)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(x)') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: B, IsImplicit) (Syntax: ': base(x)') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: y) (OperationKind.Argument, Type: null) (Syntax: 'x') + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (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) + Next (Regular) Block[B4] +Block[B4] - Exit + Predecessors: [B3] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedConstructorWithFieldInitializers() + { + var source = @" +class C +{ + int y = 5; + public C(string x!) { y++; } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(st ... !) { y++; }') + Initializer: + null + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ y++; }') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'y++;') + Expression: + IIncrementOrDecrementOperation (Postfix) (OperationKind.Increment, Type: System.Int32) (Syntax: 'y++') + Target: + IFieldReferenceOperation: System.Int32 C.y (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'y') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'y') + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(st ... !) { y++; }') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(st ... !) { y++; }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public C(st ... !) { y++; }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(st ... !) { y++; }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(st ... !) { y++; }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public C(st ... !) { 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) + Initializer: + null +Block[B3] - Block + Predecessors: [B1] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'y++;') + Expression: + IIncrementOrDecrementOperation (Postfix) (OperationKind.Increment, Type: System.Int32) (Syntax: 'y++') + Target: + IFieldReferenceOperation: System.Int32 C.y (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'y') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'y') + Next (Regular) Block[B4] +Block[B4] - Exit + Predecessors: [B3] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedExpressionBodyMethod() + { + var source = @" +class C +{ + object Local(object arg!) => arg; +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'object Loca ... g!) => arg;') + BlockBody: + null + ExpressionBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> arg') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'arg') + ReturnedValue: + IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'arg')"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'object Loca ... g!) => arg;') + Left: + IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Object, IsImplicit) (Syntax: 'object Loca ... g!) => arg;') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'object Loca ... g!) => arg;') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'object Loca ... g!) => arg;') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'object Loca ... g!) => arg;') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""arg"", IsImplicit) (Syntax: 'object Loca ... g!) => arg;') + 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 +Block[B3] - Block + Predecessors: [B1] + Statements (0) + Next (Return) Block[B4] + IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'arg') +Block[B4] - Exit + Predecessors: [B3] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedIterator() + { + var source = @" +using System.Collections.Generic; +class C +{ + IEnumerable GetChars(string s!) + { + foreach (var c in s) + { + yield return c; + } + } + public static void Main() + { + C c = new C(); + IEnumerable e = c.GetChars(""hello""); + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(0); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'IEnumerable ... }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IForEachLoopOperation (LoopKind.ForEach, Continue Label Id: 0, Exit Label Id: 1) (OperationKind.Loop, Type: null) (Syntax: 'foreach (va ... }') + Locals: Local_1: System.Char c + LoopControlVariable: + IVariableDeclaratorOperation (Symbol: System.Char c) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'var') + Initializer: + null + Collection: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 's') + Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String) (Syntax: 's') + Body: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return c;') + ReturnedValue: + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.Char) (Syntax: 'c') + NextVariables(0) + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'IEnumerable ... }') + Left: + IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'IEnumerable ... }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'IEnumerable ... }') + Entering: {R1} + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'IEnumerable ... }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'IEnumerable ... }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s"", IsImplicit) (Syntax: 'IEnumerable ... }') + 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 +.locals {R1} +{ + CaptureIds: [0] + Block[B3] - Block + Predecessors: [B1] + Statements (1) + IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 's') + Value: + IInvocationOperation ( System.CharEnumerator System.String.GetEnumerator()) (OperationKind.Invocation, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + Instance Receiver: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 's') + Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + Operand: + IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String) (Syntax: 's') + Arguments(0) + Next (Regular) Block[B4] + Entering: {R2} {R3} + .try {R2, R3} + { + Block[B4] - Block + Predecessors: [B3] [B5] + Statements (0) + Jump if False (Regular) to Block[B9] + IInvocationOperation ( System.Boolean System.CharEnumerator.MoveNext()) (OperationKind.Invocation, Type: System.Boolean, IsImplicit) (Syntax: 's') + Instance Receiver: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + Arguments(0) + Finalizing: {R5} + Leaving: {R3} {R2} {R1} + Next (Regular) Block[B5] + Entering: {R4} + .locals {R4} + { + Locals: [System.Char c] + Block[B5] - Block + Predecessors: [B4] + Statements (2) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: null, IsImplicit) (Syntax: 'var') + Left: + ILocalReferenceOperation: c (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Char, IsImplicit) (Syntax: 'var') + Right: + IPropertyReferenceOperation: System.Char System.CharEnumerator.Current { get; } (OperationKind.PropertyReference, Type: System.Char, IsImplicit) (Syntax: 'var') + Instance Receiver: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return c;') + ReturnedValue: + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.Char) (Syntax: 'c') + Next (Regular) Block[B4] + Leaving: {R4} + } + } + .finally {R5} + { + Block[B6] - Block + Predecessors (0) + Statements (0) + Jump if True (Regular) to Block[B8] + IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 's') + Operand: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + Next (Regular) Block[B7] + Block[B7] - Block + Predecessors: [B6] + Statements (1) + IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 's') + Instance Receiver: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsImplicit) (Syntax: 's') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + (ImplicitReference) + Operand: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + Arguments(0) + Next (Regular) Block[B8] + Block[B8] - Block + Predecessors: [B6] [B7] + Statements (0) + Next (StructuredExceptionHandling) Block[null] + } +} +Block[B9] - Exit + Predecessors: [B4] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedIteratorInLocalFunction() + { + var source = @" +using System.Collections.Generic; +class Iterators +{ + void Use() + { + IEnumerable e = GetChars(""hello""); + IEnumerable GetChars(string s!) + { + foreach (var c in s) + { + yield return c; + } + } + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + ILocalFunctionOperation (Symbol: System.Collections.Generic.IEnumerable GetChars(System.String s)) (OperationKind.LocalFunction, Type: null) (Syntax: 'IEnumerable ... }') + IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IForEachLoopOperation (LoopKind.ForEach, Continue Label Id: 0, Exit Label Id: 1) (OperationKind.Loop, Type: null) (Syntax: 'foreach (va ... }') + Locals: Local_1: System.Char c + LoopControlVariable: + IVariableDeclaratorOperation (Symbol: System.Char c) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'var') + Initializer: + null + Collection: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 's') + Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: + IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String) (Syntax: 's') + Body: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return c;') + ReturnedValue: + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.Char) (Syntax: 'c') + NextVariables(0) + IReturnOperation (OperationKind.YieldBreak, Type: null, IsImplicit) (Syntax: '{ ... }') + ReturnedValue: + null"); + + VerifyFlowGraph(compilation, node2, @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Locals: [System.Collections.Generic.IEnumerable e] + Methods: [System.Collections.Generic.IEnumerable GetChars(System.String s)] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Collections.Generic.IEnumerable, IsImplicit) (Syntax: 'e = GetChars(""hello"")') + Left: + ILocalReferenceOperation: e (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Collections.Generic.IEnumerable, IsImplicit) (Syntax: 'e = GetChars(""hello"")') + Right: + IInvocationOperation (System.Collections.Generic.IEnumerable GetChars(System.String s)) (OperationKind.Invocation, Type: System.Collections.Generic.IEnumerable) (Syntax: 'GetChars(""hello"")') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: s) (OperationKind.Argument, Type: null) (Syntax: '""hello""') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""hello"") (Syntax: '""hello""') + 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) + Next (Regular) Block[B2] + Leaving: {R1} + + { System.Collections.Generic.IEnumerable GetChars(System.String s) + + Block[B0#0R1] - Entry + Statements (0) + Next (Regular) Block[B1#0R1] + Block[B1#0R1] - Block + Predecessors: [B0#0R1] + Statements (0) + Jump if False (Regular) to Block[B3#0R1] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'IEnumerable ... }') + Left: + IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'IEnumerable ... }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'IEnumerable ... }') + Entering: {R1#0R1} + Next (Regular) Block[B2#0R1] + Block[B2#0R1] - Block + Predecessors: [B1#0R1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'IEnumerable ... }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'IEnumerable ... }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s"", IsImplicit) (Syntax: 'IEnumerable ... }') + 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 + .locals {R1#0R1} + { + CaptureIds: [0] + Block[B3#0R1] - Block + Predecessors: [B1#0R1] + Statements (1) + IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 's') + Value: + IInvocationOperation ( System.CharEnumerator System.String.GetEnumerator()) (OperationKind.Invocation, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + Instance Receiver: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 's') + Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + Operand: + IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String) (Syntax: 's') + Arguments(0) + Next (Regular) Block[B4#0R1] + Entering: {R2#0R1} {R3#0R1} + .try {R2#0R1, R3#0R1} + { + Block[B4#0R1] - Block + Predecessors: [B3#0R1] [B5#0R1] + Statements (0) + Jump if False (Regular) to Block[B9#0R1] + IInvocationOperation ( System.Boolean System.CharEnumerator.MoveNext()) (OperationKind.Invocation, Type: System.Boolean, IsImplicit) (Syntax: 's') + Instance Receiver: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + Arguments(0) + Finalizing: {R5#0R1} + Leaving: {R3#0R1} {R2#0R1} {R1#0R1} + Next (Regular) Block[B5#0R1] + Entering: {R4#0R1} + .locals {R4#0R1} + { + Locals: [System.Char c] + Block[B5#0R1] - Block + Predecessors: [B4#0R1] + Statements (2) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: null, IsImplicit) (Syntax: 'var') + Left: + ILocalReferenceOperation: c (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Char, IsImplicit) (Syntax: 'var') + Right: + IPropertyReferenceOperation: System.Char System.CharEnumerator.Current { get; } (OperationKind.PropertyReference, Type: System.Char, IsImplicit) (Syntax: 'var') + Instance Receiver: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return c;') + ReturnedValue: + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.Char) (Syntax: 'c') + Next (Regular) Block[B4#0R1] + Leaving: {R4#0R1} + } + } + .finally {R5#0R1} + { + Block[B6#0R1] - Block + Predecessors (0) + Statements (0) + Jump if True (Regular) to Block[B8#0R1] + IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 's') + Operand: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + Next (Regular) Block[B7#0R1] + Block[B7#0R1] - Block + Predecessors: [B6#0R1] + Statements (1) + IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 's') + Instance Receiver: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsImplicit) (Syntax: 's') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + (ImplicitReference) + Operand: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.CharEnumerator, IsImplicit) (Syntax: 's') + Arguments(0) + Next (Regular) Block[B8#0R1] + Block[B8#0R1] - Block + Predecessors: [B6#0R1] [B7#0R1] + Statements (0) + Next (StructuredExceptionHandling) Block[null] + } + } + Block[B9#0R1] - Exit + Predecessors: [B4#0R1] + Statements (0) + } +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedEmptyIterator() + { + var source = @" +using System.Collections.Generic; +class C +{ + public static void Main() { } + static IEnumerable GetChars(string s!) + { + yield break; + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'static IEnu ... }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IReturnOperation (OperationKind.YieldBreak, Type: null) (Syntax: 'yield break;') + ReturnedValue: + null + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'static IEnu ... }') + Left: + IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'static IEnu ... }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'static IEnu ... }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'static IEnu ... }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'static IEnu ... }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s"", IsImplicit) (Syntax: 'static IEnu ... }') + 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 +Block[B3] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestIOp_NullCheckedEmptyIteratorReturningIEnumerator() + { + var source = @" +using System.Collections.Generic; +class C +{ + public static void Main() { } + static IEnumerator GetChars(string s!) + { + yield break; + } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'static IEnu ... }') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IReturnOperation (OperationKind.YieldBreak, Type: null) (Syntax: 'yield break;') + ReturnedValue: + null + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'static IEnu ... }') + Left: + IParameterReferenceOperation: s (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'static IEnu ... }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'static IEnu ... }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'static IEnu ... }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'static IEnu ... }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""s"", IsImplicit) (Syntax: 'static IEnu ... }') + 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 +Block[B3] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestNullCheckedLambdaWithMissingType() + { + var source = +@" +using System; +class Program +{ + public static void Main() + { + Func func = x! => x; + } +} + +"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + comp.MakeMemberMissing(WellKnownMember.System_ArgumentNullException__ctorString); + comp.MakeTypeMissing(WellKnownType.System_ArgumentNullException); + comp.VerifyDiagnostics( + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "x").WithArguments("System.ArgumentNullException", ".ctor").WithLocation(7, 37)); + var tree = comp.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + comp.VerifyOperationTree(node1, expectedOperationTree: @" +IMethodBodyOperation (OperationKind.MethodBody, Type: null, IsInvalid) (Syntax: 'public stat ... }') + BlockBody: + IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ ... }') + Locals: Local_1: System.Func func + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'Func x;') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'Func x') + Declarators: + IVariableDeclaratorOperation (Symbol: System.Func func) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: 'func = x! => x') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null, IsInvalid) (Syntax: '= x! => x') + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsInvalid, IsImplicit) (Syntax: 'x! => x') + Target: + IAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.AnonymousFunction, Type: null, IsInvalid) (Syntax: 'x! => x') + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'x') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: 'x') + ReturnedValue: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') + Initializer: + null + ExpressionBody: + null"); + VerifyFlowGraph(comp, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Locals: [System.Func func] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Func, IsInvalid, IsImplicit) (Syntax: 'func = x! => x') + Left: + ILocalReferenceOperation: func (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Func, IsInvalid, IsImplicit) (Syntax: 'func = x! => x') + Right: + IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Func, IsInvalid, IsImplicit) (Syntax: 'x! => x') + Target: + IFlowAnonymousFunctionOperation (Symbol: lambda expression) (OperationKind.FlowAnonymousFunction, Type: null, IsInvalid) (Syntax: 'x! => x') + { + Block[B0#A0] - Entry + Statements (0) + Next (Regular) Block[B1#A0] + Block[B1#A0] - Block + Predecessors: [B0#A0] + Statements (0) + Jump if False (Regular) to Block[B3#A0] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'x! => x') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsInvalid, IsImplicit) (Syntax: 'x! => x') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsInvalid, IsImplicit) (Syntax: 'x! => x') + Next (Regular) Block[B2#A0] + Block[B2#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Throw) Block[null] + IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'x! => x') + Children(1): + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsInvalid, IsImplicit) (Syntax: 'x! => x') + Block[B3#A0] - Block + Predecessors: [B1#A0] + Statements (0) + Next (Return) Block[B4#A0] + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String) (Syntax: 'x') + Block[B4#A0] - Exit + Predecessors: [B3#A0] + Statements (0) + } + Next (Regular) Block[B2] + Leaving: {R1} +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestNullCheckedLocalFunctionWithMissingType() + { + var source = +@" +class Program +{ + public static void Main() + { + M(""ok""); + void M(string x!) { } + } +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + comp.MakeMemberMissing(WellKnownMember.System_ArgumentNullException__ctorString); + comp.MakeTypeMissing(WellKnownType.System_ArgumentNullException); + comp.VerifyDiagnostics( + // (7,23): error CS0656: Missing compiler required member 'System.ArgumentNullException..ctor' + // void M(string x!) { } + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "x").WithArguments("System.ArgumentNullException", ".ctor").WithLocation(7, 23)); + var tree = comp.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + var node2 = tree.GetRoot().DescendantNodes().OfType().Single(); + comp.VerifyOperationTree(node1, expectedOperationTree: @" + ILocalFunctionOperation (Symbol: void M(System.String x)) (OperationKind.LocalFunction, Type: null, IsInvalid) (Syntax: 'void M(string x!) { }') + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '{ }') + ReturnedValue: + null"); + VerifyFlowGraph(comp, node2, @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Methods: [void M(System.String x)] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'M(""ok"");') + Expression: + IInvocationOperation (void M(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'M(""ok"")') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '""ok""') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""ok"") (Syntax: '""ok""') + 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) + Next (Regular) Block[B2] + Leaving: {R1} + + { void M(System.String x) + + Block[B0#0R1] - Entry + Statements (0) + Next (Regular) Block[B1#0R1] + Block[B1#0R1] - Block + Predecessors: [B0#0R1] + Statements (0) + Jump if False (Regular) to Block[B3#0R1] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') + Left: + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') + Next (Regular) Block[B2#0R1] + Block[B2#0R1] - Block + Predecessors: [B1#0R1] + Statements (0) + Next (Throw) Block[null] + IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') + Children(1): + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsInvalid, IsImplicit) (Syntax: 'void M(string x!) { }') + Block[B3#0R1] - Exit + Predecessors: [B1#0R1] + Statements (0) + } +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestNullCheckedMethodWithMissingHasValue() + { + var source = +@" +class Program +{ + public void Method(int? x!) { } +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + comp.MakeMemberMissing(SpecialMember.System_Nullable_T_get_HasValue); + comp.VerifyDiagnostics( + // (4,29): warning CS8721: Nullable value type 'int?' is null-checked and will throw if null. + // public void Method(int? x!) { } + Diagnostic(ErrorCode.WRN_NullCheckingOnNullableValueType, "x").WithArguments("int?").WithLocation(4, 29)); + var tree = comp.SyntaxTrees.Single(); + var node = tree.GetRoot().DescendantNodes().OfType().Single(); + comp.VerifyOperationTree(node, expectedOperationTree: @" + IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'public void ... nt? x!) { }') + BlockBody: + IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + ExpressionBody: + null"); + VerifyFlowGraph(comp, node, @" + Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if True (Regular) to Block[B3] + IInvalidOperation (OperationKind.Invalid, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... nt? x!) { }') + Children(1): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32?, IsImplicit) (Syntax: 'public void ... nt? x!) { }') + Next (Regular) Block[B2] + Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... nt? x!) { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... nt? x!) { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""x"", IsImplicit) (Syntax: 'public void ... nt? 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) + Initializer: + null + Block[B3] - Exit + Predecessors: [B1] + Statements (0)"); + } + + [Fact] + public void TestNoNullChecksInBlockOperation() + { + // PROTOTYPE - Nullchecks currently included when only BlockSyntax is bound. Falls into VisitMethodBody instead of VisitBlock. + var source = @" +public class C +{ + public void M(string input!) + /**/{ }/**/ +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().Single(); + + compilation.VerifyOperationTree(node1, expectedOperationTree: @" +IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') +"); + var output = @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public void ... */{ }') + Left: + IParameterReferenceOperation: input (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public void ... */{ }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public void ... */{ }') + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public void ... */{ }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public void ... */{ }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""input"", IsImplicit) (Syntax: 'public void ... */{ }') + 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 +Block[B3] - Exit + Predecessors: [B1] + Statements (0)"; + VerifyFlowGraphAndDiagnosticsForTest(compilation, expectedFlowGraph: output, DiagnosticDescription.None); + } + + [Fact] + public void TestNullCheckedBaseCallOrdering() + { + var source = @" +public class B +{ + public B(string x) { } +} +public class C : B +{ + public C(string param!) : base(param ?? """") { } +}"; + var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var node1 = tree.GetRoot().DescendantNodes().OfType().ElementAt(1); + compilation.VerifyOperationTree(node1, expectedOperationTree: @" +IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C(st ... ?? """") { }') + Initializer: + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(param ?? """")') + Expression: + IInvocationOperation ( B..ctor(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(param ?? """")') + Instance Receiver: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: B, IsImplicit) (Syntax: ': base(param ?? """")') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'param ?? """"') + ICoalesceOperation (OperationKind.Coalesce, Type: System.String) (Syntax: 'param ?? """"') + Expression: + IParameterReferenceOperation: param (OperationKind.ParameterReference, Type: System.String) (Syntax: 'param') + ValueConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + WhenNull: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: """") (Syntax: '""""') + 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) + BlockBody: + IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }') + ExpressionBody: + null"); + + VerifyFlowGraph(compilation, node1, expectedFlowGraph: @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (0) + Jump if False (Regular) to Block[B3] + IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: 'public C(st ... ?? """") { }') + Left: + IParameterReferenceOperation: param (OperationKind.ParameterReference, Type: System.String, IsImplicit) (Syntax: 'public C(st ... ?? """") { }') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: null, IsImplicit) (Syntax: 'public C(st ... ?? """") { }') + Entering: {R1} + Next (Regular) Block[B2] +Block[B2] - Block + Predecessors: [B1] + Statements (0) + Next (Throw) Block[null] + IObjectCreationOperation (Constructor: System.ArgumentNullException..ctor(System.String paramName)) (OperationKind.ObjectCreation, Type: System.ArgumentNullException, IsImplicit) (Syntax: 'public C(st ... ?? """") { }') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: paramName) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'public C(st ... ?? """") { }') + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""param"", IsImplicit) (Syntax: 'public C(st ... ?? """") { }') + 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 +.locals {R1} +{ + CaptureIds: [0] [2] + Block[B3] - Block + Predecessors: [B1] + Statements (1) + IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: ': base(param ?? """")') + Value: + IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: B, IsImplicit) (Syntax: ': base(param ?? """")') + Next (Regular) Block[B4] + Entering: {R2} + .locals {R2} + { + CaptureIds: [1] + Block[B4] - Block + Predecessors: [B3] + Statements (1) + IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'param') + Value: + IParameterReferenceOperation: param (OperationKind.ParameterReference, Type: System.String) (Syntax: 'param') + Jump if True (Regular) to Block[B6] + IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'param') + Operand: + IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 'param') + Leaving: {R2} + Next (Regular) Block[B5] + Block[B5] - Block + Predecessors: [B4] + Statements (1) + IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'param') + Value: + IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 'param') + Next (Regular) Block[B7] + Leaving: {R2} + } + Block[B6] - Block + Predecessors: [B4] + Statements (1) + IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: '""""') + Value: + ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: """") (Syntax: '""""') + Next (Regular) Block[B7] + Block[B7] - Block + Predecessors: [B5] [B6] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(param ?? """")') + Expression: + IInvocationOperation ( B..ctor(System.String x)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(param ?? """")') + Instance Receiver: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: B, IsImplicit) (Syntax: ': base(param ?? """")') + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'param ?? """"') + IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 'param ?? """"') + 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) + Next (Regular) Block[B8] + Leaving: {R1} +} +Block[B8] - Exit + Predecessors: [B7] + Statements (0)"); + } + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullCheckedParameterTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullCheckedParameterTests.cs index 456d956965a59..143ebf18b961e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullCheckedParameterTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullCheckedParameterTests.cs @@ -1,4 +1,6 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System.Diagnostics; using System.Linq; @@ -210,7 +212,7 @@ void M2(__arglist!) { } }"; - CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( // (8,22): error CS1003: Syntax error, ',' expected // void M2(__arglist!) Diagnostic(ErrorCode.ERR_SyntaxError, "!").WithArguments(",", "!").WithLocation(8, 22)); @@ -337,8 +339,8 @@ public void M() .DescendantNodes() .OfType() .Single(); - var lambdaSymbol = (LambdaSymbol)model.GetSymbolInfo(node).Symbol; - Assert.True(((SourceParameterSymbol)lambdaSymbol.Parameters[0]).IsNullChecked); + var methodSymbol = (IMethodSymbol)model.GetSymbolInfo(node).Symbol; + Assert.True(methodSymbol.Parameters[0].IsNullChecked); } [Fact] @@ -364,9 +366,9 @@ public void M() .DescendantNodes() .OfType() .Single(); - var lambdaSymbol = (LambdaSymbol)model.GetSymbolInfo(node).Symbol; - Assert.True(((SourceParameterSymbol)lambdaSymbol.Parameters[0]).IsNullChecked); - Assert.False(((SourceParameterSymbol)lambdaSymbol.Parameters[1]).IsNullChecked); + var methodSymbol = (IMethodSymbol)model.GetSymbolInfo(node).Symbol; + Assert.True(methodSymbol.Parameters[0].IsNullChecked); + Assert.False(methodSymbol.Parameters[1].IsNullChecked); } [Fact] @@ -392,8 +394,8 @@ public void M() .DescendantNodes() .OfType() .Single(); - LambdaSymbol lambdaSymbol = (LambdaSymbol)model.GetSymbolInfo(node).Symbol; - Assert.True(((SourceParameterSymbol)lambdaSymbol.Parameters[0]).IsNullChecked); + var methodSymbol = (IMethodSymbol)model.GetSymbolInfo(node).Symbol; + Assert.True(methodSymbol.Parameters[0].IsNullChecked); } [Fact] @@ -437,8 +439,8 @@ public void M() .DescendantNodes() .OfType() .Single(); - LambdaSymbol lambdaSymbol = (LambdaSymbol)model.GetSymbolInfo(node).Symbol; - Assert.True(((SourceParameterSymbol)lambdaSymbol.Parameters[0]).IsNullChecked); + var methodSymbol = (IMethodSymbol)model.GetSymbolInfo(node).Symbol; + Assert.True(methodSymbol.Parameters[0].IsNullChecked); } [Fact] @@ -464,9 +466,9 @@ public void M() .DescendantNodes() .OfType() .Single(); - LambdaSymbol lambdaSymbol = (LambdaSymbol)model.GetSymbolInfo(node).Symbol; - Assert.True(((SourceParameterSymbol)lambdaSymbol.Parameters[0]).IsNullChecked); - Assert.False(((SourceParameterSymbol)lambdaSymbol.Parameters[1]).IsNullChecked); + var methodSymbol = (IMethodSymbol)model.GetSymbolInfo(node).Symbol; + Assert.True(methodSymbol.Parameters[0].IsNullChecked); + Assert.False(methodSymbol.Parameters[1].IsNullChecked); } [Fact] @@ -492,9 +494,9 @@ public void M() .DescendantNodes() .OfType() .Single(); - LambdaSymbol lambdaSymbol = (LambdaSymbol)model.GetSymbolInfo(node).Symbol; - Assert.True(((SourceParameterSymbol)lambdaSymbol.Parameters[0]).IsNullChecked); - Assert.True(((SourceParameterSymbol)lambdaSymbol.Parameters[1]).IsNullChecked); + var methodSymbol = (IMethodSymbol)model.GetSymbolInfo(node).Symbol; + Assert.True(methodSymbol.Parameters[0].IsNullChecked); + Assert.True(methodSymbol.Parameters[1].IsNullChecked); } [Fact] @@ -520,8 +522,8 @@ public void M() .DescendantNodes() .OfType() .Single(); - LambdaSymbol lambdaSymbol = (LambdaSymbol)model.GetSymbolInfo(node).Symbol; - Assert.True(((SourceParameterSymbol)lambdaSymbol.Parameters[0]).IsNullChecked); + var methodSymbol = (IMethodSymbol)model.GetSymbolInfo(node).Symbol; + Assert.True(methodSymbol.Parameters[0].IsNullChecked); } [Fact] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs index 8836bb721f44b..bfae864efaf5a 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs @@ -7241,7 +7241,7 @@ public void TestOptParamMethodDeclarationWithNullValidation() } } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestOptParamMethodDeclarationWithNullValidationNoSpaces() { UsingStatement(@"void M(string name!=null) { }", options: TestOptions.RegularPreview, expectedErrors: new DiagnosticDescription[] @@ -7319,7 +7319,7 @@ public void TestNullCheckedArgList() } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestNullCheckedArgWithLeadingSpace() { UsingStatement(@"void M(string name !=null) { }", options: TestOptions.RegularPreview, expectedErrors: new DiagnosticDescription[] @@ -7365,7 +7365,7 @@ public void TestNullCheckedArgWithLeadingSpace() } } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestNullCheckedArgWithLeadingNewLine() { UsingStatement(@"void M(string name @@ -7412,7 +7412,7 @@ public void TestNullCheckedArgWithLeadingNewLine() } } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestNullCheckedArgWithTrailingSpace() { UsingStatement(@"void M(string name!= null) { }", options: TestOptions.RegularPreview, expectedErrors: new DiagnosticDescription[] @@ -7458,7 +7458,7 @@ public void TestNullCheckedArgWithTrailingSpace() } } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestNullCheckedArgWithTrailingNewLine() { UsingStatement(@"void M(string name!= @@ -7505,7 +7505,7 @@ public void TestNullCheckedArgWithTrailingNewLine() } } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestNullCheckedMethod() { UsingTree(@" @@ -7552,7 +7552,7 @@ public void M(string x!) { } } } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestNullCheckedConstructor() { UsingTree(@" @@ -7669,7 +7669,7 @@ class Box N(SyntaxKind.EndOfFileToken); } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestAnonymousDelegateNullChecking() { // PROTOTYPE : During semantics, make sure this causes an error @@ -7743,6 +7743,8 @@ public void TestAnonymousDelegateNullChecking() } N(SyntaxKind.SemicolonToken); } + } + [Fact, WorkItem(30102, "https://github.com/dotnet/roslyn/issues/30102")] public void IncompleteGenericInBaseList1() { diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs index 19779cff4517c..b53e8e968b9f0 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs @@ -771,7 +771,7 @@ public void TestNullCheckedSingleParamInParens() } } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestNullCheckedSingleParamNoSpaces() { UsingDeclaration("Func func1 = x!=>x;", options: TestOptions.RegularPreview, expectedErrors: new DiagnosticDescription[] @@ -1032,7 +1032,7 @@ public void TestManyNullCheckedTypedParams() } } - [Fact] + [Fact(Skip = "PROTOTYPE(BangBang)")] public void TestNullCheckedNoParams() { UsingDeclaration("Func func1 = (!) => 42;", options: TestOptions.RegularPreview, expectedErrors: new DiagnosticDescription[] diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs index 20c64306110b9..b75ac68dde073 100644 --- a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs @@ -1482,8 +1482,7 @@ private void VisitNullChecks(IOperation operation, ImmutableArray constantValue = default(Optional); - var paramReference = new ParameterReferenceOperation(parameter, semanticModel, syntax, parameter.Type, constantValue, isImplicit: true); + var paramReference = new ParameterReferenceOperation(parameter, semanticModel, syntax, parameter.Type, constantValue: null, isImplicit: true); var boolType = _compilation.GetSpecialType(SpecialType.System_Boolean); IOperation conditionOp; @@ -1499,7 +1498,7 @@ private ConditionalOperation GenerateNullCheckForParameter(IParameterSymbol para semanticModel, syntax, boolType, - constantValue, + constantValue: null, isImplicit: true), isLifted: false, isChecked: false, @@ -1507,7 +1506,7 @@ private ConditionalOperation GenerateNullCheckForParameter(IParameterSymbol para semanticModel, syntax, boolType, - constantValue, + constantValue: null, isImplicit: true); } else @@ -1522,7 +1521,7 @@ private ConditionalOperation GenerateNullCheckForParameter(IParameterSymbol para semanticModel, syntax, boolType, - constantValue, + constantValue: null, isImplicit: true), isLifted: false, isChecked: false, @@ -1530,7 +1529,7 @@ private ConditionalOperation GenerateNullCheckForParameter(IParameterSymbol para semanticModel, syntax, boolType, - constantValue, + constantValue: null, isImplicit: true); } } @@ -1548,12 +1547,12 @@ private ConditionalOperation GenerateNullCheckForParameter(IParameterSymbol para semanticModel, syntax, boolType, - constantValue, + constantValue: null, isImplicit: true); } - var paramNameLiteral = new LiteralOperation(semanticModel, syntax, _compilation.GetSpecialType(SpecialType.System_String), parameter.Name, isImplicit: true); - var argumentNullExceptionMethod = (IMethodSymbol)_compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_ArgumentNullException__ctorString); + var paramNameLiteral = new LiteralOperation(semanticModel, syntax, _compilation.GetSpecialType(SpecialType.System_String), ConstantValue.Create(parameter.Name), isImplicit: true); + var argumentNullExceptionMethod = (IMethodSymbol)_compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_ArgumentNullException__ctorString)?.GetISymbol(); var argumentNullExceptionType = argumentNullExceptionMethod?.ContainingType; // Occurs when a member is missing. @@ -1565,7 +1564,7 @@ private ConditionalOperation GenerateNullCheckForParameter(IParameterSymbol para semanticModel, syntax, argumentNullExceptionType, - constantValue, + constantValue: null, isImplicit: true); } else @@ -1586,7 +1585,7 @@ private ConditionalOperation GenerateNullCheckForParameter(IParameterSymbol para semanticModel, syntax, argumentNullExceptionType, - constantValue, + constantValue: null, isImplicit: true); } @@ -1596,14 +1595,14 @@ private ConditionalOperation GenerateNullCheckForParameter(IParameterSymbol para semanticModel, syntax, argumentNullExceptionType, - constantValue, + constantValue: null, isImplicit: true), semanticModel, syntax, type: null, - constantValue, + constantValue: null, isImplicit: true); - return new ConditionalOperation(conditionOp, whenTrue, whenFalse: null, isRef: false, semanticModel, syntax, boolType, constantValue, isImplicit: true); + return new ConditionalOperation(conditionOp, whenTrue, whenFalse: null, isRef: false, semanticModel, syntax, boolType, constantValue: null, isImplicit: true); } private void VisitMethodBodyBaseOperation(IMethodBodyBaseOperation operation) diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 001ea1d7b9c3a..561c91cddc9b6 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -9,6 +9,7 @@ Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.GetAnalysisResultAsy Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.GetAnalysisResultAsync(Microsoft.CodeAnalysis.AdditionalText file, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task Microsoft.CodeAnalysis.Diagnostics.Telemetry.AnalyzerTelemetryInfo.AdditionalFileActionsCount.get -> int Microsoft.CodeAnalysis.Diagnostics.Telemetry.AnalyzerTelemetryInfo.AdditionalFileActionsCount.set -> void +Microsoft.CodeAnalysis.IParameterSymbol.IsNullChecked.get -> bool const Microsoft.CodeAnalysis.WellKnownMemberNames.TopLevelStatementsEntryPointMethodName = "
$" -> string const Microsoft.CodeAnalysis.WellKnownMemberNames.TopLevelStatementsEntryPointTypeName = "$" -> string Microsoft.CodeAnalysis.Operations.IPatternOperation.NarrowedType.get -> Microsoft.CodeAnalysis.ITypeSymbol diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index 77a1480ead2ab..84b73bf67d1ad 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3476,7 +3476,6 @@ static WellKnownMembers() 1, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_String, // Argument - (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type // System_Runtime_CompilerServices_NativeIntegerAttribute__ctor (byte)MemberFlags.Constructor, // Flags diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs index 418020de912f7..d4706ba9252f4 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -615,11 +615,12 @@ internal static class WellKnownTypes "System.InvalidOperationException", "System.Runtime.CompilerServices.SwitchExpressionException", "System.Collections.Generic.IEqualityComparer`1", - "System.ArgumentNullException", "System.Runtime.CompilerServices.NativeIntegerAttribute", "System.Runtime.CompilerServices.IsExternalInit", "System.Runtime.InteropServices.OutAttribute", + + "System.ArgumentNullException", }; private readonly static Dictionary s_nameToTypeIdMap = new Dictionary((int)Count); @@ -673,7 +674,7 @@ private static void AssertEnumAndTableInSync() typeIdName = typeIdName.Substring(0, separator); } - Debug.Assert(name == typeIdName, "Enum name and type name must match"); + Debug.Assert(name == typeIdName, $"Enum name ({typeIdName}) and type name ({name}) must match at {i}"); } Debug.Assert((int)WellKnownType.ExtSentinel == 255);