diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.NamespaceOrTypeOrAliasSymbolWithAnnotations.cs b/src/Compilers/CSharp/Portable/Binder/Binder.NamespaceOrTypeOrAliasSymbolWithAnnotations.cs index 3ae271a9e6eda..c8e22fc4e1ce7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.NamespaceOrTypeOrAliasSymbolWithAnnotations.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.NamespaceOrTypeOrAliasSymbolWithAnnotations.cs @@ -15,7 +15,7 @@ internal struct NamespaceOrTypeOrAliasSymbolWithAnnotations private NamespaceOrTypeOrAliasSymbolWithAnnotations(TypeSymbolWithAnnotations type) { - Debug.Assert(!type.IsNull); + Debug.Assert(type.HasType); _type = type; _symbol = null; _isNullableEnabled = false; // Not meaningful for a TypeSymbolWithAnnotations, it already baked the fact into its content. @@ -31,10 +31,10 @@ private NamespaceOrTypeOrAliasSymbolWithAnnotations(Symbol symbol, bool isNullab internal TypeSymbolWithAnnotations Type => _type; internal Symbol Symbol => _symbol ?? Type.TypeSymbol; - internal bool IsType => !_type.IsNull; + internal bool IsType => !_type.IsDefault; internal bool IsAlias => _symbol?.Kind == SymbolKind.Alias; internal NamespaceOrTypeSymbol NamespaceOrTypeSymbol => Symbol as NamespaceOrTypeSymbol; - internal bool IsDefault => _type.IsNull && _symbol is null; + internal bool IsDefault => !_type.HasType && _symbol is null; internal bool IsNullableEnabled { diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs index 44336f5de08b3..4ce3903ef64ac 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs @@ -954,7 +954,7 @@ private bool CheckPropertyValueKind(SyntaxNode node, BoundExpression expr, BindV // change from Dev10 which reports this error for struct types only, // not for type parameters constrained to "struct". - Debug.Assert(!propertySymbol.Type.IsNull); + Debug.Assert(propertySymbol.Type.HasType); Error(diagnostics, ErrorCode.ERR_ReturnNotLValue, expr.Syntax, propertySymbol); } else @@ -1665,7 +1665,7 @@ private static void ReportReadOnlyFieldError(FieldSymbol field, SyntaxNode node, { Debug.Assert((object)field != null); Debug.Assert(RequiresAssignableVariable(kind)); - Debug.Assert(!field.Type.IsNull); + Debug.Assert(field.Type.HasType); // It's clearer to say that the address can't be taken than to say that the field can't be modified // (even though the latter message gives more explanation of why). diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs index 1fbacddf13d28..a85cd53a1599e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs @@ -226,7 +226,7 @@ private void ValidateTypeForAttributeParameters(ImmutableArray foreach (var parameter in parameters) { var paramType = parameter.Type; - Debug.Assert(!paramType.IsNull); + Debug.Assert(paramType.HasType); if (!paramType.TypeSymbol.IsValidAttributeParameterType(Compilation)) { diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index a5ec34756cdce..86283e62beb12 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -75,7 +75,7 @@ protected BoundExpression CreateConversion( sourceTuple.Type, sourceTuple.Arguments, sourceTuple.Type, // same type to keep original element names - sourceTuple.HasErrors); + sourceTuple.HasErrors).WithSuppression(sourceTuple.IsSuppressed); } // We need to preserve any conversion that changes the type (even identity conversions, like object->dynamic), diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs index db92d81954936..c45f45942d801 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs @@ -500,7 +500,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder t.IsNull)) + if (typesBuilder.Any(t => !t.HasType)) { typesBuilder.Free(); locationsBuilder.Free(); @@ -721,7 +721,7 @@ private DeconstructionVariable BindDeconstructionVariables( bool isConst = false; AliasSymbol alias; var declType = BindVariableType(component.Designation, diagnostics, component.Type, ref isConst, out isVar, out alias); - Debug.Assert(isVar == declType.IsNull); + Debug.Assert(isVar == !declType.HasType); if (component.Designation.Kind() == SyntaxKind.ParenthesizedVariableDesignation && !isVar) { // An explicit is not allowed with a parenthesized designation @@ -819,7 +819,7 @@ private BoundExpression BindDeconstructionVariable( // might own nested scope. var hasErrors = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics); - if (!declType.IsNull) + if (declType.HasType) { return new BoundLocal(syntax, localSymbol, BoundLocalDeclarationKind.WithExplicitType, constantValueOpt: null, isNullableUnknown: false, type: declType.TypeSymbol, hasErrors: hasErrors); } @@ -839,7 +839,7 @@ private BoundExpression BindDeconstructionVariable( BoundThisReference receiver = ThisReference(designation, this.ContainingType, hasErrors: false, wasCompilerGenerated: true); - if (!declType.IsNull) + if (declType.HasType) { var fieldType = field.GetFieldType(this.FieldsBeingBound); Debug.Assert(TypeSymbol.Equals(declType.TypeSymbol, fieldType.TypeSymbol, TypeCompareKind.ConsiderEverything2)); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index c5bc69fb8e43a..5ac61eaab2e5c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -692,7 +692,7 @@ private BoundExpression BindDeclarationExpression(DeclarationExpressionSyntax no /// private BoundExpression BindDeclarationVariables(TypeSymbolWithAnnotations declType, VariableDesignationSyntax node, CSharpSyntaxNode syntax, DiagnosticBag diagnostics) { - declType = declType.IsNull ? TypeSymbolWithAnnotations.Create(CreateErrorType("var")) : declType; + declType = declType.HasType ? declType : TypeSymbolWithAnnotations.Create(CreateErrorType("var")); switch (node.Kind()) { case SyntaxKind.SingleVariableDesignation: @@ -799,7 +799,7 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost var elementType = TypeSymbolWithAnnotations.Create(boundArgument.Type); elementTypes.Add(elementType); - if (elementType.IsNull) + if (!elementType.HasType) { hasNaturalType = false; } @@ -2237,7 +2237,7 @@ private void GenerateExplicitConversionErrorsForTupleLiteralArguments( /// private BoundExpression BindExplicitNullableCastFromNonNullable(ExpressionSyntax node, BoundExpression operand, TypeSymbolWithAnnotations targetType, DiagnosticBag diagnostics) { - Debug.Assert(!targetType.IsNull && targetType.IsNullableType()); + Debug.Assert(targetType.HasType && targetType.IsNullableType()); Debug.Assert((object)operand.Type != null && !operand.Type.IsNullableType()); // Section 6.2.3 of the spec only applies when the non-null version of the types involved have a @@ -2491,7 +2491,7 @@ private BoundExpression BindOutDeclarationArgument(DeclarationExpressionSyntax d bool isConst = false; AliasSymbol alias; var declType = BindVariableType(designation, diagnostics, typeSyntax, ref isConst, out isVar, out alias); - Debug.Assert(isVar == declType.IsNull); + Debug.Assert(isVar != declType.HasType); return new BoundDiscardExpression(declarationExpression, declType.TypeSymbol); } @@ -2744,7 +2744,7 @@ private void CoerceArguments( else if (argument.Kind == BoundKind.DiscardExpression && !argument.HasExpressionType()) { TypeSymbolWithAnnotations parameterType = GetCorrespondingParameterType(ref result, parameters, arg); - Debug.Assert(!parameterType.IsNull); + Debug.Assert(parameterType.HasType); arguments[arg] = ((BoundDiscardExpression)argument).SetInferredType(parameterType); } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs index 6e094f6c1cc2b..8c47a6c284076 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs @@ -228,7 +228,7 @@ private UnboundLambda BindAnonymousFunction(CSharpSyntaxNode syntax, DiagnosticB foreach (var type in types) { // UNDONE: Where do we report improper use of pointer types? - if (!type.IsNull && type.IsStatic) + if (type.HasType && type.IsStatic) { Error(diagnostics, ErrorCode.ERR_ParameterIsStaticClass, syntax, type.TypeSymbol); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index 8511666456a71..55bcad3eecfd9 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -377,7 +377,7 @@ private BoundTypeExpression BindPatternType( Debug.Assert(inputType != (object)null); Debug.Assert(!typeSyntax.IsVar); // if the syntax had `var`, it would have been parsed as a var pattern. TypeSymbolWithAnnotations declType = BindType(typeSyntax, diagnostics, out AliasSymbol aliasOpt); - Debug.Assert(!declType.IsNull); + Debug.Assert(declType.HasType); Debug.Assert(typeSyntax.Kind() != SyntaxKind.NullableType); // the syntax does not permit nullable annotations BoundTypeExpression boundDeclType = new BoundTypeExpression(typeSyntax, aliasOpt, inferredType: false, type: declType.TypeSymbol); hasErrors |= CheckValidPatternType(typeSyntax, inputType, declType.TypeSymbol, patternTypeWasInSource: true, diagnostics: diagnostics); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index b7b9771466752..196528f1fa70f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -728,7 +728,7 @@ declarationNode is VariableDesignationSyntax || // we want to treat the declaration as an explicitly typed declaration. TypeSymbolWithAnnotations declType = BindTypeOrVarKeyword(typeSyntax.SkipRef(out _), diagnostics, out isVar, out alias); - Debug.Assert(!declType.IsNull || isVar); + Debug.Assert(declType.HasType || isVar); if (isVar) { @@ -915,7 +915,7 @@ protected BoundLocalDeclaration BindVariableDeclaration( CSharpSyntaxNode associatedSyntaxNode = null) { Debug.Assert(declarator != null); - Debug.Assert(!declTypeOpt.IsNull || isVar); + Debug.Assert(declTypeOpt.HasType || isVar); Debug.Assert(typeSyntax != null); var localDiagnostics = DiagnosticBag.GetInstance(); @@ -999,7 +999,7 @@ protected BoundLocalDeclaration BindVariableDeclaration( } } - Debug.Assert(!declTypeOpt.IsNull); + Debug.Assert(declTypeOpt.HasType); if (kind == LocalDeclarationKind.FixedVariable) { @@ -2344,7 +2344,7 @@ internal BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSyn bool isVar; TypeSymbolWithAnnotations declType = BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar, out alias); - Debug.Assert(!declType.IsNull || isVar); + Debug.Assert(declType.HasType || isVar); var variables = nodeOpt.Variables; int count = variables.Count; @@ -2495,7 +2495,7 @@ protected virtual TypeSymbol GetCurrentReturnType(out RefKind refKind) TypeSymbolWithAnnotations returnType = symbol.ReturnType; - if (returnType.IsNull || (object)returnType.TypeSymbol == LambdaSymbol.ReturnTypeIsBeingInferred) + if ((object)returnType.TypeSymbol == LambdaSymbol.ReturnTypeIsBeingInferred) { return null; } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index d71d9e05286bd..f748c5bf5c393 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -469,7 +469,7 @@ void reportNullableReferenceTypesIfNeeded(SyntaxToken questionToken, TypeSymbolW var location = questionToken.GetLocation(); // Inside a method body or other executable code, we can question IsValueType without causing cycles. - if (!typeArgument.IsNull && !ShouldCheckConstraints) + if (typeArgument.HasType && !ShouldCheckConstraints) { LazyMissingNonNullTypesContextDiagnosticInfo.AddAll(isNullableEnabled, typeArgument, location, diagnostics); } diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachEnumeratorInfo.cs b/src/Compilers/CSharp/Portable/Binder/ForEachEnumeratorInfo.cs index 1fd5b917398e0..e6ffcdd52a951 100644 --- a/src/Compilers/CSharp/Portable/Binder/ForEachEnumeratorInfo.cs +++ b/src/Compilers/CSharp/Portable/Binder/ForEachEnumeratorInfo.cs @@ -58,7 +58,7 @@ private ForEachEnumeratorInfo( BinderFlags location) { Debug.Assert((object)collectionType != null, "Field 'collectionType' cannot be null"); - Debug.Assert(!elementType.IsNull, "Field 'elementType' cannot be null"); + Debug.Assert(elementType.HasType, "Field 'elementType' cannot be null"); Debug.Assert((object)getEnumeratorMethod != null, "Field 'getEnumeratorMethod' cannot be null"); Debug.Assert((object)currentPropertyGetter != null, "Field 'currentPropertyGetter' cannot be null"); Debug.Assert((object)moveNextMethod != null, "Field 'moveNextMethod' cannot be null"); diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs index dc56726834b19..e0c740f5cd4e2 100644 --- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs @@ -244,11 +244,11 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics, if (isVar) { - declType = inferredType.IsNull ? TypeSymbolWithAnnotations.Create(CreateErrorType("var")) : inferredType; + declType = inferredType.HasType ? inferredType : TypeSymbolWithAnnotations.Create(CreateErrorType("var")); } else { - Debug.Assert(!declType.IsNull); + Debug.Assert(declType.HasType); } iterationVariableType = declType.TypeSymbol; diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs index c9e10282842d7..7ca5118e0d477 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs @@ -15,7 +15,7 @@ public static NullableAnnotation GetNullableAnnotation(ArrayBuilder types) + { + ArrayBuilder builder = ArrayBuilder.GetInstance(); + foreach (var type in types) + { + builder.Add(type.ToTypeSymbolWithAnnotations()); + } + var result = GetNullableAnnotation(builder); + builder.Free(); + return result; + } + /// /// This method finds the best common type of a set of expressions as per section 7.5.2.14 of the specification. /// NOTE: If some or all of the expressions have error types, we return error type as the inference result. diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs index 8dd8d93161ec4..3d956d2ad5234 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs @@ -212,6 +212,7 @@ internal static Conversion GetTrivialConversion(ConversionKind kind) return new Conversion(kind); } + internal static Conversion UnsetConversion => new Conversion(ConversionKind.UnsetConversionKind); internal static Conversion NoConversion => new Conversion(ConversionKind.NoConversion); internal static Conversion Identity => new Conversion(ConversionKind.Identity); internal static Conversion ImplicitConstant => new Conversion(ConversionKind.ImplicitConstant); diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs index 9835831a860a8..e6b10e04b7df8 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs @@ -8,6 +8,7 @@ namespace Microsoft.CodeAnalysis.CSharp { internal enum ConversionKind : byte { + UnsetConversionKind = 0, NoConversion, Identity, ImplicitNumeric, diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs index 682d3a1d1fbdf..e95d7d1d00bf4 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs @@ -1399,12 +1399,12 @@ internal bool HasTopLevelNullabilityIdentityConversion(TypeSymbolWithAnnotations return true; } - if (source.IsPossiblyNullableReferenceTypeTypeParameter() && !destination.IsPossiblyNullableReferenceTypeTypeParameter()) + if (source.IsPossiblyNullableTypeTypeParameter() && !destination.IsPossiblyNullableTypeTypeParameter()) { return destination.NullableAnnotation.IsAnyNullable(); } - if (destination.IsPossiblyNullableReferenceTypeTypeParameter() && !source.IsPossiblyNullableReferenceTypeTypeParameter()) + if (destination.IsPossiblyNullableTypeTypeParameter() && !source.IsPossiblyNullableTypeTypeParameter()) { return source.NullableAnnotation.IsAnyNullable(); } @@ -1431,7 +1431,7 @@ internal bool HasTopLevelNullabilityImplicitConversion(TypeSymbolWithAnnotations return true; } - if (source.IsPossiblyNullableReferenceTypeTypeParameter() && !destination.IsPossiblyNullableReferenceTypeTypeParameter()) + if (source.IsPossiblyNullableTypeTypeParameter() && !destination.IsPossiblyNullableTypeTypeParameter()) { return false; } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs index 93e6f616458ba..af30e77158331 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs @@ -212,8 +212,8 @@ public static MethodTypeInferenceResult Infer( // the delegate. ImmutableArray formalParameterRefKinds, // Optional; assume all value if missing. - ImmutableArray arguments, // Required; in scenarios like method group conversions where there are - // no arguments per se we cons up some fake arguments. + ImmutableArray arguments,// Required; in scenarios like method group conversions where there are + // no arguments per se we cons up some fake arguments. ref HashSet useSiteDiagnostics, Func getTypeWithAnnotationOpt = null) { @@ -338,7 +338,7 @@ internal string Dump() var fixedType = _fixedResults[i]; - if (fixedType.IsNull) + if (!fixedType.HasType) { sb.Append("UNFIXED "); } @@ -384,7 +384,7 @@ private ImmutableArray GetResults() for (int i = 0; i < _methodTypeParameters.Length; i++) { - if (!_fixedResults[i].IsNull) + if (_fixedResults[i].HasType) { if (!_fixedResults[i].IsErrorType()) { @@ -411,12 +411,12 @@ private bool ValidIndex(int index) private bool IsUnfixed(int methodTypeParameterIndex) { Debug.Assert(ValidIndex(methodTypeParameterIndex)); - return _fixedResults[methodTypeParameterIndex].IsNull; + return !_fixedResults[methodTypeParameterIndex].HasType; } private bool IsUnfixedTypeParameter(TypeSymbolWithAnnotations type) { - Debug.Assert(!type.IsNull); + Debug.Assert(type.HasType); if (type.TypeKind != TypeKind.TypeParameter) return false; @@ -1169,7 +1169,7 @@ private bool AnyDependsOn(int iParam) private void OutputTypeInference(Binder binder, BoundExpression expression, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { Debug.Assert(expression != null); - Debug.Assert(!target.IsNull); + Debug.Assert(target.HasType); // SPEC: An output type inference is made from an expression E to a type T // SPEC: in the following way: @@ -1192,7 +1192,7 @@ private void OutputTypeInference(Binder binder, BoundExpression expression, Type // SPEC: * Otherwise, if E is an expression with type U then a lower-bound // SPEC: inference is made from U to T. var sourceType = GetTypeWithAnnotations(expression); - if (!sourceType.IsNull) + if (sourceType.HasType) { LowerBoundInference(sourceType, target, ref useSiteDiagnostics); } @@ -1202,7 +1202,7 @@ private void OutputTypeInference(Binder binder, BoundExpression expression, Type private bool InferredReturnTypeInference(BoundExpression source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { Debug.Assert(source != null); - Debug.Assert(!target.IsNull); + Debug.Assert(target.HasType); // SPEC: * If E is an anonymous function with inferred return type U and // SPEC: T is a delegate type or expression tree with return type Tb // SPEC: then a lower bound inference is made from U to Tb. @@ -1218,13 +1218,13 @@ private bool InferredReturnTypeInference(BoundExpression source, TypeSymbolWithA Debug.Assert((object)delegateType.DelegateInvokeMethod != null && !delegateType.DelegateInvokeMethod.HasUseSiteError, "This method should only be called for valid delegate types."); var returnType = delegateType.DelegateInvokeMethod.ReturnType; - if (returnType.IsNull || returnType.SpecialType == SpecialType.System_Void) + if (!returnType.HasType || returnType.SpecialType == SpecialType.System_Void) { return false; } var inferredReturnType = InferReturnType(source, delegateType, ref useSiteDiagnostics); - if (inferredReturnType.IsNull) + if (!inferredReturnType.HasType) { return false; } @@ -1261,7 +1261,7 @@ private bool MethodGroupReturnTypeInference(Binder binder, BoundExpression sourc "This method should only be called for valid delegate types"); TypeSymbolWithAnnotations delegateReturnType = delegateInvokeMethod.ReturnType; - if (delegateReturnType.IsNull || delegateReturnType.SpecialType == SpecialType.System_Void) + if (!delegateReturnType.HasType || delegateReturnType.SpecialType == SpecialType.System_Void) { return false; } @@ -1280,7 +1280,9 @@ private bool MethodGroupReturnTypeInference(Binder binder, BoundExpression sourc return false; } - NullableAnnotation returnIsNullable = NullableAnnotation.Unknown; // https://github.com/dotnet/roslyn/issues/27961 Review this + // https://github.com/dotnet/roslyn/issues/33635 : We should preserve the return nullability from the + // selected method of the method group, possibly turning oblivious into non-null. + NullableAnnotation returnIsNullable = NullableAnnotation.Unknown; LowerBoundInference(TypeSymbolWithAnnotations.Create(returnType, returnIsNullable), delegateReturnType, ref useSiteDiagnostics); return true; @@ -1324,7 +1326,7 @@ private static TypeSymbol MethodGroupReturnType( private void ExplicitParameterTypeInference(BoundExpression source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { Debug.Assert(source != null); - Debug.Assert(!target.IsNull); + Debug.Assert(target.HasType); // SPEC: An explicit type parameter type inference is made from an expression // SPEC: E to a type T in the following way. @@ -1382,8 +1384,8 @@ private void ExplicitParameterTypeInference(BoundExpression source, TypeSymbolWi // private void ExactInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // SPEC: An exact inference from a type U to a type V is made as follows: @@ -1429,8 +1431,8 @@ private void ExactInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnno private bool ExactTypeParameterInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // SPEC: * If V is one of the unfixed Xi then U is added to the set of bounds // SPEC: for Xi. @@ -1444,8 +1446,8 @@ private bool ExactTypeParameterInference(TypeSymbolWithAnnotations source, TypeS private bool ExactArrayInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // SPEC: * Otherwise, if U is an array type UE[...] and V is an array type VE[...] // SPEC: of the same rank then an exact inference from UE to VE is made. @@ -1490,8 +1492,8 @@ private void ExactOrBoundsInference(ExactOrBoundsKind kind, TypeSymbolWithAnnota private bool ExactOrBoundsNullableInference(ExactOrBoundsKind kind, TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); if (source.IsNullableType() && target.IsNullableType()) { @@ -1519,8 +1521,8 @@ private bool ExactNullableInference(TypeSymbolWithAnnotations source, TypeSymbol private bool LowerBoundTupleInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // NOTE: we are losing tuple element names when unwrapping tuple types to underlying types. // that is ok, because we are inferring type parameters used in the matching elements, @@ -1546,8 +1548,8 @@ private bool LowerBoundTupleInference(TypeSymbolWithAnnotations source, TypeSymb private bool ExactConstructedInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // SPEC: * Otherwise, if V is a constructed type C and U is a constructed // SPEC: type C then an exact inference @@ -1614,8 +1616,8 @@ private void ExactTypeArgumentInference(NamedTypeSymbol source, NamedTypeSymbol // private void LowerBoundInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // SPEC: A lower-bound inference from a type U to a type V is made as follows: @@ -1696,8 +1698,8 @@ private void LowerBoundInference(TypeSymbolWithAnnotations source, TypeSymbolWit private bool LowerBoundTypeParameterInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // SPEC: * If V is one of the unfixed Xi then U is added to the set of bounds // SPEC: for Xi. @@ -1765,7 +1767,7 @@ private bool LowerBoundArrayInference(TypeSymbol source, TypeSymbol target, ref var arraySource = (ArrayTypeSymbol)source; var elementSource = arraySource.ElementType; var elementTarget = GetMatchingElementType(arraySource, target, ref useSiteDiagnostics); - if (elementTarget.IsNull) + if (!elementTarget.HasType) { return false; } @@ -2003,8 +2005,8 @@ private void LowerBoundTypeArgumentInference(NamedTypeSymbol source, NamedTypeSy // private void UpperBoundInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // SPEC: An upper-bound inference from a type U to a type V is made as follows: @@ -2059,8 +2061,8 @@ private void UpperBoundInference(TypeSymbolWithAnnotations source, TypeSymbolWit private bool UpperBoundTypeParameterInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // SPEC: * If V is one of the unfixed Xi then U is added to the set of upper bounds // SPEC: for Xi. if (IsUnfixedTypeParameter(target)) @@ -2073,8 +2075,8 @@ private bool UpperBoundTypeParameterInference(TypeSymbolWithAnnotations source, private bool UpperBoundArrayInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet useSiteDiagnostics) { - Debug.Assert(!source.IsNull); - Debug.Assert(!target.IsNull); + Debug.Assert(source.HasType); + Debug.Assert(target.HasType); // SPEC: * Otherwise, if V is an array type Ve[...] and U is an array // SPEC: type Ue[...] of the same rank, or if V is a one-dimensional array @@ -2091,7 +2093,7 @@ private bool UpperBoundArrayInference(TypeSymbolWithAnnotations source, TypeSymb var arrayTarget = (ArrayTypeSymbol)target.TypeSymbol; var elementTarget = arrayTarget.ElementType; var elementSource = GetMatchingElementType(arrayTarget, source.TypeSymbol, ref useSiteDiagnostics); - if (elementSource.IsNull) + if (!elementSource.HasType) { return false; } @@ -2115,8 +2117,8 @@ private bool UpperBoundNullableInference(TypeSymbolWithAnnotations source, TypeS private bool UpperBoundConstructedInference(TypeSymbolWithAnnotations sourceWithAnnotations, TypeSymbolWithAnnotations targetWithAnnotations, ref HashSet useSiteDiagnostics) { - Debug.Assert(!sourceWithAnnotations.IsNull); - Debug.Assert(!targetWithAnnotations.IsNull); + Debug.Assert(sourceWithAnnotations.HasType); + Debug.Assert(targetWithAnnotations.HasType); var source = sourceWithAnnotations.TypeSymbol.TupleUnderlyingTypeOrSelf(); var target = targetWithAnnotations.TypeSymbol.TupleUnderlyingTypeOrSelf(); @@ -2302,7 +2304,7 @@ private bool Fix(int iParam, ref HashSet useSiteDiagnostics) var upper = _upperBounds[iParam]; var best = Fix(exact, lower, upper, ref useSiteDiagnostics, _conversions); - if (best.IsNull) + if (!best.HasType) { return false; } @@ -2415,7 +2417,7 @@ private static TypeSymbolWithAnnotations Fix( } } - if (best.IsNull) + if (!best.HasType) { best = candidate; } @@ -2454,6 +2456,7 @@ internal static TypeSymbolWithAnnotations Merge(TypeSymbolWithAnnotations first, // distinct "not computed" state from initial binding. return merged.SetUnknownNullabilityForReferenceTypes(); } + return merged.MergeNullability(second, variance); } @@ -2785,6 +2788,7 @@ private static void AddAllCandidates( // distinct "not computed" state from initial binding. type = type.SetUnknownNullabilityForReferenceTypes(); } + AddOrMergeCandidate(candidates, type, variance, conversions); } } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index 7173128edfbb4..fc8ac7fab2025 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -2248,7 +2248,7 @@ private bool ExpressionMatchExactly(BoundExpression node, TypeSymbol t, ref Hash // - an inferred return type X exists for E in the context of the parameter list of D(ยง7.5.2.12), and an identity conversion exists from X to Y var x = lambda.GetInferredReturnType(ref useSiteDiagnostics); - if (!x.IsNull && Conversions.HasIdentityConversion(x.TypeSymbol, y)) + if (x.HasType && Conversions.HasIdentityConversion(x.TypeSymbol, y)) { return true; } @@ -2673,7 +2673,7 @@ private bool CanDowngradeConversionFromLambdaToNeither(BetterResult currentResul } var x = lambda.InferReturnType(Conversions, d1, ref useSiteDiagnostics); - if (x.IsNull) + if (!x.HasType) { return true; } diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundDiscardExpression.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundDiscardExpression.cs index eb242e7056c09..5468797c532cb 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundDiscardExpression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundDiscardExpression.cs @@ -9,7 +9,7 @@ internal partial class BoundDiscardExpression { public BoundExpression SetInferredType(TypeSymbolWithAnnotations type) { - Debug.Assert((object)Type == null && !type.IsNull); + Debug.Assert((object)Type == null && type.HasType); return this.Update(type.TypeSymbol); } diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs index 8bb0e052aa782..ebdef5512dc1e 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs @@ -16,15 +16,18 @@ internal partial class BoundExpression /// protected abstract BoundExpression ShallowClone(); - internal BoundExpression WithSuppression() + internal BoundExpression WithSuppression(bool suppress = true) { - if (this.IsSuppressed) + if (this.IsSuppressed == suppress) { return this; } + // There is no scenario where suppression goes away + Debug.Assert(suppress || !this.IsSuppressed); + var result = ShallowClone(); - result.IsSuppressed = true; + result.IsSuppressed = suppress; return result; } diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNode.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundNode.cs index e015bfd1376b6..53c0404018eb6 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNode.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNode.cs @@ -70,7 +70,7 @@ public bool HasAnyErrors return true; } var expression = this as BoundExpression; - return expression != null && !ReferenceEquals(expression.Type, null) && expression.Type.IsErrorType(); + return expression?.Type?.IsErrorType() == true; } } diff --git a/src/Compilers/CSharp/Portable/BoundTree/ConversionGroup.cs b/src/Compilers/CSharp/Portable/BoundTree/ConversionGroup.cs index aec1e38691576..995ea5a20f087 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/ConversionGroup.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/ConversionGroup.cs @@ -22,7 +22,7 @@ internal ConversionGroup(Conversion conversion, TypeSymbolWithAnnotations explic /// /// True if the conversion is an explicit conversion. /// - internal bool IsExplicitConversion => !ExplicitType.IsNull; + internal bool IsExplicitConversion => ExplicitType.HasType; /// /// The conversion (from Conversions.ClassifyConversionFromExpression for @@ -43,7 +43,7 @@ internal ConversionGroup(Conversion conversion, TypeSymbolWithAnnotations explic internal string GetDebuggerDisplay() { var str = $"#{_id} {Conversion}"; - if (!ExplicitType.IsNull) + if (ExplicitType.HasType) { str += $" ({ExplicitType})"; } diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs index 24a3047c870a2..66cc51401547f 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs @@ -234,7 +234,7 @@ private static TypeSymbolWithAnnotations CalculateReturnType( return TypeSymbolWithAnnotations.Create(resultType); } - if (bestResultType.IsNull || bestResultType.SpecialType == SpecialType.System_Void) + if (!bestResultType.HasType || bestResultType.SpecialType == SpecialType.System_Void) { // If the best type was 'void', ERR_CantReturnVoid is reported while binding the "return void" // statement(s). @@ -428,7 +428,7 @@ internal IEnumerable InferredReturnTypes() foreach (var lambda in _returnInferenceCache.Values) { var type = lambda.InferredReturnType.Type; - if (!type.IsNull) + if (type.HasType) { any = true; yield return type.TypeSymbol; @@ -438,7 +438,7 @@ internal IEnumerable InferredReturnTypes() if (!any) { var type = BindForErrorRecovery().InferredReturnType.Type; - if (!type.IsNull) + if (type.HasType) { yield return type.TypeSymbol; } @@ -528,7 +528,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType) var lambdaParameters = lambdaSymbol.Parameters; ParameterHelpers.EnsureIsReadOnlyAttributeExists(lambdaParameters, diagnostics, modifyCompilation: false); - if (!returnType.IsNull) + if (returnType.HasType) { if (returnType.NeedsNullableAttribute()) { @@ -563,7 +563,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType) if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics)) { - if (!returnType.IsNull && // Can be null if "delegateType" is not actually a delegate type. + if (returnType.HasType && // Can be null if "delegateType" is not actually a delegate type. returnType.SpecialType != SpecialType.System_Void && !returnType.TypeSymbol.IsNonGenericTaskType(binder.Compilation) && !returnType.TypeSymbol.IsGenericTaskType(binder.Compilation)) @@ -633,7 +633,7 @@ private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType, Immutabl // TODO: Should InferredReturnType.UseSiteDiagnostics be merged into BoundLambda.Diagnostics? var returnType = inferredReturnType.Type; - if (returnType.IsNull) + if (!returnType.HasType) { returnType = TypeSymbolWithAnnotations.Create(LambdaSymbol.InferenceFailureReturnType); } @@ -842,7 +842,7 @@ private static string GetLambdaSortString(LambdaSymbol lambda) builder.Builder.Append(parameter.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat)); } - if (!lambda.ReturnType.IsNull) + if (lambda.ReturnType.HasType) { builder.Builder.Append(lambda.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)); } diff --git a/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs b/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs index ba76d9d0adfc1..e6d211ce4684e 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs @@ -22,19 +22,19 @@ internal partial class VariablePendingInference : BoundExpression { internal BoundExpression SetInferredType(TypeSymbolWithAnnotations type, DiagnosticBag diagnosticsOpt) { - Debug.Assert(!type.IsNull); + Debug.Assert(type.HasType); return SetInferredType(type, null, diagnosticsOpt); } internal BoundExpression SetInferredType(TypeSymbolWithAnnotations type, Binder binderOpt, DiagnosticBag diagnosticsOpt) { - Debug.Assert(binderOpt != null || !type.IsNull); + Debug.Assert(binderOpt != null || type.HasType); Debug.Assert(this.Syntax.Kind() == SyntaxKind.SingleVariableDesignation || (this.Syntax.Kind() == SyntaxKind.DeclarationExpression && ((DeclarationExpressionSyntax)this.Syntax).Designation.Kind() == SyntaxKind.SingleVariableDesignation)); - bool inferenceFailed = type.IsNull; + bool inferenceFailed = !type.HasType; if (inferenceFailed) { diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index f6df8f1576902..5e80c82011d32 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -10716,60 +10716,6 @@ internal static string GenericParameterDefinition { } } - /// - /// Looks up a localized string similar to Expression is probably never null.. - /// - internal static string HDN_ExpressionIsProbablyNeverNull { - get { - return ResourceManager.GetString("HDN_ExpressionIsProbablyNeverNull", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Expression is probably never null.. - /// - internal static string HDN_ExpressionIsProbablyNeverNull_Title { - get { - return ResourceManager.GetString("HDN_ExpressionIsProbablyNeverNull_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Result of the comparison is possibly always false.. - /// - internal static string HDN_NullCheckIsProbablyAlwaysFalse { - get { - return ResourceManager.GetString("HDN_NullCheckIsProbablyAlwaysFalse", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Result of the comparison is possibly always false.. - /// - internal static string HDN_NullCheckIsProbablyAlwaysFalse_Title { - get { - return ResourceManager.GetString("HDN_NullCheckIsProbablyAlwaysFalse_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Result of the comparison is possibly always true.. - /// - internal static string HDN_NullCheckIsProbablyAlwaysTrue { - get { - return ResourceManager.GetString("HDN_NullCheckIsProbablyAlwaysTrue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Result of the comparison is possibly always true.. - /// - internal static string HDN_NullCheckIsProbablyAlwaysTrue_Title { - get { - return ResourceManager.GetString("HDN_NullCheckIsProbablyAlwaysTrue_Title", resourceCulture); - } - } - /// /// Looks up a localized string similar to Unused extern alias.. /// @@ -12400,6 +12346,24 @@ internal static string WRN_AnalyzerCannotBeCreated_Title { } } + /// + /// Looks up a localized string similar to The 'as' operator may produce a null value when '{0}' is a non-nullable reference type.. + /// + internal static string WRN_AsOperatorMayReturnNull { + get { + return ResourceManager.GetString("WRN_AsOperatorMayReturnNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'as' operator may produce a null value for a type parameter.. + /// + internal static string WRN_AsOperatorMayReturnNull_Title { + get { + return ResourceManager.GetString("WRN_AsOperatorMayReturnNull_Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to Attribute '{0}' from module '{1}' will be ignored in favor of the instance appearing in source. /// @@ -13543,6 +13507,24 @@ internal static string WRN_ComparisonToSelf_Title { } } + /// + /// Looks up a localized string similar to Conditional access may produce a null value when '{0}' is a non-nullable reference type.. + /// + internal static string WRN_ConditionalAccessMayReturnNull { + get { + return ResourceManager.GetString("WRN_ConditionalAccessMayReturnNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Conditional access may produce a null value for a type parameter.. + /// + internal static string WRN_ConditionalAccessMayReturnNull_Title { + get { + return ResourceManager.GetString("WRN_ConditionalAccessMayReturnNull_Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to Different checksum values given for '{0}'. /// @@ -13615,6 +13597,24 @@ internal static string WRN_DebugFullNameTooLong_Title { } } + /// + /// Looks up a localized string similar to A default expression introduces a null value when '{0}' is a non-nullable reference type.. + /// + internal static string WRN_DefaultExpressionMayIntroduceNullT { + get { + return ResourceManager.GetString("WRN_DefaultExpressionMayIntroduceNullT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A default expression introduces a null value for a type parameter.. + /// + internal static string WRN_DefaultExpressionMayIntroduceNullT_Title { + get { + return ResourceManager.GetString("WRN_DefaultExpressionMayIntroduceNullT_Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to 'default' is converted to 'null', not 'default({0})'. /// @@ -15412,6 +15412,24 @@ internal static string WRN_NullAsNonNullable_Title { } } + /// + /// Looks up a localized string similar to A null literal introduces a null value when '{0}' is a non-nullable reference type.. + /// + internal static string WRN_NullLiteralMayIntroduceNullT { + get { + return ResourceManager.GetString("WRN_NullLiteralMayIntroduceNullT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A null literal introduces a null value for a type parameter.. + /// + internal static string WRN_NullLiteralMayIntroduceNullT_Title { + get { + return ResourceManager.GetString("WRN_NullLiteralMayIntroduceNullT_Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to Possible null reference argument for parameter '{0}' in '{1}'.. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 63d95b2203ecd..2da15661085fa 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5325,24 +5325,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Possible null value. - - Result of the comparison is possibly always true. - - - Result of the comparison is possibly always true. - - - Result of the comparison is possibly always false. - - - Result of the comparison is possibly always false. - - - Expression is probably never null. - - - Expression is probably never null. - Nullability of reference types in type doesn't match overridden member. @@ -5415,6 +5397,30 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Nullability of reference types in value doesn't match target type. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + Conditional access may produce a null value for a type parameter. + + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + The 'as' operator may produce a null value for a type parameter. + + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + A default expression introduces a null value for a type parameter. + + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + A null literal introduces a null value for a type parameter. + Argument of type '{0}' cannot be used as an input of type '{1}' for parameter '{2}' in '{3}' due to differences in the nullability of reference types. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index db13d0c449938..14282f970663d 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1299,7 +1299,7 @@ internal enum ErrorCode ERR_FeatureNotAvailableInVersion6 = 8059, // available 8062-8069 ERR_SwitchFallOut = 8070, - // ERR_UnexpectedBoundGenericName = 8071, // for nameof - used in an early prototype + // available = 8071, ERR_NullPropagatingOpInExpressionTree = 8072, WRN_NubExprIsConstBool2 = 8073, ERR_DictionaryInitializerInExpressionTree = 8074, @@ -1633,9 +1633,9 @@ internal enum ErrorCode WRN_NullReferenceReceiver = 8602, WRN_NullReferenceReturn = 8603, WRN_NullReferenceArgument = 8604, - HDN_NullCheckIsProbablyAlwaysTrue = 8605, - HDN_NullCheckIsProbablyAlwaysFalse = 8606, - HDN_ExpressionIsProbablyNeverNull = 8607, + // Available = 8605, + // Available = 8606, + // Available = 8607, WRN_NullabilityMismatchInTypeOnOverride = 8608, WRN_NullabilityMismatchInReturnTypeOnOverride = 8609, WRN_NullabilityMismatchInParameterTypeOnOverride = 8610, @@ -1654,7 +1654,7 @@ internal enum ErrorCode ERR_ExplicitNullableAttribute = 8623, WRN_NullabilityMismatchInArgumentForOutput = 8624, WRN_NullAsNonNullable = 8625, - // Available = 8626, + WRN_AsOperatorMayReturnNull = 8626, ERR_NullableUnconstrainedTypeParameter = 8627, ERR_AnnotationDisallowedInObjectCreation = 8628, WRN_NullableValueTypeMayBeNull = 8629, @@ -1666,7 +1666,7 @@ internal enum ErrorCode ERR_TripleDotNotAllowed = 8635, ERR_BadNullableContextOption = 8636, ERR_NullableDirectiveQualifierExpected = 8637, - // Available = 8638, + WRN_ConditionalAccessMayReturnNull = 8638, // Available = 8639, ERR_ExpressionTreeCantContainRefStruct = 8640, ERR_ElseCannotStartStatement = 8641, @@ -1681,6 +1681,8 @@ internal enum ErrorCode ERR_IsNullableType = 8650, ERR_AsNullableType = 8651, ERR_FeatureInPreview = 8652, + WRN_DefaultExpressionMayIntroduceNullT = 8653, + WRN_NullLiteralMayIntroduceNullT = 8654, #endregion diagnostics introduced for C# 8.0 diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index bd97747e60fca..272aace97be35 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -36,14 +36,15 @@ static ErrorFacts() builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint)); builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint)); builder.Add(getId(ErrorCode.WRN_PossibleNull)); + builder.Add(getId(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT)); + builder.Add(getId(ErrorCode.WRN_NullLiteralMayIntroduceNullT)); + builder.Add(getId(ErrorCode.WRN_ConditionalAccessMayReturnNull)); + builder.Add(getId(ErrorCode.WRN_AsOperatorMayReturnNull)); NullableFlowAnalysisSafetyWarnings = builder.ToImmutable(); builder.Clear(); builder.Add(getId(ErrorCode.WRN_ConvertingNullableToNonNullable)); - builder.Add(getId(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse)); - builder.Add(getId(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue)); - builder.Add(getId(ErrorCode.HDN_ExpressionIsProbablyNeverNull)); NullableFlowAnalysisNonSafetyWarnings = builder.ToImmutable(); @@ -399,6 +400,10 @@ internal static int GetWarningLevel(ErrorCode code) case ErrorCode.WRN_GivenExpressionAlwaysMatchesConstant: case ErrorCode.WRN_CaseConstantNamedUnderscore: case ErrorCode.WRN_PossibleNull: + case ErrorCode.WRN_DefaultExpressionMayIntroduceNullT: + case ErrorCode.WRN_NullLiteralMayIntroduceNullT: + case ErrorCode.WRN_ConditionalAccessMayReturnNull: + case ErrorCode.WRN_AsOperatorMayReturnNull: return 1; default: return 0; diff --git a/src/Compilers/CSharp/Portable/Errors/LazyMissingNonNullTypesContextDiagnosticInfo.cs b/src/Compilers/CSharp/Portable/Errors/LazyMissingNonNullTypesContextDiagnosticInfo.cs index c82b9c4814141..4e06ce62d896b 100644 --- a/src/Compilers/CSharp/Portable/Errors/LazyMissingNonNullTypesContextDiagnosticInfo.cs +++ b/src/Compilers/CSharp/Portable/Errors/LazyMissingNonNullTypesContextDiagnosticInfo.cs @@ -16,7 +16,7 @@ internal sealed class LazyMissingNonNullTypesContextDiagnosticInfo : LazyDiagnos private LazyMissingNonNullTypesContextDiagnosticInfo(TypeSymbolWithAnnotations type, DiagnosticInfo info) { - Debug.Assert(!type.IsNull); + Debug.Assert(type.HasType); _type = type; _info = info; } @@ -48,7 +48,7 @@ private static void GetRawDiagnosticInfos(bool isNullableEnabled, CSharpParseOpt } private static bool IsNullableReference(TypeSymbolWithAnnotations type) - => type.IsNull || !(type.IsValueType || type.IsErrorType()); + => !type.HasType || !(type.IsValueType || type.IsErrorType()); protected override DiagnosticInfo ResolveInfo() => IsNullableReference(_type) ? _info : null; diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs index e8d7e0f039308..4827fd4cca209 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs @@ -597,11 +597,10 @@ private void AdjustConditionalState(BoundExpression node) /// AssignedWhenFalse. /// /// - protected BoundNode VisitRvalue(BoundExpression node) + protected virtual void VisitRvalue(BoundExpression node) { - var result = Visit(node); + Visit(node); Unsplit(); - return result; } /// @@ -1590,7 +1589,7 @@ public sealed override BoundNode VisitReturnStatement(BoundReturnStatement node) protected virtual BoundNode VisitReturnStatementNoAdjust(BoundReturnStatement node) { - var result = VisitRvalue(node.ExpressionOpt); + VisitRvalue(node.ExpressionOpt); // byref return is also a potential write if (node.RefKind != RefKind.None) @@ -1598,7 +1597,7 @@ protected virtual BoundNode VisitReturnStatementNoAdjust(BoundReturnStatement no WriteArgument(node.ExpressionOpt, node.RefKind, method: null); } - return result; + return null; } private void AdjustStateAfterReturnStatement(BoundReturnStatement node) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index 42db163fc1bd1..50f238ba36703 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -20,6 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp /// /// Nullability flow analysis. /// + [DebuggerDisplay("{GetDebuggerDisplay(), nq}")] internal sealed partial class NullableWalker : LocalDataFlowPass { /// @@ -29,7 +30,7 @@ internal sealed partial class NullableWalker : LocalDataFlowPass VariableSlot; internal readonly ImmutableArray VariableBySlot; @@ -53,10 +54,10 @@ internal VariableState( /// private readonly struct VisitResult { - public readonly TypeSymbolWithAnnotations RValueType; + public readonly TypeWithState RValueType; public readonly TypeSymbolWithAnnotations LValueType; - public VisitResult(TypeSymbolWithAnnotations resultType, TypeSymbolWithAnnotations lValueType) + public VisitResult(TypeWithState resultType, TypeSymbolWithAnnotations lValueType) { RValueType = resultType; LValueType = lValueType; @@ -110,7 +111,7 @@ public VisitResult(TypeSymbolWithAnnotations resultType, TypeSymbolWithAnnotatio /// Invalid type, used only to catch Visit methods that do not set /// _result.Type. See VisitExpressionWithoutStackGuard. /// - private static readonly TypeSymbolWithAnnotations _invalidType = TypeSymbolWithAnnotations.Create(ErrorTypeSymbol.UnknownResultType); + private static readonly TypeWithState _invalidType = new TypeWithState(ErrorTypeSymbol.UnknownResultType, NullableFlowState.NotNull); /// /// The result and l-value type of the last visited expression. @@ -120,16 +121,41 @@ public VisitResult(TypeSymbolWithAnnotations resultType, TypeSymbolWithAnnotatio /// /// The result type represents the state of the last visited expression. /// - private TypeSymbolWithAnnotations ResultType + private TypeWithState ResultType { get => _visitResult.RValueType; set { - SetResult(resultType: value, lvalueType: default); + SetResult(resultType: value, lvalueType: value.ToTypeSymbolWithAnnotations()); } } - private void SetResult(TypeSymbolWithAnnotations resultType, TypeSymbolWithAnnotations lvalueType) + /// + /// Force the inference of the LValueResultType from ResultType. + /// + private void UseRvalueOnly() + { + ResultType = ResultType; + } + + private TypeSymbolWithAnnotations LvalueResultType + { + get => _visitResult.LValueType; + set + { + SetResult(resultType: value.ToTypeWithState(), lvalueType: value); + } + } + + /// + /// Force the inference of the ResultType from LValueResultType. + /// + private void UseLvalueOnly() + { + LvalueResultType = LvalueResultType; + } + + private void SetResult(TypeWithState resultType, TypeSymbolWithAnnotations lvalueType) { _visitResult = new VisitResult(resultType, lvalueType); } @@ -195,6 +221,18 @@ private NullableWalker( } } + public string GetDebuggerDisplay() + { + if (this.IsConditionalState) + { + return $"{{{GetType().Name} WhenTrue:{Dump(StateWhenTrue)} WhenFalse:{Dump(StateWhenFalse)}{"}"}"; + } + else + { + return $"{{{GetType().Name} {Dump(State)}{"}"}"; + } + } + // For purpose of nullability analysis, awaits create pending branches, so async usings and foreachs do too public sealed override bool AwaitUsingAndForeachAddsPendingBranch => true; @@ -290,6 +328,9 @@ private static void Analyze( protected override void Normalize(ref LocalState state) { + if (!state.Reachable) + return; + int oldNext = state.Capacity; state.EnsureCapacity(nextVariableSlot); Populate(ref state, oldNext); @@ -300,18 +341,17 @@ private void Populate(ref LocalState state, int start) int capacity = state.Capacity; for (int slot = start; slot < capacity; slot++) { - (NullableAnnotation value, bool assigned) = GetDefaultState(ref state, slot); - state[slot] = value; - state.SetAssigned(slot, assigned); + state[slot] = GetDefaultState(ref state, slot); } } - private (NullableAnnotation annotation, bool assigned) GetDefaultState(ref LocalState state, int slot) + private NullableFlowState GetDefaultState(ref LocalState state, int slot) { + if (!state.Reachable) + return NullableFlowState.NotNull; + if (slot == 0) - { - return (NullableAnnotation.Unknown, false); - } + return NullableFlowState.MaybeNull; var variable = variableBySlot[slot]; var symbol = variable.Symbol; @@ -319,36 +359,26 @@ private void Populate(ref LocalState state, int start) switch (symbol.Kind) { case SymbolKind.Local: - return (NullableAnnotation.Unknown, false); + return NullableFlowState.NotNull; case SymbolKind.Parameter: { var parameter = (ParameterSymbol)symbol; if (parameter.RefKind == RefKind.Out) { - return (NullableAnnotation.Unknown, false); + return NullableFlowState.NotNull; } - TypeSymbolWithAnnotations parameterType; - if (!_variableTypes.TryGetValue(parameter, out parameterType)) + + if (!_variableTypes.TryGetValue(parameter, out TypeSymbolWithAnnotations parameterType)) { parameterType = parameter.Type; } - return (parameterType.NullableAnnotation, true); + return parameterType.ToTypeWithState().State; } case SymbolKind.Field: case SymbolKind.Property: case SymbolKind.Event: - { - int containingSlot = variable.ContainingSlot; - if (containingSlot > 0 && - variableBySlot[containingSlot].Symbol.GetTypeOrReturnType().TypeKind == TypeKind.Struct && - !state.IsAssigned(containingSlot)) - { - return (NullableAnnotation.Unknown, false); - } - - return (symbol.GetTypeOrReturnType().NullableAnnotation, true); - } + return symbol.GetTypeOrReturnType().ToTypeWithState().State; default: throw ExceptionUtilities.UnexpectedValue(symbol.Kind); } @@ -441,7 +471,7 @@ private Symbol GetBackingFieldIfStructProperty(Symbol symbol) protected override int GetOrCreateSlot(Symbol symbol, int containingSlot = 0) { symbol = GetBackingFieldIfStructProperty(symbol); - if ((object)symbol == null) + if (symbol is null) { return -1; } @@ -587,12 +617,26 @@ bool isSupportedConversion(Conversion conversion, BoundExpression operandOpt) } } - private TypeSymbolWithAnnotations VisitRvalueWithResult(BoundExpression node) + protected override void VisitRvalue(BoundExpression node) { - base.VisitRvalue(node); + Visit(node); + Unsplit(); + UseRvalueOnly(); // drop lvalue part + } + + private TypeWithState VisitRvalueWithState(BoundExpression node) + { + VisitRvalue(node); return ResultType; } + private TypeSymbolWithAnnotations VisitLvalueWithAnnotations(BoundExpression node) + { + Visit(node); + Unsplit(); + return LvalueResultType; + } + private static object GetTypeAsDiagnosticArgument(TypeSymbol typeOpt) { return typeOpt ?? (object)""; @@ -608,20 +652,22 @@ private enum AssignmentKind /// /// Reports top-level nullability problem in assignment. /// - private bool ReportNullableAssignmentIfNecessary(BoundExpression value, TypeSymbolWithAnnotations targetType, TypeSymbolWithAnnotations valueType, bool useLegacyWarnings, AssignmentKind assignmentKind = AssignmentKind.Assignment, Symbol target = null) + private bool ReportNullableAssignmentIfNecessary( + BoundExpression value, + TypeSymbolWithAnnotations targetType, + TypeWithState valueType, + bool useLegacyWarnings, + AssignmentKind assignmentKind = AssignmentKind.Assignment, + Symbol target = null, + Conversion conversion = default) { Debug.Assert((object)target != null || assignmentKind != AssignmentKind.Argument); - if (value == null) - { - return false; - } - - if (targetType.IsNull || + if (value == null || + !targetType.HasType || targetType.IsValueType || - !targetType.NullableAnnotation.IsAnyNotNullable() || - valueType.IsNull || - !valueType.NullableAnnotation.IsAnyNullable()) + targetType.CanBeAssignedNull || + valueType.State == NullableFlowState.NotNull) { return false; } @@ -631,14 +677,27 @@ private bool ReportNullableAssignmentIfNecessary(BoundExpression value, TypeSymb { return false; } - if (reportNullLiteralAssignmentIfNecessary(value)) + + HashSet useSiteDiagnostics = null; + if (RequiresSafetyWarningWhenNullIntroduced(targetType.TypeSymbol)) { - return true; + if (conversion.Kind == ConversionKind.UnsetConversionKind) + conversion = this._conversions.ClassifyImplicitConversionFromType(valueType.Type, targetType.TypeSymbol, ref useSiteDiagnostics); + + if (conversion.IsImplicit && !conversion.IsDynamic) + { + // For type parameters that cannot be annotated, the analysis must report those + // places where null values first sneak in, like `default`, `null`, and `GetFirstOrDefault`, + // as a safety diagnostic. This is NOT one of those places. + return false; + } + + useLegacyWarnings = false; } - if (valueType.IsNull) + if (reportNullLiteralAssignmentIfNecessary(value)) { - return false; + return true; } if (assignmentKind == AssignmentKind.Argument) @@ -662,12 +721,15 @@ private bool ReportNullableAssignmentIfNecessary(BoundExpression value, TypeSymb // target (e.g.: `object x = null;` or calling `void F(object y)` with `F(null)`). bool reportNullLiteralAssignmentIfNecessary(BoundExpression expr) { - if (expr.ConstantValue?.IsNull != true && !IsDefaultOfUnconstrainedTypeParameter(expr)) + if (expr.ConstantValue?.IsNull != true) { return false; } - if (useLegacyWarnings) + // For type parameters that cannot be annotated, the analysis must report those + // places where null values first sneak in, like `default`, `null`, and `GetFirstOrDefault`, + // as a safety diagnostic. This is one of those places. + if (useLegacyWarnings && !RequiresSafetyWarningWhenNullIntroduced(expr.Type)) { ReportNonSafetyDiagnostic(expr.Syntax); } @@ -679,23 +741,6 @@ bool reportNullLiteralAssignmentIfNecessary(BoundExpression expr) } } - private static bool IsDefaultOfUnconstrainedTypeParameter(BoundExpression expr) - { - switch (expr.Kind) - { - case BoundKind.Conversion: - { - var conversion = (BoundConversion)expr; - return conversion.Conversion.Kind == ConversionKind.DefaultOrNullLiteral && - IsDefaultOfUnconstrainedTypeParameter(conversion.Operand); - } - case BoundKind.DefaultExpression: - return IsTypeParameterDisallowingAnnotation(expr.Type); - default: - return false; - } - } - private static bool IsDefaultValue(BoundExpression expr) { switch (expr.Kind) @@ -714,13 +759,17 @@ private static bool IsDefaultValue(BoundExpression expr) } // Maybe this method can be replaced by VisitOptionalImplicitConversion or ApplyConversion - private void ReportAssignmentWarnings(BoundExpression value, TypeSymbolWithAnnotations targetType, TypeSymbolWithAnnotations valueType, bool useLegacyWarnings) + private void ReportAssignmentWarnings( + BoundExpression value, + TypeSymbolWithAnnotations targetType, + TypeWithState valueType, + bool useLegacyWarnings) { Debug.Assert(value != null); if (this.State.Reachable) { - if (targetType.IsNull || valueType.IsNull) + if (!targetType.HasType || valueType.HasNullType) { return; } @@ -729,7 +778,7 @@ private void ReportAssignmentWarnings(BoundExpression value, TypeSymbolWithAnnot ReportNullableAssignmentIfNecessary(value, targetType, valueType, useLegacyWarnings, AssignmentKind.Assignment); // Report nested nullability issues - var sourceType = valueType.TypeSymbol; + var sourceType = valueType.Type; var destinationType = targetType.TypeSymbol; if ((object)sourceType != null && IsNullabilityMismatch(destinationType, sourceType)) { @@ -746,14 +795,19 @@ private void ReportNullabilityMismatchInAssignment(SyntaxNode syntaxNode, object /// /// Update tracked value on assignment. /// - private void TrackNullableStateForAssignment(BoundExpression value, TypeSymbolWithAnnotations targetType, int targetSlot, TypeSymbolWithAnnotations valueType, int valueSlot = -1) + private void TrackNullableStateForAssignment( + BoundExpression value, + TypeSymbolWithAnnotations targetType, + int targetSlot, + TypeWithState valueType, + int valueSlot = -1) { Debug.Assert(value != null); Debug.Assert(!IsConditionalState); if (this.State.Reachable) { - if (targetType.IsNull) + if (!targetType.HasType) { return; } @@ -765,12 +819,12 @@ private void TrackNullableStateForAssignment(BoundExpression value, TypeSymbolWi if (targetSlot >= this.State.Capacity) Normalize(ref this.State); - var newState = valueType.NullableAnnotation; + var newState = valueType.State; this.State[targetSlot] = newState; - if (newState.IsAnyNullable() && _tryState.HasValue) + if (newState == NullableFlowState.MaybeNull && _tryState.HasValue) { var state = _tryState.Value; - state[targetSlot] = NullableAnnotation.Nullable; + state[targetSlot] = NullableFlowState.MaybeNull; _tryState = state; } @@ -797,8 +851,8 @@ private void TrackNullableStateForAssignment(BoundExpression value, TypeSymbolWi } } - bool areEquivalentTypes(TypeSymbolWithAnnotations t1, TypeSymbolWithAnnotations t2) => - t1.TypeSymbol.Equals(t2.TypeSymbol, TypeCompareKind.AllIgnoreOptions); + bool areEquivalentTypes(TypeSymbolWithAnnotations target, TypeWithState assignedValue) => + target.TypeSymbol.Equals(assignedValue.Type, TypeCompareKind.AllIgnoreOptions); } private void ReportNonSafetyDiagnostic(SyntaxNode syntax) @@ -865,14 +919,12 @@ private void InheritNullableStateOfMember(int targetContainerSlot, int valueCont // Nullable is handled here rather than in InheritNullableStateOfTrackableStruct since that // method only clones auto-properties (see https://github.com/dotnet/roslyn/issues/29619). // When that issue is fixed, Nullable should be handled there instead. - if (fieldOrPropertyType.IsReferenceType || fieldOrPropertyType.IsPossiblyNullableReferenceTypeTypeParameter() || fieldOrPropertyType.IsNullableType()) + if (fieldOrPropertyType.TypeSymbol.CanContainNull()) { int targetMemberSlot = GetOrCreateSlot(member, targetContainerSlot); Debug.Assert(targetMemberSlot > 0); - NullableAnnotation value = (isDefaultValue && fieldOrPropertyType.IsReferenceType) ? - NullableAnnotation.Nullable : - fieldOrPropertyType.NullableAnnotation; + NullableFlowState value = isDefaultValue ? NullableFlowState.MaybeNull : fieldOrPropertyType.ToTypeWithState().State; int valueMemberSlot = -1; if (valueContainerSlot > 0) @@ -884,7 +936,7 @@ private void InheritNullableStateOfMember(int targetContainerSlot, int valueCont } value = valueMemberSlot > 0 && valueMemberSlot < this.State.Capacity ? this.State[valueMemberSlot] : - NullableAnnotation.Unknown; + NullableFlowState.NotNull; } this.State[targetMemberSlot] = value; @@ -921,7 +973,7 @@ private void InheritDefaultState(int targetSlot) { continue; } - this.State[slot] = variable.Symbol.GetTypeOrReturnType().NullableAnnotation; + this.State[slot] = variable.Symbol.GetTypeOrReturnType().ToTypeWithState().State; InheritDefaultState(slot); } } @@ -952,22 +1004,22 @@ private TypeSymbol GetSlotType(int slot) protected override LocalState TopState() { - var state = new LocalState(reachable: true, BitVector.Create(nextVariableSlot), new ArrayBuilder(nextVariableSlot)); + var state = new LocalState(reachable: true, new ArrayBuilder(nextVariableSlot)); Populate(ref state, start: 0); return state; } protected override LocalState UnreachableState() { - return new LocalState(reachable: false, BitVector.Empty, null); + return new LocalState(reachable: false, null); } protected override LocalState ReachableBottomState() { // Create a reachable state in which all variables are known to be non-null. - var builder = new ArrayBuilder(nextVariableSlot); - builder.AddMany(NullableAnnotation.NotNullable, nextVariableSlot); - return new LocalState(reachable: true, BitVector.AllSet(nextVariableSlot), builder); + var builder = new ArrayBuilder(nextVariableSlot); + builder.AddMany(NullableFlowState.NotNull, nextVariableSlot); + return new LocalState(reachable: true, builder); } private void EnterParameters() @@ -1005,12 +1057,9 @@ private void EnterParameter(ParameterSymbol parameter, TypeSymbolWithAnnotations public override BoundNode VisitIsPatternExpression(BoundIsPatternExpression node) { - VisitRvalue(node.Expression); - var expressionResultType = this.ResultType; - - VisitPattern(node.Expression, expressionResultType, node.Pattern); - - SetResult(node); + var resultType = VisitRvalueWithState(node.Expression); + VisitPattern(node.Expression, resultType, node.Pattern); + SetNotNullResult(node); return node; } @@ -1023,10 +1072,11 @@ public override BoundNode VisitIsPatternExpression(BoundIsPatternExpression node /// If the pattern is a `var` pattern, we'll also have re-inferred the `var` type with nullability and /// updated the state for that declared local. /// - private void VisitPattern(BoundExpression expression, TypeSymbolWithAnnotations expressionResultType, BoundPattern pattern) + private void VisitPattern(BoundExpression expression, TypeWithState expressionResultType, BoundPattern pattern) { - NullableAnnotation whenTrue = NullableAnnotation.Unknown; // the pattern tells us the expression (1) is null, (2) isn't null, or (3) we don't know. - NullableAnnotation whenFalse = NullableAnnotation.Unknown; + NullableFlowState whenTrue = expressionResultType.State; + NullableFlowState whenFalse = expressionResultType.State; + switch (pattern.Kind) { case BoundKind.ConstantPattern: @@ -1036,12 +1086,12 @@ private void VisitPattern(BoundExpression expression, TypeSymbolWithAnnotations switch (((BoundConstantPattern)pattern).ConstantValue?.IsNull) { case true: - whenTrue = NullableAnnotation.Nullable; - whenFalse = NullableAnnotation.NotNullable; + whenTrue = NullableFlowState.MaybeNull; + whenFalse = NullableFlowState.NotNull; break; case false: - whenTrue = NullableAnnotation.NotNullable; - whenFalse = expressionResultType.NullableAnnotation; + whenTrue = NullableFlowState.NotNull; + whenFalse = NullableFlowState.MaybeNull; break; } break; @@ -1054,60 +1104,51 @@ private void VisitPattern(BoundExpression expression, TypeSymbolWithAnnotations // No variable declared for discard (`i is var _`) if ((object)variable != null) { - _variableTypes[variable] = expressionResultType; - TrackNullableStateForAssignment(expression, expressionResultType, GetOrCreateSlot(variable), expressionResultType); + var variableType = expressionResultType.ToTypeSymbolWithAnnotations(); + _variableTypes[variable] = variableType; + TrackNullableStateForAssignment(expression, variableType, GetOrCreateSlot(variable), expressionResultType); } - whenFalse = NullableAnnotation.NotNullable; // whenFalse is unreachable + whenFalse = NullableFlowState.NotNull; // whenFalse is unreachable } else { - whenTrue = NullableAnnotation.NotNullable; // the pattern tells us the expression is not null - whenFalse = expressionResultType.NullableAnnotation; + whenTrue = NullableFlowState.NotNull; // the pattern tells us the expression is not null } break; + default: + // https://github.com/dotnet/roslyn/issues/29909 : handle other kinds of patterns + break; } Debug.Assert(!IsConditionalState); - int mainSlot = -1; - if (whenTrue != NullableAnnotation.Unknown) - { - // Create slot when the state is unconditional since EnsureCapacity should be - // called on all fields and that is simpler if state is limited to this.State. - mainSlot = MakeSlot(expression); - } + // Create slot since EnsureCapacity should be + // called on all fields and that is simpler if state is limited to this.State. + int mainSlot = MakeSlot(expression); base.VisitPattern(pattern); Debug.Assert(IsConditionalState); - // https://github.com/dotnet/roslyn/issues/29873 We should only report such - // diagnostics for locals that are set or checked explicitly within this method. - if (!expressionResultType.IsPointerType() && !expressionResultType.IsNull && expressionResultType.ValueCanBeNull() == false && whenTrue == NullableAnnotation.Nullable) - { - ReportNonSafetyDiagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, pattern.Syntax); - } - if (mainSlot > 0) { - Debug.Assert(whenTrue != NullableAnnotation.Unknown); this.StateWhenTrue[mainSlot] = whenTrue; this.StateWhenFalse[mainSlot] = whenFalse; } - if (whenTrue == NullableAnnotation.NotNullable || whenFalse == NullableAnnotation.NotNullable) + if (whenTrue == NullableFlowState.NotNull || whenFalse == NullableFlowState.NotNull) { var slotBuilder = ArrayBuilder.GetInstance(); GetSlotsToMarkAsNotNullable(expression, slotBuilder); // Set all nested conditional slots. For example in a?.b?.c we'll set a, b, and c. - if (whenTrue == NullableAnnotation.NotNullable) + if (whenTrue == NullableFlowState.NotNull) { - MarkSlotsAsNotNullable(slotBuilder, ref StateWhenTrue); + MarkSlotsAsNotNull(slotBuilder, ref StateWhenTrue); } - else if (whenFalse == NullableAnnotation.NotNullable) + else if (whenFalse == NullableFlowState.NotNull) { - MarkSlotsAsNotNullable(slotBuilder, ref StateWhenFalse); + MarkSlotsAsNotNull(slotBuilder, ref StateWhenFalse); } slotBuilder.Free(); @@ -1132,10 +1173,10 @@ protected override BoundNode VisitReturnStatementNoAdjust(BoundReturnStatement n } else { - TypeSymbolWithAnnotations result = VisitRvalueWithResult(expr); + var result = VisitRvalueWithState(expr); if (_returnTypesOpt != null) { - _returnTypesOpt.Add((node, result)); + _returnTypesOpt.Add((node, result.ToTypeSymbolWithAnnotations())); } } @@ -1170,9 +1211,9 @@ private bool TryGetReturnType(out TypeSymbolWithAnnotations type) return false; } - private static bool IsTypeParameterDisallowingAnnotation(TypeSymbol typeOpt) + private static bool RequiresSafetyWarningWhenNullIntroduced(TypeSymbol typeOpt) { - return typeOpt?.IsTypeParameterDisallowingAnnotation() == true; + return typeOpt?.IsTypeParameterDisallowingAnnotation() == true && !typeOpt.IsNullableTypeOrTypeParameter(); } public override BoundNode VisitLocal(BoundLocal node) @@ -1197,17 +1238,18 @@ public override BoundNode VisitLocalDeclaration(BoundLocalDeclaration node) bool inferredType = node.DeclaredType.InferredType; TypeSymbolWithAnnotations type = local.Type; - TypeSymbolWithAnnotations valueType = VisitOptionalImplicitConversion(initializer, targetTypeOpt: inferredType ? default : type, useLegacyWarnings: true, AssignmentKind.Assignment); + TypeWithState valueType = VisitOptionalImplicitConversion(initializer, targetTypeOpt: inferredType ? default : type, useLegacyWarnings: true, AssignmentKind.Assignment); if (inferredType) { - if (valueType.IsNull) + if (valueType.HasNullType) { Debug.Assert(type.IsErrorType()); - valueType = type; + valueType = type.ToTypeWithState(); } - _variableTypes[local] = valueType; - type = valueType; + + type = valueType.ToTypeSymbolWithAnnotations(); + _variableTypes[local] = type; } TrackNullableStateForAssignment(initializer, type, slot, valueType, MakeSlot(initializer)); @@ -1217,25 +1259,24 @@ public override BoundNode VisitLocalDeclaration(BoundLocalDeclaration node) protected override BoundExpression VisitExpressionWithoutStackGuard(BoundExpression node) { Debug.Assert(!IsConditionalState); + bool wasReachable = this.State.Reachable; ResultType = _invalidType; - var result = base.VisitExpressionWithoutStackGuard(node); + _ = base.VisitExpressionWithoutStackGuard(node); + TypeWithState resultType = ResultType; #if DEBUG // Verify Visit method set _result. - TypeSymbolWithAnnotations resultType = ResultType; - Debug.Assert((object)resultType.TypeSymbol != _invalidType.TypeSymbol); - Debug.Assert(AreCloseEnough(resultType.TypeSymbol, node.Type)); + Debug.Assert((object)resultType.Type != _invalidType.Type); + Debug.Assert(AreCloseEnough(resultType.Type, node.Type)); #endif - if (_callbackOpt != null) - { - _callbackOpt(node, ResultType); - } + _callbackOpt?.Invoke(node, resultType.ToTypeSymbolWithAnnotations()); - if (node.IsSuppressed && !ResultType.IsNull) + if (node.IsSuppressed || node.HasAnyErrors || !wasReachable) { - SetResult(_visitResult.RValueType.WithTopLevelNonNullability(), _visitResult.LValueType); + var result = resultType.WithNotNullState(); + SetResult(result, LvalueResultType); } - return result; + return null; } #if DEBUG @@ -1248,7 +1289,7 @@ private static bool AreCloseEnough(TypeSymbol typeA, TypeSymbol typeB) } if (typeA is null || typeB is null) { - return false; + return typeA?.IsErrorType() != false && typeB?.IsErrorType() != false; } return canIgnoreAnyType(typeA) || canIgnoreAnyType(typeB) || @@ -1296,7 +1337,7 @@ private void VisitObjectOrDynamicObjectCreation( int slot = -1; TypeSymbol type = node.Type; - NullableAnnotation resultAnnotation = NullableAnnotation.NotNullable; + NullableFlowState resultState = NullableFlowState.NotNull; if ((object)type != null) { bool isTrackableStructType = EmptyStructTypeCache.IsTrackableStructType(type); @@ -1308,7 +1349,7 @@ private void VisitObjectOrDynamicObjectCreation( slot = GetOrCreateObjectCreationPlaceholderSlot(node); if (slot > 0 && isTrackableStructType) { - this.State[slot] = NullableAnnotation.NotNullable; + this.State[slot] = NullableFlowState.NotNull; var tupleType = constructor?.ContainingType as TupleTypeSymbol; if ((object)tupleType != null && !isDefaultValueTypeConstructor) { @@ -1328,7 +1369,7 @@ private void VisitObjectOrDynamicObjectCreation( else if (type.IsNullableType() && isDefaultValueTypeConstructor) { // a nullable value type created with its default constructor is by definition null - resultAnnotation = NullableAnnotation.Nullable; + resultState = NullableFlowState.MaybeNull; } } @@ -1337,7 +1378,7 @@ private void VisitObjectOrDynamicObjectCreation( VisitObjectCreationInitializer(null, slot, initializerOpt); } - ResultType = TypeSymbolWithAnnotations.Create(type, resultAnnotation); + ResultType = new TypeWithState(type, resultState); } private void VisitObjectCreationInitializer(Symbol containingSymbol, int containingSlot, BoundExpression node) @@ -1373,7 +1414,7 @@ private void VisitObjectCreationInitializer(Symbol containingSymbol, int contain } break; default: - TypeSymbolWithAnnotations resultType = VisitRvalueWithResult(node); + TypeWithState resultType = VisitRvalueWithState(node); Debug.Assert((object)containingSymbol != null); if ((object)containingSymbol != null) { @@ -1418,9 +1459,9 @@ private void VisitObjectElementInitializer(int containingSlot, BoundAssignmentOp SetUnknownResultNullability(); } - private void SetResult(BoundExpression node) + private void SetNotNullResult(BoundExpression node) { - ResultType = TypeSymbolWithAnnotations.Create(node.Type); + ResultType = new TypeWithState(node.Type, NullableFlowState.NotNull); } private int GetOrCreateObjectCreationPlaceholderSlot(BoundExpression node) @@ -1436,7 +1477,7 @@ private int GetOrCreateObjectCreationPlaceholderSlot(BoundExpression node) _placeholderLocalsOpt.TryGetValue(node, out placeholder); } - if ((object)placeholder == null) + if (placeholder is null) { placeholder = new ObjectCreationPlaceholderLocal(_symbol, node); _placeholderLocalsOpt.Add(node, placeholder); @@ -1453,11 +1494,14 @@ public override BoundNode VisitAnonymousObjectCreationExpression(BoundAnonymousO Debug.Assert(anonymousType.IsAnonymousType); var arguments = node.Arguments; - var argumentTypes = arguments.SelectAsArray((arg, visitor) => visitor.VisitRvalueWithResult(arg), this); + var argumentTypes = arguments.SelectAsArray((arg, self) => + self.VisitRvalueWithState(arg), this); + var argumentsWithAnnotations = argumentTypes.SelectAsArray((arg, self) => + arg.ToTypeSymbolWithAnnotations().AsSpeakable(), this); - if (argumentTypes.All(argType => !argType.IsNull)) + if (argumentsWithAnnotations.All(argType => argType.HasType)) { - anonymousType = AnonymousTypeManager.ConstructAnonymousTypeSymbol(anonymousType, argumentTypes); + anonymousType = AnonymousTypeManager.ConstructAnonymousTypeSymbol(anonymousType, argumentsWithAnnotations); int receiverSlot = GetOrCreateObjectCreationPlaceholderSlot(node); for (int i = 0; i < arguments.Length; i++) { @@ -1468,7 +1512,7 @@ public override BoundNode VisitAnonymousObjectCreationExpression(BoundAnonymousO } } - ResultType = TypeSymbolWithAnnotations.Create(anonymousType, NullableAnnotation.NotNullable); + ResultType = new TypeWithState(anonymousType, NullableFlowState.NotNull); return null; } @@ -1479,7 +1523,7 @@ public override BoundNode VisitArrayCreation(BoundArrayCreation node) VisitRvalue(expr); } TypeSymbol resultType = (node.InitializerOpt == null) ? node.Type : VisitArrayInitializer(node); - ResultType = TypeSymbolWithAnnotations.Create(resultType, NullableAnnotation.NotNullable); + ResultType = new TypeWithState(resultType, NullableFlowState.NotNull); return null; } @@ -1507,21 +1551,21 @@ private ArrayTypeSymbol VisitArrayInitializer(BoundArrayCreation node) } var conversions = ArrayBuilder.GetInstance(n); - var resultTypes = ArrayBuilder.GetInstance(n); + var resultTypes = ArrayBuilder.GetInstance(n); for (int i = 0; i < n; i++) { // collect expressions, conversions and result types (BoundExpression expression, Conversion conversion) = RemoveConversion(expressions[i], includeExplicitConversions: false); expressions[i] = expression; conversions.Add(conversion); - var resultType = VisitRvalueWithResult(expression); + var resultType = VisitRvalueWithState(expression); resultTypes.Add(resultType); } var placeholderBuilder = ArrayBuilder.GetInstance(n); for (int i = 0; i < n; i++) { - placeholderBuilder.Add(CreatePlaceholderIfNecessary(expressions[i], resultTypes[i])); + placeholderBuilder.Add(CreatePlaceholderIfNecessary(expressions[i], resultTypes[i].ToTypeSymbolWithAnnotations())); } var placeholders = placeholderBuilder.ToImmutableAndFree(); @@ -1553,13 +1597,13 @@ private ArrayTypeSymbol VisitArrayInitializer(BoundArrayCreation node) } // Set top-level nullability on inferred element type - inferredType = TypeSymbolWithAnnotations.Create(inferredType.TypeSymbol, BestTypeInferrer.GetNullableAnnotation(resultTypes)); + inferredType = TypeSymbolWithAnnotations.Create(inferredType.TypeSymbol, BestTypeInferrer.GetNullableAnnotation(resultTypes)).AsSpeakable(); for (int i = 0; i < n; i++) { var nodeForSyntax = expressions[i]; // Report top-level warnings - _ = ApplyConversion(nodeForSyntax, operandOpt: null, Conversion.Identity, targetTypeWithNullability: inferredType, operandType: resultTypes[i], + _ = ApplyConversion(nodeForSyntax, operandOpt: nodeForSyntax, Conversion.Identity, targetTypeWithNullability: inferredType, operandType: resultTypes[i], checkConversion: true, fromExplicitCast: false, useLegacyWarnings: false, AssignmentKind.Assignment, reportRemainingWarnings: false); } } @@ -1612,9 +1656,9 @@ internal static TypeSymbolWithAnnotations BestTypeForLambdaReturns( { BoundExpression placeholder = placeholders[i]; Conversion conversion = conversionsWithoutNullability.ClassifyConversionFromExpression(placeholder, bestType, ref useSiteDiagnostics); - resultTypes[i] = walker.ApplyConversion(placeholder, placeholder, conversion, bestTypeWithObliviousAnnotation, resultTypes[i], + resultTypes[i] = walker.ApplyConversion(placeholder, placeholder, conversion, bestTypeWithObliviousAnnotation, resultTypes[i].ToTypeWithState(), checkConversion: false, fromExplicitCast: false, useLegacyWarnings: false, AssignmentKind.Return, - reportRemainingWarnings: false, reportTopLevelWarnings: false); + reportRemainingWarnings: false, reportTopLevelWarnings: false).ToTypeSymbolWithAnnotations(); } // Set top-level nullability on inferred type @@ -1659,7 +1703,7 @@ public override BoundNode VisitArrayAccess(BoundArrayAccess node) // after indices have been visited, and only if the receiver has not changed. CheckPossibleNullReceiver(node.Expression); - var type = ResultType.TypeSymbol as ArrayTypeSymbol; + var type = ResultType.Type as ArrayTypeSymbol; foreach (var i in node.Indices) { @@ -1676,30 +1720,27 @@ public override BoundNode VisitArrayAccess(BoundArrayAccess node) { result = type?.ElementType ?? default; } - SetResult(result, result); + LvalueResultType = result; return null; } - private TypeSymbolWithAnnotations InferResultNullability(BoundBinaryOperator node, TypeSymbolWithAnnotations leftType, TypeSymbolWithAnnotations rightType) + private TypeWithState InferResultNullability(BoundBinaryOperator node, TypeWithState leftType, TypeWithState rightType) { return InferResultNullability(node.OperatorKind, node.MethodOpt, node.Type, leftType, rightType); } - private TypeSymbolWithAnnotations InferResultNullability(BinaryOperatorKind operatorKind, MethodSymbol methodOpt, TypeSymbol resultType, TypeSymbolWithAnnotations leftType, TypeSymbolWithAnnotations rightType) + private TypeWithState InferResultNullability(BinaryOperatorKind operatorKind, MethodSymbol methodOpt, TypeSymbol resultType, TypeWithState leftType, TypeWithState rightType) { - NullableAnnotation nullableAnnotation = NullableAnnotation.Unknown; + NullableFlowState resultState = NullableFlowState.NotNull; if (operatorKind.IsUserDefined()) { - if (operatorKind.IsLifted()) - { - // https://github.com/dotnet/roslyn/issues/29953 Conversions: Lifted operator - return TypeSymbolWithAnnotations.Create(resultType); - } // Update method based on operand types: see https://github.com/dotnet/roslyn/issues/29605. if ((object)methodOpt != null && methodOpt.ParameterCount == 2) { - return methodOpt.ReturnType; + return operatorKind.IsLifted() && !operatorKind.IsComparison() + ? LiftedReturnType(methodOpt.ReturnType, leftType.State.JoinForFlowAnalysisBranches(rightType.State)) + : methodOpt.ReturnType.ToTypeWithState(); } } else if (!operatorKind.IsDynamic() && !resultType.IsValueType) @@ -1707,33 +1748,23 @@ private TypeSymbolWithAnnotations InferResultNullability(BinaryOperatorKind oper switch (operatorKind.Operator() | operatorKind.OperandTypes()) { case BinaryOperatorKind.DelegateCombination: - { - NullableAnnotation left = leftType.GetValueNullableAnnotation(); - NullableAnnotation right = rightType.GetValueNullableAnnotation(); - if (left.IsAnyNotNullable() || right.IsAnyNotNullable()) - { - nullableAnnotation = NullableAnnotation.NotNullable; - } - else if (left.IsAnyNullable() && right.IsAnyNullable()) - { - nullableAnnotation = NullableAnnotation.Nullable; - } - else - { - Debug.Assert(left == NullableAnnotation.Unknown || right == NullableAnnotation.Unknown); - } - } + resultState = leftType.State.MeetForFlowAnalysisFinally(rightType.State); break; case BinaryOperatorKind.DelegateRemoval: - nullableAnnotation = NullableAnnotation.Nullable; // Delegate removal can produce null. + resultState = NullableFlowState.MaybeNull; // Delegate removal can produce null. break; default: - nullableAnnotation = NullableAnnotation.NotNullable; + resultState = NullableFlowState.NotNull; break; } } - return TypeSymbolWithAnnotations.Create(resultType, nullableAnnotation); + if (operatorKind.IsLifted()) + { + resultState = leftType.State.JoinForFlowAnalysisBranches(rightType.State); + } + + return new TypeWithState(resultType, resultState); } protected override void AfterLeftChildHasBeenVisited(BoundBinaryOperator binary) @@ -1741,7 +1772,7 @@ protected override void AfterLeftChildHasBeenVisited(BoundBinaryOperator binary) Debug.Assert(!IsConditionalState); //if (this.State.Reachable) // Consider reachability: see https://github.com/dotnet/roslyn/issues/28798 { - TypeSymbolWithAnnotations leftType = ResultType; + TypeWithState leftType = ResultType; bool warnOnNullReferenceArgument = (binary.OperatorKind.IsUserDefined() && (object)binary.MethodOpt != null && binary.MethodOpt.ParameterCount == 2); if (warnOnNullReferenceArgument) @@ -1749,12 +1780,10 @@ protected override void AfterLeftChildHasBeenVisited(BoundBinaryOperator binary) ReportArgumentWarnings(binary.Left, leftType, binary.MethodOpt.Parameters[0]); } - VisitRvalue(binary.Right); + var rightType = VisitRvalueWithState(binary.Right); Debug.Assert(!IsConditionalState); - // At this point, State.Reachable may be false for // invalid code such as `s + throw new Exception()`. - TypeSymbolWithAnnotations rightType = ResultType; if (warnOnNullReferenceArgument) { @@ -1768,7 +1797,7 @@ protected override void AfterLeftChildHasBeenVisited(BoundBinaryOperator binary) if (op == BinaryOperatorKind.Equal || op == BinaryOperatorKind.NotEqual) { BoundExpression operandComparedToNull = null; - TypeSymbolWithAnnotations operandComparedToNullType = default; + TypeWithState operandComparedToNullType = default; if (binary.Right.ConstantValue?.IsNull == true) { @@ -1783,16 +1812,6 @@ protected override void AfterLeftChildHasBeenVisited(BoundBinaryOperator binary) if (operandComparedToNull != null) { - // https://github.com/dotnet/roslyn/issues/29953: We should only report such - // diagnostics for locals that are set or checked explicitly within this method. - if (!operandComparedToNullType.IsNull && operandComparedToNullType.NullableAnnotation.IsAnyNotNullable()) - { - ReportNonSafetyDiagnostic(op == BinaryOperatorKind.Equal ? - ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse : - ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, - binary.Syntax); - } - // Skip reference conversions operandComparedToNull = SkipReferenceConversions(operandComparedToNull); @@ -1803,7 +1822,7 @@ protected override void AfterLeftChildHasBeenVisited(BoundBinaryOperator binary) { Split(); ref LocalState stateToUpdate = ref (op == BinaryOperatorKind.Equal) ? ref this.StateWhenFalse : ref this.StateWhenTrue; - MarkSlotsAsNotNullable(slotBuilder, ref stateToUpdate); + MarkSlotsAsNotNull(slotBuilder, ref stateToUpdate); } slotBuilder.Free(); } @@ -1906,10 +1925,9 @@ private void GetSlotsToMarkAsNotNullable(BoundExpression operand, ArrayBuilder !(operandType is null) && (!operandType.IsValueType || operandType.IsNullableType()); + private static bool PossiblyNullableType(TypeSymbol operandType) => operandType?.CanContainNull() == true; - private static void MarkSlotsAsNotNullable(ArrayBuilder slots, ref LocalState stateToUpdate) + private static void MarkSlotsAsNotNull(ArrayBuilder slots, ref LocalState stateToUpdate) { if (slots is null) { @@ -1918,7 +1936,7 @@ private static void MarkSlotsAsNotNullable(ArrayBuilder slots, ref LocalSta foreach (int slot in slots) { - stateToUpdate[slot] = NullableAnnotation.NotNullable; + stateToUpdate[slot] = NullableFlowState.NotNull; } } @@ -1926,7 +1944,7 @@ private void LearnFromNonNullTest(BoundExpression expression, ref LocalState sta { var slotBuilder = ArrayBuilder.GetInstance(); GetSlotsToMarkAsNotNullable(expression, slotBuilder); - MarkSlotsAsNotNullable(slotBuilder, ref state); + MarkSlotsAsNotNull(slotBuilder, ref state); slotBuilder.Free(); } @@ -1957,27 +1975,20 @@ public override BoundNode VisitNullCoalescingAssignmentOperator(BoundNullCoalesc // The assignment to the left below needs the declared type from VisitLvalue, but the hidden // unnecessary check diagnostic needs the current adjusted type of the slot - Visit(leftOperand); - TypeSymbolWithAnnotations targetType = _visitResult.LValueType; - TypeSymbolWithAnnotations currentLeftType = GetAdjustedResult(targetType, leftSlot); - - if (currentLeftType.ValueCanBeNull() == false) - { - ReportNonSafetyDiagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, leftOperand.Syntax); - } + TypeSymbolWithAnnotations targetType = VisitLvalueWithAnnotations(leftOperand); + TypeWithState currentLeftType = GetAdjustedResult(targetType, leftSlot); var leftState = this.State.Clone(); - - TypeSymbolWithAnnotations rightResult = VisitOptionalImplicitConversion(rightOperand, targetType, UseLegacyWarnings(leftOperand), AssignmentKind.Assignment); + TypeWithState rightResult = VisitOptionalImplicitConversion(rightOperand, targetType, UseLegacyWarnings(leftOperand), AssignmentKind.Assignment); TrackNullableStateForAssignment(rightOperand, targetType, leftSlot, rightResult, MakeSlot(rightOperand)); Join(ref this.State, ref leftState); - TypeSymbolWithAnnotations resultType = GetNullCoalescingResultType(leftOperand, currentLeftType, rightOperand, rightResult, targetType.TypeSymbol); + TypeWithState resultType = GetNullCoalescingResultType(leftOperand, currentLeftType, rightOperand, rightResult, targetType.TypeSymbol); ResultType = resultType; if (leftSlot > 0) { - this.State[leftSlot] = resultType.NullableAnnotation; + this.State[leftSlot] = resultType.State; } return null; @@ -1990,15 +2001,15 @@ public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperato BoundExpression leftOperand = node.LeftOperand; BoundExpression rightOperand = node.RightOperand; - TypeSymbolWithAnnotations leftResult = VisitRvalueWithResult(leftOperand); - TypeSymbolWithAnnotations rightResult; + TypeWithState leftResult = VisitRvalueWithState(leftOperand); + TypeWithState rightResult; if (IsConstantNull(leftOperand)) { - rightResult = VisitRvalueWithResult(rightOperand); + rightResult = VisitRvalueWithState(rightOperand); // Should be able to use rightResult for the result of the operator but // binding may have generated a different result type in the case of errors. - ResultType = TypeSymbolWithAnnotations.Create(node.Type, getNullableAnnotation(rightOperand, rightResult)); + ResultType = new TypeWithState(node.Type, getNullableState(rightOperand, rightResult)); return null; } @@ -2008,11 +2019,6 @@ public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperato // Consider learning in whenNull branch as well // https://github.com/dotnet/roslyn/issues/30297 - if (leftResult.ValueCanBeNull() == false) - { - ReportNonSafetyDiagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, leftOperand.Syntax); - } - bool leftIsConstant = leftOperand.ConstantValue != null; if (leftIsConstant) { @@ -2021,11 +2027,11 @@ public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperato // https://github.com/dotnet/roslyn/issues/29955 For cases where the left operand determines // the type, we should unwrap the right conversion and re-apply. - rightResult = VisitRvalueWithResult(rightOperand); + rightResult = VisitRvalueWithState(rightOperand); Join(ref this.State, ref whenNotNull); TypeSymbol resultType; - var leftResultType = leftResult.TypeSymbol; - var rightResultType = rightResult.TypeSymbol; + var leftResultType = leftResult.Type; + var rightResultType = rightResult.Type; switch (node.OperatorResultKind) { case BoundNullCoalescingOperatorResultKind.NoCommonType: @@ -2053,14 +2059,14 @@ public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperato ResultType = GetNullCoalescingResultType(leftOperand, leftResult, rightOperand, rightResult, resultType); return null; - NullableAnnotation getNullableAnnotation(BoundExpression e, TypeSymbolWithAnnotations t) + NullableFlowState getNullableState(BoundExpression e, TypeWithState t) { - if (t.IsNull) + if (t.HasNullType) { - return GetNullableAnnotation(e); + return GetNullableAnnotation(e).IsAnyNullable() ? NullableFlowState.MaybeNull : NullableFlowState.NotNull; } - return t.NullableAnnotation; + return t.State; } TypeSymbol getLeftResultType(TypeSymbol leftType, TypeSymbol rightType) @@ -2078,6 +2084,7 @@ TypeSymbol getLeftResultType(TypeSymbol leftType, TypeSymbol rightType) GenerateConversionForConditionalOperator(node.RightOperand, rightType, leftType, reportMismatch: true); return leftType; } + TypeSymbol getRightResultType(TypeSymbol leftType, TypeSymbol rightType) { GenerateConversionForConditionalOperator(node.LeftOperand, leftType, rightType, reportMismatch: true); @@ -2098,63 +2105,41 @@ private static NullableAnnotation GetNullableAnnotation(BoundExpression expr) case BoundKind.DefaultExpression: case BoundKind.Literal: { - var constant = expr.ConstantValue; - if (constant != null) - { - if (constant.IsNull) - { - return NullableAnnotation.Nullable; - } - if (expr.Type?.IsReferenceType == true) - { - return NullableAnnotation.NotNullable; - } - } - return NullableAnnotation.Unknown; + return (expr.ConstantValue?.IsNull != false) ? NullableAnnotation.NotNullable : NullableAnnotation.Nullable; } case BoundKind.ExpressionWithNullability: return ((BoundExpressionWithNullability)expr).NullableAnnotation; case BoundKind.MethodGroup: case BoundKind.UnboundLambda: - return NullableAnnotation.Unknown; + return NullableAnnotation.NotNullable; default: Debug.Assert(false); // unexpected value return NullableAnnotation.Unknown; } } - private static TypeSymbolWithAnnotations GetNullCoalescingResultType(BoundExpression leftOperand, TypeSymbolWithAnnotations leftResult, BoundExpression rightOperand, TypeSymbolWithAnnotations rightResult, TypeSymbol resultType) + private static TypeWithState GetNullCoalescingResultType(BoundExpression leftOperand, TypeWithState leftResult, BoundExpression rightOperand, TypeWithState rightResult, TypeSymbol resultType) { - NullableAnnotation resultNullableAnnotation; - if (getValueNullableAnnotation(leftOperand, leftResult).IsAnyNotNullable()) + NullableFlowState resultState; + if (getNullableState(leftOperand, leftResult) == NullableFlowState.NotNull) { - resultNullableAnnotation = getNullableAnnotation(leftOperand, leftResult); + resultState = getNullableState(leftOperand, leftResult); } else { - resultNullableAnnotation = getNullableAnnotation(rightOperand, rightResult); + resultState = getNullableState(rightOperand, rightResult); } - return TypeSymbolWithAnnotations.Create(resultType, resultNullableAnnotation); - - NullableAnnotation getNullableAnnotation(BoundExpression e, TypeSymbolWithAnnotations t) - { - if (t.IsNull) - { - return GetNullableAnnotation(e); - } - - return t.NullableAnnotation; - } + return new TypeWithState(resultType, resultState); - NullableAnnotation getValueNullableAnnotation(BoundExpression e, TypeSymbolWithAnnotations t) + NullableFlowState getNullableState(BoundExpression e, TypeWithState t) { - if (t.IsNull) + if (t.HasNullType) { - return GetNullableAnnotation(e); + return GetNullableAnnotation(e).IsAnyNullable() ? NullableFlowState.MaybeNull : NullableFlowState.NotNull; } - return t.GetValueNullableAnnotation(); + return t.State; } } @@ -2163,110 +2148,43 @@ public override BoundNode VisitConditionalAccess(BoundConditionalAccess node) Debug.Assert(!IsConditionalState); var receiver = node.Receiver; - var receiverType = VisitRvalueWithResult(receiver); + var receiverType = VisitRvalueWithState(receiver); var receiverState = this.State.Clone(); - - if (receiver.Type?.IsValueType == false) + if (IsConstantNull(node.Receiver)) { - if (receiverType.ValueCanBeNull() == false) - { - ReportNonSafetyDiagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, receiver.Syntax); - } - + SetUnreachable(); + } + else + { + // In the right-hand-side, the left-hand-side is known to be non-null. + // https://github.com/dotnet/roslyn/issues/33347: This should probably be using GetSlotsToMarkAsNotNullable() rather than marking only one slot int slot = MakeSlot(SkipReferenceConversions(receiver)); if (slot > 0) { if (slot >= this.State.Capacity) Normalize(ref this.State); - this.State[slot] = NullableAnnotation.NotNullable; + this.State[slot] = NullableFlowState.NotNull; } } - if (IsConstantNull(node.Receiver)) - { - SetUnreachable(); - } - - VisitRvalue(node.AccessExpression); + var accessExpressionType = VisitRvalueWithState(node.AccessExpression); Join(ref this.State, ref receiverState); + // Per LDM 2019-02-13 decision, the result of a conditional access might be null even if + // both the receiver and right-hand-side are believed not to be null. + NullableFlowState resultState = NullableFlowState.MaybeNull; + // https://github.com/dotnet/roslyn/issues/29956 Use flow analysis type rather than node.Type + // so that nested nullability is inferred from flow analysis. See VisitConditionalOperator. TypeSymbol type = node.Type; - NullableAnnotation resultAnnotation; - - // If receiver or the access can produce nullable value, the result can be nullable. - // Otherwise, result is not nullable. - - if (type.SpecialType == SpecialType.System_Void || type.IsErrorType() || ResultType.IsNull) - { - resultAnnotation = NullableAnnotation.Unknown; - } - else if (ResultType.IsPossiblyNullableReferenceTypeTypeParameter()) - { - Debug.Assert(TypeSymbol.Equals(ResultType.TypeSymbol, type, TypeCompareKind.ConsiderEverything2)); - Conversion conversion; - HashSet useSiteDiagnostics = null; - if (!receiverType.GetValueNullableAnnotation().IsAnyNullable()) - { - resultAnnotation = NullableAnnotation.NotAnnotated; // Inherit nullability of the access - } - else if (receiverType.IsPossiblyNullableReferenceTypeTypeParameter() && - (conversion = _conversions.ClassifyConversionFromType(receiverType.TypeSymbol, ResultType.TypeSymbol, ref useSiteDiagnostics)).Exists && - !conversion.IsUserDefined) - { - // where T : U - // T?.U or U?.T - - // T?.U - // If T is nullable, U is also nullable - result is nullable - // If T is not nullable - result is nullable if U is nullable - // If U is nullable - result is nullable - // If U is not nullable, T is also not nullable - result is not nullable - // So, nullability of the result can be inferred from nullability of U, and the type of the result is U. - - // U ?. T - // If U is nullable - result is nullable - // If U is not nullable, T is also not nullable - result is not nullable - // If T is nullable, U is also nullable - result is nullable - // If T is not nullable - result is nullable if U is nullable - // So, nullability of the result can be inferred from nullability of U, but the type of the result is T. - // At the moment we don't have a way to represent this correlation, result type is one type parameter, but - // nullability comes from another. - // Ideally, we would want to have the following behavior: - // U x = U?.T - no warning - // T y = U?.T - a warning - // But we can track the state only in the way when either both produce a warning, or none. - // It feels like it is reasonable to prefer the latter approach, i.e. produce no warnings - // for both scenarios - no false diagnostics. - resultAnnotation = NullableAnnotation.NotAnnotated; // Inherit nullability of U - } - else - { - resultAnnotation = NullableAnnotation.Nullable; - } - } - else + // If the result type does not allow annotations, then we produce a warning because + // the result may be null. + if (RequiresSafetyWarningWhenNullIntroduced(type)) { - NullableAnnotation receiverAnnotation = receiverType.GetValueNullableAnnotation(); - NullableAnnotation accessAnnotation = ResultType.GetValueNullableAnnotation(); - if (receiverAnnotation.IsAnyNullable() || accessAnnotation.IsAnyNullable()) - { - resultAnnotation = NullableAnnotation.Nullable; - } - else if (receiverAnnotation == NullableAnnotation.Unknown || accessAnnotation == NullableAnnotation.Unknown) - { - resultAnnotation = NullableAnnotation.Unknown; - } - else - { - resultAnnotation = NullableAnnotation.NotNullable; - } + ReportSafetyDiagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, node.Syntax, node.Type); } - // https://github.com/dotnet/roslyn/issues/29956 Use flow analysis type rather than node.Type - // so that nested nullability is inferred from flow analysis. See VisitConditionalOperator. - ResultType = TypeSymbolWithAnnotations.Create(type, resultAnnotation); - // https://github.com/dotnet/roslyn/issues/29956 Report conversion warnings. + ResultType = new TypeWithState(type, resultState); return null; } @@ -2342,12 +2260,12 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node consequence, consequenceConversion, resultTypeWithAnnotations, - consequenceResult, + consequenceResult.ToTypeWithState(), checkConversion: true, fromExplicitCast: false, useLegacyWarnings: false, AssignmentKind.Assignment, - reportTopLevelWarnings: false); + reportTopLevelWarnings: false).ToTypeSymbolWithAnnotations(); } if (!isConstantTrue) @@ -2357,30 +2275,28 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node alternative, alternativeConversion, resultTypeWithAnnotations, - alternativeResult, + alternativeResult.ToTypeWithState(), checkConversion: true, fromExplicitCast: false, useLegacyWarnings: false, AssignmentKind.Assignment, - reportTopLevelWarnings: false); + reportTopLevelWarnings: false).ToTypeSymbolWithAnnotations(); } - if (convertedAlternativeResult.IsNull) + if (!convertedAlternativeResult.HasType) { - Debug.Assert(!convertedConsequenceResult.IsNull); + Debug.Assert(convertedConsequenceResult.HasType); visitResult = convertedConsequenceResult; } - else if (convertedConsequenceResult.IsNull) + else if (!convertedConsequenceResult.HasType) { - Debug.Assert(!convertedAlternativeResult.IsNull); + Debug.Assert(convertedAlternativeResult.HasType); visitResult = convertedAlternativeResult; } else { visitResult = TypeSymbolWithAnnotations.Create(resultType, - convertedConsequenceResult.NullableAnnotation.JoinForFlowAnalysisBranches(convertedAlternativeResult.NullableAnnotation, - resultType, - type => type.IsPossiblyNullableReferenceTypeTypeParameter())); + convertedConsequenceResult.NullableAnnotation.JoinForFixingLowerBounds(convertedAlternativeResult.NullableAnnotation)); } } else @@ -2397,20 +2313,18 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node } else { - resultNullableAnnotation = getNullableAnnotation(consequence, consequenceResult).JoinForFlowAnalysisBranches(getNullableAnnotation(alternative, alternativeResult), - node.Type, - type => type.IsPossiblyNullableReferenceTypeTypeParameter()); + resultNullableAnnotation = getNullableAnnotation(consequence, consequenceResult).JoinForFixingLowerBounds(getNullableAnnotation(alternative, alternativeResult)); } visitResult = TypeSymbolWithAnnotations.Create(node.Type.SetUnknownNullabilityForReferenceTypes(), resultNullableAnnotation); } - SetResult(visitResult, visitResult); + LvalueResultType = visitResult; return null; NullableAnnotation getNullableAnnotation(BoundExpression expr, TypeSymbolWithAnnotations type) { - if (!type.IsNull) + if (type.HasType) { return type.GetValueNullableAnnotation(); } @@ -2425,31 +2339,36 @@ NullableAnnotation getNullableAnnotation(BoundExpression expr, TypeSymbolWithAnn { Conversion conversion; SetState(state); - TypeSymbolWithAnnotations result; + TypeSymbolWithAnnotations resultWithAnnotation; if (isByRef) { - Visit(operand); - result = _visitResult.LValueType; + resultWithAnnotation = VisitLvalueWithAnnotations(operand); conversion = Conversion.Identity; } else { (operand, conversion) = RemoveConversion(operand, includeExplicitConversions: false); Visit(operand); - result = _visitResult.RValueType; + if (node.HasErrors) + { + ResultType = ResultType.WithNotNullState(); + } + + resultWithAnnotation = ResultType.ToTypeSymbolWithAnnotations(); } - return (operand, conversion, result); + + return (operand, conversion, resultWithAnnotation); } } /// - /// Placeholders are bound expressions with type and annotation, when available. + /// Placeholders are bound expressions with type and state. /// But for typeless expressions (such as `null` or `(null, null)` we hold onto the original bound expression, /// as it will be useful for conversions from expression. /// private static BoundExpression CreatePlaceholderIfNecessary(BoundExpression expr, TypeSymbolWithAnnotations type) { - return type.IsNull ? + return !type.HasType ? expr : new BoundExpressionWithNullability(expr.Syntax, expr, type.NullableAnnotation, type.TypeSymbol); } @@ -2459,29 +2378,29 @@ public override BoundNode VisitConditionalReceiver(BoundConditionalReceiver node var result = base.VisitConditionalReceiver(node); // https://github.com/dotnet/roslyn/issues/29956 ConditionalReceiver does not // have a result type. Should this be moved to ConditionalAccess? - ResultType = TypeSymbolWithAnnotations.Create(node.Type, NullableAnnotation.NotNullable); + SetNotNullResult(node); return result; } public override BoundNode VisitCall(BoundCall node) { // Note: we analyze even omitted calls - TypeSymbolWithAnnotations receiverType = VisitCallReceiver(node); + TypeWithState receiverType = VisitCallReceiver(node); ReinferMethodAndVisitArguments(node, receiverType); return null; } - private void ReinferMethodAndVisitArguments(BoundCall node, TypeSymbolWithAnnotations receiverType) + private void ReinferMethodAndVisitArguments(BoundCall node, TypeWithState receiverType) { // https://github.com/dotnet/roslyn/issues/29605 Can we handle some error cases? // (Compare with CSharpOperationFactory.CreateBoundCallOperation.) var method = node.Method; ImmutableArray refKindsOpt = node.ArgumentRefKindsOpt; (ImmutableArray arguments, ImmutableArray conversions) = RemoveArgumentConversions(node.Arguments, refKindsOpt); - if (!receiverType.IsNull) + if (!receiverType.HasNullType) { // Update method based on inferred receiver type. - method = (MethodSymbol)AsMemberOfResultType(receiverType, method); + method = (MethodSymbol)AsMemberOfType(receiverType.Type, method); } method = VisitArguments(node, arguments, refKindsOpt, method.Parameters, node.ArgsToParamsOpt, @@ -2496,18 +2415,18 @@ private void ReinferMethodAndVisitArguments(BoundCall node, TypeSymbolWithAnnota //if (this.State.Reachable) // Consider reachability: see https://github.com/dotnet/roslyn/issues/28798 { var type = method.ReturnType; - SetResult(type, type); + LvalueResultType = type; } } - private TypeSymbolWithAnnotations VisitCallReceiver(BoundCall node) + private TypeWithState VisitCallReceiver(BoundCall node) { var receiverOpt = node.ReceiverOpt; - TypeSymbolWithAnnotations receiverType = default; + TypeWithState receiverType = default; if (receiverOpt != null && node.Method.MethodKind != MethodKind.Constructor) { - receiverType = VisitRvalueWithResult(receiverOpt); + receiverType = VisitRvalueWithState(receiverOpt); // https://github.com/dotnet/roslyn/issues/30598: Mark receiver as not null // after arguments have been visited, and only if the receiver has not changed. CheckPossibleNullReceiver(receiverOpt); @@ -2588,7 +2507,7 @@ FlowAnalysisAnnotations removeInapplicableNotNullWhenSense(ParameterSymbol param } // NotNullWhenSense must be applied to a reference type, a nullable value type, or an unconstrained generic type - if ((annotations & whenSense) != 0 && parameter.Type.IsValueType && !parameter.Type.IsNullableType()) + if ((annotations & whenSense) != 0 && !parameter.Type.TypeSymbol.CanContainNull()) { annotations &= ~whenSense; } @@ -2729,40 +2648,51 @@ private ImmutableArray VisitArgumentsEvaluate(ImmutableArray.GetInstance(n); for (int i = 0; i < n; i++) { - VisitArgumentEvaluate(arguments, refKindsOpt, i, preserveConditionalState: false); - builder.Add(_visitResult); + builder.Add(VisitArgumentEvaluate(arguments, refKindsOpt, i, preserveConditionalState: false)); } ResultType = _invalidType; return builder.ToImmutableAndFree(); } - private void VisitArgumentEvaluate(ImmutableArray arguments, ImmutableArray refKindsOpt, int i, bool preserveConditionalState) + private VisitResult VisitArgumentEvaluate(ImmutableArray arguments, ImmutableArray refKindsOpt, int i, bool preserveConditionalState) { Debug.Assert(!IsConditionalState); RefKind refKind = GetRefKind(refKindsOpt, i); var argument = arguments[i]; - if (refKind != RefKind.Out) + switch (refKind) { - if (preserveConditionalState) - { + case RefKind.Ref: + Visit(argument); + if (!preserveConditionalState) + { + Unsplit(); + } + break; + case RefKind.None: + case RefKind.In: + if (preserveConditionalState) + { + Visit(argument); + // No Unsplit + UseRvalueOnly(); // force use of flow result + } + else + { + VisitRvalue(argument); + } + break; + case RefKind.Out: + // As far as we can tell, there is no scenario relevant to nullability analysis + // where splitting an L-value (for instance with a ref conditional) would affect the result. Visit(argument); - // No Unsplit - } - else - { - VisitRvalue(argument); - } - } - else - { - // As far as we can tell, there is no scenario relevant to nullability analysis - // where splitting an L-value (for instance with a ref conditional) would affect the result. - Visit(argument); - // We'll want to use the l-value type, rather than the result type, for method re-inference - SetResult(_visitResult.LValueType, _visitResult.LValueType); + // We'll want to use the l-value type, rather than the result type, for method re-inference + UseLvalueOnly(); + break; } + + return _visitResult; } /// @@ -2833,11 +2763,11 @@ private void VisitArgumentsEvaluateHonoringAnnotations( if (notNullWhenTrue) { - MarkSlotsAsNotNullable(slotBuilder, ref StateWhenTrue); + MarkSlotsAsNotNull(slotBuilder, ref StateWhenTrue); } if (notNullWhenFalse) { - MarkSlotsAsNotNullable(slotBuilder, ref StateWhenFalse); + MarkSlotsAsNotNull(slotBuilder, ref StateWhenFalse); if (notNullWhenTrue && !wasPreviouslySplit) Unsplit(); } slotBuilder.Free(); @@ -2913,21 +2843,22 @@ private void VisitArgumentConversion( bool extensionMethodThisArgument) { var resultType = result.RValueType; + bool reported = false; switch (refKind) { case RefKind.None: case RefKind.In: { ApplyConversion( - argument, - argument, - conversion, - parameterType, - resultType, + node: argument, + operandOpt: argument, + conversion: conversion, + targetTypeWithNullability: parameterType, + operandType: resultType, checkConversion: true, fromExplicitCast: false, useLegacyWarnings: false, - AssignmentKind.Argument, + assignmentKind: AssignmentKind.Argument, target: parameter, extensionMethodThisArgument: extensionMethodThisArgument); } @@ -2936,13 +2867,15 @@ private void VisitArgumentConversion( { if (!argument.IsSuppressed) { - if (!ReportNullableAssignmentIfNecessary(argument, parameterType, resultType, - useLegacyWarnings: false, AssignmentKind.Argument, target: parameter)) + reported = ReportNullableAssignmentIfNecessary(argument, parameterType, resultType, + useLegacyWarnings: false, AssignmentKind.Argument, target: parameter); + if (!reported) { HashSet useSiteDiagnostics = null; - if (!_conversions.HasIdentityOrImplicitReferenceConversion(resultType.TypeSymbol, parameterType.TypeSymbol, ref useSiteDiagnostics)) + if (!_conversions.HasIdentityOrImplicitReferenceConversion(resultType.Type, parameterType.TypeSymbol, ref useSiteDiagnostics)) { - ReportNullabilityMismatchInArgument(argument, resultType.TypeSymbol, parameter, parameterType.TypeSymbol, forOutput: false); + ReportNullabilityMismatchInArgument(argument, resultType.Type, parameter, parameterType.TypeSymbol, forOutput: false); + reported = true; } } } @@ -2950,6 +2883,7 @@ private void VisitArgumentConversion( goto case RefKind.Out; case RefKind.Out: { + var parameterWithState = parameterType.ToTypeWithState(); if (argument is BoundLocal local && local.DeclarationKind == BoundLocalDeclarationKind.WithInferredType) { _variableTypes[local.LocalSymbol] = parameterType; @@ -2960,9 +2894,9 @@ private void VisitArgumentConversion( // so we're going to check assignment from a fictional value from the parameter to the argument. var parameterValue = new BoundParameter(argument.Syntax, parameter); - if (!argument.IsSuppressed) + if (!argument.IsSuppressed && !reported) { - ReportNullableAssignmentIfNecessary(parameterValue, lValueType, parameterType, useLegacyWarnings: UseLegacyWarnings(argument)); + ReportNullableAssignmentIfNecessary(parameterValue, lValueType, parameterWithState, useLegacyWarnings: UseLegacyWarnings(argument)); HashSet useSiteDiagnostics = null; if (!_conversions.HasIdentityOrImplicitReferenceConversion(parameterType.TypeSymbol, lValueType.TypeSymbol, ref useSiteDiagnostics)) @@ -2972,11 +2906,11 @@ private void VisitArgumentConversion( } else { - parameterType = parameterType.WithTopLevelNonNullability(); + parameterWithState = parameterWithState.WithNotNullState(); } // Set nullable state of argument to parameter type. - TrackNullableStateForAssignment(parameterValue, lValueType, MakeSlot(argument), parameterType); + TrackNullableStateForAssignment(parameterValue, lValueType, MakeSlot(argument), parameterWithState); } break; default: @@ -3145,6 +3079,7 @@ private MethodSymbol InferMethodTypeArguments(BoundCall node, MethodSymbol metho { return method; } + return definition.Construct(result.InferredTypeArguments); } @@ -3163,7 +3098,10 @@ private ImmutableArray GetArgumentsForMethodTypeInference(Immut var builder = ArrayBuilder.GetInstance(n); for (int i = 0; i < n; i++) { - builder.Add(getArgumentForMethodTypeInference(arguments[i], argumentResults[i].RValueType)); + var argumentResult = argumentResults[i].LValueType; + if (!argumentResult.HasType) + argumentResult = argumentResults[i].RValueType.ToTypeSymbolWithAnnotations(); + builder.Add(getArgumentForMethodTypeInference(arguments[i], argumentResult)); } return builder.ToImmutableAndFree(); @@ -3176,7 +3114,7 @@ BoundExpression getArgumentForMethodTypeInference(BoundExpression argument, Type // to re-bind lambdas in MethodTypeInferrer. return GetUnboundLambda((BoundLambda)argument, GetVariableState()); } - if (argumentType.IsNull) + if (!argumentType.HasType) { return argument; } @@ -3325,32 +3263,32 @@ private static bool UseExpressionForConversion(BoundExpression value) /// /// Adjust declared type based on inferred nullability at the point of reference. /// - private TypeSymbolWithAnnotations GetAdjustedResult(TypeSymbolWithAnnotations type, int slot) + private TypeWithState GetAdjustedResult(TypeSymbolWithAnnotations type, int slot) + { + return GetAdjustedResult(type.ToTypeWithState(), slot); + } + + private TypeWithState GetAdjustedResult(TypeWithState type, int slot) { if (slot > 0 && slot < this.State.Capacity) { - NullableAnnotation annotation = this.State[slot]; - if (annotation != type.NullableAnnotation) - { - return TypeSymbolWithAnnotations.Create(type.TypeSymbol, annotation); - } + NullableFlowState state = this.State[slot]; + return new TypeWithState(type.Type, state); } + return type; } - private static Symbol AsMemberOfResultType(TypeSymbolWithAnnotations resultType, Symbol symbol) + private static Symbol AsMemberOfType(TypeSymbol type, Symbol symbol) { - var containingType = resultType.TypeSymbol as NamedTypeSymbol; - if ((object)containingType == null || containingType.IsErrorType() || symbol is ErrorMethodSymbol) + Debug.Assert((object)symbol != null); + + var containingType = type as NamedTypeSymbol; + if (containingType is null || containingType.IsErrorType() || symbol is ErrorMethodSymbol) { return symbol; } - return AsMemberOfType(containingType, symbol); - } - private static Symbol AsMemberOfType(NamedTypeSymbol containingType, Symbol symbol) - { - Debug.Assert((object)symbol != null); if (symbol.Kind == SymbolKind.Method) { if (((MethodSymbol)symbol).MethodKind == MethodKind.LocalFunction) @@ -3386,7 +3324,7 @@ private static Symbol AsMemberOfType(NamedTypeSymbol containingType, Symbol symb return result; } containingType = containingType.BaseTypeNoUseSiteDiagnostics; - if ((object)containingType == null) + if (containingType is null) { break; } @@ -3431,12 +3369,12 @@ public override BoundNode VisitConversion(BoundConversion node) //Debug.Assert(!node.ConversionGroupOpt.ExplicitType.IsNull); TypeSymbolWithAnnotations explicitType = node.ConversionGroupOpt?.ExplicitType ?? default; - bool fromExplicitCast = !explicitType.IsNull; + bool fromExplicitCast = explicitType.HasType; TypeSymbolWithAnnotations targetType = fromExplicitCast ? explicitType : TypeSymbolWithAnnotations.Create(node.Type); - Debug.Assert(!targetType.IsNull); + Debug.Assert(targetType.HasType); (BoundExpression operand, Conversion conversion) = RemoveConversion(node, includeExplicitConversions: true); - TypeSymbolWithAnnotations operandType = VisitRvalueWithResult(operand); + TypeWithState operandType = VisitRvalueWithState(operand); ResultType = ApplyConversion( node, operand, @@ -3445,7 +3383,7 @@ public override BoundNode VisitConversion(BoundConversion node) operandType, checkConversion: true, fromExplicitCast: fromExplicitCast, - useLegacyWarnings: fromExplicitCast, + useLegacyWarnings: fromExplicitCast && !RequiresSafetyWarningWhenNullIntroduced(explicitType.TypeSymbol), AssignmentKind.Assignment, reportTopLevelWarnings: fromExplicitCast, reportRemainingWarnings: true); @@ -3467,15 +3405,15 @@ public override BoundNode VisitConversion(BoundConversion node) /// an implicit conversion, even if that conversion was omitted from the bound tree, /// so the conversion can be re-classified with nullability. /// - private TypeSymbolWithAnnotations VisitOptionalImplicitConversion(BoundExpression expr, TypeSymbolWithAnnotations targetTypeOpt, bool useLegacyWarnings, AssignmentKind assignmentKind) + private TypeWithState VisitOptionalImplicitConversion(BoundExpression expr, TypeSymbolWithAnnotations targetTypeOpt, bool useLegacyWarnings, AssignmentKind assignmentKind) { - if (targetTypeOpt.IsNull) + if (!targetTypeOpt.HasType) { - return VisitRvalueWithResult(expr); + return VisitRvalueWithState(expr); } (BoundExpression operand, Conversion conversion) = RemoveConversion(expr, includeExplicitConversions: false); - var operandType = VisitRvalueWithResult(operand); + var operandType = VisitRvalueWithState(operand); // If an explicit conversion was used in place of an implicit conversion, the explicit // conversion was created by initial binding after reporting "error CS0266: // Cannot implicitly convert type '...' to '...'. An explicit conversion exists ...". @@ -3534,7 +3472,8 @@ public override BoundNode VisitConvertedTupleLiteral(BoundConvertedTupleLiteral private void VisitTupleExpression(BoundTupleExpression node) { var arguments = node.Arguments; - ImmutableArray elementTypes = arguments.SelectAsArray((a, w) => w.VisitRvalueWithResult(a), this); + ImmutableArray elementTypes = arguments.SelectAsArray((a, w) => w.VisitRvalueWithState(a), this); + ImmutableArray elementTypesWithAnnotations = elementTypes.SelectAsArray(a => a.ToTypeSymbolWithAnnotations()); var tupleOpt = (TupleTypeSymbol)node.Type; if (tupleOpt is null) { @@ -3545,14 +3484,14 @@ private void VisitTupleExpression(BoundTupleExpression node) int slot = GetOrCreateObjectCreationPlaceholderSlot(node); if (slot > 0) { - this.State[slot] = NullableAnnotation.NotNullable; + this.State[slot] = NullableFlowState.NotNull; TrackNullableStateOfTupleElements(slot, tupleOpt, arguments, elementTypes, useRestField: false); } - tupleOpt = tupleOpt.WithElementTypes(elementTypes); + tupleOpt = tupleOpt.WithElementTypes(elementTypesWithAnnotations); var locations = tupleOpt.TupleElements.SelectAsArray((element, location) => element.Locations.FirstOrDefault() ?? location, node.Syntax.Location); tupleOpt.CheckConstraints(_conversions, includeNullability: true, node.Syntax, locations, compilation, diagnosticsOpt: null, nullabilityDiagnosticsOpt: Diagnostics); - ResultType = TypeSymbolWithAnnotations.Create(tupleOpt, NullableAnnotation.NotNullable); + ResultType = new TypeWithState(tupleOpt, NullableFlowState.NotNull); } } @@ -3565,7 +3504,7 @@ private void TrackNullableStateOfTupleElements( int slot, TupleTypeSymbol tupleType, ImmutableArray values, - ImmutableArray types, + ImmutableArray types, bool useRestField) { Debug.Assert(values.Length == types.Length); @@ -3593,11 +3532,11 @@ private void TrackNullableStateOfTupleElements( } } - void trackState(BoundExpression value, FieldSymbol field, TypeSymbolWithAnnotations valueType) => + void trackState(BoundExpression value, FieldSymbol field, TypeWithState valueType) => TrackNullableStateForAssignment(value, field.Type, GetOrCreateSlot(field, slot), valueType, MakeSlot(value)); } - private void TrackNullableStateOfNullableValue(int containingSlot, TypeSymbol containingType, BoundExpression value, TypeSymbolWithAnnotations valueType, int valueSlot) + private void TrackNullableStateOfNullableValue(int containingSlot, TypeSymbol containingType, BoundExpression value, TypeWithState valueType, int valueSlot) { Debug.Assert(containingType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T); Debug.Assert(containingSlot > 0); @@ -3626,7 +3565,7 @@ private void TrackNullableStateIfNullableConversion(BoundConversion node) { int containingSlot = GetOrCreateObjectCreationPlaceholderSlot(node); Debug.Assert(containingSlot > 0); - TrackNullableStateOfNullableValue(containingSlot, convertedType, operand, underlyingType, valueSlot); + TrackNullableStateOfNullableValue(containingSlot, convertedType, operand, underlyingType.ToTypeWithState(), valueSlot); } } } @@ -3634,7 +3573,7 @@ private void TrackNullableStateIfNullableConversion(BoundConversion node) public override BoundNode VisitTupleBinaryOperator(BoundTupleBinaryOperator node) { base.VisitTupleBinaryOperator(node); - SetResult(node); + SetNotNullResult(node); return null; } @@ -3736,12 +3675,12 @@ private bool HasTopLevelNullabilityConversion(TypeSymbolWithAnnotations source, /// the type returned by this method.) `canConvertNestedNullability` is set if the conversion /// considering nested nullability succeeded. `node` is used only for the location of diagnostics. /// - private TypeSymbolWithAnnotations ApplyConversion( + private TypeWithState ApplyConversion( BoundExpression node, BoundExpression operandOpt, Conversion conversion, TypeSymbolWithAnnotations targetTypeWithNullability, - TypeSymbolWithAnnotations operandType, + TypeWithState operandType, bool checkConversion, bool fromExplicitCast, bool useLegacyWarnings, @@ -3752,12 +3691,11 @@ private TypeSymbolWithAnnotations ApplyConversion( bool extensionMethodThisArgument = false) { Debug.Assert(node != null); - Debug.Assert(operandOpt != null || !operandType.IsNull); - Debug.Assert(!targetTypeWithNullability.IsNull); + Debug.Assert(operandOpt != null || !operandType.HasNullType); + Debug.Assert(targetTypeWithNullability.HasType); Debug.Assert((object)target != null || assignmentKind != AssignmentKind.Argument); - NullableAnnotation resultAnnotation = NullableAnnotation.Unknown; - bool forceOperandAnnotationForResult = false; + NullableFlowState resultState = NullableFlowState.NotNull; bool canConvertNestedNullability = true; bool isSuppressed = false; @@ -3776,7 +3714,7 @@ private TypeSymbolWithAnnotations ApplyConversion( { ReportNullabilityMismatchWithTargetDelegate(node.Syntax, targetType.GetDelegateType(), conversion.Method); } - resultAnnotation = NullableAnnotation.NotNullable; + resultState = NullableFlowState.NotNull; break; case ConversionKind.AnonymousFunction: @@ -3792,12 +3730,13 @@ private TypeSymbolWithAnnotations ApplyConversion( { ReportNullabilityMismatchWithTargetDelegate(node.Syntax, delegateType, unboundLambda); } - return TypeSymbolWithAnnotations.Create(targetType, NullableAnnotation.NotNullable); + + return new TypeWithState(targetType, NullableFlowState.NotNull); } break; case ConversionKind.InterpolatedString: - resultAnnotation = NullableAnnotation.NotNullable; + resultState = NullableFlowState.NotNull; break; case ConversionKind.ExplicitUserDefined: @@ -3830,14 +3769,17 @@ private TypeSymbolWithAnnotations ApplyConversion( Debug.Assert(methodOpt.ParameterCount == 1); var parameter = methodOpt.Parameters[0]; var parameterType = parameter.Type; - TypeSymbolWithAnnotations underlyingOperandType = default; - bool isLiftedConversion = - operandType.IsNullableType() && - !parameterType.IsNullableType() && - parameterType.Equals(underlyingOperandType = operandType.GetNullableUnderlyingType(), TypeCompareKind.AllIgnoreOptions); + TypeWithState underlyingOperandType = default; + bool isLiftedConversion = false; + if (operandType.Type.IsNullableType() && !parameterType.IsNullableType()) + { + var underlyingOperandTypeWithAnnotations = operandType.Type.GetNullableUnderlyingTypeWithAnnotations(); + underlyingOperandType = underlyingOperandTypeWithAnnotations.ToTypeWithState(); + isLiftedConversion = parameterType.Equals(underlyingOperandTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions); + } // conversion "from" type -> method parameter type - NullableAnnotation operandAnnotation = operandType.NullableAnnotation; + NullableFlowState operandState = operandType.State; _ = ClassifyAndApplyConversion(operandOpt ?? node, parameterType, isLiftedConversion ? underlyingOperandType : operandType, useLegacyWarnings, AssignmentKind.Argument, target: parameter, reportWarnings: reportRemainingWarnings); @@ -3845,17 +3787,15 @@ private TypeSymbolWithAnnotations ApplyConversion( var methodReturnType = methodOpt.ReturnType; if (isLiftedConversion) { - operandType = TypeSymbolWithAnnotations.Create( - methodReturnType.IsValueType && !methodReturnType.IsNullableType() ? - compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(ImmutableArray.Create(methodReturnType)) : - methodReturnType.TypeSymbol, - methodReturnType.NullableAnnotation.IsAnyNullable() || operandAnnotation.IsAnyNullable() ? - NullableAnnotation.Nullable : - (methodReturnType.IsPossiblyNullableReferenceTypeTypeParameter() ? methodReturnType.NullableAnnotation : NullableAnnotation.NotNullable)); + operandType = LiftedReturnType(methodReturnType, operandState); + if (RequiresSafetyWarningWhenNullIntroduced(methodReturnType.TypeSymbol) && operandState == NullableFlowState.MaybeNull) + { + ReportNullableAssignmentIfNecessary(node, targetTypeWithNullability, operandType, useLegacyWarnings: useLegacyWarnings, assignmentKind, target, conversion: conversion); + } } else { - operandType = methodReturnType; + operandType = methodReturnType.ToTypeWithState(); } // method return type -> conversion "to" type @@ -3874,65 +3814,12 @@ private TypeSymbolWithAnnotations ApplyConversion( case ConversionKind.ExplicitDynamic: case ConversionKind.ImplicitDynamic: - resultAnnotation = operandType.IsNull ? NullableAnnotation.Unknown : operandType.NullableAnnotation; - if (resultAnnotation == NullableAnnotation.NotAnnotated && targetType.IsTypeParameter()) - { - resultAnnotation = NullableAnnotation.NotNullable; - } - else if (targetType.IsValueType) - { - Debug.Assert(!operandType.IsNull); // If assert fails, add a test that verifies resulting type is nullable. - resultAnnotation = (targetType.IsNullableType() && (operandType.IsNull || operandType.NullableAnnotation.IsAnyNullable())) ? NullableAnnotation.Nullable : NullableAnnotation.NotNullable; - } - break; - - case ConversionKind.ImplicitThrow: - break; - case ConversionKind.Unboxing: - if (targetType.IsValueType) - { - Debug.Assert(!operandType.IsNull); // If assert fails, add a test that verifies resulting type is nullable. - resultAnnotation = (targetType.IsNullableTypeOrTypeParameter() && (operandType.IsNull || operandType.NullableAnnotation.IsAnyNullable())) ? NullableAnnotation.Nullable : NullableAnnotation.NotNullable; - } - else if (!operandType.IsNull && targetType.IsTypeParameter()) - { - resultAnnotation = operandType.GetValueNullableAnnotation(); - - if (resultAnnotation == NullableAnnotation.NotAnnotated) - { - resultAnnotation = NullableAnnotation.NotNullable; - } - } + case ConversionKind.Boxing: + resultState = operandType.State; break; - case ConversionKind.Boxing: - if (!operandType.IsNull) - { - if (operandType.IsValueType) - { - resultAnnotation = (operandType.IsNullableTypeOrTypeParameter() && operandType.GetValueNullableAnnotation().IsAnyNullable()) ? NullableAnnotation.Nullable : NullableAnnotation.NotNullable; - break; - } - else if (IsTypeParameterDisallowingAnnotation(operandType.TypeSymbol)) - { - if (operandType.IsPossiblyNullableReferenceTypeTypeParameter() && !targetTypeWithNullability.IsPossiblyNullableReferenceTypeTypeParameter()) - { - resultAnnotation = NullableAnnotation.Nullable; - forceOperandAnnotationForResult = targetType.IsPossiblyNullableReferenceTypeTypeParameter(); - } - else - { - resultAnnotation = operandType.NullableAnnotation; - } - break; - } - } - Debug.Assert(operandType.IsNull || - !operandType.IsReferenceType || - operandType.SpecialType == SpecialType.System_ValueType || - operandType.TypeKind == TypeKind.Interface || - operandType.TypeKind == TypeKind.Dynamic); + case ConversionKind.ImplicitThrow: break; case ConversionKind.NoConversion: @@ -3949,90 +3836,62 @@ private TypeSymbolWithAnnotations ApplyConversion( { var operandConversion = (BoundConversion)operandOpt; var explicitType = operandConversion.ConversionGroupOpt.ExplicitType; - if (!explicitType.IsNull && explicitType.Equals(targetTypeWithNullability, TypeCompareKind.IgnoreInsignificantNullableModifiersDifference)) + if (explicitType.HasType && explicitType.Equals(targetTypeWithNullability, TypeCompareKind.IgnoreInsignificantNullableModifiersDifference)) { return operandType; } } - if (operandType.TypeSymbol?.IsTupleType == true) + if (operandType.Type?.IsTupleType == true) { goto case ConversionKind.ImplicitTuple; } goto case ConversionKind.ImplicitReference; case ConversionKind.ImplicitReference: - case ConversionKind.ExplicitReference: - if (operandType.IsNull && operandOpt.IsLiteralNullOrDefault()) + if (reportTopLevelWarnings && + operandOpt?.Kind == BoundKind.Literal && + operandOpt.ConstantValue?.IsNull == true && + !isSuppressed && + RequiresSafetyWarningWhenNullIntroduced(targetType)) { - resultAnnotation = NullableAnnotation.Nullable; + // For type parameters that cannot be annotated, the analysis must report those + // places where null values first sneak in, like `default`, `null`, and `GetFirstOrDefault`. + // This is one of those places. + ReportSafetyDiagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, node.Syntax, targetType); } - else - { - // Inherit state from the operand. - if (checkConversion) - { - // https://github.com/dotnet/roslyn/issues/29959 Assert conversion is similar to original. - conversion = GenerateConversion(_conversions, operandOpt, operandType.TypeSymbol, targetType, fromExplicitCast, extensionMethodThisArgument); - canConvertNestedNullability = conversion.Exists; - } + goto case ConversionKind.ExplicitReference; - if (operandType.IsNull) - { - resultAnnotation = NullableAnnotation.Unknown; - } - else if (operandType.IsPossiblyNullableReferenceTypeTypeParameter()) - { - if (conversion.Kind == ConversionKind.ExplicitReference) - { - resultAnnotation = NullableAnnotation.Nullable; - } - else if (!targetTypeWithNullability.IsPossiblyNullableReferenceTypeTypeParameter()) - { - resultAnnotation = NullableAnnotation.Nullable; - forceOperandAnnotationForResult = targetType.IsPossiblyNullableReferenceTypeTypeParameter(); - } - else - { - resultAnnotation = operandType.NullableAnnotation; - } - } - else - { - resultAnnotation = operandType.NullableAnnotation; - if (resultAnnotation == NullableAnnotation.NotAnnotated && targetType.IsTypeParameter()) - { - resultAnnotation = NullableAnnotation.NotNullable; - } - } + case ConversionKind.ExplicitReference: + // Inherit state from the operand. + if (checkConversion) + { + // https://github.com/dotnet/roslyn/issues/29959 Assert conversion is similar to original. + conversion = GenerateConversion(_conversions, operandOpt, operandType.Type, targetType, fromExplicitCast, extensionMethodThisArgument); + canConvertNestedNullability = conversion.Exists; } + + resultState = operandType.State; break; case ConversionKind.ImplicitNullable: if (checkConversion) { - conversion = GenerateConversion(_conversions, operandOpt, operandType.TypeSymbol, targetType, fromExplicitCast, extensionMethodThisArgument); + conversion = GenerateConversion(_conversions, operandOpt, operandType.Type, targetType, fromExplicitCast, extensionMethodThisArgument); canConvertNestedNullability = conversion.Exists; } - if ((targetType.IsValueType && !targetType.IsNullableType()) || - (operandType.IsValueType && !operandType.IsNullableType())) - { - resultAnnotation = NullableAnnotation.NotNullable; - } - else - { - resultAnnotation = operandType.NullableAnnotation.IsAnyNullable() ? NullableAnnotation.Nullable : NullableAnnotation.NotNullable; - } + + resultState = operandType.State; break; case ConversionKind.ExplicitNullable: - if (operandType.TypeSymbol?.IsNullableType() == true && - !targetType.IsNullableType()) + if (operandType.Type?.IsNullableType() == true && !targetType.IsNullableType()) { // Explicit conversion of Nullable to T is equivalent to Nullable.Value. - if (reportTopLevelWarnings && operandType.NullableAnnotation.IsAnyNullable()) + if (reportTopLevelWarnings && operandType.MaybeNull) { ReportSafetyDiagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, node.Syntax); } + // Mark the value as not nullable, regardless of whether it was known to be nullable, // because the implied call to `.Value` will only succeed if not null. if (operandOpt != null) @@ -4040,7 +3899,7 @@ private TypeSymbolWithAnnotations ApplyConversion( int slot = MakeSlot(operandOpt); if (slot > 0) { - this.State[slot] = NullableAnnotation.NotNullable; + this.State[slot] = NullableFlowState.NotNull; } } } @@ -4053,10 +3912,10 @@ private TypeSymbolWithAnnotations ApplyConversion( if (checkConversion) { // https://github.com/dotnet/roslyn/issues/29699: Report warnings for user-defined conversions on tuple elements. - conversion = GenerateConversion(_conversions, operandOpt, operandType.TypeSymbol, targetType, fromExplicitCast, extensionMethodThisArgument); + conversion = GenerateConversion(_conversions, operandOpt, operandType.Type, targetType, fromExplicitCast, extensionMethodThisArgument); canConvertNestedNullability = conversion.Exists; } - resultAnnotation = NullableAnnotation.NotNullable; + resultState = NullableFlowState.NotNull; break; case ConversionKind.Deconstruction: @@ -4075,54 +3934,82 @@ private TypeSymbolWithAnnotations ApplyConversion( if (isSuppressed) { - resultAnnotation = NullableAnnotation.NotNullable; + resultState = NullableFlowState.NotNull; + } + else if (fromExplicitCast && targetTypeWithNullability.NullableAnnotation == NullableAnnotation.Annotated && !targetType.IsNullableType()) + { + // An explicit cast to a nullable reference type introduces nullability + resultState = NullableFlowState.MaybeNull; } - var resultType = TypeSymbolWithAnnotations.Create(targetType, resultAnnotation); + var resultType = new TypeWithState(targetType, resultState); - if (operandType.TypeSymbol?.IsErrorType() != true && !targetType.IsErrorType()) + if (operandType.Type?.IsErrorType() != true && !targetType.IsErrorType()) { // Need to report all warnings that apply since the warnings can be suppressed individually. if (reportTopLevelWarnings) { - ReportNullableAssignmentIfNecessary(node, targetTypeWithNullability, resultType, useLegacyWarnings, assignmentKind, target); + if (RequiresSafetyWarningWhenNullIntroduced(targetType) && conversion.IsImplicit && !conversion.IsDynamic) + { + // For type parameters that cannot be annotated, the analysis must report those + // places where null values first sneak in, like `default`, `null`, and `GetFirstOrDefault`, + // as a safety diagnostic. But we do not warn when such values flow through implicit conversion. + } + else + { + ReportNullableAssignmentIfNecessary(node, targetTypeWithNullability, operandType, useLegacyWarnings, assignmentKind, target, conversion: conversion); + } } if (reportRemainingWarnings && !canConvertNestedNullability) { if (assignmentKind == AssignmentKind.Argument) { - ReportNullabilityMismatchInArgument(node, operandType.TypeSymbol, target, targetType, forOutput: false); + ReportNullabilityMismatchInArgument(node, operandType.Type, target, targetType, forOutput: false); } else { - ReportNullabilityMismatchInAssignment(node.Syntax, GetTypeAsDiagnosticArgument(operandType.TypeSymbol), targetType); + ReportNullabilityMismatchInAssignment(node.Syntax, GetTypeAsDiagnosticArgument(operandType.Type), targetType); } } } - if (forceOperandAnnotationForResult) - { - resultType = TypeSymbolWithAnnotations.Create(targetType, operandType.NullableAnnotation); - } - return resultType; } - private TypeSymbolWithAnnotations ClassifyAndApplyConversion(BoundExpression node, TypeSymbolWithAnnotations targetType, TypeSymbolWithAnnotations operandType, - bool useLegacyWarnings, AssignmentKind assignmentKind, ParameterSymbol target, bool reportWarnings) + /// + /// Return the return type for a lifted operator, given the nullability state of its operands. + /// + private TypeWithState LiftedReturnType(TypeSymbolWithAnnotations returnType, NullableFlowState operandState) + { + bool typeNeedsLifting = returnType.TypeSymbol.IsNonNullableValueType(); + TypeSymbol type = typeNeedsLifting + ? compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(ImmutableArray.Create(returnType)) + : returnType.TypeSymbol; + NullableFlowState state = returnType.ToTypeWithState().State.JoinForFlowAnalysisBranches(operandState); + return new TypeWithState(type, state); + } + + private TypeWithState ClassifyAndApplyConversion( + BoundExpression node, + TypeSymbolWithAnnotations targetType, + TypeWithState operandType, + bool useLegacyWarnings, + AssignmentKind assignmentKind, + ParameterSymbol target, + bool reportWarnings) { Debug.Assert((object)target != null || assignmentKind != AssignmentKind.Argument); HashSet useSiteDiagnostics = null; - var conversion = _conversions.ClassifyStandardConversion(null, operandType.TypeSymbol, targetType.TypeSymbol, ref useSiteDiagnostics); + var conversion = _conversions.ClassifyStandardConversion(null, operandType.Type, targetType.TypeSymbol, ref useSiteDiagnostics); if (reportWarnings && !conversion.Exists) { if (assignmentKind == AssignmentKind.Argument) { - ReportNullabilityMismatchInArgument(node, operandType.TypeSymbol, target, targetType.TypeSymbol, forOutput: false); + ReportNullabilityMismatchInArgument(node, operandType.Type, target, targetType.TypeSymbol, forOutput: false); } else { - ReportNullabilityMismatchInAssignment(node.Syntax, operandType.TypeSymbol, targetType.TypeSymbol); + ReportNullabilityMismatchInAssignment(node.Syntax, operandType.Type, targetType.TypeSymbol); } } @@ -4151,7 +4038,7 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE } base.VisitDelegateCreationExpression(node); - ResultType = TypeSymbolWithAnnotations.Create(node.Type, NullableAnnotation.NotNullable); + SetNotNullResult(node); return null; } @@ -4170,17 +4057,13 @@ public override BoundNode VisitMethodGroup(BoundMethodGroup node) CheckPossibleNullReceiver(receiverOpt); } - //if (this.State.Reachable) // Consider reachability: see https://github.com/dotnet/roslyn/issues/28798 - { - ResultType = default; - } - + SetNotNullResult(node); return null; } public override BoundNode VisitLambda(BoundLambda node) { - SetResult(node); + SetNotNullResult(node); return null; } @@ -4190,7 +4073,7 @@ public override BoundNode VisitUnboundLambda(UnboundLambda node) // Analyze the body to report any additional warnings. var lambda = node.BindForErrorRecovery(); Analyze(compilation, lambda, Diagnostics, delegateInvokeMethod: null, returnTypes: null, initialState: GetVariableState()); - SetResult(node); + SetNotNullResult(node); return null; } @@ -4223,8 +4106,9 @@ public override BoundNode VisitThisReference(BoundThisReference node) private void VisitThisOrBaseReference(BoundExpression node) { - var result = TypeSymbolWithAnnotations.Create(node.Type, NullableAnnotation.NotNullable); - SetResult(result, result); + var rvalueResult = new TypeWithState(node.Type, NullableFlowState.NotNull); + var lvalueResult = TypeSymbolWithAnnotations.Create(node.Type, NullableAnnotation.NotNullable); + SetResult(rvalueResult, lvalueResult); } public override BoundNode VisitParameter(BoundParameter node) @@ -4243,7 +4127,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) var left = node.Left; var right = node.Right; Visit(left); - TypeSymbolWithAnnotations leftLValueType = _visitResult.LValueType; + TypeSymbolWithAnnotations leftLValueType = LvalueResultType; if (left.Kind == BoundKind.EventAccess && ((BoundEventAccess)left).EventSymbol.IsWindowsRuntimeEvent) { @@ -4251,15 +4135,13 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) // of non-field-like events uses BoundEventAssignmentOperator // rather than BoundAssignmentOperator.) VisitRvalue(right); - SetResult(node); + SetNotNullResult(node); } else { - TypeSymbolWithAnnotations rightType = VisitOptionalImplicitConversion(right, leftLValueType, UseLegacyWarnings(left), AssignmentKind.Assignment); + TypeWithState rightType = VisitOptionalImplicitConversion(right, leftLValueType, UseLegacyWarnings(left), AssignmentKind.Assignment); TrackNullableStateForAssignment(right, leftLValueType, MakeSlot(left), rightType, MakeSlot(right)); - // https://github.com/dotnet/roslyn/issues/30066 Check node.Type.IsErrorType() instead? - var result = node.HasErrors ? TypeSymbolWithAnnotations.Create(node.Type) : rightType; - SetResult(result, result); + SetResult(new TypeWithState(leftLValueType.TypeSymbol, rightType.State), leftLValueType); } return null; @@ -4270,10 +4152,10 @@ private static bool UseLegacyWarnings(BoundExpression expr) switch (expr.Kind) { case BoundKind.Local: - return true; + return !RequiresSafetyWarningWhenNullIntroduced(expr.Type); case BoundKind.Parameter: RefKind kind = ((BoundParameter)expr).ParameterSymbol.RefKind; - return kind == RefKind.None; + return kind == RefKind.None && !RequiresSafetyWarningWhenNullIntroduced(expr.Type); default: return false; } @@ -4301,7 +4183,7 @@ public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstruct // https://github.com/dotnet/roslyn/issues/33011: Result type should be inferred and the constraints should // be re-verified. Even though the standard tuple type has no constraints we support that scenario. Constraints_78 // has a test for this case that should start failing when this is fixed. - SetResult(node); + SetNotNullResult(node); return null; } @@ -4349,7 +4231,9 @@ private void VisitDeconstructionArguments(ArrayBuilder v else { var parameter = parameters[i + offset]; - VisitArgumentConversion(variable.Expression, underlyingConversion, parameter.RefKind, parameter, parameter.Type, new VisitResult(variable.Type, variable.Type), extensionMethodThisArgument: false); + VisitArgumentConversion( + variable.Expression, underlyingConversion, parameter.RefKind, parameter, parameter.Type, + new VisitResult(variable.Type.ToTypeWithState(), variable.Type), extensionMethodThisArgument: false); } } } @@ -4372,8 +4256,8 @@ private void VisitDeconstructionArguments(ArrayBuilder v else { var targetType = variable.Type; - TypeSymbolWithAnnotations operandType; - TypeSymbolWithAnnotations valueType; + TypeWithState operandType; + TypeWithState valueType; int valueSlot; if (underlyingConversion.IsIdentity) { @@ -4383,7 +4267,7 @@ private void VisitDeconstructionArguments(ArrayBuilder v } else { - operandType = VisitRvalueWithResult(rightPart); + operandType = VisitRvalueWithState(rightPart); valueType = ApplyConversion( rightPart, rightPart, @@ -4406,12 +4290,13 @@ private void VisitDeconstructionArguments(ArrayBuilder v // (Should this check be moved to VisitOptionalImplicitConversion or TrackNullableStateForAssignment?) if (targetSlot > 0 && underlyingConversion.Kind == ConversionKind.ImplicitNullable && - AreNullableAndUnderlyingTypes(targetType.TypeSymbol, operandType.TypeSymbol, out TypeSymbolWithAnnotations underlyingType)) + AreNullableAndUnderlyingTypes(targetType.TypeSymbol, operandType.Type, out TypeSymbolWithAnnotations underlyingType)) { valueSlot = MakeSlot(rightPart); if (valueSlot > 0) { - TrackNullableStateOfNullableValue(targetSlot, targetType.TypeSymbol, rightPart, underlyingType, valueSlot); + var valueBeforeNullableWrapping = new TypeWithState(underlyingType.TypeSymbol, NullableFlowState.NotNull); + TrackNullableStateOfNullableValue(targetSlot, targetType.TypeSymbol, rightPart, valueBeforeNullableWrapping, valueSlot); } } } @@ -4459,7 +4344,7 @@ DeconstructionVariable getDeconstructionAssignmentVariable(BoundExpression expr) return new DeconstructionVariable(GetDeconstructionAssignmentVariables((BoundTupleExpression)expr)); default: Visit(expr); - return new DeconstructionVariable(expr, _visitResult.LValueType); + return new DeconstructionVariable(expr, LvalueResultType); } } } @@ -4505,8 +4390,8 @@ public override BoundNode VisitIncrementOperator(BoundIncrementOperator node) { Debug.Assert(!IsConditionalState); - VisitRvalue(node.Operand); - var operandType = ResultType; + var operandType = VisitRvalueWithState(node.Operand); + var operandLvalue = LvalueResultType; bool setResult = false; if (this.State.Reachable) @@ -4534,9 +4419,9 @@ public override BoundNode VisitIncrementOperator(BoundIncrementOperator node) targetTypeOfOperandConversion = default; } - TypeSymbolWithAnnotations resultOfOperandConversionType; + TypeWithState resultOfOperandConversionType; - if (!targetTypeOfOperandConversion.IsNull) + if (targetTypeOfOperandConversion.HasType) { // https://github.com/dotnet/roslyn/issues/29961 Should something special be done for targetTypeOfOperandConversion for lifted case? resultOfOperandConversionType = ApplyConversion( @@ -4558,21 +4443,22 @@ public override BoundNode VisitIncrementOperator(BoundIncrementOperator node) resultOfOperandConversionType = operandType; } - TypeSymbolWithAnnotations resultOfIncrementType; - if ((object)incrementOperator == null) + TypeWithState resultOfIncrementType; + if (incrementOperator is null) { resultOfIncrementType = resultOfOperandConversionType; } else { - resultOfIncrementType = incrementOperator.ReturnType; + resultOfIncrementType = incrementOperator.ReturnType.ToTypeWithState(); } + var operandTypeWithAnnotations = operandType.ToTypeSymbolWithAnnotations(); resultOfIncrementType = ApplyConversion( node, node, node.ResultConversion, - operandType, + operandTypeWithAnnotations, resultOfIncrementType, checkConversion: true, fromExplicitCast: false, @@ -4586,13 +4472,13 @@ public override BoundNode VisitIncrementOperator(BoundIncrementOperator node) ResultType = (op == UnaryOperatorKind.PrefixIncrement || op == UnaryOperatorKind.PrefixDecrement) ? resultOfIncrementType : operandType; setResult = true; - TrackNullableStateForAssignment(node, targetType: operandType, targetSlot: MakeSlot(node.Operand), valueType: resultOfIncrementType); + TrackNullableStateForAssignment(node, targetType: operandLvalue, targetSlot: MakeSlot(node.Operand), valueType: resultOfIncrementType); } } if (!setResult) { - this.SetResult(node); + SetNotNullResult(node); } return null; @@ -4601,15 +4487,15 @@ public override BoundNode VisitIncrementOperator(BoundIncrementOperator node) public override BoundNode VisitCompoundAssignmentOperator(BoundCompoundAssignmentOperator node) { Visit(node.Left); - TypeSymbolWithAnnotations leftLValueType = _visitResult.LValueType; - TypeSymbolWithAnnotations leftResultType = _visitResult.RValueType; + TypeSymbolWithAnnotations leftLValueType = LvalueResultType; + TypeWithState leftResultType = ResultType; - TypeSymbolWithAnnotations resultType; + TypeWithState resultType; Debug.Assert(!IsConditionalState); //if (this.State.Reachable) // Consider reachability: see https://github.com/dotnet/roslyn/issues/28798 { - TypeSymbolWithAnnotations leftOnRightType = GetAdjustedResult(leftResultType, MakeSlot(node.Left)); + TypeWithState leftOnRightType = GetAdjustedResult(leftResultType, MakeSlot(node.Left)); // https://github.com/dotnet/roslyn/issues/29962 Update operator based on inferred argument types. if ((object)node.Operator.LeftType != null) @@ -4633,9 +4519,7 @@ public override BoundNode VisitCompoundAssignmentOperator(BoundCompoundAssignmen leftOnRightType = default; } - VisitRvalue(node.Right); - TypeSymbolWithAnnotations rightType = ResultType; - + TypeWithState rightType = VisitRvalueWithState(node.Right); if ((object)node.Operator.ReturnType != null) { if (node.Operator.Kind.IsUserDefined() && (object)node.Operator.Method != null && node.Operator.Method.ParameterCount == 2) @@ -4658,7 +4542,7 @@ public override BoundNode VisitCompoundAssignmentOperator(BoundCompoundAssignmen } else { - resultType = TypeSymbolWithAnnotations.Create(node.Type); + resultType = new TypeWithState(node.Type, NullableFlowState.NotNull); } TrackNullableStateForAssignment(node, leftLValueType, MakeSlot(node.Left), resultType); @@ -4682,25 +4566,25 @@ public override BoundNode VisitFixedLocalCollectionInitializer(BoundFixedLocalCo initializer = ((BoundAddressOfOperator)initializer).Operand; } - this.VisitRvalue(initializer); - SetResult(node); + VisitRvalue(initializer); + SetNotNullResult(node); return null; } public override BoundNode VisitAddressOfOperator(BoundAddressOfOperator node) { - SetResult(node); + SetNotNullResult(node); return null; } - private void ReportArgumentWarnings(BoundExpression argument, TypeSymbolWithAnnotations argumentType, ParameterSymbol parameter) + private void ReportArgumentWarnings(BoundExpression argument, TypeWithState argumentType, ParameterSymbol parameter) { var paramType = parameter.Type; ReportNullableAssignmentIfNecessary(argument, paramType, argumentType, useLegacyWarnings: false, AssignmentKind.Argument, target: parameter); - if (!argumentType.IsNull && IsNullabilityMismatch(paramType.TypeSymbol, argumentType.TypeSymbol)) + if (!argumentType.HasNullType && IsNullabilityMismatch(paramType.TypeSymbol, argumentType.Type)) { - ReportNullabilityMismatchInArgument(argument, argumentType.TypeSymbol, parameter, paramType.TypeSymbol, forOutput: false); + ReportNullabilityMismatchInArgument(argument, argumentType.Type, parameter, paramType.TypeSymbol, forOutput: false); } } @@ -4749,6 +4633,12 @@ public override BoundNode VisitPropertyAccess(BoundPropertyAccess node) } public override BoundNode VisitIndexerAccess(BoundIndexerAccess node) + { + VisitIndexerAccess(node, out _); + return null; + } + + private void VisitIndexerAccess(BoundIndexerAccess node, out PropertySymbol indexer) { var receiverOpt = node.ReceiverOpt; VisitRvalue(receiverOpt); @@ -4757,11 +4647,11 @@ public override BoundNode VisitIndexerAccess(BoundIndexerAccess node) CheckPossibleNullReceiver(receiverOpt); // https://github.com/dotnet/roslyn/issues/29964 Update indexer based on inferred receiver type. + indexer = node.Indexer; + VisitArguments(node, node.Arguments, node.ArgumentRefKindsOpt, node.Indexer, node.ArgsToParamsOpt, node.Expanded); - TypeSymbolWithAnnotations type = node.Indexer.Type; - SetResult(type, type); - return null; + LvalueResultType = node.Indexer.Type; } public override BoundNode VisitEventAccess(BoundEventAccess node) @@ -4772,59 +4662,53 @@ public override BoundNode VisitEventAccess(BoundEventAccess node) private void VisitMemberAccess(BoundExpression node, BoundExpression receiverOpt, Symbol member) { + //if (this.State.Reachable) // Consider reachability: see https://github.com/dotnet/roslyn/issues/28798 + Debug.Assert(!IsConditionalState); - //if (this.State.Reachable) // Consider reachability: see https://github.com/dotnet/roslyn/issues/28798 - { - VisitRvalue(receiverOpt); + var receiverType = (receiverOpt != null) ? VisitRvalueWithState(receiverOpt) : default; - SpecialMember? nullableOfTMember = null; - if (!member.IsStatic) - { - member = AsMemberOfResultType(ResultType, member); - nullableOfTMember = GetNullableOfTMember(compilation, member); - // https://github.com/dotnet/roslyn/issues/30598: For l-values, mark receiver as not null - // after RHS has been visited, and only if the receiver has not changed. - bool allowValueType = nullableOfTMember == SpecialMember.System_Nullable_T_get_Value; - CheckPossibleNullReceiver(receiverOpt, allowValueType, (allowValueType ? node : (receiverOpt ?? node)).Syntax); - } + SpecialMember? nullableOfTMember = null; + if (!member.IsStatic) + { + member = AsMemberOfType(receiverType.Type, member); + nullableOfTMember = GetNullableOfTMember(member); + // https://github.com/dotnet/roslyn/issues/30598: For l-values, mark receiver as not null + // after RHS has been visited, and only if the receiver has not changed. + bool skipReceiverNullCheck = nullableOfTMember != SpecialMember.System_Nullable_T_get_Value; + CheckPossibleNullReceiver(receiverOpt, checkNullableValueType: !skipReceiverNullCheck); + } - var type = member.GetTypeOrReturnType(); - var resultType = type; + var type = member.GetTypeOrReturnType(); + var resultType = type.ToTypeWithState(); - // We are supposed to track information for the node. Use whatever we managed to - // accumulate so far. - if (PossiblyNullableType(resultType.TypeSymbol)) + // We are supposed to track information for the node. Use whatever we managed to + // accumulate so far. + if (PossiblyNullableType(resultType.Type)) + { + int slot = MakeMemberSlot(receiverOpt, member); + if (slot > 0 && slot < this.State.Capacity) { - int slot = MakeMemberSlot(receiverOpt, member); - if (slot > 0 && slot < this.State.Capacity) - { - var annotation = this.State[slot]; - if (annotation != resultType.NullableAnnotation) - { - resultType = TypeSymbolWithAnnotations.Create(resultType.TypeSymbol, annotation); - } - } + var state = this.State[slot]; + resultType = new TypeWithState(resultType.Type, state); } + } - Debug.Assert(!IsConditionalState); - if (nullableOfTMember == SpecialMember.System_Nullable_T_get_HasValue) + Debug.Assert(!IsConditionalState); + if (nullableOfTMember == SpecialMember.System_Nullable_T_get_HasValue) + { + int containingSlot = (receiverOpt is null) ? -1 : MakeSlot(receiverOpt); + if (containingSlot > 0) { - int containingSlot = (receiverOpt is null) ? -1 : MakeSlot(receiverOpt); - if (containingSlot > 0) - { - // https://github.com/dotnet/roslyn/issues/31516: Report HDN_NullCheckIsProbablyAlwaysTrue/False - // when HasValue check is unnecessary. - Split(); - this.StateWhenTrue[containingSlot] = NullableAnnotation.NotNullable; - } + Split(); + this.StateWhenTrue[containingSlot] = NullableFlowState.NotNull; } - - SetResult(resultType, type); } + + SetResult(resultType, type); } - private static SpecialMember? GetNullableOfTMember(CSharpCompilation compilation, Symbol member) + private SpecialMember? GetNullableOfTMember(Symbol member) { if (member.Kind == SymbolKind.Property) { @@ -4866,36 +4750,37 @@ public override void VisitForEachIterationVariables(BoundForEachStatement node) // declare and assign all iteration variables foreach (var iterationVariable in node.IterationVariables) { - TypeSymbolWithAnnotations sourceType = node.EnumeratorInfoOpt?.ElementType ?? default; - NullableAnnotation annotation = NullableAnnotation.Unknown; - if (!sourceType.IsNull) + TypeWithState sourceType = node.EnumeratorInfoOpt?.ElementType.ToTypeWithState() ?? default; + var state = NullableFlowState.NotNull; + if (!sourceType.HasNullType) { TypeSymbolWithAnnotations destinationType = iterationVariable.Type; HashSet useSiteDiagnostics = null; - Conversion conversion = _conversions.ClassifyImplicitConversionFromType(sourceType.TypeSymbol, destinationType.TypeSymbol, ref useSiteDiagnostics); - TypeSymbolWithAnnotations result = ApplyConversion( + Conversion conversion = _conversions.ClassifyImplicitConversionFromType(sourceType.Type, destinationType.TypeSymbol, ref useSiteDiagnostics); + TypeWithState result = ApplyConversion( node.IterationVariableType, operandOpt: null, conversion, destinationType, sourceType, checkConversion: false, - fromExplicitCast: true, + fromExplicitCast: false, useLegacyWarnings: false, AssignmentKind.Assignment, reportTopLevelWarnings: false, reportRemainingWarnings: false); - if (destinationType.IsReferenceType && destinationType.NullableAnnotation.IsAnyNotNullable() && result.NullableAnnotation.IsAnyNullable()) + if (destinationType.IsReferenceType && destinationType.NullableAnnotation.IsAnyNotNullable() && result.MaybeNull) { ReportNonSafetyDiagnostic(node.IterationVariableType.Syntax); } - annotation = result.NullableAnnotation; + + state = result.State; } int slot = GetOrCreateSlot(iterationVariable); if (slot > 0) { - this.State[slot] = annotation; + this.State[slot] = state; } } } @@ -4903,7 +4788,7 @@ public override void VisitForEachIterationVariables(BoundForEachStatement node) public override BoundNode VisitFromEndIndexExpression(BoundFromEndIndexExpression node) { var result = base.VisitFromEndIndexExpression(node); - SetResult(node); + SetNotNullResult(node); return result; } @@ -4915,7 +4800,7 @@ public override BoundNode VisitObjectInitializerMember(BoundObjectInitializerMem public override BoundNode VisitDynamicObjectInitializerMember(BoundDynamicObjectInitializerMember node) { - SetResult(node); + SetNotNullResult(node); return null; } @@ -4923,21 +4808,22 @@ public override BoundNode VisitBadExpression(BoundBadExpression node) { var result = base.VisitBadExpression(node); var type = TypeSymbolWithAnnotations.Create(node.Type); - SetResult(type, type); + LvalueResultType = type; return result; } public override BoundNode VisitTypeExpression(BoundTypeExpression node) { var result = base.VisitTypeExpression(node); - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitTypeOrValueExpression(BoundTypeOrValueExpression node) { + // These should not appear after initial binding except in error cases. var result = base.VisitTypeOrValueExpression(node); - SetResult(node); + SetNotNullResult(node); return result; } @@ -4945,24 +4831,29 @@ public override BoundNode VisitUnaryOperator(BoundUnaryOperator node) { Debug.Assert(!IsConditionalState); - var result = base.VisitUnaryOperator(node); - TypeSymbolWithAnnotations resultType = default; + _ = base.VisitUnaryOperator(node); + var argumentResult = ResultType; + TypeWithState resultType; - // Update method based on inferred operand type: see https://github.com/dotnet/roslyn/issues/29605. - if (node.OperatorKind.IsUserDefined()) + if (node.OperatorKind.IsUserDefined() && (object)node.MethodOpt != null && node.MethodOpt.ParameterCount == 1) { + // Update method based on inferred operand type: see https://github.com/dotnet/roslyn/issues/29605. + ReportArgumentWarnings(node.Operand, argumentResult, node.MethodOpt.Parameters[0]); if (node.OperatorKind.IsLifted()) { - // https://github.com/dotnet/roslyn/issues/29953 Conversions: Lifted operator + resultType = LiftedReturnType(node.MethodOpt.ReturnType, argumentResult.State); } - else if ((object)node.MethodOpt != null && node.MethodOpt.ParameterCount == 1) + else { - ReportArgumentWarnings(node.Operand, ResultType, node.MethodOpt.Parameters[0]); - resultType = node.MethodOpt.ReturnType; + resultType = node.MethodOpt.ReturnType.ToTypeWithState(); } } + else + { + resultType = new TypeWithState(node.Type, node.OperatorKind.IsLifted() ? argumentResult.State : NullableFlowState.NotNull); + } - ResultType = resultType.IsNull ? TypeSymbolWithAnnotations.Create(node.Type) : resultType; + ResultType = resultType; return null; } @@ -4970,7 +4861,7 @@ public override BoundNode VisitPointerIndirectionOperator(BoundPointerIndirectio { var result = base.VisitPointerIndirectionOperator(node); var type = TypeSymbolWithAnnotations.Create(node.Type); - SetResult(type, type); + LvalueResultType = type; return result; } @@ -4978,21 +4869,21 @@ public override BoundNode VisitPointerElementAccess(BoundPointerElementAccess no { var result = base.VisitPointerElementAccess(node); var type = TypeSymbolWithAnnotations.Create(node.Type); - SetResult(type, type); + LvalueResultType = type; return result; } public override BoundNode VisitRefTypeOperator(BoundRefTypeOperator node) { VisitRvalue(node.Operand); - SetResult(node); + SetNotNullResult(node); return null; } public override BoundNode VisitMakeRefOperator(BoundMakeRefOperator node) { var result = base.VisitMakeRefOperator(node); - SetResult(node); + SetNotNullResult(node); return result; } @@ -5000,21 +4891,23 @@ public override BoundNode VisitRefValueOperator(BoundRefValueOperator node) { var result = base.VisitRefValueOperator(node); var type = TypeSymbolWithAnnotations.Create(node.Type); - SetResult(type, type); + LvalueResultType = type; return result; } - private TypeSymbolWithAnnotations InferResultNullability(BoundUserDefinedConditionalLogicalOperator node) + private TypeWithState InferResultNullability(BoundUserDefinedConditionalLogicalOperator node) { if (node.OperatorKind.IsLifted()) { // https://github.com/dotnet/roslyn/issues/29953 Conversions: Lifted operator - return TypeSymbolWithAnnotations.Create(node.Type); + // Should this use the updated flow type and state? How should it compute nullability? + return new TypeWithState(node.Type, NullableFlowState.NotNull); } + // Update method based on inferred operand types: see https://github.com/dotnet/roslyn/issues/29605. if ((object)node.LogicalOperator != null && node.LogicalOperator.ParameterCount == 2) { - return node.LogicalOperator.ReturnType; + return node.LogicalOperator.ReturnType.ToTypeWithState(); } else { @@ -5027,7 +4920,7 @@ protected override void AfterLeftChildOfBinaryLogicalOperatorHasBeenVisited(Boun Debug.Assert(!IsConditionalState); //if (this.State.Reachable) // Consider reachability: see https://github.com/dotnet/roslyn/issues/28798 { - TypeSymbolWithAnnotations leftType = ResultType; + TypeWithState leftType = ResultType; // https://github.com/dotnet/roslyn/issues/29605 Update operator methods based on inferred operand types. MethodSymbol logicalOperator = null; MethodSymbol trueFalseOperator = null; @@ -5056,7 +4949,7 @@ protected override void AfterLeftChildOfBinaryLogicalOperatorHasBeenVisited(Boun throw ExceptionUtilities.UnexpectedValue(node.Kind); } - Debug.Assert((object)trueFalseOperator == null || ((object)logicalOperator != null && left != null)); + Debug.Assert(trueFalseOperator is null || ((object)logicalOperator != null && left != null)); if ((object)trueFalseOperator != null) { @@ -5069,7 +4962,7 @@ protected override void AfterLeftChildOfBinaryLogicalOperatorHasBeenVisited(Boun } Visit(right); - TypeSymbolWithAnnotations rightType = ResultType; + TypeWithState rightType = ResultType; ResultType = InferResultNullabilityOfBinaryLogicalOperator(node, leftType, rightType); @@ -5082,7 +4975,7 @@ protected override void AfterLeftChildOfBinaryLogicalOperatorHasBeenVisited(Boun AfterRightChildOfBinaryLogicalOperatorHasBeenVisited(node, right, isAnd, isBool, ref leftTrue, ref leftFalse); } - private TypeSymbolWithAnnotations InferResultNullabilityOfBinaryLogicalOperator(BoundExpression node, TypeSymbolWithAnnotations leftType, TypeSymbolWithAnnotations rightType) + private TypeWithState InferResultNullabilityOfBinaryLogicalOperator(BoundExpression node, TypeWithState leftType, TypeWithState rightType) { switch (node.Kind) { @@ -5099,36 +4992,37 @@ public override BoundNode VisitAwaitExpression(BoundAwaitExpression node) { var result = base.VisitAwaitExpression(node); CheckPossibleNullReceiver(node.Expression); - if (node.Type.IsValueType || node.HasErrors || (object)node.AwaitableInfo.GetResult == null) + if (node.Type.IsValueType || node.HasErrors || node.AwaitableInfo.GetResult is null) { - SetResult(node); + SetNotNullResult(node); } else { // Update method based on inferred receiver type: see https://github.com/dotnet/roslyn/issues/29605. - ResultType = node.AwaitableInfo.GetResult.ReturnType; + ResultType = node.AwaitableInfo.GetResult.ReturnType.ToTypeWithState(); } + return result; } public override BoundNode VisitTypeOfOperator(BoundTypeOfOperator node) { var result = base.VisitTypeOfOperator(node); - ResultType = TypeSymbolWithAnnotations.Create(node.Type, NullableAnnotation.NotNullable); + ResultType = new TypeWithState(node.Type, NullableFlowState.NotNull); return result; } public override BoundNode VisitMethodInfo(BoundMethodInfo node) { var result = base.VisitMethodInfo(node); - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitFieldInfo(BoundFieldInfo node) { var result = base.VisitFieldInfo(node); - SetResult(node); + SetNotNullResult(node); return result; } @@ -5143,11 +5037,23 @@ public override BoundNode VisitDefaultExpression(BoundDefaultExpression node) int slot = GetOrCreateObjectCreationPlaceholderSlot(node); if (slot > 0) { - this.State[slot] = NullableAnnotation.NotNullable; + this.State[slot] = NullableFlowState.NotNull; InheritNullableStateOfTrackableStruct(type, slot, valueSlot: -1, isDefaultValue: true); } } - ResultType = TypeSymbolWithAnnotations.Create(type, (type is null || type.IsNullableType() || !type.IsValueType) ? NullableAnnotation.Nullable : NullableAnnotation.Unknown); + + // https://github.com/dotnet/roslyn/issues/33344: this fails to produce an updated tuple type for a default expression + // (should produce nullable element types for those elements that are of reference types) + ResultType = TypeWithState.ForType(type); + + if (ResultType.State == NullableFlowState.MaybeNull && RequiresSafetyWarningWhenNullIntroduced(ResultType.Type) && !node.IsSuppressed) + { + // For type parameters that cannot be annotated, the analysis must report those + // places where null values first sneak in, like `default`, `null`, and `GetFirstOrDefault`. + // This is one of those places. + ReportSafetyDiagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, node.Syntax, GetTypeAsDiagnosticArgument(ResultType.Type)); + } + return result; } @@ -5166,104 +5072,50 @@ public override BoundNode VisitIsOperator(BoundIsOperator node) if (slotBuilder.Count > 0) { Split(); - MarkSlotsAsNotNullable(slotBuilder, ref StateWhenTrue); + MarkSlotsAsNotNull(slotBuilder, ref StateWhenTrue); } slotBuilder.Free(); } - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitAsOperator(BoundAsOperator node) { - VisitRvalue(node.Operand); + var argumentType = VisitRvalueWithState(node.Operand); + NullableFlowState resultState = NullableFlowState.NotNull; + var type = node.Type; - //if (this.State.Reachable) // Consider reachability: see https://github.com/dotnet/roslyn/issues/28798 + if (type.CanContainNull()) { - NullableAnnotation nullableAnnotation = NullableAnnotation.Unknown; - var type = node.Type; - - if (PossiblyNullableType(type)) + switch (node.Conversion.Kind) { - var operandType = ResultType; - switch (node.Conversion.Kind) - { - case ConversionKind.Identity: - // Inherit nullability from the operand - nullableAnnotation = operandType.NullableAnnotation; - break; - - case ConversionKind.ImplicitReference: - // Inherit nullability from the operand - if (!operandType.IsNull && operandType.IsPossiblyNullableReferenceTypeTypeParameter()) - { - if (!type.IsPossiblyNullableReferenceTypeTypeParameter()) - { - nullableAnnotation = NullableAnnotation.Nullable; - } - else - { - nullableAnnotation = NullableAnnotation.NotAnnotated; - } - } - else - { - nullableAnnotation = operandType.NullableAnnotation; - if (nullableAnnotation == NullableAnnotation.NotAnnotated && type.IsTypeParameter()) - { - nullableAnnotation = NullableAnnotation.NotNullable; - } - } - break; - - case ConversionKind.Boxing: - if (operandType.TypeSymbol?.IsValueType == true) - { - nullableAnnotation = (operandType.TypeSymbol.IsNullableType() && operandType.NullableAnnotation.IsAnyNullable()) ? NullableAnnotation.Nullable : NullableAnnotation.NotNullable; - } - else - { - Debug.Assert(operandType.TypeSymbol?.IsReferenceType != true); - - if (!operandType.IsNull) - { - if (operandType.IsPossiblyNullableReferenceTypeTypeParameter() && type.IsPossiblyNullableReferenceTypeTypeParameter()) - { - nullableAnnotation = NullableAnnotation.NotAnnotated; - } - else - { - nullableAnnotation = operandType.GetValueNullableAnnotation(); - } - } - else - { - nullableAnnotation = NullableAnnotation.Nullable; - } - } - break; - - case ConversionKind.ImplicitNullable: - nullableAnnotation = (operandType.IsNullableType() && operandType.NullableAnnotation.IsAnyNullable()) ? NullableAnnotation.Nullable : NullableAnnotation.NotNullable; - break; + case ConversionKind.Identity: + case ConversionKind.ImplicitReference: + case ConversionKind.Boxing: + case ConversionKind.ImplicitNullable: + resultState = argumentType.State; + break; - default: - nullableAnnotation = NullableAnnotation.Nullable; - break; - } + default: + resultState = NullableFlowState.MaybeNull; + if (RequiresSafetyWarningWhenNullIntroduced(type)) + { + ReportSafetyDiagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, node.Syntax, type); + } + break; } - - ResultType = TypeSymbolWithAnnotations.Create(type, nullableAnnotation); } + ResultType = new TypeWithState(type, resultState); return null; } public override BoundNode VisitSizeOfOperator(BoundSizeOfOperator node) { var result = base.VisitSizeOfOperator(node); - SetResult(node); + SetNotNullResult(node); return result; } @@ -5271,15 +5123,15 @@ public override BoundNode VisitArgList(BoundArgList node) { var result = base.VisitArgList(node); Debug.Assert(node.Type.SpecialType == SpecialType.System_RuntimeArgumentHandle); - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitArgListOperator(BoundArgListOperator node) { VisitArgumentsEvaluate(node.Arguments, node.ArgumentRefKindsOpt); - Debug.Assert((object)node.Type == null); - SetResult(node); + Debug.Assert(node.Type is null); + SetNotNullResult(node); return null; } @@ -5289,19 +5141,7 @@ public override BoundNode VisitLiteral(BoundLiteral node) Debug.Assert(!IsConditionalState); //if (this.State.Reachable) // Consider reachability: see https://github.com/dotnet/roslyn/issues/28798 - { - var constant = node.ConstantValue; - - if (constant != null && - ((object)node.Type != null ? node.Type.IsReferenceType : constant.IsNull)) - { - ResultType = TypeSymbolWithAnnotations.Create(node.Type, constant.IsNull ? NullableAnnotation.Nullable : NullableAnnotation.NotNullable); - } - else - { - SetResult(node); - } - } + ResultType = new TypeWithState(node.Type, node.Type?.CanContainNull() != false && node.ConstantValue?.IsNull == true ? NullableFlowState.MaybeNull : NullableFlowState.NotNull); return result; } @@ -5310,7 +5150,7 @@ public override BoundNode VisitPreviousSubmissionReference(BoundPreviousSubmissi { var result = base.VisitPreviousSubmissionReference(node); Debug.Assert(node.WasCompilerGenerated); - SetResult(node); + SetNotNullResult(node); return result; } @@ -5318,28 +5158,28 @@ public override BoundNode VisitHostObjectMemberReference(BoundHostObjectMemberRe { var result = base.VisitHostObjectMemberReference(node); Debug.Assert(node.WasCompilerGenerated); - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitPseudoVariable(BoundPseudoVariable node) { var result = base.VisitPseudoVariable(node); - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitRangeExpression(BoundRangeExpression node) { var result = base.VisitRangeExpression(node); - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitRangeVariable(BoundRangeVariable node) { var result = base.VisitRangeVariable(node); - SetResult(node); // https://github.com/dotnet/roslyn/issues/29863 Need to review this + SetNotNullResult(node); // https://github.com/dotnet/roslyn/issues/29863 Need to review this return result; } @@ -5358,7 +5198,7 @@ public override BoundNode VisitDynamicMemberAccess(BoundDynamicMemberAccess node Debug.Assert(node.Type.IsDynamic()); var result = TypeSymbolWithAnnotations.Create(node.Type); - SetResult(result, result); + LvalueResultType = result; return null; } @@ -5373,7 +5213,7 @@ public override BoundNode VisitDynamicInvocation(BoundDynamicInvocation node) // https://github.com/dotnet/roslyn/issues/29893 Update applicable members based on inferred argument types. NullableAnnotation nullableAnnotation = InferResultNullabilityFromApplicableCandidates(StaticCast.From(node.ApplicableMethods)); var result = TypeSymbolWithAnnotations.Create(node.Type, nullableAnnotation); - SetResult(result, result); + LvalueResultType = result; return null; } @@ -5385,14 +5225,14 @@ public override BoundNode VisitEventAssignmentOperator(BoundEventAssignmentOpera var @event = node.Event; if (!@event.IsStatic) { - @event = (EventSymbol)AsMemberOfResultType(ResultType, @event); + @event = (EventSymbol)AsMemberOfType(ResultType.Type, @event); // https://github.com/dotnet/roslyn/issues/30598: Mark receiver as not null // after arguments have been visited, and only if the receiver has not changed. CheckPossibleNullReceiver(receiverOpt); } VisitRvalue(node.Argument); // https://github.com/dotnet/roslyn/issues/31018: Check for delegate mismatch. - SetResult(node); // https://github.com/dotnet/roslyn/issues/29969 Review whether this is the correct result + SetNotNullResult(node); // https://github.com/dotnet/roslyn/issues/29969 Review whether this is the correct result return null; } @@ -5408,56 +5248,56 @@ public override BoundNode VisitDynamicObjectCreationExpression(BoundDynamicObjec public override BoundNode VisitObjectInitializerExpression(BoundObjectInitializerExpression node) { // Only reachable from bad expression. Otherwise handled in VisitObjectCreationExpression(). - SetResult(node); + SetNotNullResult(node); return null; } public override BoundNode VisitCollectionInitializerExpression(BoundCollectionInitializerExpression node) { // Only reachable from bad expression. Otherwise handled in VisitObjectCreationExpression(). - SetResult(node); + SetNotNullResult(node); return null; } public override BoundNode VisitDynamicCollectionElementInitializer(BoundDynamicCollectionElementInitializer node) { // Only reachable from bad expression. Otherwise handled in VisitObjectCreationExpression(). - SetResult(node); + SetNotNullResult(node); return null; } public override BoundNode VisitImplicitReceiver(BoundImplicitReceiver node) { var result = base.VisitImplicitReceiver(node); - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitAnonymousPropertyDeclaration(BoundAnonymousPropertyDeclaration node) { var result = base.VisitAnonymousPropertyDeclaration(node); - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitNoPiaObjectCreationExpression(BoundNoPiaObjectCreationExpression node) { var result = base.VisitNoPiaObjectCreationExpression(node); - ResultType = TypeSymbolWithAnnotations.Create(node.Type, NullableAnnotation.NotNullable); + ResultType = new TypeWithState(node.Type, NullableFlowState.NotNull); return result; } public override BoundNode VisitNewT(BoundNewT node) { var result = base.VisitNewT(node); - ResultType = TypeSymbolWithAnnotations.Create(node.Type, NullableAnnotation.NotNullable); + ResultType = new TypeWithState(node.Type, NullableFlowState.NotNull); return result; } public override BoundNode VisitArrayInitialization(BoundArrayInitialization node) { var result = base.VisitArrayInitialization(node); - SetResult(node); + SetNotNullResult(node); return result; } @@ -5469,8 +5309,8 @@ private void SetUnknownResultNullability() public override BoundNode VisitStackAllocArrayCreation(BoundStackAllocArrayCreation node) { var result = base.VisitStackAllocArrayCreation(node); - Debug.Assert((object)node.Type == null || node.Type.IsPointerType() || node.Type.IsRefLikeType); - SetResult(node); + Debug.Assert(node.Type is null || node.Type.IsPointerType() || node.Type.IsRefLikeType); + SetNotNullResult(node); return result; } @@ -5489,34 +5329,32 @@ public override BoundNode VisitDynamicIndexerAccess(BoundDynamicIndexerAccess no NullableAnnotation nullableAnnotation = (object)node.Type != null && !node.Type.IsValueType ? InferResultNullabilityFromApplicableCandidates(StaticCast.From(node.ApplicableIndexers)) : NullableAnnotation.Unknown; - var result = TypeSymbolWithAnnotations.Create(node.Type, nullableAnnotation); - SetResult(result, result); + LvalueResultType = TypeSymbolWithAnnotations.Create(node.Type, nullableAnnotation); return null; } - private void CheckPossibleNullReceiver(BoundExpression receiverOpt, bool checkNullableValueType = false, SyntaxNode syntaxOpt = null) + private void CheckPossibleNullReceiver(BoundExpression receiverOpt, bool checkNullableValueType = false) { Debug.Assert(!this.IsConditionalState); if (receiverOpt != null && this.State.Reachable) { -#if DEBUG - Debug.Assert(receiverOpt.Type is null || ResultType.TypeSymbol is null || AreCloseEnough(receiverOpt.Type, ResultType.TypeSymbol)); -#endif - var resultType = ResultType.TypeSymbol; - if (resultType is null) + var resultTypeSymbol = ResultType.Type; + if (resultTypeSymbol is null) { return; } - - if (ResultType.GetValueNullableAnnotation().IsAnyNullable()) +#if DEBUG + Debug.Assert(receiverOpt.Type is null || AreCloseEnough(receiverOpt.Type, resultTypeSymbol)); +#endif + if (ResultType.MaybeNull) { - bool isValueType = resultType.IsValueType; - if (isValueType && (!checkNullableValueType || !resultType.IsNullableType())) + bool isValueType = resultTypeSymbol.IsValueType; + if (isValueType && (!checkNullableValueType || !resultTypeSymbol.IsNullableTypeOrTypeParameter() || resultTypeSymbol.GetNullableUnderlyingType().IsErrorType())) { return; } - ReportSafetyDiagnostic(isValueType ? ErrorCode.WRN_NullableValueTypeMayBeNull : ErrorCode.WRN_NullReferenceReceiver, syntaxOpt ?? receiverOpt.Syntax); + ReportSafetyDiagnostic(isValueType ? ErrorCode.WRN_NullableValueTypeMayBeNull : ErrorCode.WRN_NullReferenceReceiver, receiverOpt.Syntax); } LearnFromNonNullTest(receiverOpt, ref this.State); @@ -5580,14 +5418,14 @@ private NullableAnnotation InferResultNullabilityFromApplicableCandidates(Immuta public override BoundNode VisitQueryClause(BoundQueryClause node) { var result = base.VisitQueryClause(node); - SetResult(node); // https://github.com/dotnet/roslyn/issues/29863 Implement nullability analysis in LINQ queries + SetNotNullResult(node); // https://github.com/dotnet/roslyn/issues/29863 Implement nullability analysis in LINQ queries return result; } public override BoundNode VisitNameOfOperator(BoundNameOfOperator node) { var result = base.VisitNameOfOperator(node); - ResultType = TypeSymbolWithAnnotations.Create(node.Type, NullableAnnotation.NotNullable); + ResultType = new TypeWithState(node.Type, NullableFlowState.NotNull); return result; } @@ -5601,7 +5439,7 @@ public override BoundNode VisitNamespaceExpression(BoundNamespaceExpression node public override BoundNode VisitInterpolatedString(BoundInterpolatedString node) { var result = base.VisitInterpolatedString(node); - ResultType = TypeSymbolWithAnnotations.Create(node.Type, NullableAnnotation.NotNullable); + ResultType = new TypeWithState(node.Type, NullableFlowState.NotNull); return result; } @@ -5615,14 +5453,15 @@ public override BoundNode VisitStringInsert(BoundStringInsert node) public override BoundNode VisitConvertedStackAllocExpression(BoundConvertedStackAllocExpression node) { var result = base.VisitConvertedStackAllocExpression(node); - SetResult(node); + SetNotNullResult(node); return result; } public override BoundNode VisitDiscardExpression(BoundDiscardExpression node) { var result = TypeSymbolWithAnnotations.Create(node.Type); - SetResult(result, result); + var rValueType = new TypeWithState(node.Type, NullableFlowState.MaybeNull); + SetResult(rValueType, result); return null; } @@ -5643,18 +5482,14 @@ private void VisitThrow(BoundExpression expr) { if (expr != null) { - var result = VisitRvalueWithResult(expr); + var result = VisitRvalueWithState(expr); // Cases: // null // null! // Other (typed) expression, including suppressed ones - if (expr.ConstantValue?.IsNull == true || - result.GetValueNullableAnnotation().IsAnyNullable()) + if (result.MaybeNull) { - if (!expr.IsSuppressed) - { - ReportSafetyDiagnostic(ErrorCode.WRN_PossibleNull, expr.Syntax); - } + ReportSafetyDiagnostic(ErrorCode.WRN_PossibleNull, expr.Syntax); } } SetUnreachable(); @@ -5671,17 +5506,68 @@ public override BoundNode VisitYieldReturnStatement(BoundYieldReturnStatement no TypeSymbolWithAnnotations elementType = InMethodBinder.GetIteratorElementTypeFromReturnType(compilation, RefKind.None, method.ReturnType.TypeSymbol, errorLocationNode: null, diagnostics: null).elementType; - VisitOptionalImplicitConversion(expr, elementType, useLegacyWarnings: false, AssignmentKind.Return); + _ = VisitOptionalImplicitConversion(expr, elementType, useLegacyWarnings: false, AssignmentKind.Return); return null; } + protected override void VisitCatchBlock(BoundCatchBlock node, ref LocalState finallyState) + { + if (node.Locals.Length > 0) + { + LocalSymbol local = node.Locals[0]; + if (local.DeclarationKind == LocalDeclarationKind.CatchVariable) + { + int slot = GetOrCreateSlot(local); + if (slot > 0) + this.State[slot] = NullableFlowState.NotNull; + } + } + + base.VisitCatchBlock(node, ref finallyState); + } + protected override string Dump(LocalState state) { - return string.Empty; + if (!state.Reachable) + return "unreachable"; + + var pooledBuilder = PooledStringBuilder.GetInstance(); + var builder = pooledBuilder.Builder; + for (int i = 0; i < state.Capacity; i++) + { + if (nameForSlot(i) is string name) + { + builder.Append(name); + builder.Append(state[i] == NullableFlowState.MaybeNull ? "?" : "!"); + } + } + + return pooledBuilder.ToStringAndFree(); + + string nameForSlot(int slot) + { + if (slot < 0) + return null; + VariableIdentifier id = this.variableBySlot[slot]; + var name = id.Symbol?.Name; + if (name == null) + return null; + return nameForSlot(id.ContainingSlot) is string containingSlotName + ? containingSlotName + "." + name : name; + } } protected override void Meet(ref LocalState self, ref LocalState other) { + if (!self.Reachable) + return; + + if (!other.Reachable) + { + self = other.Clone(); + return; + } + if (self.Capacity != other.Capacity) { Normalize(ref self); @@ -5690,74 +5576,49 @@ protected override void Meet(ref LocalState self, ref LocalState other) for (int slot = 1; slot < self.Capacity; slot++) { - NullableAnnotation selfAnnotation = self[slot]; - NullableAnnotation otherAnnotation = other[slot]; - NullableAnnotation union = selfAnnotation.MeetForFlowAnalysisFinally(otherAnnotation); + NullableFlowState selfState = self[slot]; + NullableFlowState otherState = other[slot]; + NullableFlowState union = selfState.MeetForFlowAnalysisFinally(otherState); - if (selfAnnotation != union) + if (selfState != union) { self[slot] = union; } - - bool selfIsAssigned = self.IsAssigned(slot); - bool isAssigned = selfIsAssigned || other.IsAssigned(slot); - if (selfIsAssigned != isAssigned) - { - self.SetAssigned(slot, isAssigned); - } } } protected override bool Join(ref LocalState self, ref LocalState other) { - if (self.Reachable == other.Reachable) - { - bool result = false; - - if (self.Capacity != other.Capacity) - { - Normalize(ref self); - Normalize(ref other); - } - - for (int slot = 1; slot < self.Capacity; slot++) - { - NullableAnnotation selfAnnotation = self[slot]; - NullableAnnotation intersection = selfAnnotation.JoinForFlowAnalysisBranches(other[slot], (slot, this), IsPossiblyNullableReferenceTypeTypeParameterDelegate); - if (selfAnnotation != intersection) - { - self[slot] = intersection; - result = true; - } - - bool selfIsAssigned = self.IsAssigned(slot); - bool isAssigned = selfIsAssigned && other.IsAssigned(slot); - if (selfIsAssigned != isAssigned) - { - self.SetAssigned(slot, isAssigned); - result = true; - } - } + if (!other.Reachable) + return false; - return result; - } - else if (!self.Reachable) + if (!self.Reachable) { self = other.Clone(); return true; } - else + + bool result = false; + + if (self.Capacity != other.Capacity) { - Debug.Assert(!other.Reachable); - return false; + Normalize(ref self); + Normalize(ref other); } - } - private readonly static Func<(int slot, NullableWalker self), bool> IsPossiblyNullableReferenceTypeTypeParameterDelegate = args => - { - Symbol symbol = args.self.variableBySlot[args.slot].Symbol; - return (object)symbol != null && VariableType(symbol).TypeSymbol?.IsPossiblyNullableReferenceTypeTypeParameter() == true; - }; + for (int slot = 1; slot < self.Capacity; slot++) + { + NullableFlowState selfAnnotation = self[slot]; + NullableFlowState intersection = selfAnnotation.JoinForFlowAnalysisBranches(other[slot]); + if (selfAnnotation != intersection) + { + self[slot] = intersection; + result = true; + } + } + + return result; + } [DebuggerDisplay("{GetDebuggerDisplay(), nq}")] #if REFERENCE_STATE @@ -5766,15 +5627,12 @@ internal class LocalState : ILocalState internal struct LocalState : ILocalState #endif { - private BitVector _assigned; - private ArrayBuilder _state; + private ArrayBuilder _state; public bool Reachable { get; } - internal LocalState(bool reachable, BitVector assigned, ArrayBuilder state) + internal LocalState(bool reachable, ArrayBuilder state) { - Debug.Assert(!assigned.IsNull); this.Reachable = reachable; - this._assigned = assigned; this._state = state; } @@ -5782,11 +5640,9 @@ internal LocalState(bool reachable, BitVector assigned, ArrayBuilder(capacity); + _state = new ArrayBuilder(capacity); } if (_state.Count < capacity) @@ -5795,7 +5651,7 @@ internal void EnsureCapacity(int capacity) } } - internal NullableAnnotation this[int slot] + internal NullableFlowState this[int slot] { get { @@ -5804,33 +5660,24 @@ internal NullableAnnotation this[int slot] return _state[slot]; } - return NullableAnnotation.Unknown; + return NullableFlowState.NotNull; } set { + // https://github.com/dotnet/roslyn/issues/32047 : all variables should be considered not null in unreachable code. + // Moreover, no states should be modified in unreachable code, as there is only one unreachable state. EnsureCapacity(slot + 1); _state[slot] = value; - SetAssigned(slot, true); } } - internal void SetAssigned(int slot, bool value) - { - _assigned[slot] = value; - } - - internal bool IsAssigned(int slot) - { - return _assigned[slot]; - } - /// /// Produce a duplicate of this flow analysis state. /// /// public LocalState Clone() { - ArrayBuilder clone; + ArrayBuilder clone; if (_state == null) { @@ -5838,12 +5685,12 @@ public LocalState Clone() } else { - clone = new ArrayBuilder(_state.Count); + clone = new ArrayBuilder(_state.Count); clone.Count = 0; clone.AddRange(_state); } - return new LocalState(Reachable, _assigned.Clone(), clone); + return new LocalState(Reachable, clone); } internal string GetDebuggerDisplay() @@ -5857,26 +5704,12 @@ internal string GetDebuggerDisplay() switch (_state[i]) { - case NullableAnnotation.Unknown: - append = "__"; + case NullableFlowState.NotNull: + append = "!"; break; - - case NullableAnnotation.Annotated: - append = "?-"; + case NullableFlowState.MaybeNull: + append = "?"; break; - - case NullableAnnotation.Nullable: - append = "?+"; - break; - - case NullableAnnotation.NotNullable: - append = "!+"; - break; - - case NullableAnnotation.NotAnnotated: - append = "!-"; - break; - default: throw ExceptionUtilities.UnexpectedValue(_state[i]); } diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs index 82c39caf92209..13ecfb21cbdea 100644 --- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs @@ -210,14 +210,18 @@ public static bool IsWarning(ErrorCode code) case ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate: case ErrorCode.WRN_NullabilityMismatchInArgumentForOutput: case ErrorCode.WRN_NullAsNonNullable: + case ErrorCode.WRN_AsOperatorMayReturnNull: case ErrorCode.WRN_NullableValueTypeMayBeNull: case ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint: case ErrorCode.WRN_MissingNonNullTypesContextForAnnotation: case ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation: case ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint: + case ErrorCode.WRN_ConditionalAccessMayReturnNull: case ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface: case ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase: case ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList: + case ErrorCode.WRN_DefaultExpressionMayIntroduceNullT: + case ErrorCode.WRN_NullLiteralMayIntroduceNullT: return true; default: return false; @@ -258,9 +262,6 @@ public static bool IsHidden(ErrorCode code) { case ErrorCode.HDN_UnusedUsingDirective: case ErrorCode.HDN_UnusedExternAlias: - case ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue: - case ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse: - case ErrorCode.HDN_ExpressionIsProbablyNeverNull: return true; default: return false; diff --git a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaCapturedVariable.cs b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaCapturedVariable.cs index ab851bd8b3a17..610bb9ad6b253 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaCapturedVariable.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaCapturedVariable.cs @@ -23,7 +23,7 @@ private LambdaCapturedVariable(SynthesizedContainer frame, TypeSymbolWithAnnotat isReadOnly: false, isStatic: false) { - Debug.Assert(!type.IsNull); + Debug.Assert(type.HasType); // lifted fields do not need to have the CompilerGeneratedAttribute attached to it, the closure is already // marked as being compiler generated. diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs index 70a8a94e3c54c..562814be3ed60 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs @@ -59,7 +59,7 @@ private void VisitArrayType(IArrayTypeSymbol symbol, TypeSymbolWithAnnotations t } while (underlyingType.Kind == SymbolKind.ArrayType && !ShouldAddNullableAnnotation(underlyingTypeWithAnnotations)); - if (!underlyingTypeWithAnnotations.IsNull) + if (underlyingTypeWithAnnotations.HasType) { VisitTypeSymbolWithAnnotations(underlyingTypeWithAnnotations); } @@ -91,7 +91,7 @@ private void AddNullableAnnotations(TypeSymbolWithAnnotations typeOpt) private bool ShouldAddNullableAnnotation(TypeSymbolWithAnnotations typeOpt) { - if (typeOpt.IsNull) + if (!typeOpt.HasType) { return false; } diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/AnonymousTypeField.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/AnonymousTypeField.cs index 152cf19ba7ac7..8a1acbefc76b7 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/AnonymousTypeField.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/AnonymousTypeField.cs @@ -28,7 +28,7 @@ public AnonymousTypeField(string name, Location location, TypeSymbolWithAnnotati [Conditional("DEBUG")] internal void AssertIsGood() { - Debug.Assert(this.Name != null && this.Location != null && !this.Type.IsNull); + Debug.Assert(this.Name != null && this.Location != null && this.Type.HasType); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertySymbol.cs index 0223d7a138a8b..c722ed4857dbe 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertySymbol.cs @@ -42,7 +42,7 @@ private AnonymousTypePropertySymbol( { Debug.Assert((object)container != null); Debug.Assert((object)field != null); - Debug.Assert(!fieldType.IsNull); + Debug.Assert(fieldType.HasType); Debug.Assert(index >= 0); Debug.Assert(!locations.IsDefault); diff --git a/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs index 67fd1092f60a6..5c6564da864dd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs @@ -22,7 +22,7 @@ private ArrayTypeSymbol( TypeSymbolWithAnnotations elementType, NamedTypeSymbol array) { - Debug.Assert(!elementType.IsNull); + Debug.Assert(elementType.HasType); Debug.Assert((object)array != null); _elementType = elementType; @@ -401,7 +401,7 @@ internal override TypeSymbol SetNullabilityForReferenceTypes(Func nullableTransformFlags; diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs index c07f41f5a1c12..14b2a9aeaf9a5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs @@ -89,7 +89,7 @@ internal PEEventSymbol( } TypeSymbol originalEventType = _eventType.TypeSymbol; - if (_eventType.IsNull) + if (!_eventType.HasType) { var metadataDecoder = new MetadataDecoder(moduleSymbol, containingType); originalEventType = metadataDecoder.GetTypeOfToken(eventType); diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs index c30ead345fcce..a1dbfbc5cbc0a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs @@ -203,7 +203,7 @@ internal void SetAssociatedEvent(PEEventSymbol eventSymbol) private void EnsureSignatureIsLoaded() { - if (_lazyType.IsNull) + if (_lazyType.IsDefault) { var moduleSymbol = _containingType.ContainingPEModule; bool isVolatile; diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs index 6438939901f99..8fdccb0da24b5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs @@ -199,7 +199,7 @@ private PEParameterSymbol( Debug.Assert((object)moduleSymbol != null); Debug.Assert((object)containingSymbol != null); Debug.Assert(ordinal >= 0); - Debug.Assert(!type.IsNull); + Debug.Assert(type.HasType); isBad = false; _moduleSymbol = moduleSymbol; diff --git a/src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs index d6fbfd1baa4ce..6ae3de100a225 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs @@ -84,7 +84,7 @@ public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol m var typeArgsForConstraintsCheck = typeArgs; for (int i = 0; i < typeArgsForConstraintsCheck.Length; i++) { - if (typeArgsForConstraintsCheck[i].IsNull) + if (!typeArgsForConstraintsCheck[i].HasType) { firstNullInTypeArgs = i; var builder = ArrayBuilder.GetInstance(); @@ -93,7 +93,7 @@ public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol m for (; i < typeArgsForConstraintsCheck.Length; i++) { var typeArg = typeArgsForConstraintsCheck[i]; - if (typeArg.IsNull) + if (!typeArg.HasType) { notInferredTypeParameters.Add(typeParams[i]); builder.Add(TypeSymbolWithAnnotations.Create(ErrorTypeSymbol.UnknownResultType)); @@ -146,7 +146,7 @@ public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol m for (int i = firstNullInTypeArgs; i < typeArgsForConstruct.Length; i++) { var typeArgForConstruct = typeArgsForConstruct[i]; - builder.Add(!typeArgForConstruct.IsNull ? typeArgForConstruct : TypeSymbolWithAnnotations.Create(typeParams[i])); + builder.Add(typeArgForConstruct.HasType ? typeArgForConstruct : TypeSymbolWithAnnotations.Create(typeParams[i])); } typeArgsForConstruct = builder.ToImmutableAndFree(); diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index f808b02b18b9d..d8bc21e8b3bf5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs @@ -1005,9 +1005,9 @@ internal NamedTypeSymbol GetUnboundGenericTypeOrSelf() /// internal abstract bool HasCodeAnalysisEmbeddedAttribute { get; } - internal static readonly Func TypeSymbolIsNullFunction = type => type.IsNull; + internal static readonly Func TypeSymbolIsNullFunction = type => !type.HasType; - internal static readonly Func TypeSymbolIsErrorType = type => !type.IsNull && type.IsErrorType(); + internal static readonly Func TypeSymbolIsErrorType = type => type.HasType && type.IsErrorType(); private NamedTypeSymbol ConstructWithoutModifiers(ImmutableArray typeArguments, bool unbound) { diff --git a/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs index fb34a3d4037c3..01a67639e41b3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs @@ -23,7 +23,7 @@ internal sealed partial class PointerTypeSymbol : TypeSymbol, IPointerTypeSymbol /// The type being pointed at. internal PointerTypeSymbol(TypeSymbolWithAnnotations pointedAtType) { - Debug.Assert(!pointedAtType.IsNull); + Debug.Assert(pointedAtType.HasType); _pointedAtType = pointedAtType; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs index 2b08b452e339d..f0cb4d7a04395 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs @@ -130,7 +130,7 @@ public override TypeSymbolWithAnnotations ReturnType { get { - if (_lazyReturnType.IsNull) + if (_lazyReturnType.IsDefault) { _lazyReturnType = this.RetargetingTranslator.Retarget(_underlyingMethod.ReturnType, RetargetOptions.RetargetPrimitiveTypesByTypeCode, this.ContainingType); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs index f1a573e77bbf8..bcb960b448f24 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs @@ -59,7 +59,7 @@ public override TypeSymbolWithAnnotations Type { get { - if (_lazyType.IsNull) + if (_lazyType.IsDefault) { var type = this.RetargetingTranslator.Retarget(_underlyingProperty.Type, RetargetOptions.RetargetPrimitiveTypesByTypeCode); if (type.TypeSymbol.TryAsDynamicIfNoPia(this.ContainingType, out TypeSymbol asDynamic)) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs b/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs index 1c30128bb4360..e6c7e91c7b965 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs @@ -66,7 +66,7 @@ internal override TypeSymbolWithAnnotations GetFieldType(ConsList f { Debug.Assert(fieldsBeingBound != null); - if (!_lazyType.IsNull) + if (!_lazyType.IsDefault) { return _lazyType.ToType(); } @@ -93,12 +93,12 @@ internal override TypeSymbolWithAnnotations GetFieldType(ConsList f type = default; } - Debug.Assert(!type.IsNull || isVar); + Debug.Assert(type.HasType || isVar); if (isVar && !fieldsBeingBound.ContainsReference(this)) { InferFieldType(fieldsBeingBound, binder); - Debug.Assert(!_lazyType.IsNull); + Debug.Assert(!_lazyType.IsDefault); } else { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs index 95da5e1c742c8..8c5e11afb6635 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs @@ -47,7 +47,7 @@ public LambdaSymbol( _messageID = unboundLambda.Data.MessageID; _syntax = unboundLambda.Syntax; _refKind = refKind; - _returnType = returnType.IsNull ? TypeSymbolWithAnnotations.Create(ReturnTypeIsBeingInferred) : returnType; + _returnType = !returnType.HasType ? TypeSymbolWithAnnotations.Create(ReturnTypeIsBeingInferred) : returnType; _isSynthesized = unboundLambda.WasCompilerGenerated; _isAsync = unboundLambda.IsAsync; // No point in making this lazy. We are always going to need these soon after creation of the symbol. @@ -166,7 +166,7 @@ internal override ImmutableArray GetAppliedConditionalSymbols() public override bool ReturnsVoid { - get { return !this.ReturnType.IsNull && this.ReturnType.SpecialType == SpecialType.System_Void; } + get { return this.ReturnType.HasType && this.ReturnType.SpecialType == SpecialType.System_Void; } } public override RefKind RefKind @@ -185,7 +185,7 @@ public override TypeSymbolWithAnnotations ReturnType // IDE might inspect the symbol and want to know the return type. internal void SetInferredReturnType(RefKind refKind, TypeSymbolWithAnnotations inferredReturnType) { - Debug.Assert(!inferredReturnType.IsNull); + Debug.Assert(inferredReturnType.HasType); Debug.Assert((object)_returnType.TypeSymbol == ReturnTypeIsBeingInferred); _refKind = refKind; _returnType = inferredReturnType; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs index e79ea449bcd28..204f98601810e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs @@ -208,7 +208,7 @@ public override TypeSymbolWithAnnotations ReturnType internal void ComputeReturnType() { - if (!_lazyReturnType.IsNull) + if (!_lazyReturnType.IsDefault) { return; } @@ -254,7 +254,7 @@ internal void ComputeReturnType() lock (_declarationDiagnostics) { - if (!_lazyReturnType.IsNull) + if (!_lazyReturnType.IsDefault) { diagnostics.Free(); return; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs index ff4ef49887eba..2b6a987425b3c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs @@ -40,14 +40,14 @@ public sealed override Symbol AssociatedSymbol protected sealed override void MethodChecks(DiagnosticBag diagnostics) { - Debug.Assert(_lazyParameters.IsDefault == _lazyReturnType.IsNull); + Debug.Assert(_lazyParameters.IsDefault != _lazyReturnType.HasType); // CONSIDER: currently, we're copying the custom modifiers of the event overridden // by this method's associated event (by using the associated event's type, which is // copied from the overridden event). It would be more correct to copy them from // the specific accessor that this method is overriding (as in SourceMemberMethodSymbol). - if (_lazyReturnType.IsNull) + if (_lazyReturnType.IsDefault) { CSharpCompilation compilation = this.DeclaringCompilation; Debug.Assert(compilation != null); @@ -105,7 +105,7 @@ public sealed override bool ReturnsVoid get { LazyMethodChecks(); - Debug.Assert(!_lazyReturnType.IsNull); + Debug.Assert(!_lazyReturnType.IsDefault); return base.ReturnsVoid; } } @@ -120,7 +120,7 @@ public sealed override TypeSymbolWithAnnotations ReturnType get { LazyMethodChecks(); - Debug.Assert(!_lazyReturnType.IsNull); + Debug.Assert(!_lazyReturnType.IsDefault); return _lazyReturnType; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs index c46ee4c9555eb..09ffc46508b49 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs @@ -100,7 +100,7 @@ internal Binder TypeSyntaxBinder // don't let the debugger force inference. internal override string GetDebuggerDisplay() { - return !_type.IsNull + return !_type.IsDefault ? base.GetDebuggerDisplay() : $"{this.Kind} ${this.Name}"; } @@ -287,7 +287,7 @@ public override TypeSymbolWithAnnotations Type { get { - if (_type.IsNull) + if (_type.IsDefault) { #if DEBUG concurrentTypeResolutions++; @@ -346,7 +346,7 @@ private TypeSymbolWithAnnotations GetTypeSymbol() // If we got a valid result that was not void then use the inferred type // else create an error type. - if (!inferredType.IsNull && + if (inferredType.HasType && inferredType.SpecialType != SpecialType.System_Void) { declType = inferredType; @@ -357,7 +357,7 @@ private TypeSymbolWithAnnotations GetTypeSymbol() } } - Debug.Assert(!declType.IsNull); + Debug.Assert(declType.HasType); // // Note that we drop the diagnostics on the floor! That is because this code is invoked mainly in @@ -688,7 +688,7 @@ protected override TypeSymbolWithAnnotations InferTypeOfVarVariable(DiagnosticBa throw ExceptionUtilities.UnexpectedValue(_deconstruction.Kind()); } - Debug.Assert(!this._type.IsNull); + Debug.Assert(!this._type.IsDefault); return _type.ToType(); } @@ -783,7 +783,7 @@ protected override TypeSymbolWithAnnotations InferTypeOfVarVariable(DiagnosticBa break; } - if (this._type.IsNull) + if (this._type.IsDefault) { Debug.Assert(this.DeclarationKind == LocalDeclarationKind.DeclarationExpressionVariable); SetType(TypeSymbolWithAnnotations.Create(_nodeBinder.CreateErrorType("var"))); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index cedb40fb085a5..9ac9b7fccef95 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -351,7 +351,7 @@ internal override bool HasPointerType { get { - if (!_lazyType.IsNull) + if (!_lazyType.IsDefault) { Debug.Assert(_lazyType.DefaultType.IsPointerType() == IsPointerFieldSyntactically()); @@ -389,7 +389,7 @@ internal sealed override TypeSymbolWithAnnotations GetFieldType(ConsList fieldsBeingBound) { - if (_lazyType.IsNull) + if (_lazyType.IsDefault) { _lazyType.InterlockedInitialize(_containingType.TypeSubstitution.SubstituteTypeWithTupleUnification(OriginalDefinition.GetFieldType(fieldsBeingBound))); } diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs index 68b112bc0fda5..e5f1854cfcd6d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs @@ -230,7 +230,7 @@ public sealed override TypeSymbolWithAnnotations ReturnType { get { - if (_lazyReturnType.IsNull) + if (_lazyReturnType.IsDefault) { var returnType = Map.SubstituteTypeWithTupleUnification(OriginalDefinition.ReturnType); _lazyReturnType.InterlockedInitialize(returnType); diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedPropertySymbol.cs index 2cff86934f85e..6445ce0c1cd84 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedPropertySymbol.cs @@ -23,7 +23,7 @@ public override TypeSymbolWithAnnotations Type { get { - if (_lazyType.IsNull) + if (_lazyType.IsDefault) { _lazyType.InterlockedInitialize(_containingType.TypeSubstitution.SubstituteTypeWithTupleUnification(OriginalDefinition.Type)); } diff --git a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs index 12cbe27892aff..f8fc11e4737a0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs @@ -58,7 +58,7 @@ public static bool Any(this ImmutableArray array, Sym for (int i = 0, n = array.Length; i < n; i++) { var item = array[i]; - if (!item.IsNull && item.Kind == kind) + if (item.HasType && item.Kind == kind) { return true; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs index d1e5f33333b41..b4593e9611b3c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs @@ -28,7 +28,7 @@ public SynthesizedParameterSymbolBase( RefKind refKind, string name = "") { - Debug.Assert(!type.IsNull); + Debug.Assert(type.HasType); Debug.Assert(name != null); Debug.Assert(ordinal >= 0); diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/TypeSubstitutedLocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/TypeSubstitutedLocalSymbol.cs index ab8f8ee69d259..f48b047a9f8c4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/TypeSubstitutedLocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/TypeSubstitutedLocalSymbol.cs @@ -15,7 +15,7 @@ internal sealed class TypeSubstitutedLocalSymbol : LocalSymbol public TypeSubstitutedLocalSymbol(LocalSymbol originalVariable, TypeSymbolWithAnnotations type, Symbol containingSymbol) { Debug.Assert(originalVariable != null); - Debug.Assert(!type.IsNull); + Debug.Assert(type.HasType); Debug.Assert(containingSymbol != null); _originalVariable = originalVariable; diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs index 8acaf8e974080..01452e9dda1e2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs @@ -221,7 +221,7 @@ internal TupleTypeSymbol WithUnderlyingType(NamedTypeSymbol newUnderlyingType) internal TupleTypeSymbol WithElementTypes(ImmutableArray newElementTypes) { Debug.Assert(_elementTypes.Length == newElementTypes.Length); - Debug.Assert(newElementTypes.All(t => !t.IsNull)); + Debug.Assert(newElementTypes.All(t => t.HasType)); NamedTypeSymbol firstTupleType; NamedTypeSymbol chainedTupleType; @@ -1522,11 +1522,11 @@ NullableAnnotation mergeNullableAnnotation(TypeSymbol type, NullableAnnotation a switch (variance) { case VarianceKind.In: - return a.MeetForFlowAnalysisFinally(b); + return a.MeetForFixingUpperBounds(b); case VarianceKind.Out: - return a.JoinForFlowAnalysisBranches(b, type, _IsPossiblyNullableReferenceTypeTypeParameterDelegate); + return a.JoinForFixingLowerBounds(b); case VarianceKind.None: - return a.EnsureCompatibleForTuples(b, type, _IsPossiblyNullableReferenceTypeTypeParameterDelegate); + return a.EnsureCompatibleForTuples(b); default: throw ExceptionUtilities.UnexpectedValue(variance); } diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs index e26da30cfe631..20a2d2e04219d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs @@ -598,7 +598,7 @@ public static TypeSymbol VisitType( T arg, bool canDigThroughNullable = false) { - Debug.Assert(typeWithAnnotationsOpt.IsNull != (typeOpt is null)); + Debug.Assert(typeWithAnnotationsOpt.HasType == (typeOpt is null)); // In order to handle extremely "deep" types like "int[][][][][][][][][]...[]" // or int*****************...* we implement manual tail recursion rather than @@ -636,7 +636,7 @@ public static TypeSymbol VisitType( break; } - if (!typeWithAnnotationsOpt.IsNull && typeWithAnnotationsPredicateOpt != null) + if (typeWithAnnotationsOpt.HasType && typeWithAnnotationsPredicateOpt != null) { if (typeWithAnnotationsPredicateOpt(typeWithAnnotationsOpt, arg, isNestedNamedType)) { diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs index 427fd9304b4a4..64907235180d2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs @@ -20,6 +20,41 @@ internal enum NullableAnnotation : byte Nullable, // Explicitly set by flow analysis } + /// + /// The nullable state of an rvalue computed in . + /// When in doubt we conservatively use + /// to minimize diagnostics. + /// + internal enum NullableFlowState : byte + { + NotNull, + MaybeNull + } + + /// + /// A type and its corresponding flow state resulting from evaluating an rvalue expression. + /// + [DebuggerDisplay("{GetDebuggerDisplay(), nq}")] + internal readonly struct TypeWithState + { + public TypeSymbol Type { get; } + public NullableFlowState State { get; } + public bool HasNullType => Type is null; + public bool MaybeNull => State == NullableFlowState.MaybeNull; + public bool NotNull => State == NullableFlowState.NotNull; + public static TypeWithState ForType(TypeSymbol type) => new TypeWithState(type, type?.CanContainNull() == true ? NullableFlowState.MaybeNull : NullableFlowState.NotNull); + public TypeWithState(TypeSymbol type, NullableFlowState state) => (Type, State) = (type, state); + public void Deconstruct(out TypeSymbol type, out NullableFlowState state) => (type, state) = (Type, State); + public string GetDebuggerDisplay() => $"{{Type:{Type?.GetDebuggerDisplay()}, State:{State}{"}"}"; + public TypeWithState WithNotNullState() => new TypeWithState(Type, NullableFlowState.NotNull); + public TypeSymbolWithAnnotations ToTypeSymbolWithAnnotations() + { + NullableAnnotation annotation = (this.State == NullableFlowState.NotNull) + ? NullableAnnotation.NotNullable : NullableAnnotation.Nullable; + return TypeSymbolWithAnnotations.Create(this.Type, annotation); + } + } + internal static class NullableAnnotationExtensions { public static bool IsAnyNullable(this NullableAnnotation annotation) @@ -82,8 +117,10 @@ public static NullableAnnotation AsSpeakable(this NullableAnnotation annotation, /// public static NullableAnnotation JoinForFixingLowerBounds(this NullableAnnotation a, NullableAnnotation b) { - Debug.Assert(a.IsSpeakable()); - Debug.Assert(b.IsSpeakable()); + if (a == NullableAnnotation.Nullable || b == NullableAnnotation.Nullable) + { + return NullableAnnotation.Nullable; + } if (a == NullableAnnotation.Annotated || b == NullableAnnotation.Annotated) { @@ -95,67 +132,21 @@ public static NullableAnnotation JoinForFixingLowerBounds(this NullableAnnotatio return NullableAnnotation.Unknown; } + if (a == NullableAnnotation.NotNullable || b == NullableAnnotation.NotNullable) + { + return NullableAnnotation.NotNullable; + } + return NullableAnnotation.NotAnnotated; } /// - /// Join nullable annotations from distinct branches during flow analysis. + /// Join nullable flow states from distinct branches during flow analysis. /// - public static NullableAnnotation JoinForFlowAnalysisBranches(this NullableAnnotation selfAnnotation, NullableAnnotation otherAnnotation, T type, Func isPossiblyNullableReferenceTypeTypeParameter) + public static NullableFlowState JoinForFlowAnalysisBranches(this NullableFlowState selfState, NullableFlowState otherState) { - if (selfAnnotation == otherAnnotation) - { - return selfAnnotation; - } - - if (selfAnnotation.IsAnyNullable() || otherAnnotation.IsAnyNullable()) - { - return selfAnnotation == NullableAnnotation.Annotated || otherAnnotation == NullableAnnotation.Annotated ? - NullableAnnotation.Annotated : NullableAnnotation.Nullable; - } - else if (selfAnnotation == NullableAnnotation.Unknown) - { - if (otherAnnotation == NullableAnnotation.Unknown || otherAnnotation == NullableAnnotation.NotNullable) - { - return NullableAnnotation.Unknown; - } - else - { - Debug.Assert(otherAnnotation == NullableAnnotation.NotAnnotated); - if (isPossiblyNullableReferenceTypeTypeParameter(type)) - { - return otherAnnotation; - } - else - { - return NullableAnnotation.Unknown; - } - } - } - else if (otherAnnotation == NullableAnnotation.Unknown) - { - if (selfAnnotation == NullableAnnotation.NotNullable) - { - return NullableAnnotation.Unknown; - } - else - { - Debug.Assert(selfAnnotation == NullableAnnotation.NotAnnotated); - if (isPossiblyNullableReferenceTypeTypeParameter(type)) - { - return selfAnnotation; - } - else - { - return NullableAnnotation.Unknown; - } - } - } - else - { - return selfAnnotation == NullableAnnotation.NotAnnotated || otherAnnotation == NullableAnnotation.NotAnnotated ? - NullableAnnotation.NotAnnotated : NullableAnnotation.NotNullable; - } + return (selfState == NullableFlowState.MaybeNull || otherState == NullableFlowState.MaybeNull) + ? NullableFlowState.MaybeNull : NullableFlowState.NotNull; } /// @@ -164,8 +155,10 @@ public static NullableAnnotation JoinForFlowAnalysisBranches(this NullableAnn /// public static NullableAnnotation MeetForFixingUpperBounds(this NullableAnnotation a, NullableAnnotation b) { - Debug.Assert(a.IsSpeakable()); - Debug.Assert(b.IsSpeakable()); + if (a == NullableAnnotation.NotNullable || b == NullableAnnotation.NotNullable) + { + return NullableAnnotation.NotNullable; + } if (a == NullableAnnotation.NotAnnotated || b == NullableAnnotation.NotAnnotated) { @@ -177,33 +170,21 @@ public static NullableAnnotation MeetForFixingUpperBounds(this NullableAnnotatio return NullableAnnotation.Unknown; } + if (a == NullableAnnotation.Nullable || b == NullableAnnotation.Nullable) + { + return NullableAnnotation.Nullable; + } + return NullableAnnotation.Annotated; } /// - /// Meet two nullable annotations from distinct states for the meet (union) operation in flow analysis. + /// Meet two nullable flow states from distinct states for the meet (union) operation in flow analysis. /// - public static NullableAnnotation MeetForFlowAnalysisFinally(this NullableAnnotation selfAnnotation, NullableAnnotation otherAnnotation) + public static NullableFlowState MeetForFlowAnalysisFinally(this NullableFlowState selfState, NullableFlowState otherState) { - if (selfAnnotation == otherAnnotation) - { - return selfAnnotation; - } - - if (selfAnnotation.IsAnyNotNullable() || otherAnnotation.IsAnyNotNullable()) - { - return selfAnnotation == NullableAnnotation.NotNullable || otherAnnotation == NullableAnnotation.NotNullable ? - NullableAnnotation.NotNullable : NullableAnnotation.NotAnnotated; - } - else if (selfAnnotation == NullableAnnotation.Unknown || otherAnnotation == NullableAnnotation.Unknown) - { - return NullableAnnotation.Unknown; - } - else - { - return selfAnnotation == NullableAnnotation.Nullable || otherAnnotation == NullableAnnotation.Nullable ? - NullableAnnotation.Nullable : NullableAnnotation.Annotated; - } + return (selfState == NullableFlowState.NotNull || otherState == NullableFlowState.NotNull) + ? NullableFlowState.NotNull : NullableFlowState.MaybeNull; } /// @@ -230,55 +211,32 @@ public static NullableAnnotation EnsureCompatible(this NullableAnnotation a, Nul } /// - /// Check that two nullable annotations are "compatible", which means they could be the same. - /// This method can handle unspeakable types (for merging tuple types). + /// Check that two nullable annotations are "compatible", which means they could be the same. Return the + /// nullable annotation to be used as a result. This method can handle unspeakable types (for merging tuple types). /// - public static NullableAnnotation EnsureCompatibleForTuples(this NullableAnnotation a, NullableAnnotation b, T type, Func isPossiblyNullableReferenceTypeTypeParameter) + public static NullableAnnotation EnsureCompatibleForTuples(this NullableAnnotation a, NullableAnnotation b) { - if (a == b) + if (a == NullableAnnotation.NotNullable || b == NullableAnnotation.NotNullable) { - return a; + return NullableAnnotation.NotNullable; } - if (a.IsAnyNullable() && b.IsAnyNullable()) - { - return NullableAnnotation.Annotated; - } - - // If nullability on both sides matches - result is that nullability (trivial cases like these are handled above) - // If either candidate is "oblivious" - result is the nullability of the other candidate - // Otherwise - we declare a mismatch and result is not nullable. - - if (a == NullableAnnotation.Unknown) + if (a == NullableAnnotation.NotAnnotated || b == NullableAnnotation.NotAnnotated) { - return b; + return NullableAnnotation.NotAnnotated; } - if (b == NullableAnnotation.Unknown) + if (a == NullableAnnotation.Nullable || b == NullableAnnotation.Nullable) { - return a; + return NullableAnnotation.Nullable; } - // At this point we know that either nullability of both sides is significantly different NotNullable vs. Nullable, - // or we are dealing with different flavors of not nullable for both candidates - if ((a == NullableAnnotation.NotAnnotated && b == NullableAnnotation.NotNullable) || - (b == NullableAnnotation.NotAnnotated && a == NullableAnnotation.NotNullable)) - { - if (!isPossiblyNullableReferenceTypeTypeParameter(type)) - { - // For this type both not nullable annotations are equivalent and therefore match. - return NullableAnnotation.NotAnnotated; - } - - // We are dealing with different flavors of not nullable for a possibly nullable reference type parameter, - // we don't have a reliable way to merge them since one of them can actually represent a nullable type. - } - else + if (a == NullableAnnotation.Annotated || b == NullableAnnotation.Annotated) { - Debug.Assert(a.IsAnyNullable() != b.IsAnyNullable()); + return NullableAnnotation.Annotated; } - return NullableAnnotation.NotAnnotated; + return NullableAnnotation.Unknown; } } @@ -306,7 +264,7 @@ internal struct Builder /// /// True if the fields of the builder are unset. /// - internal bool IsNull => _defaultType is null; + internal bool IsDefault => _defaultType is null && _nullableAnnotation == 0 && (_extensions == null || _extensions == Extensions.Default); /// /// Set the fields of the builder. @@ -335,7 +293,7 @@ internal bool InterlockedInitialize(TypeSymbolWithAnnotations type) /// internal TypeSymbolWithAnnotations ToType() { - return (object)_defaultType == null ? + return IsDefault ? default : new TypeSymbolWithAnnotations(_defaultType, _nullableAnnotation, _extensions); } @@ -358,8 +316,7 @@ internal TypeSymbolWithAnnotations ToType() private TypeSymbolWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableAnnotation, Extensions extensions) { - Debug.Assert((object)defaultType != null); - Debug.Assert(!defaultType.IsNullableType() || (nullableAnnotation != NullableAnnotation.Unknown && nullableAnnotation != NullableAnnotation.NotAnnotated)); + Debug.Assert(defaultType?.IsNullableType() != true || (nullableAnnotation != NullableAnnotation.Unknown && nullableAnnotation != NullableAnnotation.NotAnnotated)); Debug.Assert(extensions != null); _defaultType = defaultType; @@ -369,7 +326,7 @@ private TypeSymbolWithAnnotations(TypeSymbol defaultType, NullableAnnotation nul public TypeSymbolWithAnnotations AsSpeakable() { - if (IsNull) + if (!HasType) { return default; } @@ -414,7 +371,7 @@ internal static TypeSymbolWithAnnotations Create(bool isNullableEnabled, TypeSym internal static TypeSymbolWithAnnotations Create(TypeSymbol typeSymbol, NullableAnnotation nullableAnnotation = NullableAnnotation.Unknown, ImmutableArray customModifiers = default) { - if (typeSymbol is null) + if (typeSymbol is null && nullableAnnotation == 0) { return default; } @@ -423,7 +380,7 @@ internal static TypeSymbolWithAnnotations Create(TypeSymbol typeSymbol, Nullable { case NullableAnnotation.Unknown: case NullableAnnotation.NotAnnotated: - if (typeSymbol.IsNullableType()) + if (typeSymbol?.IsNullableType() == true) { // int?, T? where T : struct (add annotation) nullableAnnotation = NullableAnnotation.Annotated; @@ -434,14 +391,16 @@ internal static TypeSymbolWithAnnotations Create(TypeSymbol typeSymbol, Nullable return CreateNonLazyType(typeSymbol, nullableAnnotation, customModifiers.NullToEmpty()); } - internal bool IsPossiblyNullableReferenceTypeTypeParameter() + internal bool IsPossiblyNullableTypeTypeParameter() { - return NullableAnnotation == NullableAnnotation.NotAnnotated && TypeSymbol.IsPossiblyNullableReferenceTypeTypeParameter(); + return NullableAnnotation == NullableAnnotation.NotAnnotated && + (TypeSymbol?.IsPossiblyNullableReferenceTypeTypeParameter() == true || + TypeSymbol?.IsNullableTypeOrTypeParameter() == true); } internal NullableAnnotation GetValueNullableAnnotation() { - if (IsPossiblyNullableReferenceTypeTypeParameter()) + if (IsPossiblyNullableTypeTypeParameter()) { return NullableAnnotation.Nullable; } @@ -455,25 +414,28 @@ internal NullableAnnotation GetValueNullableAnnotation() return NullableAnnotation; } - internal bool? ValueCanBeNull() + internal bool CanBeAssignedNull { - switch (NullableAnnotation) + get { - case NullableAnnotation.Unknown: - return null; + switch (NullableAnnotation) + { + case NullableAnnotation.Unknown: + return true; - case NullableAnnotation.Annotated: - case NullableAnnotation.Nullable: - return true; + case NullableAnnotation.Annotated: + case NullableAnnotation.Nullable: + return true; - case NullableAnnotation.NotNullable: - return false; + case NullableAnnotation.NotNullable: + return false; - case NullableAnnotation.NotAnnotated: - return TypeSymbol.IsPossiblyNullableReferenceTypeTypeParameter(); + case NullableAnnotation.NotAnnotated: + return TypeSymbol.IsNullableType(); - default: - throw ExceptionUtilities.UnexpectedValue(NullableAnnotation); + default: + throw ExceptionUtilities.UnexpectedValue(NullableAnnotation); + } } } @@ -494,9 +456,14 @@ private static TypeSymbolWithAnnotations CreateLazyNullableType(CSharpCompilatio } /// - /// True if the fields are unset. + /// True if the fields are unset. Appropriate when detecting if a lazily-initialized variable has been initialized. + /// + internal bool IsDefault => _defaultType is null && this.NullableAnnotation == 0 && (_extensions == null || _extensions == Extensions.Default); + + /// + /// True if the type is not null. /// - internal bool IsNull => _defaultType is null; + internal bool HasType => !(_defaultType is null); public TypeSymbolWithAnnotations SetIsAnnotated(CSharpCompilation compilation) { @@ -605,7 +572,7 @@ internal bool GetIsValueType(ConsList inProgress) => public string ToDisplayString(SymbolDisplayFormat format = null) { - var str = TypeSymbol.ToDisplayString(format); + var str = !HasType ? "" : TypeSymbol.ToDisplayString(format); if (format != null) { if (format.MiscellaneousOptions.IncludesOption(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier) && @@ -625,7 +592,7 @@ public string ToDisplayString(SymbolDisplayFormat format = null) return str; } - internal string GetDebuggerDisplay() => _defaultType is null ? "null" : ToDisplayString(DebuggerDisplayFormat); + internal string GetDebuggerDisplay() => !this.HasType ? "" : ToDisplayString(DebuggerDisplayFormat); string IFormattable.ToString(string format, IFormatProvider formatProvider) { @@ -639,7 +606,12 @@ public bool Equals(TypeSymbolWithAnnotations other, TypeCompareKind comparison) return true; } - if (other.IsNull || !TypeSymbolEquals(other, comparison)) + if (!HasType) + { + if (other.HasType || NullableAnnotation != other.NullableAnnotation) + return false; + } + else if (!other.HasType || !TypeSymbolEquals(other, comparison)) { return false; } @@ -651,10 +623,14 @@ public bool Equals(TypeSymbolWithAnnotations other, TypeCompareKind comparison) return false; } - if ((comparison & TypeCompareKind.IgnoreNullableModifiersForReferenceTypes) == 0) + var thisAnnotation = NullableAnnotation; + var otherAnnotation = other.NullableAnnotation; + if (!HasType) + { + return thisAnnotation == otherAnnotation; + } + else if ((comparison & TypeCompareKind.IgnoreNullableModifiersForReferenceTypes) == 0) { - var thisAnnotation = NullableAnnotation; - var otherAnnotation = other.NullableAnnotation; if (otherAnnotation != thisAnnotation && (!TypeSymbol.IsValueType || TypeSymbol.IsNullableType())) { if (thisAnnotation == NullableAnnotation.Unknown || otherAnnotation == NullableAnnotation.Unknown) @@ -704,7 +680,7 @@ private EqualsComparer() public override int GetHashCode(TypeSymbolWithAnnotations obj) { - if (obj.IsNull) + if (!obj.HasType) { return 0; } @@ -713,9 +689,9 @@ public override int GetHashCode(TypeSymbolWithAnnotations obj) public override bool Equals(TypeSymbolWithAnnotations x, TypeSymbolWithAnnotations y) { - if (x.IsNull) + if (!x.HasType) { - return y.IsNull; + return !y.HasType; } return x.Equals(y, TypeCompareKind.ConsiderEverything); } @@ -989,7 +965,7 @@ public TypeSymbolWithAnnotations SetUnknownNullabilityForReferenceTypes() public TypeSymbolWithAnnotations SetSpeakableNullabilityForReferenceTypes() { - if (IsNull) + if (!HasType) { return default; } @@ -1027,7 +1003,7 @@ public override bool Equals(object other) public override int GetHashCode() #pragma warning restore CS0809 { - if (IsNull) + if (!HasType) { return 0; } @@ -1363,5 +1339,19 @@ internal override bool TypeSymbolEquals(TypeSymbolWithAnnotations type, TypeSymb return type.TypeSymbolEqualsCore(other, comparison); } } + + /// + /// Compute the flow state resulting from reading from an lvalue. + /// + internal TypeWithState ToTypeWithState() + { + // This operation reflects reading from an lvalue, which produces an rvalue. + // Reading from a variable of a type parameter (that could be substituted with a nullable type), but which + // cannot itself be annotated (because it isn't known to be a reference type), may yield a null value + // even though the type parameter isn't annotated. + return new TypeWithState( + this.TypeSymbol, + IsPossiblyNullableTypeTypeParameter() || this.NullableAnnotation.IsAnyNullable() ? NullableFlowState.MaybeNull : NullableFlowState.NotNull); + } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeUnification.cs b/src/Compilers/CSharp/Portable/Symbols/TypeUnification.cs index a64cfd433f0ef..63b120ba3ea95 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeUnification.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeUnification.cs @@ -76,7 +76,7 @@ private static bool CanUnifyHelper(TypeSymbol t1, TypeSymbol t2, ref MutableType /// private static bool CanUnifyHelper(TypeSymbolWithAnnotations t1, TypeSymbolWithAnnotations t2, ref MutableTypeMap substitution) { - if (t1.IsNull || t2.IsNull) + if (!t1.HasType || !t2.HasType) { return t1.IsSameAs(t2); } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 7811cf6d420dc..ed964d9626e61 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -357,36 +357,6 @@ Nรกzev souboru {0} je prรกzdnรฝ, obsahuje neplatnรฉ znaky, mรก specifikaci jednotky bez absolutnรญ cesty nebo je moc dlouhรฝ. - - Expression is probably never null. - Vรฝraz pravdฤ›podobnฤ› nenรญ nikdy null. - - - - Expression is probably never null. - Vรฝraz pravdฤ›podobnฤ› nenรญ nikdy null. - - - - Result of the comparison is possibly always false. - Vรฝsledek porovnรกnรญ je pravdฤ›podobnฤ› vลพdy false. - - - - Result of the comparison is possibly always false. - Vรฝsledek porovnรกnรญ je pravdฤ›podobnฤ› vลพdy false. - - - - Result of the comparison is possibly always true. - Vรฝsledek porovnรกnรญ je pravdฤ›podobnฤ› vลพdy true. - - - - Result of the comparison is possibly always true. - Vรฝsledek porovnรกnรญ je pravdฤ›podobnฤ› vลพdy true. - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ SyntaxTree nenรญ souฤรกstรญ kompilace, takลพe se nedรก odebrat. + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. Nรกzev โ€ž_โ€œ odkazuje na konstantu, ne na vzor discard. Zadรกnรญm โ€žvar _โ€œ hodnotu zahodรญte a zadรกnรญm โ€ž@_โ€œ nastavรญte pod tรญmto nรกzvem odkaz na konstantu. @@ -1202,6 +1182,16 @@ Nepouลพรญvejte โ€ž_โ€œ jako konstantu case. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. Literรกl s hodnotou null nebo s moลพnou hodnotou null se pล™evรกdรญ na typ bez moลพnosti hodnoty null. @@ -1212,6 +1202,16 @@ Literรกl s hodnotou null nebo s moลพnou hodnotou null se pล™evรกdรญ na typ bez moลพnosti hodnoty null. + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' Hodnota default se pล™evede na null, nikoli na default({0}). @@ -1292,6 +1292,16 @@ Literรกl s hodnotou null nejde pล™evรฉst na odkaz bez moลพnosti hodnoty null ani na parametr neomezenรฉho typu. + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 8f85f18231110..24cc784fc3ce6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -357,36 +357,6 @@ Der Dateiname "{0}" ist leer, enthรคlt ungรผltige Zeichen, weist eine Laufwerkangabe ohne absoluten Pfad auf oder ist zu lang. - - Expression is probably never null. - Der Ausdruck ist wahrscheinlich niemals NULL. - - - - Expression is probably never null. - Der Ausdruck ist wahrscheinlich niemals NULL. - - - - Result of the comparison is possibly always false. - Das Ergebnis des Vergleichs ist mรถglicherweise immer FALSE. - - - - Result of the comparison is possibly always false. - Das Ergebnis des Vergleichs ist mรถglicherweise immer FALSE. - - - - Result of the comparison is possibly always true. - Das Ergebnis des Vergleichs ist mรถglicherweise immer TRUE. - - - - Result of the comparison is possibly always true. - Das Ergebnis des Vergleichs ist mรถglicherweise immer TRUE. - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ SyntaxTree ist kein Teil der Kompilierung und kann daher nicht entfernt werden. + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. Der Name "_" verweist auf die Konstante, nicht auf das discard-Muster. Verwenden Sie "var _" zum Verwerfen des Werts oder "@_" zum Verweis auf eine Konstante รผber diesen Namen. @@ -1202,6 +1182,16 @@ Verwenden Sie "_" nicht fรผr eine case-Konstante. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. Das NULL-Literal oder ein mรถglicher NULL-Wert wird in einen Nicht-Nullable-Typ konvertiert. @@ -1212,6 +1202,16 @@ Das NULL-Literal oder ein mรถglicher NULL-Wert wird in einen Nicht-Nullable-Typ konvertiert. + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' "default" wird in "null", nicht "default({0})" konvertiert. @@ -1292,6 +1292,16 @@ NULL-Literal kann nicht in einen Nicht-Nullable-Verweis- oder uneingeschrรคnkten Typparameter konvertiert werden. + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 cd0b0fbda5785..cc727847e53ca 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -357,36 +357,6 @@ El nombre de archivo '{0}' estรก vacรญo, contiene caracteres no vรกlidos, tiene una especificaciรณn de unidad sin ruta de acceso absoluta o es demasiado largo - - Expression is probably never null. - Probablemente, la expresiรณn nunca es NULL. - - - - Expression is probably never null. - Probablemente, la expresiรณn nunca es NULL - - - - Result of the comparison is possibly always false. - Posiblemente, el resultado de la comparaciรณn es siempre false. - - - - Result of the comparison is possibly always false. - Posiblemente, el resultado de la comparaciรณn es siempre false - - - - Result of the comparison is possibly always true. - Posiblemente, el resultado de la comparaciรณn es siempre true. - - - - Result of the comparison is possibly always true. - Posiblemente, el resultado de la comparaciรณn es siempre true - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ SyntaxTree no forma parte de la compilaciรณn, asรญ que no se puede quitar + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. El nombre "_" hace referencia a la constante, no al patrรณn de descarte. Use "var _" para descartar el valor o "@_" para hacer referencia a una constante con ese nombre. @@ -1202,6 +1182,16 @@ No use "_" para una constante de caso. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. Se va a convertir un literal nulo o un posible valor nulo en un tipo que no acepta valores NULL @@ -1212,6 +1202,16 @@ Se va a convertir un literal nulo o un posible valor nulo en un tipo que no acepta valores NULL + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' "default" se convierte en "null", no "default({0})". @@ -1292,6 +1292,16 @@ No se puede convertir un literal nulo en un parรกmetro de tipo de referencia que no acepta valores NULL o un parรกmetro de tipo sin restricciones + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 f342b9db9cdb5..86f3331f8ad46 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -357,36 +357,6 @@ Le nom de fichier '{0}' est vide, contient des caractรจres non valides, spรฉcifie un lecteur sans chemin d'accรจs absolu ou est trop long - - Expression is probably never null. - L'expression n'a probablement jamais une valeur null. - - - - Expression is probably never null. - L'expression n'a probablement jamais une valeur null. - - - - Result of the comparison is possibly always false. - Le rรฉsultat de la comparaison est peut-รชtre toujours faux. - - - - Result of the comparison is possibly always false. - Le rรฉsultat de la comparaison est peut-รชtre toujours faux. - - - - Result of the comparison is possibly always true. - Le rรฉsultat de la comparaison est peut-รชtre toujours vrai. - - - - Result of the comparison is possibly always true. - Le rรฉsultat de la comparaison est peut-รชtre toujours vrai. - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ SyntaxTree ne faisant pas partie de la compilation, il ne peut pas รชtre supprimรฉ + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. Le nom '_' fait rรฉfรฉrence ร  la constante, pas au modรจle d'abandon. Utilisez 'var _' pour abandonner la valeur, ou '@_' pour faire rรฉfรฉrence ร  une constante par ce nom. @@ -1202,6 +1182,16 @@ N'utilisez pas '_' pour une constante case. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. Conversion de littรฉral ayant une valeur null ou d'une รฉventuelle valeur null en type non Nullable. @@ -1212,6 +1202,16 @@ Conversion de littรฉral ayant une valeur null ou d'une รฉventuelle valeur null en type non Nullable. + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' 'default' converti en 'null', et non 'default({0})' @@ -1292,6 +1292,16 @@ Impossible de convertir un littรฉral ayant une valeur null en paramรจtre de type rรฉfรฉrence non Nullable ou non contraint. + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 1c9811125e42c..a511c3ccacdea 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -357,36 +357,6 @@ Il nome file '{0}' รจ vuoto, contiene caratteri non validi, include una specifica di unitร  senza percorso assoluto oppure รจ troppo lungo - - Expression is probably never null. - L'espressione non รจ probabilmente mai Null. - - - - Expression is probably never null. - L'espressione non รจ probabilmente mai Null. - - - - Result of the comparison is possibly always false. - Il risultato del confronto รจ probabilmente sempre false. - - - - Result of the comparison is possibly always false. - Il risultato del confronto รจ probabilmente sempre false. - - - - Result of the comparison is possibly always true. - Il risultato del confronto รจ probabilmente sempre true. - - - - Result of the comparison is possibly always true. - Il risultato del confronto รจ probabilmente sempre true. - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ L'elemento SyntaxTree non fa parte della compilazione, di conseguenza non puรฒ essere rimosso + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. Il nome '_' fa riferimento alla costante e non al criterio di eliminazione. Usare 'var _' per eliminare il valore oppure '@_' per fare riferimento a una costante in base a tale nome. @@ -1202,6 +1182,16 @@ Non usare '_' per una costante di case. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. Conversione del valore letterale Null o di un possibile valore Null in tipo non nullable. @@ -1212,6 +1202,16 @@ Conversione del valore letterale Null o di un possibile valore Null in tipo non nullable. + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' 'default' viene convertito in 'null', non in 'default({0})' @@ -1292,6 +1292,16 @@ Non รจ possibile convertire il valore letterale Null in riferimento non nullable o parametro di tipo senza vincoli. + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 c8fae3f69c5a7..e59c860aeb8c0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -357,36 +357,6 @@ ใƒ•ใ‚กใ‚คใƒซๅ '{0}' ใฏใ€็ฉบใงใ‚ใ‚‹ใ€็„กๅŠนใชๆ–‡ๅญ—ใ‚’ๅซใ‚“ใงใ„ใ‚‹ใ€็ตถๅฏพใƒ‘ใ‚นใŒๆŒ‡ๅฎšใ•ใ‚Œใฆใ„ใชใ„ใƒ‰ใƒฉใ‚คใƒ–ๆŒ‡ๅฎšใŒใ‚ใ‚‹ใ€ใพใŸใฏ้•ทใ™ใŽใ‚‹ใ‹ใฎใ„ใšใ‚Œใ‹ใงใ™ใ€‚ - - Expression is probably never null. - ๅผใฏๆฑบใ—ใฆ Null ใซใชใ‚‰ใชใ„ใ‚‚ใฎใจๆ€ใ‚ใ‚Œใพใ™ใ€‚ - - - - Expression is probably never null. - ๅผใฏๆฑบใ—ใฆ Null ใซใชใ‚‰ใชใ„ใ‚‚ใฎใจๆ€ใ‚ใ‚Œใพใ™ใ€‚ - - - - Result of the comparison is possibly always false. - ๆฏ”่ผƒใฎ็ตๆžœใŒๅธธใซ false ใซใชใ‚‹ใ‚‚ใฎใจๆ€ใ‚ใ‚Œใพใ™ใ€‚ - - - - Result of the comparison is possibly always false. - ๆฏ”่ผƒใฎ็ตๆžœใŒๅธธใซ false ใซใชใ‚‹ใ‚‚ใฎใจๆ€ใ‚ใ‚Œใพใ™ใ€‚ - - - - Result of the comparison is possibly always true. - ๆฏ”่ผƒใฎ็ตๆžœใŒๅธธใซ true ใซใชใ‚‹ใ‚‚ใฎใจๆ€ใ‚ใ‚Œใพใ™ใ€‚ - - - - Result of the comparison is possibly always true. - ๆฏ”่ผƒใฎ็ตๆžœใŒๅธธใซ true ใซใชใ‚‹ใ‚‚ใฎใจๆ€ใ‚ใ‚Œใพใ™ใ€‚ - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ SyntaxTree ใฏใ‚ณใƒณใƒ‘ใ‚คใƒซใฎไธ€้ƒจใงใฏใชใ„ใŸใ‚ๅ‰Š้™คใงใใพใ›ใ‚“ + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. ๅๅ‰ '_' ใฏใ€็ ดๆฃ„ใƒ‘ใ‚ฟใƒผใƒณใงใฏใชใๅฎšๆ•ฐใ‚’ๅ‚็…งใ—ใฆใ„ใพใ™ใ€‚ๅ€คใ‚’็ ดๆฃ„ใ™ใ‚‹ๅ ดๅˆใซใฏ 'var _' ใ‚’ใ€ใใฎใ‚ˆใ†ใชๅๅ‰ใฎๅฎšๆ•ฐใ‚’ๅ‚็…งใ™ใ‚‹ๅ ดๅˆใซใฏ '@_' ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ @@ -1202,6 +1182,16 @@ case ๅฎšๆ•ฐใซ '_' ใ‚’ไฝฟ็”จใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. Null ใƒชใƒ†ใƒฉใƒซใพใŸใฏ Null ใฎๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ๅ€คใ‚’ Null ้ž่จฑๅฎนๅž‹ใซๅค‰ๆ›ใ—ใฆใ„ใพใ™ใ€‚ @@ -1212,6 +1202,16 @@ Null ใƒชใƒ†ใƒฉใƒซใพใŸใฏ Null ใฎๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ๅ€คใ‚’ Null ้ž่จฑๅฎนๅž‹ใซๅค‰ๆ›ใ—ใฆใ„ใพใ™ใ€‚ + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' 'default' ใฏใ€'default({0})' ใงใฏใชใ 'null' ใซๅค‰ๆ›ใ•ใ‚Œใพใ™ @@ -1292,6 +1292,16 @@ Null ใƒชใƒ†ใƒฉใƒซใ‚’ Null ้ž่จฑๅฎนๅ‚็…งๅž‹ใพใŸใฏ้žๅˆถ็ด„ๅž‹ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใซๅค‰ๆ›ใงใใพใ›ใ‚“ใ€‚ + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 b9a5b497b9f1a..ba33df05b1137 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -357,36 +357,6 @@ {0}' ํŒŒ์ผ ์ด๋ฆ„์ด ๋น„์–ด ์žˆ๊ฑฐ๋‚˜, ์ž˜๋ชป๋œ ๋ฌธ์ž๊ฐ€ ์žˆ๊ฑฐ๋‚˜, ์ ˆ๋Œ€ ๊ฒฝ๋กœ๊ฐ€ ์—†๋Š” ๋“œ๋ผ์ด๋ธŒ ์‚ฌ์–‘์ด ์žˆ๊ฑฐ๋‚˜, ๋„ˆ๋ฌด ๊น๋‹ˆ๋‹ค. - - Expression is probably never null. - ์‹์€ null์ผ ์ˆ˜ ์—†๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. - - - - Expression is probably never null. - ์‹์€ null์ผ ์ˆ˜ ์—†๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. - - - - Result of the comparison is possibly always false. - ๋น„๊ต ๊ฒฐ๊ณผ๋Š” ์•„๋งˆ๋„ ํ•ญ์ƒ false์ž…๋‹ˆ๋‹ค. - - - - Result of the comparison is possibly always false. - ๋น„๊ต ๊ฒฐ๊ณผ๋Š” ์•„๋งˆ๋„ ํ•ญ์ƒ false์ž…๋‹ˆ๋‹ค. - - - - Result of the comparison is possibly always true. - ๋น„๊ต ๊ฒฐ๊ณผ๋Š” ์•„๋งˆ๋„ ํ•ญ์ƒ true์ž…๋‹ˆ๋‹ค. - - - - Result of the comparison is possibly always true. - ๋น„๊ต ๊ฒฐ๊ณผ๋Š” ์•„๋งˆ๋„ ํ•ญ์ƒ true์ž…๋‹ˆ๋‹ค. - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ SyntaxTree๋Š” ์ปดํŒŒ์ผ์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์ œ๊ฑฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. '_' ์ด๋ฆ„์€ ์ƒ์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋ฉฐ, ๋ฌด์‹œ ํŒจํ„ด์€ ์ฐธ์กฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. 'var _'์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ’์„ ๋ฌด์‹œํ•˜๊ฑฐ๋‚˜ '@_'์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ์ด๋ฆ„๋ณ„ ์ƒ์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. @@ -1202,6 +1182,16 @@ case ์ƒ์ˆ˜์— '_'์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. null ๋ฆฌํ„ฐ๋Ÿด ๋˜๋Š” ๊ฐ€๋Šฅํ•œ null ๊ฐ’์„ nullable์ด ์•„๋‹Œ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. @@ -1212,6 +1202,16 @@ null ๋ฆฌํ„ฐ๋Ÿด ๋˜๋Š” ๊ฐ€๋Šฅํ•œ null ๊ฐ’์„ nullable์ด ์•„๋‹Œ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' 'default'๋Š” 'default({0})'๊ฐ€ ์•„๋‹ˆ๋ผ 'null'๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. @@ -1292,6 +1292,16 @@ null ๋ฆฌํ„ฐ๋Ÿด์„ nullable์ด ์•„๋‹Œ ์ฐธ์กฐ ๋˜๋Š” ๋น„์ œํ•œ ํ˜•์‹ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 87c5a8770aa87..c2446947929f2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -357,36 +357,6 @@ Nazwa pliku โ€ž{0}โ€ jest pusta, zawiera nieprawidล‚owe znaki, zawiera specyfikacjฤ™ dysku bez bezwzglฤ™dnej ล›cieลผki lub jest za dล‚uga - - Expression is probably never null. - Wyraลผenie prawdopodobnie nigdy nie przyjmuje wartoล›ci null. - - - - Expression is probably never null. - Wyraลผenie prawdopodobnie nigdy nie przyjmuje wartoล›ci null. - - - - Result of the comparison is possibly always false. - Byฤ‡ moลผe wynik porรณwnania zawsze ma wartoล›ฤ‡ false. - - - - Result of the comparison is possibly always false. - Byฤ‡ moลผe wynik porรณwnania zawsze ma wartoล›ฤ‡ false. - - - - Result of the comparison is possibly always true. - Byฤ‡ moลผe wynik porรณwnania zawsze ma wartoล›ฤ‡ true. - - - - Result of the comparison is possibly always true. - Byฤ‡ moลผe wynik porรณwnania zawsze ma wartoล›ฤ‡ true. - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ Element SyntaxTree nie jest czฤ™ล›ciฤ… kompilacji, wiฤ™c nie moลผna go usunฤ…ฤ‡ + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. Nazwa โ€ž_โ€ odwoล‚uje siฤ™ do staล‚ej, a nie do wzorca odrzucania. Uลผyj elementu โ€žvar _โ€, aby odrzuciฤ‡ wartoล›ฤ‡, lub uลผyj elementu โ€ž@_โ€, aby odwoล‚aฤ‡ siฤ™ do staล‚ej za pomocฤ… tej nazwy. @@ -1202,6 +1182,16 @@ Nie uลผywaj elementu โ€ž_โ€ dla staล‚ej case. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. Konwertowanie literaล‚u o wartoล›ci null lub moลผliwej wartoล›ci null na typ niedopuszczajฤ…cy wartoล›ci null. @@ -1212,6 +1202,16 @@ Konwertowanie literaล‚u o wartoล›ci null lub moลผliwej wartoล›ci null na typ niedopuszczajฤ…cy wartoล›ci null. + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' Element โ€ždefaultโ€ jest konwertowany na wartoล›ฤ‡ โ€žnullโ€, a nie na โ€ždefault({0})โ€ @@ -1292,6 +1292,16 @@ Nie moลผna przekonwertowaฤ‡ literaล‚u o wartoล›ci null na referencyjny parametr typu niedopuszczajฤ…cy wartoล›ci null lub na parametr typu bez ograniczeล„. + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 61e92df7b6024..1ef81a3563caf 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -357,36 +357,6 @@ Nome do arquivo "{0}" estรก vazio, contรฉm caracteres invรกlidos, tem uma especificaรงรฃo de unidade sem um caminho absoluto ou รฉ muito longo - - Expression is probably never null. - A expressรฃo provavelmente รฉ nunca nula. - - - - Expression is probably never null. - A expressรฃo provavelmente รฉ nunca nula. - - - - Result of the comparison is possibly always false. - O resultado da comparaรงรฃo possivelmente รฉ sempre falso. - - - - Result of the comparison is possibly always false. - O resultado da comparaรงรฃo possivelmente รฉ sempre falso. - - - - Result of the comparison is possibly always true. - O resultado da comparaรงรฃo possivelmente รฉ sempre verdadeiro. - - - - Result of the comparison is possibly always true. - O resultado da comparaรงรฃo possivelmente รฉ sempre verdadeiro. - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ A SyntaxTree nรฃo faz parte da compilaรงรฃo, portanto, nรฃo pode ser removida + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. O nome '_' refere-se ร  constante, nรฃo ao padrรฃo de descarte. Use 'var _' para descartar o valor ou '@_' para referir-se a uma constante por esse nome. @@ -1202,6 +1182,16 @@ Nรฃo use '_' para uma constante de caso. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. Conversรฃo de literal nula ou possรญvel valor nulo em tipo nรฃo nulo. @@ -1212,6 +1202,16 @@ Conversรฃo de literal nula ou possรญvel valor nulo em tipo nรฃo nulo. + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' 'default' รฉ convertido em 'null', e nรฃo 'default({0})' @@ -1292,6 +1292,16 @@ Nรฃo รฉ possรญvel converter uma literal nula em referรชncia nรฃo nula ou em parรขmetro de tipo irrestrito. + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 b46394403ec56..f2403f2df7be4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -357,36 +357,6 @@ ะ˜ะผั ั„ะฐะนะปะฐ "{0}" ะฟัƒัั‚ะพะต, ัะพะดะตั€ะถะธั‚ ะฝะตะดะพะฟัƒัั‚ะธะผั‹ะต ัะธะผะฒะพะปั‹, ะธะผะตะตั‚ ะธะผั ะดะธัะบะฐ ะฑะตะท ะฐะฑัะพะปัŽั‚ะฝะพะณะพ ะฟัƒั‚ะธ ะธะปะธ ัะปะธัˆะบะพะผ ะดะปะธะฝะฝะพะต. - - Expression is probably never null. - ะ’ะพะทะผะพะถะฝะพ, ะฒั‹ั€ะฐะถะตะฝะธะต ะฝะธะบะพะณะดะฐ ะฝะต ะผะพะถะตั‚ ะธะผะตั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต NULL. - - - - Expression is probably never null. - ะ’ะพะทะผะพะถะฝะพ, ะฒั‹ั€ะฐะถะตะฝะธะต ะฝะธะบะพะณะดะฐ ะฝะต ะผะพะถะตั‚ ะธะผะตั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต NULL. - - - - Result of the comparison is possibly always false. - ะ’ะพะทะผะพะถะฝะพ, ั€ะตะทัƒะปัŒั‚ะฐั‚ ัั€ะฐะฒะฝะตะฝะธั ะฒัะตะณะดะฐ ะธะผะตะตั‚ ะทะฝะฐั‡ะตะฝะธะต false. - - - - Result of the comparison is possibly always false. - ะ’ะพะทะผะพะถะฝะพ, ั€ะตะทัƒะปัŒั‚ะฐั‚ ัั€ะฐะฒะฝะตะฝะธั ะฒัะตะณะดะฐ ะธะผะตะตั‚ ะทะฝะฐั‡ะตะฝะธะต false. - - - - Result of the comparison is possibly always true. - ะ’ะพะทะผะพะถะฝะพ, ั€ะตะทัƒะปัŒั‚ะฐั‚ ัั€ะฐะฒะฝะตะฝะธั ะฒัะตะณะดะฐ ะธะผะตะตั‚ ะทะฝะฐั‡ะตะฝะธะต true. - - - - Result of the comparison is possibly always true. - ะ’ะพะทะผะพะถะฝะพ, ั€ะตะทัƒะปัŒั‚ะฐั‚ ัั€ะฐะฒะฝะตะฝะธั ะฒัะตะณะดะฐ ะธะผะตะตั‚ ะทะฝะฐั‡ะตะฝะธะต true. - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ SyntaxTree ะฝะต ะฒั…ะพะดะธั‚ ะฒ ะบะพะผะฟะธะปัั†ะธัŽ, ะฟะพัั‚ะพะผัƒ ะตะณะพ ะฝะตะฒะพะทะผะพะถะฝะพ ัƒะดะฐะปะธั‚ัŒ + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. ะ˜ะผั "_" ััั‹ะปะฐะตั‚ัั ะฝะฐ ะบะพะฝัั‚ะฐะฝั‚ัƒ, ะฐ ะฝะต ะฝะฐ ัˆะฐะฑะปะพะฝ ะพั‚ะผะตะฝั‹. ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต "var _", ั‡ั‚ะพะฑั‹ ะพั‚ะผะตะฝะธั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต, ะธะปะธ "@_", ั‡ั‚ะพะฑั‹ ัะพัะปะฐั‚ัŒัั ะฝะฐ ะบะพะฝัั‚ะฐะฝั‚ัƒ ะฟะพ ัั‚ะพะผัƒ ะธะผะตะฝะธ. @@ -1202,6 +1182,16 @@ ะะต ะธัะฟะพะปัŒะทัƒะนั‚ะต "_" ะดะปั ะบะพะฝัั‚ะฐะฝั‚ั‹ case. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะปะธั‚ะตั€ะฐะปะฐ, ะดะพะฟัƒัะบะฐัŽั‰ะตะณะพ ะทะฝะฐั‡ะตะฝะธะต NULL ะธะปะธ ะฒะพะทะผะพะถะฝะพะณะพ ะทะฝะฐั‡ะตะฝะธั NULL ะฒ ั‚ะธะฟ, ะฝะต ะดะพะฟัƒัะบะฐัŽั‰ะธะน ะทะฝะฐั‡ะตะฝะธะต NULL. @@ -1212,6 +1202,16 @@ ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะปะธั‚ะตั€ะฐะปะฐ, ะดะพะฟัƒัะบะฐัŽั‰ะตะณะพ ะทะฝะฐั‡ะตะฝะธะต NULL ะธะปะธ ะฒะพะทะผะพะถะฝะพะณะพ ะทะฝะฐั‡ะตะฝะธั NULL ะฒ ั‚ะธะฟ, ะฝะต ะดะพะฟัƒัะบะฐัŽั‰ะธะน ะทะฝะฐั‡ะตะฝะธะต NULL. + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' "default" ะฟั€ะตะพะฑั€ะฐะทัƒะตั‚ัั ะฒ "null", ะฐ ะฝะต ะฒ "default({0})" @@ -1292,6 +1292,16 @@ ะะต ัƒะดะฐะตั‚ัั ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐั‚ัŒ ะปะธั‚ะตั€ะฐะป, ะดะพะฟัƒัะบะฐัŽั‰ะธะน ะทะฝะฐั‡ะตะฝะธะต NULL ะฒ ััั‹ะปะบัƒ, ะฝะต ะดะพะฟัƒัะบะฐัŽั‰ัƒัŽ ะทะฝะฐั‡ะตะฝะธะต NULL ะธะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ะฝะตะพะณั€ะฐะฝะธั‡ะตะฝะฝะพะณะพ ั‚ะธะฟะฐ. + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 9e6fe33b88f31..699bb8703c402 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -357,36 +357,6 @@ File name '{0}' is empty, contains invalid characters, has a drive specification without an absolute path, or is too long - - Expression is probably never null. - ฤฐfade bรผyรผk ihtimalle hiรงbir zaman null deฤŸildir. - - - - Expression is probably never null. - ฤฐfade bรผyรผk ihtimalle hiรงbir zaman null deฤŸildir. - - - - Result of the comparison is possibly always false. - KarลŸฤฑlaลŸtฤฑrma sonucunun her zaman false olmasฤฑ mรผmkรผndรผr. - - - - Result of the comparison is possibly always false. - KarลŸฤฑlaลŸtฤฑrma sonucunun her zaman false olmasฤฑ mรผmkรผndรผr. - - - - Result of the comparison is possibly always true. - KarลŸฤฑlaลŸtฤฑrma sonucunun her zaman true olmasฤฑ mรผmkรผndรผr. - - - - Result of the comparison is possibly always true. - KarลŸฤฑlaลŸtฤฑrma sonucunun her zaman true olmasฤฑ mรผmkรผndรผr. - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ SyntaxTree derlemenin bir parรงasฤฑ olmadฤฑฤŸฤฑndan kaldฤฑrฤฑlamaz + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. '_' adฤฑ atma desenine deฤŸil sabite baลŸvuruyor. DeฤŸeri atmak iรงin 'var _' adฤฑnฤฑ ya da bu ada sahip bir sabite baลŸvurmak iรงin '@_' adฤฑnฤฑ kullanฤฑn. @@ -1202,6 +1182,16 @@ Bir case sabiti iรงin '_' adฤฑnฤฑ kullanmayฤฑn. + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. Null sabit deฤŸeri veya olasฤฑ null deฤŸeri, boลŸ deฤŸer atanamaz tรผre dรถnรผลŸtรผrรผlรผyor. @@ -1212,6 +1202,16 @@ Null sabit deฤŸeri veya olasฤฑ null deฤŸeri, boลŸ deฤŸer atanamaz tรผre dรถnรผลŸtรผrรผlรผyor. + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' 'default', 'default({0})' deฤŸil 'null' deฤŸerine dรถnรผลŸtรผrรผlรผr @@ -1292,6 +1292,16 @@ Null sabit deฤŸeri, boลŸ deฤŸer atanamaz baลŸvuruya veya kฤฑsฤฑtlanmamฤฑลŸ tรผr parametresine dรถnรผลŸtรผrรผlemiyor. + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 7b3c0fa408676..32deae39ef5f5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -357,36 +357,6 @@ ๆ–‡ไปถๅโ€œ{0}โ€ไธบ็ฉบใ€ๅŒ…ๅซๆ— ๆ•ˆๅญ—็ฌฆใ€ๆœชไฝฟ็”จ็ปๅฏน่ทฏๅพ„ๆŒ‡ๅฎš้ฉฑๅŠจๅ™จๆˆ–ๅคช้•ฟ - - Expression is probably never null. - ่กจ่พพๅผๅฏ่ƒฝไธไธบ nullใ€‚ - - - - Expression is probably never null. - ่กจ่พพๅผๅฏ่ƒฝไธไธบ nullใ€‚ - - - - Result of the comparison is possibly always false. - ๆฏ”่พƒ็ป“ๆžœๅฏ่ƒฝๅง‹็ปˆไธบ้”™่ฏฏใ€‚ - - - - Result of the comparison is possibly always false. - ๆฏ”่พƒ็ป“ๆžœๅฏ่ƒฝๅง‹็ปˆไธบ้”™่ฏฏใ€‚ - - - - Result of the comparison is possibly always true. - ๆฏ”่พƒ็ป“ๆžœๅฏ่ƒฝๅง‹็ปˆไธบๆญฃ็กฎใ€‚ - - - - Result of the comparison is possibly always true. - ๆฏ”่พƒ็ป“ๆžœๅฏ่ƒฝๅง‹็ปˆไธบๆญฃ็กฎใ€‚ - - disposable ๅฏๅค„็ฝฎ็š„ @@ -897,6 +867,16 @@ ็ผ–่ฏ‘ไธญไธๅŒ…ๅซ SyntaxTree๏ผŒๅ› ๆญคๆ— ๆณ•ๅฐ†ๅ…ถๅˆ ้™ค + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. ๅ็งฐ "_" ๅผ•็”จๅธธ้‡๏ผŒ่€Œไธๅผ•็”จๆ”พๅผƒๆจกๅผใ€‚่ฏทไฝฟ็”จ "var _" ๆ”พๅผƒ่ฏฅๅ€ผ๏ผŒๆˆ–ไฝฟ็”จ "@_" ๆฅๅผ•็”จ่ฏฅๅ็งฐ็š„ๅธธ้‡ใ€‚ @@ -907,6 +887,16 @@ ไธ่ฆๅฏนๅคงๅฐๅ†™ๅธธ้‡ไฝฟ็”จ "_"ใ€‚ + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. ๅฐ† null ๆ–‡ๆœฌๆˆ–ๅฏ่ƒฝ็š„ null ๅ€ผ่ฝฌๆขไธบ้ž null ็ฑปๅž‹ใ€‚ @@ -917,6 +907,16 @@ ๅฐ† null ๆ–‡ๆœฌๆˆ–ๅฏ่ƒฝ็š„ null ๅ€ผ่ฝฌๆขไธบ้ž null ็ฑปๅž‹ใ€‚ + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' โ€œdefaultโ€ ่ขซ่ฝฌๆขไธบ โ€œnullโ€ ่€Œ้žโ€œdefault({0})โ€ @@ -997,6 +997,16 @@ ๆ— ๆณ•ๅฐ† null ๆ–‡ๆœฌ่ฝฌๆขไธบ้ž null ๅผ•็”จๆˆ–ๆ— ็บฆๆŸ็ฑปๅž‹ๅ‚ๆ•ฐใ€‚ + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + 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 ba53695101a1a..7854691d4e68c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -357,36 +357,6 @@ ๆช”ๆกˆๅ็จฑ '{0}' ๆ˜ฏ็ฉบ็š„ใ€ๅŒ…ๅซไบ†็„กๆ•ˆๅญ—ๅ…ƒใ€ๆŒ‡ๅฎšไบ†็ฃ็ขŸๆฉŸไฝ†ไธๆ˜ฏ็ต•ๅฐ่ทฏๅพ‘๏ผŒๆˆ–ๅคช้•ทไบ†ใ€‚ - - Expression is probably never null. - ้‹็ฎ—ๅผๅฏ่ƒฝๅพžๆœชๆ˜ฏ Nullใ€‚ - - - - Expression is probably never null. - ้‹็ฎ—ๅผๅฏ่ƒฝๅพžๆœชๆ˜ฏ Nullใ€‚ - - - - Result of the comparison is possibly always false. - ๆฏ”่ผƒ็š„็ตๆžœๅฏ่ƒฝไธ€็›ด้ƒฝๆ˜ฏ Falseใ€‚ - - - - Result of the comparison is possibly always false. - ๆฏ”่ผƒ็š„็ตๆžœๅฏ่ƒฝไธ€็›ด้ƒฝๆ˜ฏ Falseใ€‚ - - - - Result of the comparison is possibly always true. - ๆฏ”่ผƒ็š„็ตๆžœๅฏ่ƒฝไธ€็›ด้ƒฝๆ˜ฏ Trueใ€‚ - - - - Result of the comparison is possibly always true. - ๆฏ”่ผƒ็š„็ตๆžœๅฏ่ƒฝไธ€็›ด้ƒฝๆ˜ฏ Trueใ€‚ - - Visual C# Compiler Options @@ -1192,6 +1162,16 @@ ๅ› ็‚บ SyntaxTree ไธๅฑฌๆ–ผ็ทจ่ญฏ็š„ไธ€้ƒจไปฝ๏ผŒๆ‰€ไปฅ็„กๆณ•ๅฐ‡ๅ…ถ็งป้™ค + + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + The 'as' operator may produce a null value when '{0}' is a non-nullable reference type. + + + + The 'as' operator may produce a null value for a type parameter. + The 'as' operator may produce a null value for a type parameter. + + The name '_' refers to the constant, not the discard pattern. Use 'var _' to discard the value, or '@_' to refer to a constant by that name. ๅ็จฑ '_' ๅƒ่€ƒๅธธๆ•ธ่€Œ้žๆจๆฃ„ๆจกๅผใ€‚่ซ‹ไฝฟ็”จ 'var _' ไพ†ๆจๆฃ„ๅ€ผ๏ผŒๆˆ–ไฝฟ็”จ '@_' ไพ†ไพ่ฉฒๅ็จฑๅƒ่€ƒๅธธๆ•ธใ€‚ @@ -1202,6 +1182,16 @@ ไธๅฏๅฐ case ๅธธๆ•ธไฝฟ็”จ '_'ใ€‚ + + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + Conditional access may produce a null value when '{0}' is a non-nullable reference type. + + + + Conditional access may produce a null value for a type parameter. + Conditional access may produce a null value for a type parameter. + + Converting null literal or possible null value to non-nullable type. ๆญฃๅœจๅฐ‡ Null ๅธธๅ€ผๆˆ–ๅฏ่ƒฝ็š„ Null ๅ€ผ่ฝ‰ๆ›็‚บไธๅฏ็‚บ Null ็š„ๅž‹ๅˆฅใ€‚ @@ -1212,6 +1202,16 @@ ๆญฃๅœจๅฐ‡ Null ๅธธๅ€ผๆˆ–ๅฏ่ƒฝ็š„ Null ๅ€ผ่ฝ‰ๆ›็‚บไธๅฏ็‚บ Null ็š„ๅž‹ๅˆฅใ€‚ + + A default expression introduces a null value when '{0}' is a non-nullable reference type. + A default expression introduces a null value when '{0}' is a non-nullable reference type. + + + + A default expression introduces a null value for a type parameter. + A default expression introduces a null value for a type parameter. + + 'default' is converted to 'null', not 'default({0})' 'default' ๅทฒ่ฝ‰ๆ›็‚บ 'null'๏ผŒ่€Œไธๆ˜ฏ 'default({0})' @@ -1292,6 +1292,16 @@ ็„กๆณ•ๅฐ‡ Null ๅธธๅ€ผ่ฝ‰ๆ›็‚บไธๅฏ็‚บ Null ็š„ๅƒ่€ƒๅž‹ๅˆฅๆˆ–้ž้™ๅˆถๅผๅž‹ๅˆฅๅƒๆ•ธใ€‚ + + A null literal introduces a null value when '{0}' is a non-nullable reference type. + A null literal introduces a null value when '{0}' is a non-nullable reference type. + + + + A null literal introduces a null value for a type parameter. + A null literal introduces a null value for a type parameter. + + Possible null reference argument for parameter '{0}' in '{1}'. '{1}' ไธญ็š„ๅƒๆ•ธ '{0}' ๅฏ่ƒฝๆœ‰ Null ๅƒ่€ƒๅผ•ๆ•ธใ€‚ diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs index 5b08829ef0ea8..9e64430bcde55 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs @@ -270,7 +270,7 @@ public void Deconstruct(out int a) var defaultInfo = model.GetDeconstructionInfo(assignment); Assert.Null(defaultInfo.Method); Assert.Empty(defaultInfo.Nested); - Assert.Equal(ConversionKind.NoConversion, defaultInfo.Conversion.Value.Kind); + Assert.Equal(ConversionKind.UnsetConversionKind, defaultInfo.Conversion.Value.Kind); } [Fact] @@ -301,7 +301,7 @@ static void M(string s) var foreachDeconstruction = (ForEachVariableStatementSyntax)tree.FindNodeOrTokenByKind(SyntaxKind.ForEachVariableStatement).AsNode(); Assert.Equal(@"foreach (char in s) { }", foreachDeconstruction.ToString()); var deconstructionInfo = model.GetDeconstructionInfo(foreachDeconstruction); - Assert.Equal(Conversion.NoConversion, deconstructionInfo.Conversion); + Assert.Equal(Conversion.UnsetConversion, deconstructionInfo.Conversion); Assert.Null(deconstructionInfo.Method); Assert.Empty(deconstructionInfo.Nested); } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index 1f50cd0227fe2..bbf31906cdd61 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -1726,7 +1726,7 @@ .maxstack 1 "); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33615")] public void TupleLambdaCapture03() { var source = @" @@ -2286,7 +2286,7 @@ .locals init (int V_0, "); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33615")] public void TupleAsyncCapture03() { var source = @" diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EndToEndTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EndToEndTests.cs index 9608a23c9761f..15fa89aabbee1 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EndToEndTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EndToEndTests.cs @@ -33,7 +33,7 @@ public void OverflowOnFluentCall() numberFluentCalls = 460; break; case 32 when !isDebug: - numberFluentCalls = 1300; + numberFluentCalls = 1000; break; case 64 when isDebug: numberFluentCalls = 175; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 39f227f3e3481..fda65a89ab1b4 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -547,16 +547,17 @@ class Program ); } - [ClrOnlyFact(ClrOnlyReason.MemberOrder)] + [Fact] public void TestNameofIndexerName() { var source = @" +using System.Linq; class C { public static void Main(string[] args) { var t = typeof(C); - foreach (var m in t.GetMethods()) + foreach (var m in t.GetMethods().Where(m => m.DeclaringType == t).OrderBy(m => m.Name)) { System.Console.WriteLine(m.Name); } @@ -568,13 +569,10 @@ public int this[int index] get { return 0; } } }"; - CompileAndVerify(source, expectedOutput: @"Main -Other -get__Other -ToString -Equals -GetHashCode -GetType"); + CompileAndVerify(source, expectedOutput: +@"get__Other +Main +Other"); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs old mode 100755 new mode 100644 index 93c409748cd7e..18d04c35a8e0f --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -307,18 +307,12 @@ void M(string? s, string s2, dynamic d) // (8,9): error CS8598: The suppression operator is not allowed in this context // i! ??= d; // 2 Diagnostic(ErrorCode.ERR_IllegalSuppression, "i").WithLocation(8, 9), - // (9,9): hidden CS8607: Expression is probably never null. - // i ??= d!; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "i").WithLocation(9, 9), // (13,9): error CS8598: The suppression operator is not allowed in this context // s! ??= s2; // 3 Diagnostic(ErrorCode.ERR_IllegalSuppression, "s").WithLocation(13, 9), // (15,9): error CS8598: The suppression operator is not allowed in this context // s! ??= d; // 4 - Diagnostic(ErrorCode.ERR_IllegalSuppression, "s").WithLocation(15, 9), - // (16,9): hidden CS8607: Expression is probably never null. - // s ??= d!; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "s").WithLocation(16, 9) + Diagnostic(ErrorCode.ERR_IllegalSuppression, "s").WithLocation(15, 9) ); } @@ -1267,10 +1261,10 @@ static void Main(string? x) s2 /*T:string?*/ .ToString(); // 2 var s3 = M(M2); - s3 /*T:string*/ .ToString(); // 3 + s3 /*T:string!*/ .ToString(); // 3 var s4 = M(M2!); // suppressed - s4 /*T:string*/ .ToString(); // 4 + s4 /*T:string!*/ .ToString(); // 4 } static T M(System.Func x) => throw null!; static string? M2() => throw null!; @@ -1375,7 +1369,9 @@ internal static IEnumerable S(this IEnumerable c, Func f) ); } - [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] + [Fact] + [WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] + [WorkItem(33635, "https://github.com/dotnet/roslyn/issues/33635")] public void SuppressNullableWarning_MethodGroupInOverloadResolution() { var source = @@ -1386,12 +1382,12 @@ class A void M() { IEnumerable c = null!; - c.S(G); // 1 - c.S(G!); + c.S(G)/*T:IEnumerable!*/; // 1 + c.S(G!)/*T:IEnumerable!*/; IEnumerable c2 = null!; - c2.S(G); - c2.S(G2); + c2.S(G)/*T:IEnumerable!*/; + c2.S(G2)/*T:IEnumerable!*/; } static object G(string s) => throw null!; static object G2(string? s) => throw null!; @@ -1407,9 +1403,11 @@ internal static IEnumerable S(this IEnumerable c, Func f) var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8622: Nullability of reference types in type of parameter 's' of 'object A.G(string s)' doesn't match the target delegate 'Func'. - // c.S(G); // 1 + // c.S(G)/*T:IEnumerable!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "G").WithArguments("s", "object A.G(string s)", "System.Func").WithLocation(8, 13) ); + // https://github.com/dotnet/roslyn/issues/33635 + // comp.VerifyTypes(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] @@ -1982,11 +1980,7 @@ bool M(object o) } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); - comp.VerifyDiagnostics( - // (5,21): hidden CS8606: Result of the comparison is possibly always false. - // return o is null!; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "null!").WithLocation(5, 21) - ); + comp.VerifyDiagnostics(); CompileAndVerify(comp); } @@ -2055,13 +2049,7 @@ void M(object o, int? i) Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "!(null!)").WithArguments("!", "").WithLocation(19, 13), // (20,58): error CS0845: An expression tree lambda may not contain a coalescing operator with a null or default literal left-hand side // Expression> testExpr = () => null! ?? "hello"; // 13 - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsBadCoalesce, "null").WithLocation(20, 58), - // (21,13): hidden CS8606: Result of the comparison is possibly always false. - // _ = o == null; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "o == null").WithLocation(21, 13), - // (22,13): hidden CS8606: Result of the comparison is possibly always false. - // _ = o == null!; // 14 - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "o == null!").WithLocation(22, 13) + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsBadCoalesce, "null").WithLocation(20, 58) ); } @@ -2113,13 +2101,7 @@ void M2(object o) Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default ?? d").WithArguments("??", "default").WithLocation(9, 13), // (10,13): error CS8310: Operator '??' cannot be applied to operand 'default' // _ = default! ?? d; // 6 - Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default! ?? d").WithArguments("??", "default").WithLocation(10, 13), - // (16,13): hidden CS8606: Result of the comparison is possibly always false. - // _ = o == default; // 7 - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "o == default").WithLocation(16, 13), - // (17,13): hidden CS8606: Result of the comparison is possibly always false. - // _ = o == default!; // 8 - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "o == default!").WithLocation(17, 13) + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default! ?? d").WithArguments("??", "default").WithLocation(10, 13) ); } @@ -2172,10 +2154,7 @@ void M6(string s) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(18, 57), // (22,18): warning CS8602: Possible dereference of a null reference. // _ = s ?? s.ToString(); // 2 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(22, 18), - // (27,13): hidden CS8607: Expression is probably never null. - // _ = s ?? s.ToString(); // 3 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "s").WithLocation(27, 13) + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(22, 18) ); } @@ -2243,9 +2222,6 @@ interface Interface { } // (6,24): error CS8597: Possible null value. // _ = c ?? throw e; // 1 Diagnostic(ErrorCode.WRN_PossibleNull, "e").WithLocation(6, 24), - // (7,13): hidden CS8607: Expression is probably never null. - // _ = c ?? throw null; // 2 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c").WithLocation(7, 13), // (7,24): error CS8597: Possible null value. // _ = c ?? throw null; // 2 Diagnostic(ErrorCode.WRN_PossibleNull, "null").WithLocation(7, 24), @@ -2531,10 +2507,10 @@ void M2(T? t) where T : struct comp.VerifyDiagnostics( // (8,9): warning CS8629: Nullable value type may be null. // t2.Value.ToString(); // warn - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2.Value").WithLocation(8, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(8, 9), // (15,9): warning CS8629: Nullable value type may be null. // t2.Value.ToString(); // warn - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2.Value").WithLocation(15, 9) + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(15, 9) ); } @@ -2605,17 +2581,17 @@ void M(T t) where T : class? { if (t == null) throw null!; t.ToString(); - var t2 = new[] { t, null }; - t2[0].ToString(); // warn + var t2 = new[] { t, null }; // 1 + t2[0].ToString(); // warn // 2 } }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (7,29): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // var t2 = new[] { t, null }; - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 29), + // (7,29): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. + // var t2 = new[] { t, null }; // 1 + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(7, 29), // (8,9): warning CS8602: Possible dereference of a null reference. - // t2[0].ToString(); // warn + // t2[0].ToString(); // warn // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2[0]").WithLocation(8, 9) ); } @@ -2803,15 +2779,15 @@ void M4(string x4, object? y4) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,14): warning CS8601: Possible null reference assignment. // x1 = (T)y1; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)y1").WithLocation(6, 14), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)y1").WithLocation(6, 14), // (11,14): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // x2 = y2; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y2").WithArguments("object", "T").WithLocation(11, 14), - // (11,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (11,14): warning CS8601: Possible null reference assignment. // x2 = y2; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2").WithLocation(11, 14), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y2").WithLocation(11, 14), // (16,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = (string)y3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)y3").WithLocation(16, 14), @@ -2820,8 +2796,7 @@ void M4(string x4, object? y4) Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y4").WithArguments("object", "string").WithLocation(21, 14), // (21,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = y4; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4").WithLocation(21, 14) - ); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4").WithLocation(21, 14)); } [Fact] @@ -2849,10 +2824,10 @@ void M2(T? t) where T : struct comp.VerifyDiagnostics( // (8,9): warning CS8629: Nullable value type may be null. // t2[0].Value.ToString(); // warn - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2[0].Value").WithLocation(8, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2[0]").WithLocation(8, 9), // (15,9): warning CS8629: Nullable value type may be null. // t2[0].Value.ToString(); // warn - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2[0].Value").WithLocation(15, 9) + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2[0]").WithLocation(15, 9) ); } @@ -2878,7 +2853,6 @@ void M(B x, C y) b[0].ToString(); } }"; - // https://github.com/dotnet/roslyn/issues/30480: Should report WRN_NoBestNullabilityArrayElements. Problem in BestTypeInferrer.Better var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,25): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. @@ -3342,8 +3316,8 @@ class B static void G1() { object o1; - o1 = F1/*T:A*/; - o1 = F2/*T:A*/; + o1 = F1/*T:A!*/; + o1 = F2/*T:A!*/; o1 = F3/*T:A!*/; } #nullable disable @@ -3351,8 +3325,8 @@ static void G1() static void G2() { object o2; - o2 = F1/*T:A*/; - o2 = F2/*T:A*/; + o2 = F1/*T:A!*/; + o2 = F2/*T:A!*/; o2 = F3/*T:A!*/; } #nullable enable @@ -3360,8 +3334,8 @@ static void G2() static void G3() { object o3; - o3 = F1/*T:A*/; - o3 = F2/*T:A*/; + o3 = F1/*T:A!*/; + o3 = F2/*T:A!*/; o3 = F3/*T:A!*/; } }"; @@ -3388,8 +3362,8 @@ class B static void G1() { object o1; - o1 = F1/*T:A*/; - o1 = F2/*T:A*/; + o1 = F1/*T:A!*/; + o1 = F2/*T:A!*/; o1 = F3/*T:A!*/; } #nullable disable @@ -3397,8 +3371,8 @@ static void G1() static void G2() { object o2; - o2 = F1/*T:A*/; - o2 = F2/*T:A*/; + o2 = F1/*T:A!*/; + o2 = F2/*T:A!*/; o2 = F3/*T:A!*/; } #nullable enable @@ -3406,8 +3380,8 @@ static void G2() static void G3() { object o3; - o3 = F1/*T:A*/; - o3 = F2/*T:A*/; + o3 = F1/*T:A!*/; + o3 = F2/*T:A!*/; o3 = F3/*T:A!*/; } }"; @@ -3435,7 +3409,7 @@ static void G1() { object o1; o1 = F1/*T:A!*/; - o1 = F2/*T:A*/; + o1 = F2/*T:A!*/; o1 = F3/*T:A!*/; } #nullable disable @@ -3444,7 +3418,7 @@ static void G2() { object o2; o2 = F1/*T:A!*/; - o2 = F2/*T:A*/; + o2 = F2/*T:A!*/; o2 = F3/*T:A!*/; } #nullable enable @@ -3453,7 +3427,7 @@ static void G3() { object o3; o3 = F1/*T:A!*/; - o3 = F2/*T:A*/; + o3 = F2/*T:A!*/; o3 = F3/*T:A!*/; } }"; @@ -4436,7 +4410,7 @@ void M(S? s) c.VerifyDiagnostics( // (10,9): warning CS8629: Nullable value type may be null. // s.Value.field!.ToString(); - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s.Value").WithLocation(10, 9) + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s").WithLocation(10, 9) ); } @@ -6112,12 +6086,12 @@ class E { public void M() { - Oblivious.s /*T:string*/ = null; + Oblivious.s /*T:string!*/ = null; External.s /*T:string!*/ = null; // warn 1 External.ns /*T:string?*/ = null; - External.fs /*T:string*/ = null; + External.fs /*T:string!*/ = null; External.fns /*T:string?*/ = null; OuterA.A.s /*T:string!*/ = null; // warn 2 @@ -6132,7 +6106,7 @@ public void M() OuterD.D.s /*T:string!*/ = null; // warn 5 OuterD.D.ns /*T:string?*/ = null; - Oblivious2.s /*T:string*/ = null; + Oblivious2.s /*T:string!*/ = null; Oblivious2.ns /*T:string?*/ = null; } } @@ -6268,12 +6242,12 @@ class E { public void M() { - Oblivious.s.Item /*T:string*/ = null; + Oblivious.s.Item /*T:string!*/ = null; External.s.Item /*T:string!*/ = null; // warn 1 External.ns.Item /*T:string?*/ = null; - External.fs.Item /*T:string*/ = null; + External.fs.Item /*T:string!*/ = null; External.fns.Item /*T:string?*/ = null; OuterA.A.s.Item /*T:string!*/ = null; // warn 2 @@ -6285,7 +6259,7 @@ public void M() OuterD.D.s.Item /*T:string!*/ = null; // warn 4 OuterD.D.ns.Item /*T:string?*/ = null; - Oblivious2.s.Item /*T:string*/ = null; + Oblivious2.s.Item /*T:string!*/ = null; Oblivious2.ns.Item /*T:string?*/ = null; } } @@ -6309,8 +6283,7 @@ public void M() Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(57, 34), // (60,41): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // OuterD.D.s.Item /*T:string!*/ = null; // warn 4 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(60, 41) - ); + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(60, 41)); } [Fact] @@ -6373,7 +6346,7 @@ class E { public void M() { - Oblivious.t.s /*T:string*/ = null; + Oblivious.t.s /*T:string!*/ = null; External.t.s /*T:string!*/ = null; // warn 1 External.t.ns /*T:string?*/ = null; @@ -6387,7 +6360,7 @@ public void M() OuterD.D.t.s /*T:string!*/ = null; // warn 4 OuterD.D.t.ns /*T:string?*/ = null; - Oblivious2.t.s /*T:string*/ = null; + Oblivious2.t.s /*T:string!*/ = null; Oblivious2.t.ns /*T:string?*/ = null; } } @@ -6481,7 +6454,7 @@ class E { public void M() { - Oblivious.s[0] /*T:string*/ = null; + Oblivious.s[0] /*T:string!*/ = null; External.s[0] /*T:string!*/ = null; // warn 1 External.ns[0] /*T:string?*/ = null; @@ -6495,7 +6468,7 @@ public void M() OuterD.D.s[0] /*T:string!*/ = null; // warn 4 OuterD.D.ns[0] /*T:string?*/ = null; - Oblivious2.s[0] /*T:string*/ = null; + Oblivious2.s[0] /*T:string!*/ = null; Oblivious2.ns[0] /*T:string?*/ = null; } } @@ -6591,7 +6564,7 @@ class E { public void M() { - Oblivious.s /*T:string*/ = null; + Oblivious.s /*T:string!*/ = null; External.s /*T:string!*/ = null; // warn 1 External.ns /*T:string?*/ = null; @@ -6605,7 +6578,7 @@ public void M() OuterD.D.s /*T:string!*/ = null; // warn 4 OuterD.D.ns /*T:string?*/ = null; - Oblivious2.s /*T:string*/ = null; + Oblivious2.s /*T:string!*/ = null; Oblivious2.ns /*T:string?*/ = null; } } @@ -6699,7 +6672,7 @@ class E { public void M() { - Oblivious.Method(null) /*T:string*/; + Oblivious.Method(null) /*T:string!*/; External.Method(null) /*T:string!*/; // warn 1 External.NMethod(null) /*T:string?*/; @@ -6713,7 +6686,7 @@ public void M() OuterD.D.Method(null) /*T:string!*/; // warn 4 OuterD.D.NMethod(null) /*T:string?*/; - Oblivious2.Method(null) /*T:string*/; + Oblivious2.Method(null) /*T:string!*/; Oblivious2.NMethod(null) /*T:string?*/; } } @@ -6829,7 +6802,8 @@ class C comp.VerifyDiagnostics( // (3,7): warning CS8618: Non-nullable field '_f' is uninitialized. // class C - Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "C").WithArguments("field", "_f").WithLocation(3, 7)); + Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "C").WithArguments("field", "_f").WithLocation(3, 7) + ); } [Fact] @@ -6874,9 +6848,9 @@ class C void M() { string s = Oblivious.f; - s /*T:string*/ .ToString(); + s /*T:string!*/ .ToString(); string ns = Oblivious.f; - ns /*T:string*/ .ToString(); + ns /*T:string!*/ .ToString(); } } "; @@ -6921,7 +6895,7 @@ public void M2() foreach (string s in FalseCollection()) { - s /*T:string*/ .ToString(); + s /*T:string!*/ .ToString(); } foreach (string? ns in FalseNCollection()) @@ -6931,7 +6905,7 @@ public void M2() foreach (var s1 in FalseCollection()) { - s1 /*T:string*/ .ToString(); + s1 /*T:string!*/ .ToString(); } foreach (var ns1 in FalseNCollection()) @@ -7009,7 +6983,7 @@ public void M2() foreach (string s in FalseCollection()) { - s /*T:string*/ .ToString(); + s /*T:string!*/ .ToString(); } foreach (string? ns in FalseNCollection()) // 2 @@ -7019,7 +6993,7 @@ public void M2() foreach (var s1 in FalseCollection()) { - s1 /*T:string*/ .ToString(); + s1 /*T:string!*/ .ToString(); } foreach (var ns1 in FalseNCollection()) @@ -7077,7 +7051,7 @@ public void M() ns2 = null; FalseOut(out string s3); - s3 /*T:string*/ .ToString(); + s3 /*T:string!*/ .ToString(); s3 = null; // warn 3 FalseNOut(out string? ns3); @@ -7093,7 +7067,7 @@ public void M() ns4 = null; FalseOut(out var s5); - s5 /*T:string*/ .ToString(); + s5 /*T:string!*/ .ToString(); s5 = null; FalseNOut(out var ns5); @@ -7166,7 +7140,7 @@ public void M() ns2 = null; FalseOut(out string s3); - s3 /*T:string*/ .ToString(); + s3 /*T:string!*/ .ToString(); s3 = null; FalseNOut(out string? ns3); // 3 @@ -7182,7 +7156,7 @@ public void M() ns4 = null; FalseOut(out var s5); - s5 /*T:string*/ .ToString(); + s5 /*T:string!*/ .ToString(); s5 = null; FalseNOut(out var ns5); @@ -7239,7 +7213,7 @@ public void M() ns2 = null; string s3 = FalseMethod(); - s3 /*T:string*/ .ToString(); + s3 /*T:string!*/ .ToString(); s3 = null; // warn 3 string? ns3 = FalseNMethod(); @@ -7255,7 +7229,7 @@ public void M() ns4 = null; var s5 = FalseMethod(); - s5 /*T:string*/ .ToString(); + s5 /*T:string!*/ .ToString(); s5 = null; var ns5 = FalseNMethod(); @@ -7303,6 +7277,9 @@ public class Base // (30,9): warning CS8602: Possible dereference of a null reference. // ns4 /*T:string?*/ .ToString(); // warn 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns4").WithLocation(30, 9), + // (35,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // s5 = null; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(35, 14), // (38,9): warning CS8602: Possible dereference of a null reference. // ns5 /*T:string?*/ .ToString(); // warn 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns5").WithLocation(38, 9) @@ -7330,7 +7307,7 @@ public void M() ns2 = null; string s3 = FalseMethod(); - s3 /*T:string*/ .ToString(); + s3 /*T:string!*/ .ToString(); s3 = null; string? ns3 = FalseNMethod(); // 2 @@ -7346,7 +7323,7 @@ public void M() ns4 = null; var s5 = FalseMethod(); - s5 /*T:string*/ .ToString(); + s5 /*T:string!*/ .ToString(); s5 = null; var ns5 = FalseNMethod(); @@ -7557,7 +7534,7 @@ public struct D { public void M(T t, NT nt) { - t.Item /*T:S*/ .ToString(); + t.Item /*T:S!*/ .ToString(); t.Item = null; nt.Item /*T:S?*/ .ToString(); nt.Item = null; @@ -7568,16 +7545,15 @@ public void M(T t, NT nt) compilation.VerifyTypes(); compilation.VerifyDiagnostics( - // (23,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // where NT : List // warn 3 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(23, 22), // (14,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // t.Item = null; // warn 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 18), // (15,9): warning CS8602: Possible dereference of a null reference. // nt.Item /*T:S?*/ .ToString(); // warn 2 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "nt.Item").WithLocation(15, 9) - ); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "nt.Item").WithLocation(15, 9), + // (23,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. + // where NT : List // warn 3 + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(23, 22)); } [Fact] @@ -11800,8 +11776,8 @@ static void Main() void Test1() { string? x1 = null; - string? y1 = x1; - string z1 = x1; + string? y1 = x1; + string z1 = x1; } void Test2() @@ -12156,15 +12132,15 @@ struct S2 // (53,18): warning CS8602: Possible dereference of a null reference. // CL1 y7 = x7.P1; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x7").WithLocation(53, 18), - // (54,18): hidden CS8607: Expression is probably never null. + // (54,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z7 = x7?.P1; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x7").WithLocation(54, 18), + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7?.P1").WithLocation(54, 18), // (64,18): warning CS8602: Possible dereference of a null reference. // CL1 u8 = x8.M1(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x8").WithLocation(64, 18), - // (65,18): hidden CS8607: Expression is probably never null. + // (65,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z8 = x8?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x8").WithLocation(65, 18), + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x8?.M1()").WithLocation(65, 18), // (71,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // u9 = x9; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x9").WithLocation(71, 14), @@ -12189,6 +12165,9 @@ struct S2 // (109,15): error CS0170: Use of possibly unassigned field 'F4' // u12 = y12.F4; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y12.F4").WithArguments("F4").WithLocation(109, 15), + // (109,15): warning CS8600: Converting null literal or possible null value to non-nullable type. + // u12 = y12.F4; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y12.F4").WithLocation(109, 15), // (116,15): error CS0170: Use of possibly unassigned field 'F3' // u13 = y13.F3; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y13.F3").WithArguments("F3").WithLocation(116, 15), @@ -12234,6 +12213,9 @@ struct S2 // (220,15): error CS0170: Use of possibly unassigned field 'F4' // u22 = y22.F4; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y22.F4").WithArguments("F4").WithLocation(220, 15), + // (220,15): warning CS8600: Converting null literal or possible null value to non-nullable type. + // u22 = y22.F4; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y22.F4").WithLocation(220, 15), // (224,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // v22 = y22.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y22.F4").WithLocation(224, 15), @@ -12243,6 +12225,12 @@ struct S2 // (248,15): error CS0170: Use of possibly unassigned field 'F4' // u24 = y24.F5.F4; // 1 Diagnostic(ErrorCode.ERR_UseDefViolationField, "y24.F5.F4").WithArguments("F4").WithLocation(248, 15), + // (248,15): warning CS8600: Converting null literal or possible null value to non-nullable type. + // u24 = y24.F5.F4; // 1 + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y24.F5.F4").WithLocation(248, 15), + // (249,15): warning CS8600: Converting null literal or possible null value to non-nullable type. + // u24 = y24.F5.F4; // 2 + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y24.F5.F4").WithLocation(249, 15), // (253,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // v24 = y24.F5.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y24.F5.F4").WithLocation(253, 15), @@ -12264,15 +12252,10 @@ struct S2 // (296,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // x31 = default(CL1); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(CL1)").WithLocation(296, 15), - // (301,19): hidden CS8607: Expression is probably never null. - // var y32 = new CL1() ?? x32; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new CL1()").WithLocation(301, 19), // (306,29): warning CS8600: Converting null literal or possible null value to non-nullable type. // var y33 = new { p = (object)null } ?? x33; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)null").WithLocation(306, 29), - // (306,19): hidden CS8607: Expression is probably never null. - // var y33 = new { p = (object)null } ?? x33; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new { p = (object)null }").WithLocation(306, 19)); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)null").WithLocation(306, 29) + ); } [Fact] @@ -12416,7 +12399,8 @@ class CL1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "z11").WithArguments("p2", "void C.M8(CL1 p1, params CL1[] p2)").WithLocation(84, 22), // (89,16): warning CS8604: Possible null reference argument for parameter 'p2' in 'void C.M8(CL1 p1, params CL1[] p2)'. // M8(p2: x12, p1: y12); - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x12").WithArguments("p2", "void C.M8(CL1 p1, params CL1[] p2)").WithLocation(89, 16)); + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x12").WithArguments("p2", "void C.M8(CL1 p1, params CL1[] p2)").WithLocation(89, 16) + ); } [Fact] @@ -12560,7 +12544,8 @@ static void G(I x, params I[] y) Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new[] { x, x }").WithArguments("I[]", "I[]", "y", "void C.G(I x, params I[] y)").WithLocation(18, 14), // (18,33): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'void C.G(I x, params I[] y)'. // G(y: new[] { x, x }, x: y); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("I", "I", "x", "void C.G(I x, params I[] y)").WithLocation(18, 33)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("I", "I", "x", "void C.G(I x, params I[] y)").WithLocation(18, 33) + ); } [Fact] @@ -12603,8 +12588,7 @@ void M(in string xIn) c2.VerifyDiagnostics( // (6,9): error CS8331: Cannot assign to variable 'in string' because it is a readonly variable // xIn = null; - Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "xIn").WithArguments("variable", "in string").WithLocation(6, 9) - ); + Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "xIn").WithArguments("variable", "in string").WithLocation(6, 9)); } [Fact] @@ -13127,16 +13111,21 @@ struct S1 " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (15,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // y2 = x2.F2; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2.F2").WithLocation(15, 14), - // (26,14): error CS0170: Use of possibly unassigned field 'F1' - // y4 = x4.F1; - Diagnostic(ErrorCode.ERR_UseDefViolationField, "x4.F1").WithArguments("F1").WithLocation(26, 14), - // (33,14): error CS0170: Use of possibly unassigned field 'F2' - // y5 = x5.F2; - Diagnostic(ErrorCode.ERR_UseDefViolationField, "x5.F2").WithArguments("F2").WithLocation(33, 14) - ); + // (15,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // y2 = x2.F2; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2.F2").WithLocation(15, 14), + // (26,14): error CS0170: Use of possibly unassigned field 'F1' + // y4 = x4.F1; + Diagnostic(ErrorCode.ERR_UseDefViolationField, "x4.F1").WithArguments("F1").WithLocation(26, 14), + // (33,14): error CS0170: Use of possibly unassigned field 'F2' + // y5 = x5.F2; + Diagnostic(ErrorCode.ERR_UseDefViolationField, "x5.F2").WithArguments("F2").WithLocation(33, 14), + // (33,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // y5 = x5.F2; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5.F2").WithLocation(33, 14), + // (34,17): warning CS8601: Possible null reference assignment. + // x5.F1 = y5; + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y5").WithLocation(34, 17)); } [Fact] @@ -13223,16 +13212,12 @@ class CL0 // (12,16): warning CS8620: Argument of type 'CL0' cannot be used as an input of type 'CL0' for parameter 'x' in 'void C.M1(ref CL0 x)' due to differences in the nullability of reference types. // M1(ref x1); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("CL0", "CL0", "x", "void C.M1(ref CL0 x)").WithLocation(12, 16), - // (12,16): warning CS8624: Argument of type 'CL0' cannot be used as an output of type 'CL0' for parameter 'x' in 'void C.M1(ref CL0 x)' due to differences in the nullability of reference types. - // M1(ref x1); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "x1").WithArguments("CL0", "CL0", "x", "void C.M1(ref CL0 x)").WithLocation(12, 16), // (19,16): warning CS8624: Argument of type 'CL0' cannot be used as an output of type 'CL0' for parameter 'x' in 'void C.M2(out CL0 x)' due to differences in the nullability of reference types. // M2(out x2); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "x2").WithArguments("CL0", "CL0", "x", "void C.M2(out CL0 x)").WithLocation(19, 16), // (26,12): warning CS8620: Argument of type 'CL0' cannot be used as an input of type 'CL0' for parameter 'x' in 'void C.M3(CL0 x)' due to differences in the nullability of reference types. // M3(x3); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x3").WithArguments("CL0", "CL0", "x", "void C.M3(CL0 x)").WithLocation(26, 12) - ); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x3").WithArguments("CL0", "CL0", "x", "void C.M3(CL0 x)").WithLocation(26, 12)); } [Fact] @@ -13448,10 +13433,7 @@ public struct S2 c.VerifyDiagnostics( // (63,16): warning CS8603: Possible null reference return. // return y11.F1; - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y11.F1").WithLocation(63, 16), - // (70,16): hidden CS8607: Expression is probably never null. - // return y12.F1 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y12.F1").WithLocation(70, 16)); + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y11.F1").WithLocation(63, 16)); } [Fact] @@ -13514,27 +13496,9 @@ void Test6() " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics( - // (14,21): warning CS8600: Converting null literal or possible null value to non-nullable type. - // object y1 = x1; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(14, 21), - // (21,21): hidden CS8607: Expression is probably never null. - // object z2 = x2 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2").WithLocation(21, 21), - // (26,22): hidden CS8607: Expression is probably never null. - // object? x3 = M3() ?? M2(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "M3()").WithLocation(26, 22), - // (27,21): hidden CS8607: Expression is probably never null. - // object z3 = x3 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x3").WithLocation(27, 21), - // (39,21): warning CS8601: Possible null reference assignment. + // (39,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x5 = M2() ?? M2(); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M2() ?? M2()").WithLocation(39, 21), - // (44,22): hidden CS8607: Expression is probably never null. - // object? x6 = M3() ?? M3(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "M3()").WithLocation(44, 22), - // (45,21): hidden CS8607: Expression is probably never null. - // object z6 = x6 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x6").WithLocation(45, 21) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M2() ?? M2()").WithLocation(39, 21) ); } @@ -13580,15 +13544,6 @@ void Test3() " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics( - // (20,22): hidden CS8607: Expression is probably never null. - // object? x2 = M3() ?? CL0.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "M3()").WithLocation(20, 22), - // (21,21): hidden CS8607: Expression is probably never null. - // object z2 = x2 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2").WithLocation(21, 21), - // (27,21): hidden CS8607: Expression is probably never null. - // object z3 = x3 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x3").WithLocation(27, 21) ); } @@ -13659,10 +13614,7 @@ void Test6() Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M4() ? M3() : M2()").WithLocation(26, 22), // (38,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x5 = M4() ? M2() : M2(); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M4() ? M2() : M2()").WithLocation(38, 22), - // (44,21): hidden CS8607: Expression is probably never null. - // object z6 = x6 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x6").WithLocation(44, 21) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M4() ? M2() : M2()").WithLocation(38, 22) ); } @@ -13792,10 +13744,7 @@ void Test6() Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(31, 21), // (46,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y5 = x5; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5").WithLocation(46, 21), - // (53,21): hidden CS8607: Expression is probably never null. - // object z6 = x6 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x6").WithLocation(53, 21) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5").WithLocation(46, 21) ); } @@ -15060,10 +15009,10 @@ void M() } ", options: WithNonNullTypesTrue()); - // There is still an issue with catch variables having an "unkonwn" null-state, instead of being initialized with a "not null" state - // We expect a warning on // 1 - // Tracked by https://github.com/dotnet/roslyn/issues/33540 - c.VerifyDiagnostics(); + c.VerifyDiagnostics( + // (14,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // e2 = null; // 1 + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 18)); } [Fact] @@ -15089,10 +15038,10 @@ static void M() where T : System.Exception? } ", options: WithNonNullTypesTrue()); - // There is still an issue with catch variables having an "unkonwn" null-state, instead of being initialized with a "not null" state - // We expect a warning on // 1 - // Tracked by https://github.com/dotnet/roslyn/issues/33540 - c.VerifyDiagnostics(); + c.VerifyDiagnostics( + // (12,13): warning CS8602: Possible dereference of a null reference. + // e2.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e2").WithLocation(12, 13)); } [Fact] @@ -15326,11 +15275,7 @@ public void M(C s, C s2) c.VerifyDiagnostics( // (9,15): warning CS8620: Argument of type 'C' cannot be used as an input of type 'C' for parameter 's' in 'void C.M(ref C s)' due to differences in the nullability of reference types. // M(ref s2); // 1, 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s2").WithArguments("C", "C", "s", "void C.M(ref C s)").WithLocation(9, 15), - // (9,15): warning CS8624: Argument of type 'C' cannot be used as an output of type 'C' for parameter 's' in 'void C.M(ref C s)' due to differences in the nullability of reference types. - // M(ref s2); // 1, 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "s2").WithArguments("C", "C", "s", "void C.M(ref C s)").WithLocation(9, 15) - ); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s2").WithArguments("C", "C", "s", "void C.M(ref C s)").WithLocation(9, 15)); } [Fact] @@ -16094,7 +16039,7 @@ public void Main(string s, string? ns) { var listS = List.Create(s); var listO = List.Create(o); - listO /*T:List!*/ .ToString(); + listO /*T:List!*/ .ToString(); listS = listO; // ok } @@ -16107,13 +16052,13 @@ public void Main(string s, string? ns) { var listNS = List.Create(ns); var listO = List.Create(o); - listNS = listO; // ok + listNS = listO!; // 3 } { var listO = List.Create(o); var listNS = List.Create(ns); - listO = listNS; // ok + listO = listNS!; // 4 } { @@ -16593,9 +16538,6 @@ void Main(C c) ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (7,16): hidden CS8606: Result of the comparison is possibly always false. - // Assert(c == null, "hello"); - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "c == null").WithLocation(7, 16) ); } @@ -18610,10 +18552,7 @@ class CL2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y3").WithLocation(40, 18), // (48,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = y4; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4").WithLocation(48, 18), - // (58,13): hidden CS8605: Result of the comparison is possibly always true. - // if (y5 != null) - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "y5 != null").WithLocation(58, 13) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4").WithLocation(48, 18) ); } @@ -18713,10 +18652,7 @@ class CL2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y3").WithLocation(40, 18), // (48,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = y4; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4").WithLocation(48, 18), - // (58,13): hidden CS8606: Result of the comparison is possibly always false. - // if (null == y5) - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "null == y5").WithLocation(58, 13) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4").WithLocation(48, 18) ); } @@ -18849,16 +18785,7 @@ class CL1 c.VerifyDiagnostics( // (15,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z2 = y2 ?? x2; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2 ?? x2").WithLocation(15, 18), - // (20,18): hidden CS8607: Expression is probably never null. - // CL1 z3 = x3 ?? y3; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x3").WithLocation(20, 18), - // (26,18): hidden CS8607: Expression is probably never null. - // CL1 z4 = x4 ?? x4.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x4").WithLocation(26, 18), - // (38,21): hidden CS8607: Expression is probably never null. - // string z6 = y6 ?? x6.M2(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y6").WithLocation(38, 21) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2 ?? x2").WithLocation(15, 18) ); } @@ -18904,18 +18831,15 @@ public void M3(CL1 x) { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (10,18): warning CS8600: Converting null literal or possible null value to non-nullable type. - // CL1 z1 = x1?.M1(); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1?.M1()").WithLocation(10, 18), - // (16,18): hidden CS8607: Expression is probably never null. - // CL1 z2 = x2?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2").WithLocation(16, 18), - // (22,18): hidden CS8607: Expression is probably never null. - // CL1 z3 = x3?.M2(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x3").WithLocation(22, 18), - // (22,18): warning CS8600: Converting null literal or possible null value to non-nullable type. - // CL1 z3 = x3?.M2(); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3?.M2()").WithLocation(22, 18) + // (10,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // CL1 z1 = x1?.M1(); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1?.M1()").WithLocation(10, 18), + // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // CL1 z2 = x2?.M1(); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2?.M1()").WithLocation(16, 18), + // (22,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // CL1 z3 = x3?.M2(); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3?.M2()").WithLocation(22, 18) ); } @@ -18980,18 +18904,9 @@ class CL1 // (15,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z2 = y2 != null ? y2 : x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2 != null ? y2 : x2").WithLocation(15, 18), - // (20,18): hidden CS8605: Result of the comparison is possibly always true. - // CL1 z3 = x3 != null ? x3 : y3; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "x3 != null").WithLocation(20, 18), // (20,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z3 = x3 != null ? x3 : y3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 != null ? x3 : y3").WithLocation(20, 18), - // (26,18): hidden CS8605: Result of the comparison is possibly always true. - // CL1 z4 = x4 != null ? x4 : x4.M1(); - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "x4 != null").WithLocation(26, 18), - // (38,21): hidden CS8605: Result of the comparison is possibly always true. - // string z6 = y6 != null ? y6 : x6.M2(); - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "y6 != null").WithLocation(38, 21), // (44,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // string z7 = y7 != null ? y7 : x7.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y7 != null ? y7 : x7.M2()").WithLocation(44, 21) @@ -19059,18 +18974,9 @@ class CL1 // (15,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z2 = y2 == null ? x2 : y2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2 == null ? x2 : y2").WithLocation(15, 18), - // (20,18): hidden CS8606: Result of the comparison is possibly always false. - // CL1 z3 = x3 == null ? y3 : x3; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "x3 == null").WithLocation(20, 18), // (20,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z3 = x3 == null ? y3 : x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 == null ? y3 : x3").WithLocation(20, 18), - // (26,18): hidden CS8606: Result of the comparison is possibly always false. - // CL1 z4 = x4 == null ? x4.M1() : x4; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "x4 == null").WithLocation(26, 18), - // (38,21): hidden CS8606: Result of the comparison is possibly always false. - // string z6 = y6 == null ? x6.M2() : y6; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "y6 == null").WithLocation(38, 21), // (44,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // string z7 = y7 == null ? x7.M2() : y7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y7 == null ? x7.M2() : y7").WithLocation(44, 21) @@ -19135,9 +19041,6 @@ void Test1(object x1, object? y1) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (12,21): hidden CS8607: Expression is probably never null. - // object z1 = y1 ?? x1; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y1").WithLocation(12, 21) ); } @@ -19162,9 +19065,6 @@ void Test1(object x1, object? y1) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (12,21): hidden CS8605: Result of the comparison is possibly always true. - // object z1 = y1 != null ? y1 : x1; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "y1 != null").WithLocation(12, 21) ); } @@ -19189,9 +19089,6 @@ void Test1(object x1, object? y1) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (12,9): hidden CS8607: Expression is probably never null. - // y1?.GetHashCode(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y1").WithLocation(12, 9) ); } @@ -19225,9 +19122,6 @@ void Test1(object x1, object? y1) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (13,13): hidden CS8606: Result of the comparison is possibly always false. - // if (y1 == null) - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "y1 == null").WithLocation(13, 13) ); } @@ -19261,9 +19155,6 @@ void Test1(object x1, object? y1) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (13,13): hidden CS8605: Result of the comparison is possibly always true. - // if (y1 != null) - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "y1 != null").WithLocation(13, 13) ); } @@ -19854,9 +19745,6 @@ void Test(object? x) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (8,22): hidden CS8606: Result of the comparison is possibly always false. - // if (x is null) // hidden - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "null").WithLocation(8, 22), // (10,17): warning CS8602: Possible dereference of a null reference. // x.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 17) @@ -20202,9 +20090,6 @@ static void F(bool b, object x, string? y) // (8,10): warning CS8602: Possible dereference of a null reference. // (b ? y: null).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y: null").WithLocation(8, 10), - // (9,10): warning CS8602: Possible dereference of a null reference. - // (b ? null: null).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? null: null").WithLocation(9, 10), // (10,10): warning CS8602: Possible dereference of a null reference. // (b ? default : x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? default : x").WithLocation(10, 10), @@ -20216,10 +20101,8 @@ static void F(bool b, object x, string? y) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x: default").WithLocation(12, 10), // (13,10): warning CS8602: Possible dereference of a null reference. // (b ? y: default).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y: default").WithLocation(13, 10), - // (14,10): warning CS8602: Possible dereference of a null reference. - // (b ? default: default).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? default: default").WithLocation(14, 10)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y: default").WithLocation(13, 10) + ); } [Fact] @@ -20243,13 +20126,8 @@ static void F(bool b, Unknown x, Unknown? y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(3, 27), // (3,38): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) // static void F(bool b, Unknown x, Unknown? y) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(3, 38), - // (5,10): warning CS8602: Possible dereference of a null reference. - // (b ? null : x).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? null : x").WithLocation(5, 10), - // (7,10): warning CS8602: Possible dereference of a null reference. - // (b ? x: null).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x: null").WithLocation(7, 10)); + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(3, 38) + ); } [Fact] @@ -20276,12 +20154,6 @@ static void F3(bool b, UnknownA? x, UnknownB? y) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (3,28): error CS0246: The type or namespace name 'UnknownA' could not be found (are you missing a using directive or an assembly reference?) - // static void F1(bool b, UnknownA x, UnknownB y) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownA").WithArguments("UnknownA").WithLocation(3, 28), - // (3,40): error CS0246: The type or namespace name 'UnknownB' could not be found (are you missing a using directive or an assembly reference?) - // static void F1(bool b, UnknownA x, UnknownB y) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownB").WithArguments("UnknownB").WithLocation(3, 40), // (8,28): error CS0246: The type or namespace name 'UnknownA' could not be found (are you missing a using directive or an assembly reference?) // static void F2(bool b, UnknownA? x, UnknownB y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownA").WithArguments("UnknownA").WithLocation(8, 28), @@ -20294,24 +20166,19 @@ static void F3(bool b, UnknownA? x, UnknownB? y) // (13,41): error CS0246: The type or namespace name 'UnknownB' could not be found (are you missing a using directive or an assembly reference?) // static void F3(bool b, UnknownA? x, UnknownB? y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownB").WithArguments("UnknownB").WithLocation(13, 41), - // (10,10): warning CS8602: Possible dereference of a null reference. - // (b ? x : y).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x : y").WithLocation(10, 10), - // (11,10): warning CS8602: Possible dereference of a null reference. - // (b ? y : x).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y : x").WithLocation(11, 10), + // (3,28): error CS0246: The type or namespace name 'UnknownA' could not be found (are you missing a using directive or an assembly reference?) + // static void F1(bool b, UnknownA x, UnknownB y) + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownA").WithArguments("UnknownA").WithLocation(3, 28), + // (3,40): error CS0246: The type or namespace name 'UnknownB' could not be found (are you missing a using directive or an assembly reference?) + // static void F1(bool b, UnknownA x, UnknownB y) + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownB").WithArguments("UnknownB").WithLocation(3, 40), // (15,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'UnknownA?' and 'UnknownB?' // (b ? x : y).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? x : y").WithArguments("UnknownA?", "UnknownB?").WithLocation(15, 10), // (16,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'UnknownB?' and 'UnknownA?' // (b ? y : x).ToString(); - Diagnostic(ErrorCode.ERR_InvalidQM, "b ? y : x").WithArguments("UnknownB?", "UnknownA?").WithLocation(16, 10), - // (15,10): warning CS8602: Possible dereference of a null reference. - // (b ? x : y).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x : y").WithLocation(15, 10), - // (16,10): warning CS8602: Possible dereference of a null reference. - // (b ? y : x).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y : x").WithLocation(16, 10)); + Diagnostic(ErrorCode.ERR_InvalidQM, "b ? y : x").WithArguments("UnknownB?", "UnknownA?").WithLocation(16, 10) + ); } [Fact] @@ -20357,13 +20224,8 @@ static void F3(bool b, B x, C? y) Diagnostic(ErrorCode.ERR_InvalidQM, "b ? x : y").WithArguments("B", "C").WithLocation(17, 10), // (18,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'C' and 'B' // (b ? y : x).ToString(); - Diagnostic(ErrorCode.ERR_InvalidQM, "b ? y : x").WithArguments("C", "B").WithLocation(18, 10), - // (17,10): warning CS8602: Possible dereference of a null reference. - // (b ? x : y).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x : y").WithLocation(17, 10), - // (18,10): warning CS8602: Possible dereference of a null reference. - // (b ? y : x).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y : x").WithLocation(18, 10)); + Diagnostic(ErrorCode.ERR_InvalidQM, "b ? y : x").WithArguments("C", "B").WithLocation(18, 10) + ); } [Fact] @@ -20651,34 +20513,19 @@ static void F(bool b) [Fact] public void ConditionalOperator_TopLevelNullability() { - var source0 = -@"public class A -{ - public static object F; -}"; - var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); - comp0.VerifyDiagnostics(); - var ref0 = comp0.EmitToImageReference(); - var source = @"class C { static void F(bool b, object? x, object y) { - var z = A.F/*T:object*/; object? o; o = (b ? x : x)/*T:object?*/; o = (b ? x : y)/*T:object?*/; - o = (b ? x : z)/*T:object?*/; o = (b ? y : x)/*T:object?*/; o = (b ? y : y)/*T:object!*/; - o = (b ? y : z)/*T:object*/; - o = (b ? z : x)/*T:object?*/; - o = (b ? z : y)/*T:object*/; - o = (b ? z : z)/*T:object*/; } }"; - var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } @@ -20691,23 +20538,20 @@ public void ConditionalOperator_NestedNullability_Invariant() var source0 = @"public class A { - public static object F; -}"; + public static B F; +} +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"class B { } -class C +@"class C { - static B CreateB(T t) - { - throw null!; - } static void F(bool b, B x, B y) { - var z = CreateB(A.F)/*T:B!*/; + var z = A.F/*T:B!*/; object o; o = (b ? x : x)/*T:B!*/; o = (b ? x : y)/*T:B!*/; // 1 @@ -20722,12 +20566,13 @@ static void F(bool b, B x, B y) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (13,18): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // (8,18): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // o = (b ? x : y)/*T:B!*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(13, 18), - // (15,22): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(8, 18), + // (10,22): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // o = (b ? y : x)/*T:B!*/; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(15, 22)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(10, 22) + ); comp.VerifyTypes(); } @@ -20738,37 +20583,38 @@ public void ConditionalOperator_NestedNullability_Variant() var source0 = @"public class A { - public static object F; -}"; + public static I F; + public static IIn FIn; + public static IOut FOut; +} +public interface I { } +public interface IIn { } +public interface IOut { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface I { } -interface IIn { } -interface IOut { } -class C +@"class C { - static I CreateI(T t) => throw null!; static void F1(bool b, I x, I y) { - var z = CreateI(A.F)/*T:I!*/; + var z = A.F/*T:I!*/; object o; o = (b ? x : x)/*T:I!*/; - o = (b ? x : y)/*T:I!*/; + o = (b ? x : y)/*T:I!*/; // 1 o = (b ? x : z)/*T:I!*/; - o = (b ? y : x)/*T:I!*/; + o = (b ? y : x)/*T:I!*/; // 2 o = (b ? y : y)/*T:I!*/; o = (b ? y : z)/*T:I!*/; o = (b ? z : x)/*T:I!*/; o = (b ? z : y)/*T:I!*/; o = (b ? z : z)/*T:I!*/; } - static IIn CreateIIn(T t) => throw null!; static void F2(bool b, IIn x, IIn y) { - var z = CreateIIn(A.F)/*T:IIn!*/; + var z = A.FIn/*T:IIn!*/; object o; o = (b ? x : x)/*T:IIn!*/; o = (b ? x : y)/*T:IIn!*/; @@ -20780,10 +20626,9 @@ static void F2(bool b, IIn x, IIn y) o = (b ? z : y)/*T:IIn!*/; o = (b ? z : z)/*T:IIn!*/; } - static IOut CreateIOut(T t) => throw null!; static void F3(bool b, IOut x, IOut y) { - var z = CreateIOut(A.F)/*T:IOut!*/; + var z = A.FOut/*T:IOut!*/; object o; o = (b ? x : x)/*T:IOut!*/; o = (b ? x : y)/*T:IOut!*/; @@ -20798,13 +20643,13 @@ static void F3(bool b, IOut x, IOut y) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (12,22): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. - // o = (b ? x : y)/*T:I!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(12, 22), - // (14,18): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. - // o = (b ? y : x)/*T:I!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(14, 18) -); + // (8,22): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + // o = (b ? x : y)/*T:I!*/; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(8, 22), + // (10,18): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + // o = (b ? y : x)/*T:I!*/; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(10, 18) + ); comp.VerifyTypes(); } @@ -20815,42 +20660,41 @@ public void ConditionalOperator_NestedNullability_VariantAndInvariant() var source0 = @"public class A { - public static object F1; - public static string F2; -}"; + public static IIn F1; + public static IOut F2; +} +public interface IIn { } +public interface IOut { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface IIn { } -interface IOut { } -class C +@"class C { - static IIn CreateIIn(T t, U u) => throw null!; static void F1(bool b, IIn x1, IIn y1) { - var z1 = CreateIIn(A.F1, A.F2)/*T:IIn!*/; + var z1 = A.F1/*T:IIn!*/; object o; o = (b ? x1 : x1)/*T:IIn!*/; - o = (b ? x1 : y1)/*T:IIn!*/; + o = (b ? x1 : y1)/*T:IIn!*/; // 1 o = (b ? x1 : z1)/*T:IIn!*/; - o = (b ? y1 : x1)/*T:IIn!*/; + o = (b ? y1 : x1)/*T:IIn!*/; // 2 o = (b ? y1 : y1)/*T:IIn!*/; o = (b ? y1 : z1)/*T:IIn!*/; o = (b ? z1 : x1)/*T:IIn!*/; o = (b ? z1 : y1)/*T:IIn!*/; o = (b ? z1 : z1)/*T:IIn!*/; } - static IOut CreateIOut(T t, U u) => throw null!; static void F2(bool b, IOut x2, IOut y2) { - var z2 = CreateIOut(A.F1, A.F2)/*T:IOut!*/; + var z2 = A.F2/*T:IOut!*/; object o; o = (b ? x2 : x2)/*T:IOut!*/; - o = (b ? x2 : y2)/*T:IOut!*/; + o = (b ? x2 : y2)/*T:IOut!*/; // 3 o = (b ? x2 : z2)/*T:IOut!*/; - o = (b ? y2 : x2)/*T:IOut!*/; + o = (b ? y2 : x2)/*T:IOut!*/; // 4 o = (b ? y2 : y2)/*T:IOut!*/; o = (b ? y2 : z2)/*T:IOut!*/; o = (b ? z2 : x2)/*T:IOut!*/; @@ -20860,18 +20704,18 @@ static void F2(bool b, IOut x2, IOut y2) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (11,23): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. - // o = (b ? x1 : y1)/*T:IIn!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("IIn", "IIn").WithLocation(11, 23), - // (13,18): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. - // o = (b ? y1 : x1)/*T:IIn!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("IIn", "IIn").WithLocation(13, 18), - // (26,23): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. - // o = (b ? x2 : y2)/*T:IOut!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("IOut", "IOut").WithLocation(26, 23), - // (28,18): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. - // o = (b ? y2 : x2)/*T:IOut!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("IOut", "IOut").WithLocation(28, 18) + // (8,23): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. + // o = (b ? x1 : y1)/*T:IIn!*/; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("IIn", "IIn").WithLocation(8, 23), + // (10,18): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. + // o = (b ? y1 : x1)/*T:IIn!*/; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("IIn", "IIn").WithLocation(10, 18), + // (22,23): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. + // o = (b ? x2 : y2)/*T:IOut!*/; // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("IOut", "IOut").WithLocation(22, 23), + // (24,18): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. + // o = (b ? y2 : x2)/*T:IOut!*/; // 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("IOut", "IOut").WithLocation(24, 18) ); comp.VerifyTypes(); } @@ -20882,31 +20726,27 @@ public void ConditionalOperator_NestedNullability_Tuples() var source0 = @"public class A { - public static object F; -}"; + public static I F; +} +public interface I { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface I { } +@" class C { static void F1(bool b, object x1, object? y1) { - var z1 = A.F/*T:object*/; object o; o = (b ? (x1, x1) : (x1, y1))/*T:(object!, object?)*/; - o = (b ? (z1, x1) : (x1, x1))/*T:(object, object!)*/; - o = (b ? (y1, y1) : (y1, z1))/*T:(object?, object?)*/; o = (b ? (x1, y1) : (y1, y1))/*T:(object?, object?)*/; - o = (b ? (z1, z1) : (z1, x1))/*T:(object, object)*/; - o = (b ? (y1, z1) : (z1, z1))/*T:(object?, object)*/; } - static I CreateI(T t) => throw null!; static void F2(bool b, I x2, I y2) { - var z2 = CreateI(A.F)/*T:I!*/; + var z2 = A.F/*T:I!*/; object o; o = (b ? (x2, x2) : (x2, y2))/*T:(I!, I!)*/; o = (b ? (z2, x2) : (x2, x2))/*T:(I!, I!)*/; @@ -20918,12 +20758,13 @@ static void F2(bool b, I x2, I y2) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (20,29): warning CS8619: Nullability of reference types in value of type '(I x2, I y2)' doesn't match target type '(I, I)'. + // (14,29): warning CS8619: Nullability of reference types in value of type '(I x2, I y2)' doesn't match target type '(I, I)'. // o = (b ? (x2, x2) : (x2, y2))/*T:(I!, I!)*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x2, y2)").WithArguments("(I x2, I y2)", "(I, I)").WithLocation(20, 29), - // (23,29): warning CS8619: Nullability of reference types in value of type '(I, I)' doesn't match target type '(I, I)'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x2, y2)").WithArguments("(I x2, I y2)", "(I, I)").WithLocation(14, 29), + // (17,29): warning CS8619: Nullability of reference types in value of type '(I, I)' doesn't match target type '(I, I)'. // o = (b ? (x2, y2) : (y2, y2))/*T:(I!, I!)*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y2, y2)").WithArguments("(I, I)", "(I, I)").WithLocation(23, 29)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y2, y2)").WithArguments("(I, I)", "(I, I)").WithLocation(17, 29) + ); comp.VerifyTypes(); } @@ -20945,22 +20786,20 @@ public void ConditionalOperator_TopLevelNullability_Ref() { static void F(bool b, object? x, object y) { - var z = A.F/*T:object*/; ref var xx = ref b ? ref x : ref x; - ref var xy = ref b ? ref x : ref y; - ref var xz = ref b ? ref x : ref z; - ref var yx = ref b ? ref y : ref x; + ref var xy = ref b ? ref x : ref y; // 1 + ref var xz = ref b ? ref x : ref A.F; + ref var yx = ref b ? ref y : ref x; // 2 ref var yy = ref b ? ref y : ref y; - ref var yz = ref b ? ref y : ref z; - ref var zx = ref b ? ref z : ref x; - ref var zy = ref b ? ref z : ref y; - ref var zz = ref b ? ref z : ref z; + ref var yz = ref b ? ref y : ref A.F; + ref var zx = ref b ? ref A.F : ref x; + ref var zy = ref b ? ref A.F : ref y; + ref var zz = ref b ? ref A.F : ref A.F; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); // https://github.com/dotnet/roslyn/issues/30432: Report warnings for combinations of `object?` and `object!`. comp.VerifyDiagnostics(); - comp.VerifyTypes(); } [WorkItem(30432, "https://github.com/dotnet/roslyn/issues/30432")] @@ -20970,22 +20809,24 @@ public void ConditionalOperator_NestedNullability_Ref() var source0 = @"public class A { - public static object F; -}"; + public static I IOblivious; + public static IIn IInOblivious; + public static IOut IOutOblivious; +} +public interface I { } +public interface IIn { } +public interface IOut { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface I { } -interface IIn { } -interface IOut { } -class C +@"class C { - static I CreateI(T t) => throw null!; static void F1(bool b, I x1, I y1) { - var z1 = CreateI(A.F)/*T:I!*/; + var z1 = A.IOblivious/*T:I!*/; ref var xx = ref b ? ref x1 : ref x1; ref var xy = ref b ? ref x1 : ref y1; ref var xz = ref b ? ref x1 : ref z1; @@ -20996,10 +20837,9 @@ static void F1(bool b, I x1, I y1) ref var zy = ref b ? ref z1 : ref y1; ref var zz = ref b ? ref z1 : ref z1; } - static IIn CreateIIn(T t) => throw null!; static void F2(bool b, IIn x2, IIn y2) { - var z2 = CreateIIn(A.F)/*T:IIn!*/; + var z2 = A.IInOblivious/*T:IIn!*/; ref var xx = ref b ? ref x2 : ref x2; ref var xy = ref b ? ref x2 : ref y2; ref var xz = ref b ? ref x2 : ref z2; @@ -21010,10 +20850,9 @@ static void F2(bool b, IIn x2, IIn y2) ref var zy = ref b ? ref z2 : ref y2; ref var zz = ref b ? ref z2 : ref z2; } - static IOut CreateIOut(T t) => throw null!; static void F3(bool b, IOut x3, IOut y3) { - var z3 = CreateIOut(A.F)/*T:IOut!*/; + var z3 = A.IOutOblivious/*T:IOut!*/; ref var xx = ref b ? ref x3 : ref x3; ref var xy = ref b ? ref x3 : ref y3; ref var xz = ref b ? ref x3 : ref z3; @@ -21029,12 +20868,13 @@ static void F3(bool b, IOut x3, IOut y3) // https://github.com/dotnet/roslyn/issues/30432: Report warnings for combinations of `IIn` and `IIn` // and combinations of `IOut` and `IOut`. comp.VerifyDiagnostics( - // (11,43): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + // (7,43): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // ref var xy = ref b ? ref x1 : ref y1; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("I", "I").WithLocation(11, 43), - // (13,34): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("I", "I").WithLocation(7, 43), + // (9,34): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // ref var yx = ref b ? ref y1 : ref x1; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("I", "I").WithLocation(13, 34)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("I", "I").WithLocation(9, 34) + ); comp.VerifyTypes(); } @@ -21168,10 +21008,7 @@ static void F(object? x, object? y) comp.VerifyDiagnostics( // (5,10): warning CS8602: Possible dereference of a null reference. // (x ?? y).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x ?? y").WithLocation(5, 10), - // (7,25): hidden CS8607: Expression is probably never null. - // if (y != null) (y ?? x).ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y").WithLocation(7, 25)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x ?? y").WithLocation(5, 10)); } [Fact] @@ -21192,9 +21029,6 @@ static void F(object x, object? y) // (5,10): error CS0019: Operator '??' cannot be applied to operands of type '' and '' // (null ?? null).ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "null ?? null").WithArguments("??", "", "").WithLocation(5, 10), - // (5,10): warning CS8602: Possible dereference of a null reference. - // (null ?? null).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "null ?? null").WithLocation(5, 10), // (7,10): warning CS8602: Possible dereference of a null reference. // (null ?? y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "null ?? y").WithLocation(7, 10)); @@ -21214,12 +21048,7 @@ static void F(string x, string? y) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (5,10): hidden CS8607: Expression is probably never null. - // ("" ?? x).ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, @"""""").WithLocation(5, 10), - // (6,10): hidden CS8607: Expression is probably never null. - // ("" ?? y).ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, @"""""").WithLocation(6, 10)); + ); } [Fact] @@ -21257,15 +21086,15 @@ public class NotNull { static void F1(UnknownNull x1, UnknownNull y1) { - (x1.A ?? y1.B)/*T:*/.ToString(); + (x1.A ?? y1.B)/*T:!*/.ToString(); } static void F2(UnknownNull x2, MaybeNull y2) { - (x2.A ?? y2.B)/*T:?*/.ToString(); + (x2.A ?? y2.B)/*T:!*/.ToString(); } static void F3(MaybeNull x3, UnknownNull y3) { - (x3.A ?? y3.B)/*T:*/.ToString(); + (x3.A ?? y3.B)/*T:!*/.ToString(); } static void F4(MaybeNull x4, MaybeNull y4) { @@ -21296,47 +21125,33 @@ static void F9(NotNull x9, NotNull y9) comp.VerifyTypes(); comp.VerifyDiagnostics( // (5,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' - // (x1.A ?? y1.B)/*T:*/.ToString(); + // (x1.A ?? y1.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x1.A ?? y1.B").WithArguments("??", "A", "B").WithLocation(5, 10), // (9,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' - // (x2.A ?? y2.B)/*T:?*/.ToString(); + // (x2.A ?? y2.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x2.A ?? y2.B").WithArguments("??", "A", "B").WithLocation(9, 10), - // (9,10): warning CS8602: Possible dereference of a null reference. - // (x2.A ?? y2.B)/*T:?*/.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2.A ?? y2.B").WithLocation(9, 10), // (13,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' - // (x3.A ?? y3.B)/*T:*/.ToString(); + // (x3.A ?? y3.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x3.A ?? y3.B").WithArguments("??", "A", "B").WithLocation(13, 10), // (17,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x4.A ?? y4.B)/*T:?*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x4.A ?? y4.B").WithArguments("??", "A", "B").WithLocation(17, 10), - // (17,10): warning CS8602: Possible dereference of a null reference. - // (x4.A ?? y4.B)/*T:?*/.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x4.A ?? y4.B").WithLocation(17, 10), // (21,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x5.A ?? y5.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x5.A ?? y5.B").WithArguments("??", "A", "B").WithLocation(21, 10), // (25,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x6.A ?? y6.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x6.A ?? y6.B").WithArguments("??", "A", "B").WithLocation(25, 10), - // (25,10): hidden CS8607: Expression is probably never null. - // (x6.A ?? y6.B)/*T:!*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x6.A").WithLocation(25, 10), // (29,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x7.A ?? y7.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x7.A ?? y7.B").WithArguments("??", "A", "B").WithLocation(29, 10), // (33,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x8.A ?? y8.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x8.A ?? y8.B").WithArguments("??", "A", "B").WithLocation(33, 10), - // (33,10): hidden CS8607: Expression is probably never null. - // (x8.A ?? y8.B)/*T:!*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x8.A").WithLocation(33, 10), // (37,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x9.A ?? y9.B)/*T:!*/.ToString(); - Diagnostic(ErrorCode.ERR_BadBinaryOps, "x9.A ?? y9.B").WithArguments("??", "A", "B").WithLocation(37, 10), - // (37,10): hidden CS8607: Expression is probably never null. - // (x9.A ?? y9.B)/*T:!*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x9.A").WithLocation(37, 10)); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "x9.A ?? y9.B").WithArguments("??", "A", "B").WithLocation(37, 10) + ); } [Fact] @@ -21350,7 +21165,7 @@ static void F1(C x1, Unknown? y1) (x1 ?? y1)/*T:!*/.ToString(); (y1 ?? x1)/*T:!*/.ToString(); (null ?? y1)/*T:Unknown?*/.ToString(); - (y1 ?? null)/*T:Unknown?*/.ToString(); + (y1 ?? null)/*T:Unknown!*/.ToString(); } static void F2(C? x2, Unknown y2) { @@ -21361,33 +21176,21 @@ static void F2(C? x2, Unknown y2) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); - comp.VerifyTypes(); // Note: Unknown type is treated as a value type + comp.VerifyTypes(); comp.VerifyDiagnostics( - // (3,26): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) - // static void F1(C x1, Unknown? y1) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(3, 26), // (10,27): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) // static void F2(C? x2, Unknown y2) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(10, 27), + // (3,26): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) + // static void F1(C x1, Unknown? y1) + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(3, 26), // (5,10): error CS0019: Operator '??' cannot be applied to operands of type 'C' and 'Unknown?' // (x1 ?? y1)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x1 ?? y1").WithArguments("??", "C", "Unknown?").WithLocation(5, 10), // (6,10): error CS0019: Operator '??' cannot be applied to operands of type 'Unknown?' and 'C' // (y1 ?? x1)/*T:!*/.ToString(); - Diagnostic(ErrorCode.ERR_BadBinaryOps, "y1 ?? x1").WithArguments("??", "Unknown?", "C").WithLocation(6, 10), - // (5,10): hidden CS8607: Expression is probably never null. - // (x1 ?? y1)/*T:!*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1").WithLocation(5, 10), - // (8,10): warning CS8602: Possible dereference of a null reference. - // (y1 ?? null)/*T:Unknown?*/.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1 ?? null").WithLocation(8, 10), - // (13,10): hidden CS8607: Expression is probably never null. - // (y2 ?? x2)/*T:!*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y2").WithLocation(13, 10), - // (15,10): hidden CS8607: Expression is probably never null. - // (y2 ?? null)/*T:!*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y2").WithLocation(15, 10)); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "y1 ?? x1").WithArguments("??", "Unknown?", "C").WithLocation(6, 10)); } [Fact] @@ -21505,24 +21308,15 @@ static void F7(IOut? x7, IOut y7) // (8,30): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // I z1 = x1 ?? y1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("I", "I").WithLocation(8, 30), - // (9,25): hidden CS8607: Expression is probably never null. - // I w1 = y1 ?? x1; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y1").WithLocation(9, 25), // (9,31): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // I w1 = y1 ?? x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I", "I").WithLocation(9, 31), - // (14,27): hidden CS8607: Expression is probably never null. - // IIn w2 = y2 ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y2").WithLocation(14, 27), // (14,27): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // IIn w2 = y2 ?? x2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2 ?? x2").WithArguments("IIn", "IIn").WithLocation(14, 27), // (18,27): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // IOut z3 = x3 ?? y3; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3 ?? y3").WithArguments("IOut", "IOut").WithLocation(18, 27), - // (19,28): hidden CS8607: Expression is probably never null. - // IOut w3 = y3 ?? x3; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y3").WithLocation(19, 28), // (24,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // z4 = ((IIn)x4) ?? y4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IIn)x4").WithLocation(24, 15), @@ -21715,33 +21509,34 @@ static void F6(A? x6, B? y6) // (30,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B?'. // (x5 ?? y5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x5").WithArguments("A", "B?").WithLocation(30, 10), - // (30,9): warning CS8629: Nullable value type may be null. + // (30,10): warning CS8629: Nullable value type may be null. // (x5 ?? y5)/*T:B?*/.Value.F.ToString(); - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(x5 ?? y5)/*T:B?*/.Value").WithLocation(30, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x5 ?? y5").WithLocation(30, 10), // (30,9): warning CS8602: Possible dereference of a null reference. // (x5 ?? y5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x5 ?? y5)/*T:B?*/.Value.F").WithLocation(30, 9), // (31,16): warning CS8619: Nullability of reference types in value of type 'B?' doesn't match target type 'B?'. // (y5 ?? x5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x5").WithArguments("B?", "B?").WithLocation(31, 16), - // (31,9): warning CS8629: Nullable value type may be null. + // (31,10): warning CS8629: Nullable value type may be null. // (y5 ?? x5)/*T:B?*/.Value.F.ToString(); - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(y5 ?? x5)/*T:B?*/.Value").WithLocation(31, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y5 ?? x5").WithLocation(31, 10), // (31,9): warning CS8602: Possible dereference of a null reference. // (y5 ?? x5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(y5 ?? x5)/*T:B?*/.Value.F").WithLocation(31, 9), // (35,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B?'. // (x6 ?? y6)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x6").WithArguments("A", "B?").WithLocation(35, 10), - // (35,9): warning CS8629: Nullable value type may be null. + // (35,10): warning CS8629: Nullable value type may be null. // (x6 ?? y6)/*T:B?*/.Value.F.ToString(); - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(x6 ?? y6)/*T:B?*/.Value").WithLocation(35, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x6 ?? y6").WithLocation(35, 10), // (36,16): warning CS8619: Nullability of reference types in value of type 'B?' doesn't match target type 'B?'. // (y6 ?? x6)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x6").WithArguments("B?", "B?").WithLocation(36, 16), - // (36,9): warning CS8629: Nullable value type may be null. + // (36,10): warning CS8629: Nullable value type may be null. // (y6 ?? x6)/*T:B?*/.Value.F.ToString(); - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(y6 ?? x6)/*T:B?*/.Value").WithLocation(36, 9)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y6 ?? x6").WithLocation(36, 10) + ); } [Fact] @@ -21866,13 +21661,8 @@ static void F1(object? x, dynamic? y, dynamic z) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x ?? y").WithLocation(5, 10), // (7,10): warning CS8602: Possible dereference of a null reference. // (y ?? x).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y ?? x").WithLocation(7, 10), - // (9,10): hidden CS8607: Expression is probably never null. - // (z ?? x).ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z").WithLocation(9, 10), - // (10,10): hidden CS8607: Expression is probably never null. - // (z ?? y).ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z").WithLocation(10, 10)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y ?? x").WithLocation(7, 10) + ); } [Fact] @@ -21908,18 +21698,18 @@ public class NotNull { static void F1(UnknownNull x1, UnknownNull y1) { - (x1.Object ?? y1.String)/*T:object*/.ToString(); - (y1.String ?? x1.Object)/*T:object*/.ToString(); + (x1.Object ?? y1.String)/*T:object!*/.ToString(); + (y1.String ?? x1.Object)/*T:object!*/.ToString(); } static void F2(UnknownNull x2, MaybeNull y2) { - (x2.Object ?? y2.String)/*T:object?*/.ToString(); - (y2.String ?? x2.Object)/*T:object*/.ToString(); + (x2.Object ?? y2.String)/*T:object!*/.ToString(); + (y2.String ?? x2.Object)/*T:object!*/.ToString(); } static void F3(MaybeNull x3, UnknownNull y3) { - (x3.Object ?? y3.String)/*T:object*/.ToString(); - (y3.String ?? x3.Object)/*T:object?*/.ToString(); + (x3.Object ?? y3.String)/*T:object!*/.ToString(); + (y3.String ?? x3.Object)/*T:object!*/.ToString(); } static void F4(MaybeNull x4, MaybeNull y4) { @@ -21955,36 +21745,13 @@ static void F9(NotNull x9, NotNull y9) var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0, ref1 }); comp.VerifyTypes(); comp.VerifyDiagnostics( - // (10,10): warning CS8602: Possible dereference of a null reference. - // (x2.Object ?? y2.String)/*T:object?*/.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2.Object ?? y2.String").WithLocation(10, 10), - // (16,10): warning CS8602: Possible dereference of a null reference. - // (y3.String ?? x3.Object)/*T:object?*/.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y3.String ?? x3.Object").WithLocation(16, 10), // (20,10): warning CS8602: Possible dereference of a null reference. // (x4.Object ?? y4.String)/*T:object?*/.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x4.Object ?? y4.String").WithLocation(20, 10), // (21,10): warning CS8602: Possible dereference of a null reference. // (y4.String ?? x4.Object)/*T:object?*/.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y4.String ?? x4.Object").WithLocation(21, 10), - // (26,10): hidden CS8607: Expression is probably never null. - // (y5.String ?? x5.Object)/*T:object*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y5.String").WithLocation(26, 10), - // (30,10): hidden CS8607: Expression is probably never null. - // (x6.Object ?? y6.String)/*T:object*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x6.Object").WithLocation(30, 10), - // (36,10): hidden CS8607: Expression is probably never null. - // (y7.String ?? x7.Object)/*T:object!*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y7.String").WithLocation(36, 10), - // (40,10): hidden CS8607: Expression is probably never null. - // (x8.Object ?? y8.String)/*T:object*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x8.Object").WithLocation(40, 10), - // (45,10): hidden CS8607: Expression is probably never null. - // (x9.Object ?? y9.String)/*T:object!*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x9.Object").WithLocation(45, 10), - // (46,10): hidden CS8607: Expression is probably never null. - // (y9.String ?? x9.Object)/*T:object!*/.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y9.String").WithLocation(46, 10)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y4.String ?? x4.Object").WithLocation(21, 10) + ); } [Fact] @@ -22018,15 +21785,9 @@ static void G(A z, B? w) // (11,15): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // (x ?? y).F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("B", "A").WithLocation(11, 15), - // (12,10): hidden CS8607: Expression is probably never null. - // (y ?? x).F.ToString(); // 2 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y").WithLocation(12, 10), // (12,10): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // (y ?? x).F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("B", "A").WithLocation(12, 10), - // (16,10): hidden CS8607: Expression is probably never null. - // (z ?? w).F.ToString(); // 3 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z").WithLocation(16, 10), // (16,15): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // (z ?? w).F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("B", "A").WithLocation(16, 15), @@ -22068,15 +21829,9 @@ static void G(IIn z, IIn? w) // (9,10): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // (x ?? y)/*T:IIn!*/.F(string.Empty, null); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(9, 10), - // (10,10): hidden CS8607: Expression is probably never null. - // (y ?? x)/*T:IIn!*/.F(string.Empty, null); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y").WithLocation(10, 10), // (10,15): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // (y ?? x)/*T:IIn!*/.F(string.Empty, null); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(10, 15), - // (14,10): hidden CS8607: Expression is probably never null. - // (z ?? w)/*T:IIn!*/.F(string.Empty, null); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z").WithLocation(14, 10), // (14,53): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // (z ?? w)/*T:IIn!*/.F(string.Empty, null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 53), @@ -22112,15 +21867,9 @@ static void G(IOut z, IOut? w) // (9,15): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // (x ?? y)/*T:IOut!*/.P.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("IOut", "IOut").WithLocation(9, 15), - // (10,10): hidden CS8607: Expression is probably never null. - // (y ?? x)/*T:IOut!*/.P.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y").WithLocation(10, 10), // (10,10): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // (y ?? x)/*T:IOut!*/.P.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("IOut", "IOut").WithLocation(10, 10), - // (14,10): hidden CS8607: Expression is probably never null. - // (z ?? w)/*T:IOut!*/.P.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z").WithLocation(14, 10), // (14,9): warning CS8602: Possible dereference of a null reference. // (z ?? w)/*T:IOut!*/.P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(z ?? w)/*T:IOut!*/.P").WithLocation(14, 9), @@ -22236,12 +21985,6 @@ class CL1 " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (11,13): hidden CS8606: Result of the comparison is possibly always false. - // if (x1 == null) {} // 1 - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "x1 == null").WithLocation(11, 13), - // (23,13): hidden CS8606: Result of the comparison is possibly always false. - // if (x2 == null) {} // 1 - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "x2 == null").WithLocation(23, 13) ); } @@ -23495,12 +23238,12 @@ static void F3() where T : struct }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (6,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (6,24): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // a1 = new T[] { default }; // 1 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(6, 24), - // (7,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 24), + // (7,24): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // a1 = new T[] { default(T) }; // 2 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T)").WithLocation(7, 24), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(7, 24), // (12,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // a2 = new T[] { null }; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 24), @@ -23509,7 +23252,8 @@ static void F3() where T : struct Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(13, 24), // (14,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // a2 = new T[] { default(T) }; // 5 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T)").WithLocation(14, 24)); + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T)").WithLocation(14, 24) + ); } [Fact] @@ -23541,7 +23285,9 @@ static void F(object x, object? y) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0][0]").WithLocation(13, 9)); } - [Fact, WorkItem(30376, "https://github.com/dotnet/roslyn/issues/30376")] + [Fact] + [WorkItem(33346, "https://github.com/dotnet/roslyn/issues/33346")] + [WorkItem(30376, "https://github.com/dotnet/roslyn/issues/30376")] public void ImplicitlyTypedArrayCreation_02() { var source = @@ -23552,26 +23298,32 @@ static void F(object x, object? y) var a = new[] { x }; a[0].ToString(); var b = new[] { y }; - b[0].ToString(); + b[0].ToString(); // 1 } static void F(object[] a, object?[] b) { var c = new[] { a, b }; - c[0][0].ToString(); + c[0][0].ToString(); // 2 var d = new[] { a, b! }; - d[0][0].ToString(); + d[0][0].ToString(); // 3 var e = new[] { b!, a }; - e[0][0].ToString(); + e[0][0].ToString(); // 4 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Possible dereference of a null reference. - // b[0].ToString(); + // b[0].ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0]").WithLocation(8, 9), - // (12,28): warning CS8619: Nullability of reference types in value of type 'object?[]' doesn't match target type 'object[]'. - // var c = new[] { a, b }; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("object?[]", "object[]").WithLocation(12, 28) + // (13,9): warning CS8602: Possible dereference of a null reference. + // c[0][0].ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0][0]").WithLocation(13, 9), + // (15,9): warning CS8602: Possible dereference of a null reference. + // d[0][0].ToString(); // 3 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d[0][0]").WithLocation(15, 9), + // (17,9): warning CS8602: Possible dereference of a null reference. + // e[0][0].ToString(); // 4 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e[0][0]").WithLocation(17, 9) ); } @@ -23602,9 +23354,6 @@ static void F(object[]? a, object?[]? b) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (10,28): warning CS8619: Nullability of reference types in value of type 'object?[]' doesn't match target type 'object[]'. - // var c = new[] { a, b }; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("object?[]", "object[]").WithLocation(10, 28), // (11,13): warning CS8602: Possible dereference of a null reference. // _ = c[0].Length; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0]").WithLocation(11, 13), @@ -23613,8 +23362,7 @@ static void F(object[]? a, object?[]? b) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d[0]").WithLocation(13, 13), // (15,13): warning CS8602: Possible dereference of a null reference. // _ = e[0].Length; - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e[0]").WithLocation(15, 13) - ); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e[0]").WithLocation(15, 13)); } [Fact] @@ -23740,7 +23488,7 @@ public void ImplicitlyTypedArrayCreation_NestedNullability_Derived() var source0 = @"public class A { - public static object F; + public static B F; } public class B { @@ -23757,15 +23505,14 @@ public class C0 : B class C2 : B { } class Program { - static B CreateB(T t) => throw null!; static void F(B x, B y, C0 cz, C1 cx, C2 cy) { - var z = CreateB(A.F)/*T:B!*/; + var z = A.F/*T:B!*/; object o; o = (new[] { x, cx })[0]/*B*/; - o = (new[] { x, cy })[0]/*B*/; + o = (new[] { x, cy })[0]/*B*/; // 1 o = (new[] { x, cz })[0]/*B*/; - o = (new[] { y, cx })[0]/*B*/; + o = (new[] { y, cx })[0]/*B*/; // 2 o = (new[] { cy, y })[0]/*B*/; o = (new[] { cz, y })[0]/*B*/; o = (new[] { cx, z })[0]/*B*/; @@ -23774,13 +23521,15 @@ static void F(B x, B y, C0 cz, C1 cx, C2 cy) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); + comp.VerifyTypes(); comp.VerifyDiagnostics( - // (11,25): warning CS8619: Nullability of reference types in value of type 'C2' doesn't match target type 'B'. - // o = (new[] { x, cy })[0]/*B*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "cy").WithArguments("C2", "B").WithLocation(11, 25), - // (13,25): warning CS8619: Nullability of reference types in value of type 'C1' doesn't match target type 'B'. - // o = (new[] { y, cx })[0]/*B*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "cx").WithArguments("C1", "B").WithLocation(13, 25)); + // (10,25): warning CS8619: Nullability of reference types in value of type 'C2' doesn't match target type 'B'. + // o = (new[] { x, cy })[0]/*B*/; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "cy").WithArguments("C2", "B").WithLocation(10, 25), + // (12,25): warning CS8619: Nullability of reference types in value of type 'C1' doesn't match target type 'B'. + // o = (new[] { y, cx })[0]/*B*/; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "cx").WithArguments("C1", "B").WithLocation(12, 25) + ); comp.VerifyTypes(); } @@ -23829,7 +23578,8 @@ static void F(C? a, C b) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("C", "C").WithLocation(15, 32), // (17,29): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var d = new[] { b, a }; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("C", "C").WithLocation(17, 29)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("C", "C").WithLocation(17, 29) + ); } [Fact] @@ -23886,17 +23636,17 @@ public void ImplicitlyTypedArrayCreation_TopLevelNullability_01() { static void F(object? x, object y) { - var z = A.F/*T:object*/; + var z = A.F/*T:object!*/; object? o; o = (new[] { x, x })[0]/*T:object?*/; o = (new[] { x, y })[0]/*T:object?*/; o = (new[] { x, z })[0]/*T:object?*/; o = (new[] { y, x })[0]/*T:object?*/; o = (new[] { y, y })[0]/*T:object!*/; - o = (new[] { y, z })[0]/*T:object*/; + o = (new[] { y, z })[0]/*T:object!*/; o = (new[] { z, x })[0]/*T:object?*/; - o = (new[] { z, y })[0]/*T:object*/; - o = (new[] { z, z })[0]/*T:object*/; + o = (new[] { z, y })[0]/*T:object!*/; + o = (new[] { z, z })[0]/*T:object!*/; o = (new[] { x, y, z })[0]/*T:object?*/; o = (new[] { z, y, x })[0]/*T:object?*/; } @@ -23935,74 +23685,75 @@ public void ImplicitlyTypedArrayCreation_NestedNullability_Invariant() var source0 = @"public class A { - public static object F; -}"; + public static B F; +} +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"class B { } -class Program +@"class Program { - static B Create(T t) - { - throw null!; - } static void F(bool b, B x, B y) { - var z = Create(A.F); // B + var z = A.F/*T:B!*/; object o; - o = (new[] { x, y })[0]/*T:B!*/; + o = (new[] { x, y })[0]/*T:B!*/; // 1 o = (new[] { x, z })[0]/*T:B!*/; - o = (new[] { y, x })[0]/*T:B!*/; + o = (new[] { y, x })[0]/*T:B!*/; // 2 o = (new[] { y, z })[0]/*T:B!*/; o = (new[] { z, x })[0]/*T:B!*/; o = (new[] { z, y })[0]/*T:B!*/; - o = (new[] { x, y, z })[0]/*T:B!*/; - o = (new[] { z, y, x })[0]/*T:B!*/; + o = (new[] { x, y, z })[0]/*T:B!*/; // 3 + o = (new[] { z, y, x })[0]/*T:B!*/; // 4 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (12,22): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // o = (new[] { x, y })[0]/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(12, 22), - // (14,25): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // o = (new[] { y, x })[0]/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(14, 25), - // (18,22): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // o = (new[] { x, y, z })[0]/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(18, 22), - // (19,28): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // o = (new[] { z, y, x })[0]/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(19, 28)); + // (7,22): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // o = (new[] { x, y })[0]/*T:B!*/; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(7, 22), + // (9,25): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // o = (new[] { y, x })[0]/*T:B!*/; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(9, 25), + // (13,22): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // o = (new[] { x, y, z })[0]/*T:B!*/; // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(13, 22), + // (14,28): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // o = (new[] { z, y, x })[0]/*T:B!*/; // 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(14, 28) + ); comp.VerifyTypes(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] + [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] public void ImplicitlyTypedArrayCreation_NestedNullability_Variant_01() { var source0 = @"public class A { - public static object F; -}"; + public static I F; + public static IIn FIn; + public static IOut FOut; +} +public interface I { } +public interface IIn { } +public interface IOut { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface I { } -interface IIn { } -interface IOut { } -class C +@"class C { - static I CreateI(T t) => throw null!; static void F(I x, I y) { - var z = CreateI(A.F)/*T:I!*/; + var z = A.F/*T:I!*/; object o; o = (new[] { x, x })[0]/*T:I!*/; o = (new[] { x, y })[0]/*T:I!*/; // 1 @@ -24014,10 +23765,9 @@ static void F(I x, I y) o = (new[] { z, y })[0]/*T:I!*/; o = (new[] { z, z })[0]/*T:I!*/; } - static IIn CreateIIn(T t) => throw null!; static void F(IIn x, IIn y) { - var z = CreateIIn(A.F)/*T:IIn!*/; + var z = A.FIn/*T:IIn!*/; object o; o = (new[] { x, x })[0]/*T:IIn!*/; o = (new[] { x, y })[0]/*T:IIn!*/; @@ -24029,10 +23779,9 @@ static void F(IIn x, IIn y) o = (new[] { z, y })[0]/*T:IIn!*/; o = (new[] { z, z })[0]/*T:IIn!*/; } - static IOut CreateIOut(T t) => throw null!; static void F(IOut x, IOut y) { - var z = CreateIOut(A.F)/*T:IOut!*/; + var z = A.FOut/*T:IOut!*/; object o; o = (new[] { x, x })[0]/*T:IOut!*/; o = (new[] { x, y })[0]/*T:IOut!*/; @@ -24047,39 +23796,44 @@ static void F(IOut x, IOut y) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (12,25): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + // (8,25): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // o = (new[] { x, y })[0]/*T:I!*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(12, 25), - // (14,22): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(8, 25), + // (10,22): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // o = (new[] { y, x })[0]/*T:I!*/; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(14, 22)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(10, 22) + ); comp.VerifyTypes(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] + [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] public void ImplicitlyTypedArrayCreation_NestedNullability_Variant_02() { var source0 = @"public class A { - public static string F; -}"; + public static I F; + public static IIn FIn; + public static IOut FOut; +} +public interface I { } +public interface IIn { } +public interface IOut { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface I { } -interface IIn { } -interface IOut { } -class C +@"class C { static T F(T x, T y) => throw null!; - static I> Create1(T t) => throw null!; + static I Create1(T t) => throw null!; static void G1(I> x1, I> y1) { - var z1 = Create1(A.F)/*T:I!>!*/; + var z1 = Create1(A.FOut)/*T:I!>!*/; object o; o = (new [] { x1, x1 })[0]/*T:I!>!*/; o = (new [] { x1, y1 })[0]/*T:I!>!*/; // 1 @@ -24091,10 +23845,10 @@ static void G1(I> x1, I> y1) o = (new [] { z1, y1 })[0]/*T:I!>!*/; o = (new [] { z1, z1 })[0]/*T:I!>!*/; } - static IOut> Create2(T t) => throw null!; + static IOut Create2(T t) => throw null!; static void G2(IOut> x2, IOut> y2) { - var z2 = Create2(A.F)/*T:IOut!>!*/; + var z2 = Create2(A.FIn)/*T:IOut!>!*/; object o; o = (new [] { x2, x2 })[0]/*T:IOut!>!*/; o = (new [] { x2, y2 })[0]/*T:IOut!>!*/; @@ -24106,10 +23860,10 @@ static void G2(IOut> x2, IOut> y2) o = (new [] { z2, y2 })[0]/*T:IOut!>!*/; o = (new [] { z2, z2 })[0]/*T:IOut!>!*/; } - static IIn> Create3(T t) => throw null!; + static IIn Create3(T t) => throw null!; static void G3(IIn> x3, IIn> y3) { - var z3 = Create3(A.F)/*T:IIn!>!*/; + var z3 = Create3(A.FOut)/*T:IIn!>!*/; object o; o = (new [] { x3, x3 })[0]/*T:IIn!>!*/; o = (new [] { x3, y3 })[0]/*T:IIn!>!*/; @@ -24124,17 +23878,19 @@ static void G3(IIn> x3, IIn> y3) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (13,23): warning CS8619: Nullability of reference types in value of type 'I>' doesn't match target type 'I>'. + // (10,23): warning CS8619: Nullability of reference types in value of type 'I>' doesn't match target type 'I>'. // o = (new [] { x1, y1 })[0]/*T:I!>!*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I>", "I>").WithLocation(13, 23), - // (15,27): warning CS8619: Nullability of reference types in value of type 'I>' doesn't match target type 'I>'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I>", "I>").WithLocation(10, 23), + // (12,27): warning CS8619: Nullability of reference types in value of type 'I>' doesn't match target type 'I>'. // o = (new [] { y1, x1 })[0]/*T:I!>!*/; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I>", "I>").WithLocation(15, 27)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I>", "I>").WithLocation(12, 27) + ); comp.VerifyTypes(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] + [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] public void ImplicitlyTypedArrayCreation_NestedNullability_Variant_03() { var source0 = @@ -24142,26 +23898,30 @@ public void ImplicitlyTypedArrayCreation_NestedNullability_Variant_03() { public static object F1; public static string F2; + + public static B.INone BON; + public static B.I BOI; + public static B.IIn BOIIn; + public static B.IOut BOIOut; +} +public class B +{ + public interface INone { } + public interface I { } + public interface IIn { } + public interface IOut { } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"class B -{ - internal interface INone { } - internal interface I { } - internal interface IIn { } - internal interface IOut { } -} -class C +@"class C { static T F(T x, T y) => throw null!; - static B.INone CreateINone(T t) => throw null!; static void G0(B.INone x0, B.INone y0) { - var z0 = CreateINone(A.F1)/*T:B.INone!*/; + var z0 = A.BON/*T:B.INone!*/; object o; o = (new[] { x0, x0 })[0]/*T:B.INone!*/; o = (new[] { x0, y0 })[0]/*T:B.INone!*/; // 1 @@ -24173,10 +23933,9 @@ static void G0(B.INone x0, B.INone y0) o = (new[] { z0, y0 })[0]/*T:B.INone!*/; o = (new[] { z0, z0 })[0]/*T:B.INone!*/; } - static B.I CreateI(T t, U u) => throw null!; static void G1(B.I x1, B.I y1) { - var z1 = CreateI(A.F1, A.F2)/*T:B.I!*/; + var z1 = A.BOI/*T:B.I!*/; object o; o = (new[] { x1, x1 })[0]/*T:B.I!*/; o = (new[] { x1, y1 })[0]/*T:B.I!*/; // 3 @@ -24188,10 +23947,9 @@ static void G1(B.I x1, B.I y1) o = (new[] { z1, y1 })[0]/*T:B.I!*/; o = (new[] { z1, z1 })[0]/*T:B.I!*/; } - static B.IIn CreateIIn(T t, U u) => throw null!; static void G2(B.IIn x2, B.IIn y2) { - var z2 = CreateIIn(A.F1, A.F2)/*T:B.IIn!*/; + var z2 = A.BOIIn/*T:B.IIn!*/; object o; o = (new[] { x2, x2 })[0]/*T:B.IIn!*/; o = (new[] { x2, y2 })[0]/*T:B.IIn!*/; // 5 @@ -24203,10 +23961,9 @@ static void G2(B.IIn x2, B.IIn y2) o = (new[] { z2, y2 })[0]/*T:B.IIn!*/; o = (new[] { z2, z2 })[0]/*T:B.IIn!*/; } - static B.IOut CreateIOut(T t, U u) => throw null!; static void G3(B.IOut x3, B.IOut y3) { - var z3 = CreateIOut(A.F1, A.F2)/*T:B.IOut!*/; + var z3 = A.BOIOut/*T:B.IOut!*/; object o; o = (new[] { x3, x3 })[0]/*T:B.IOut!*/; o = (new[] { x3, y3 })[0]/*T:B.IOut!*/; // 7 @@ -24221,30 +23978,30 @@ static void G3(B.IOut x3, B.IOut y3) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (17,26): warning CS8619: Nullability of reference types in value of type 'B.INone' doesn't match target type 'B.INone'. + // (9,26): warning CS8619: Nullability of reference types in value of type 'B.INone' doesn't match target type 'B.INone'. // o = (new[] { x0, y0 })[0]/*T:B.INone!*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y0").WithArguments("B.INone", "B.INone").WithLocation(17, 26), - // (19,22): warning CS8619: Nullability of reference types in value of type 'B.INone' doesn't match target type 'B.INone'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y0").WithArguments("B.INone", "B.INone").WithLocation(9, 26), + // (11,22): warning CS8619: Nullability of reference types in value of type 'B.INone' doesn't match target type 'B.INone'. // o = (new[] { y0, x0 })[0]/*T:B.INone!*/; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y0").WithArguments("B.INone", "B.INone").WithLocation(19, 22), - // (32,26): warning CS8619: Nullability of reference types in value of type 'B.I' doesn't match target type 'B.I'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y0").WithArguments("B.INone", "B.INone").WithLocation(11, 22), + // (23,26): warning CS8619: Nullability of reference types in value of type 'B.I' doesn't match target type 'B.I'. // o = (new[] { x1, y1 })[0]/*T:B.I!*/; // 3 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("B.I", "B.I").WithLocation(32, 26), - // (34,22): warning CS8619: Nullability of reference types in value of type 'B.I' doesn't match target type 'B.I'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("B.I", "B.I").WithLocation(23, 26), + // (25,22): warning CS8619: Nullability of reference types in value of type 'B.I' doesn't match target type 'B.I'. // o = (new[] { y1, x1 })[0]/*T:B.I!*/; // 4 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("B.I", "B.I").WithLocation(34, 22), - // (47,26): warning CS8619: Nullability of reference types in value of type 'B.IIn' doesn't match target type 'B.IIn'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("B.I", "B.I").WithLocation(25, 22), + // (37,26): warning CS8619: Nullability of reference types in value of type 'B.IIn' doesn't match target type 'B.IIn'. // o = (new[] { x2, y2 })[0]/*T:B.IIn!*/; // 5 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("B.IIn", "B.IIn").WithLocation(47, 26), - // (49,22): warning CS8619: Nullability of reference types in value of type 'B.IIn' doesn't match target type 'B.IIn'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("B.IIn", "B.IIn").WithLocation(37, 26), + // (39,22): warning CS8619: Nullability of reference types in value of type 'B.IIn' doesn't match target type 'B.IIn'. // o = (new[] { y2, x2 })[0]/*T:B.IIn!*/; // 6 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("B.IIn", "B.IIn").WithLocation(49, 22), - // (62,26): warning CS8619: Nullability of reference types in value of type 'B.IOut' doesn't match target type 'B.IOut'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("B.IIn", "B.IIn").WithLocation(39, 22), + // (51,26): warning CS8619: Nullability of reference types in value of type 'B.IOut' doesn't match target type 'B.IOut'. // o = (new[] { x3, y3 })[0]/*T:B.IOut!*/; // 7 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y3").WithArguments("B.IOut", "B.IOut").WithLocation(62, 26), - // (64,22): warning CS8619: Nullability of reference types in value of type 'B.IOut' doesn't match target type 'B.IOut'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y3").WithArguments("B.IOut", "B.IOut").WithLocation(51, 26), + // (53,22): warning CS8619: Nullability of reference types in value of type 'B.IOut' doesn't match target type 'B.IOut'. // o = (new[] { y3, x3 })[0]/*T:B.IOut!*/; // 8 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y3").WithArguments("B.IOut", "B.IOut").WithLocation(64, 22)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y3").WithArguments("B.IOut", "B.IOut").WithLocation(53, 22)); comp.VerifyTypes(); } @@ -24255,30 +24012,31 @@ public void ImplicitlyTypedArrayCreation_NestedNullability_Tuples() @"public class A { public static object F; -}"; + public static I IF; +} +public interface I { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface I { } -class C +@"class C { static void F1(bool b, object x1, object? y1) { - var z1 = A.F/*T:object*/; + var z1 = A.F/*T:object!*/; object o; o = (new[] { (x1, x1), (x1, y1) })[0]/*T:(object!, object?)*/; - o = (new[] { (z1, x1), (x1, x1) })[0]/*T:(object, object!)*/; + o = (new[] { (z1, x1), (x1, x1) })[0]/*T:(object!, object!)*/; o = (new[] { (y1, y1), (y1, z1) })[0]/*T:(object?, object?)*/; o = (new[] { (x1, y1), (y1, y1) })[0]/*T:(object?, object?)*/; - o = (new[] { (z1, z1), (z1, x1) })[0]/*T:(object, object)*/; - o = (new[] { (y1, z1), (z1, z1) })[0]/*T:(object?, object)*/; + o = (new[] { (z1, z1), (z1, x1) })[0]/*T:(object!, object!)*/; + o = (new[] { (y1, z1), (z1, z1) })[0]/*T:(object?, object!)*/; } - static I CreateI(T t) => throw null!; static void F2(bool b, I x2, I y2) { - var z2 = CreateI(A.F)/*T:I!*/; + var z2 = A.IF/*T:I!*/; object o; o = (new[] { (x2, x2), (x2, y2) })[0]/*T:(I!, I!)*/; // 1 o = (new[] { (z2, x2), (x2, x2) })[0]/*T:(I!, I!)*/; @@ -24287,27 +24045,21 @@ static void F2(bool b, I x2, I y2) o = (new[] { (z2, z2), (z2, x2) })[0]/*T:(I!, I!)*/; o = (new[] { (y2, z2), (z2, z2) })[0]/*T:(I!, I!)*/; - o = (new[] { (x2, x2)!, (x2, y2) })[0]/*T:(I!, I!)*/; + o = (new[] { (x2, x2)!, (x2, y2) })[0]/*T:(I!, I!)*/; // 3 o = (new[] { (x2, y2), (y2, y2)! })[0]/*T:(I!, I!)*/; } }"; - // Last two diagnostics should be suppressed - // Tracked by https://github.com/dotnet/roslyn/issues/32553 - var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (20,32): warning CS8619: Nullability of reference types in value of type '(I x2, I y2)' doesn't match target type '(I, I)'. + // (18,32): warning CS8619: Nullability of reference types in value of type '(I x2, I y2)' doesn't match target type '(I, I)'. // o = (new[] { (x2, x2), (x2, y2) })[0]/*T:(I!, I!)*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x2, y2)").WithArguments("(I x2, I y2)", "(I, I)").WithLocation(20, 32), - // (23,32): warning CS8619: Nullability of reference types in value of type '(I, I)' doesn't match target type '(I, I)'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x2, y2)").WithArguments("(I x2, I y2)", "(I, I)").WithLocation(18, 32), + // (21,32): warning CS8619: Nullability of reference types in value of type '(I, I)' doesn't match target type '(I, I)'. // o = (new[] { (x2, y2), (y2, y2) })[0]/*T:(I!, I!)*/; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y2, y2)").WithArguments("(I, I)", "(I, I)").WithLocation(23, 32), - // (27,33): warning CS8619: Nullability of reference types in value of type '(I x2, I y2)' doesn't match target type '(I, I)'. - // o = (new[] { (x2, x2)!, (x2, y2) })[0]/*T:(I!, I!)*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x2, y2)").WithArguments("(I x2, I y2)", "(I, I)").WithLocation(27, 33), - // (28,32): warning CS8619: Nullability of reference types in value of type '(I, I)' doesn't match target type '(I, I)'. - // o = (new[] { (x2, y2), (y2, y2)! })[0]/*T:(I!, I!)*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y2, y2)").WithArguments("(I, I)", "(I, I)").WithLocation(28, 32)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y2, y2)").WithArguments("(I, I)", "(I, I)").WithLocation(21, 32), + // (25,33): warning CS8619: Nullability of reference types in value of type '(I x2, I y2)' doesn't match target type '(I, I)'. + // o = (new[] { (x2, x2)!, (x2, y2) })[0]/*T:(I!, I!)*/; // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x2, y2)").WithArguments("(I x2, I y2)", "(I, I)").WithLocation(25, 33)); comp.VerifyTypes(); } @@ -24404,27 +24156,27 @@ static void F(IOut x, IOut y, IOut? z, IOut? w // (9,9): warning CS8602: Possible dereference of a null reference. // (new[] { x, z })[0].ToString(); // A2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, z })[0]").WithLocation(9, 9), - // (10,21): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. - // (new[] { x, w })[0].ToString(); // A3 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("I", "I").WithLocation(10, 21), // (10,9): warning CS8602: Possible dereference of a null reference. // (new[] { x, w })[0].ToString(); // A3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, w })[0]").WithLocation(10, 9), - // (11,18): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. - // (new[] { y, z })[0].ToString(); // A4 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(11, 18), + // (10,21): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + // (new[] { x, w })[0].ToString(); // A3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("I", "I").WithLocation(10, 21), // (11,9): warning CS8602: Possible dereference of a null reference. // (new[] { y, z })[0].ToString(); // A4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, z })[0]").WithLocation(11, 9), + // (11,18): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + // (new[] { y, z })[0].ToString(); // A4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(11, 18), // (12,9): warning CS8602: Possible dereference of a null reference. // (new[] { y, w })[0].ToString(); // A5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, w })[0]").WithLocation(12, 9), - // (13,18): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. - // (new[] { w, z })[0].ToString(); // A6 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("I", "I").WithLocation(13, 18), // (13,9): warning CS8602: Possible dereference of a null reference. // (new[] { w, z })[0].ToString(); // A6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { w, z })[0]").WithLocation(13, 9), + // (13,18): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + // (new[] { w, z })[0].ToString(); // A6 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("I", "I").WithLocation(13, 18), // (18,9): warning CS8602: Possible dereference of a null reference. // (new[] { x, z })[0].ToString(); // B2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, z })[0]").WithLocation(18, 9), @@ -24454,7 +24206,8 @@ static void F(IOut x, IOut y, IOut? z, IOut? w Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, w })[0]").WithLocation(30, 9), // (31,9): warning CS8602: Possible dereference of a null reference. // (new[] { w, z })[0].ToString(); // C6 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { w, z })[0]").WithLocation(31, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { w, z })[0]").WithLocation(31, 9) + ); } [Fact] @@ -24478,7 +24231,7 @@ public class B : A { static void F(object? x, B b) { - var y = b.F/*T:object*/; + var y = b.F/*T:object!*/; (new[] { x, x! })[0].ToString(); // 1 (new[] { x!, x })[0].ToString(); // 2 (new[] { x!, x! })[0].ToString(); @@ -24968,15 +24721,9 @@ struct S2 // (22,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = y2.F1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2.F1").WithLocation(22, 14), - // (34,14): hidden CS8607: Expression is probably never null. - // x4 = y4.F2.F1 ?? x4; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y4.F2.F1").WithLocation(34, 14), // (35,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = y4.F2.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4.F2.F3").WithLocation(35, 14), - // (42,14): hidden CS8607: Expression is probably never null. - // x5 = u5.F1 ?? x5; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u5.F1").WithLocation(42, 14), // (43,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x5 = u5.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u5.F3").WithLocation(43, 14) @@ -25094,12 +24841,30 @@ struct S1 // (34,19): error CS0170: Use of possibly unassigned field 'F3' // CL1? z3 = y3.F3; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y3.F3").WithArguments("F3").WithLocation(34, 19), + // (35,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // x3 = z3; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z3").WithLocation(35, 14), + // (36,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // x3 = z3 ?? x3; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z3 ?? x3").WithLocation(36, 14), // (42,14): error CS0170: Use of possibly unassigned field 'F3' // z4 = y4.F3; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y4.F3").WithArguments("F3").WithLocation(42, 14), + // (43,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // x4 = z4; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z4").WithLocation(43, 14), + // (44,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // x4 = z4 ?? x4; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z4 ?? x4").WithLocation(44, 14), // (50,29): error CS0170: Use of possibly unassigned field 'F3' // var z5 = new { F3 = y5.F3 }; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y5.F3").WithArguments("F3").WithLocation(50, 29), + // (51,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // x5 = z5.F3; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z5.F3").WithLocation(51, 14), + // (52,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // x5 = z5.F3 ?? x5; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z5.F3 ?? x5").WithLocation(52, 14), // (59,14): error CS0165: Use of unassigned local variable 'y6' // z6 = y6; Diagnostic(ErrorCode.ERR_UseDefViolation, "y6").WithArguments("y6").WithLocation(59, 14), @@ -25108,7 +24873,13 @@ struct S1 Diagnostic(ErrorCode.ERR_UseDefViolation, "y7").WithArguments("y7").WithLocation(68, 29), // (81,18): error CS0170: Use of possibly unassigned field 'F3' // z8 = y8.F3; - Diagnostic(ErrorCode.ERR_UseDefViolationField, "y8.F3").WithArguments("F3").WithLocation(81, 18) + Diagnostic(ErrorCode.ERR_UseDefViolationField, "y8.F3").WithArguments("F3").WithLocation(81, 18), + // (82,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // x8 = z8; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z8").WithLocation(82, 18), + // (83,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // x8 = z8 ?? x8; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z8 ?? x8").WithLocation(83, 18) ); } @@ -25168,9 +24939,6 @@ struct S2 // (9,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = new S1().F1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "new S1().F1").WithLocation(9, 14), - // (19,14): hidden CS8607: Expression is probably never null. - // x3 = new S1() {F1 = x3}.F1 ?? x3; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new S1() {F1 = x3}.F1").WithLocation(19, 14), // (24,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = new S2().F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "new S2().F2").WithLocation(24, 14) @@ -25330,81 +25098,45 @@ struct S1 }" }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (10,14): hidden CS8607: Expression is probably never null. - // x1 = y1.p1 ?? x1; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y1.p1").WithLocation(10, 14), // (11,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = y1.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1.p2").WithLocation(11, 14), // (18,14): warning CS8619: Nullability of reference types in value of type '' doesn't match target type ''. // u2 = v2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "v2").WithArguments("", "").WithLocation(18, 14), - // (19,14): hidden CS8607: Expression is probably never null. - // x2 = u2.p2 ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u2.p2").WithLocation(19, 14), // (20,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = u2.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u2.p1").WithLocation(20, 14), - // (21,14): hidden CS8607: Expression is probably never null. - // x2 = v2.p2 ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "v2.p2").WithLocation(21, 14), // (22,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = v2.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v2.p1").WithLocation(22, 14), - // (29,14): hidden CS8607: Expression is probably never null. - // x3 = v3.p1 ?? x3; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "v3.p1").WithLocation(29, 14), // (30,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = v3.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v3.p2").WithLocation(30, 14), // (37,14): warning CS8619: Nullability of reference types in value of type ' p0>' doesn't match target type ' p0>'. // u4 = v4; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "v4").WithArguments(" p0>", " p0>").WithLocation(37, 14), - // (38,14): hidden CS8607: Expression is probably never null. - // x4 = u4.p0.p2 ?? x4; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u4.p0.p2").WithLocation(38, 14), // (39,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = u4.p0.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u4.p0.p1").WithLocation(39, 14), - // (40,14): hidden CS8607: Expression is probably never null. - // x4 = v4.p0.p2 ?? x4; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "v4.p0.p2").WithLocation(40, 14), // (41,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = v4.p0.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v4.p0.p1").WithLocation(41, 14), - // (48,14): hidden CS8607: Expression is probably never null. - // x5 = v5.p0.p1 ?? x5; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "v5.p0.p1").WithLocation(48, 14), // (49,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x5 = v5.p0.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v5.p0.p2").WithLocation(49, 14), - // (56,14): hidden CS8607: Expression is probably never null. - // x6 = v6.p1 ?? x6; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "v6.p1").WithLocation(56, 14), // (57,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x6 = v6.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v6.p2").WithLocation(57, 14), - // (65,14): hidden CS8607: Expression is probably never null. - // x7 = u7.p0.p2 ?? x7; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u7.p0.p2").WithLocation(65, 14), // (66,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x7 = u7.p0.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u7.p0.p1").WithLocation(66, 14), - // (67,14): hidden CS8607: Expression is probably never null. - // x7 = v7.p0.p2 ?? x7; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "v7.p0.p2").WithLocation(67, 14), // (68,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x7 = v7.p0.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v7.p0.p1").WithLocation(68, 14), - // (75,14): hidden CS8607: Expression is probably never null. - // x8 = v8.p0.p1 ?? x8; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "v8.p0.p1").WithLocation(75, 14), // (76,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x8 = v8.p0.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v8.p0.p2").WithLocation(76, 14), - // (83,14): hidden CS8607: Expression is probably never null. - // x9 = v9.p1 ?? x9; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "v9.p1").WithLocation(83, 14), // (84,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x9 = v9.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v9.p2").WithLocation(84, 14), @@ -25487,9 +25219,6 @@ class CL1 " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (14,14): hidden CS8607: Expression is probably never null. - // x3 = new {F1 = x3}.F1 ?? x3; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new {F1 = x3}.F1").WithLocation(14, 14) ); } @@ -25610,13 +25339,7 @@ static void F(string x, string y) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); - comp.VerifyDiagnostics( - // (5,13): hidden CS8607: Expression is probably never null. - // x = new { x, y }.x ?? x; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new { x, y }.x").WithLocation(5, 13), - // (6,13): hidden CS8607: Expression is probably never null. - // y = new { x, y = y }.y ?? y; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new { x, y = y }.y").WithLocation(6, 13)); + comp.VerifyDiagnostics(); } [Fact] @@ -25697,16 +25420,16 @@ static void F(T? x, T? y) where T : struct comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = new { x = x, y = y }.x.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { x = x, y = y }.x.Value").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { x = x, y = y }.x").WithLocation(6, 13), // (9,13): warning CS8629: Nullable value type may be null. // _ = new { x = y, y = x }.y.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { x = y, y = x }.y.Value").WithLocation(9, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { x = y, y = x }.y").WithLocation(9, 13), // (10,13): warning CS8629: Nullable value type may be null. // _ = new { x, y }.x.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { x, y }.x.Value").WithLocation(10, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { x, y }.x").WithLocation(10, 13), // (12,13): warning CS8629: Nullable value type may be null. // _ = new { y, x }.x.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { y, x }.x.Value").WithLocation(12, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { y, x }.x").WithLocation(12, 13)); } [Fact] @@ -25763,17 +25486,13 @@ static void F() where T : struct } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); - // https://github.com/dotnet/roslyn/issues/33577: Should not report a warning re-assigning `a`. comp.VerifyDiagnostics( // (9,13): warning CS8629: Nullable value type may be null. // _ = a.y.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "a.y.Value").WithLocation(9, 13), - // (12,13): warning CS8619: Nullability of reference types in value of type '' doesn't match target type ''. - // a = new { x, y }; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new { x, y }").WithArguments("", "").WithLocation(12, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "a.y").WithLocation(9, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = a.x.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "a.x.Value").WithLocation(13, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "a.x").WithLocation(13, 13)); } [Fact] @@ -25987,9 +25706,6 @@ void Test2() " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (14,9): hidden CS8607: Expression is probably never null. - // this?.Test1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "this").WithLocation(14, 9) ); } @@ -26148,18 +25864,18 @@ struct S1 " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (12,14): warning CS8601: Possible null reference assignment. - // P1 = x1; - Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x1").WithLocation(12, 14), // (34,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = P3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "P3").WithLocation(34, 14), // (22,14): error CS8079: Use of possibly unassigned auto-implemented property 'P2' // x2 = P2; Diagnostic(ErrorCode.ERR_UseDefViolationProperty, "P2").WithArguments("P2").WithLocation(22, 14), - // (56,14): hidden CS8607: Expression is probably never null. - // x5 = P5.F1 ?? x5; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "P5.F1").WithLocation(56, 14) + // (22,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // x2 = P2; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "P2").WithLocation(22, 14), + // (12,14): warning CS8601: Possible null reference assignment. + // P1 = x1; + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x1").WithLocation(12, 14) ); } @@ -27371,49 +27087,49 @@ public void LambdaReturnValue_NestedNullability_Invariant() var source0 = @"public class A { - public static object F; -}"; + public static B F; +} +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"using System; -class B { } class C { static T F(Func f) => throw null!; - static B Create(T t) => throw null!; static void F(B x, B y) { - var z = Create(A.F)/*T:B!*/; + var z = A.F/*T:B!*/; F(i => { switch (i) { case 0: return x; default: return x; }})/*T:B!*/; F(i => { switch (i) { case 0: return x; default: return y; }})/*T:B!*/; // 1 - F(i => { switch (i) { case 0: return x; default: return z; }})/*T:B*/; + F(i => { switch (i) { case 0: return x; default: return z; }})/*T:B!*/; F(i => { switch (i) { case 0: return y; default: return x; }})/*T:B!*/; // 2 F(i => { switch (i) { case 0: return y; default: return y; }})/*T:B!*/; - F(i => { switch (i) { case 0: return y; default: return z; }})/*T:B*/; - F(i => { switch (i) { case 0: return z; default: return x; }})/*T:B*/; - F(i => { switch (i) { case 0: return z; default: return y; }})/*T:B*/; - F(i => { switch (i) { case 0: return z; default: return z; }})/*T:B*/; - F(i => { switch (i) { case 0: return x; case 1: return y; default: return z; }})/*T:B*/; // 3 - F(i => { switch (i) { case 0: return z; case 1: return y; default: return x; }})/*T:B*/; // 4 + F(i => { switch (i) { case 0: return y; default: return z; }})/*T:B!*/; + F(i => { switch (i) { case 0: return z; default: return x; }})/*T:B!*/; + F(i => { switch (i) { case 0: return z; default: return y; }})/*T:B!*/; + F(i => { switch (i) { case 0: return z; default: return z; }})/*T:B!*/; + F(i => { switch (i) { case 0: return x; case 1: return y; default: return z; }})/*T:B!*/; // 3 + F(i => { switch (i) { case 0: return z; case 1: return y; default: return x; }})/*T:B!*/; // 4 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( - // (11,46): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // F(i => { switch (i) { case 0: return x; default: return y; }})/*T:B*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(11, 46), - // (13,65): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // F(i => { switch (i) { case 0: return y; default: return x; }})/*T:B*/; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(13, 65), - // (19,46): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // F(i => { switch (i) { case 0: return x; case 1: return y; default: return z; }})/*T:B*/; // 3 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(19, 46), - // (20,83): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // F(i => { switch (i) { case 0: return z; case 1: return y; default: return x; }})/*T:B*/; // 4 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(20, 83) + // (9,46): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // F(i => { switch (i) { case 0: return x; default: return y; }})/*T:B!*/; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(9, 46), + // (11,65): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // F(i => { switch (i) { case 0: return y; default: return x; }})/*T:B!*/; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(11, 65), + // (17,46): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // F(i => { switch (i) { case 0: return x; case 1: return y; default: return z; }})/*T:B*/; // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(17, 46), + // (18,83): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // F(i => { switch (i) { case 0: return z; case 1: return y; default: return x; }})/*T:B*/; // 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(18, 83) ); comp.VerifyTypes(); } @@ -27425,72 +27141,72 @@ public void LambdaReturnValue_NestedNullability_Variant_01() var source0 = @"public class A { - public static object F; -}"; + public static I F; + public static IIn FIn; + public static IOut FOut; +} +public interface I { } +public interface IIn { } +public interface IOut { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"using System; -interface I { } -interface IIn { } -interface IOut { } class C { static T F(Func f) => throw null!; - static I CreateI(T t) => throw null!; static void F1(I x, I y) { - var z = CreateI(A.F)/*T:I!*/; + var z = A.F/*T:I!*/; F(b => { if (b) return x; else return x; })/*T:I!*/; - F(b => { if (b) return x; else return y; })/*T:I!*/; - F(b => { if (b) return x; else return z; })/*T:I*/; - F(b => { if (b) return y; else return x; })/*T:I!*/; + F(b => { if (b) return x; else return y; })/*T:I!*/; // 1 + F(b => { if (b) return x; else return z; })/*T:I!*/; + F(b => { if (b) return y; else return x; })/*T:I!*/; // 2 F(b => { if (b) return y; else return y; })/*T:I!*/; - F(b => { if (b) return y; else return z; })/*T:I*/; - F(b => { if (b) return z; else return x; })/*T:I*/; - F(b => { if (b) return z; else return y; })/*T:I*/; - F(b => { if (b) return z; else return z; })/*T:I*/; + F(b => { if (b) return y; else return z; })/*T:I!*/; + F(b => { if (b) return z; else return x; })/*T:I!*/; + F(b => { if (b) return z; else return y; })/*T:I!*/; + F(b => { if (b) return z; else return z; })/*T:I!*/; } - static IIn CreateIIn(T t) => throw null!; static void F2(IIn x, IIn y) { - var z = CreateIIn(A.F)/*T:IIn!*/; + var z = A.FIn/*T:IIn!*/; F(b => { if (b) return x; else return x; })/*T:IIn!*/; F(b => { if (b) return x; else return y; })/*T:IIn!*/; - F(b => { if (b) return x; else return z; })/*T:IIn*/; + F(b => { if (b) return x; else return z; })/*T:IIn!*/; F(b => { if (b) return y; else return x; })/*T:IIn!*/; F(b => { if (b) return y; else return y; })/*T:IIn!*/; - F(b => { if (b) return y; else return z; })/*T:IIn*/; - F(b => { if (b) return z; else return x; })/*T:IIn*/; - F(b => { if (b) return z; else return y; })/*T:IIn*/; - F(b => { if (b) return z; else return z; })/*T:IIn*/; + F(b => { if (b) return y; else return z; })/*T:IIn!*/; + F(b => { if (b) return z; else return x; })/*T:IIn!*/; + F(b => { if (b) return z; else return y; })/*T:IIn!*/; + F(b => { if (b) return z; else return z; })/*T:IIn!*/; } - static IOut CreateIOut(T t) => throw null!; static void F3(IOut x, IOut y) { - var z = CreateIOut(A.F)/*T:IOut!*/; + var z = A.FOut/*T:IOut!*/; F(b => { if (b) return x; else return x; })/*T:IOut!*/; F(b => { if (b) return x; else return y; })/*T:IOut!*/; - F(b => { if (b) return x; else return z; })/*T:IOut*/; + F(b => { if (b) return x; else return z; })/*T:IOut!*/; F(b => { if (b) return y; else return x; })/*T:IOut!*/; F(b => { if (b) return y; else return y; })/*T:IOut!*/; - F(b => { if (b) return y; else return z; })/*T:IOut*/; - F(b => { if (b) return z; else return x; })/*T:IOut*/; - F(b => { if (b) return z; else return y; })/*T:IOut*/; - F(b => { if (b) return z; else return z; })/*T:IOut*/; + F(b => { if (b) return y; else return z; })/*T:IOut!*/; + F(b => { if (b) return z; else return x; })/*T:IOut!*/; + F(b => { if (b) return z; else return y; })/*T:IOut!*/; + F(b => { if (b) return z; else return z; })/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( - // (13,47): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. - // F(b => { if (b) return x; else return y; })/*T:I!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(13, 47), - // (15,32): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. - // F(b => { if (b) return y; else return x; })/*T:I!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(15, 32) + // (9,47): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + // F(b => { if (b) return x; else return y; })/*T:I!*/; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(9, 47), + // (11,32): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. + // F(b => { if (b) return y; else return x; })/*T:I!*/; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(11, 32) ); } @@ -27502,35 +27218,35 @@ public void LambdaReturnValue_NestedNullability_Variant_02() var source0 = @"public class A { - public static object F; -}"; + public static B F; +} +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"using System; -class B { } class C { - static B CreateB(T t) => throw null!; static Func CreateFunc(T t) => throw null!; static void F(B x, B y) { - var z = CreateB(A.F)/*T:B!*/; - var f = CreateFunc(y)/*Func>!*/; - f = i => { switch (i) { case 0: return x; default: return x; }}; - f = i => { switch (i) { case 0: return x; default: return y; }}; - f = i => { switch (i) { case 0: return x; default: return z; }}; - f = i => { switch (i) { case 0: return y; default: return x; }}; + var f = CreateFunc(y)/*Func!>!*/; + var z = A.F/*T:B!*/; + f = i => { switch (i) { case 0: return x; default: return x; }}; // 1 2 + f = i => { switch (i) { case 0: return x; default: return y; }}; // 3 + f = i => { switch (i) { case 0: return x; default: return z; }}; // 4 + f = i => { switch (i) { case 0: return y; default: return x; }}; // 5 f = i => { switch (i) { case 0: return y; default: return y; }}; f = i => { switch (i) { case 0: return y; default: return z; }}; - f = i => { switch (i) { case 0: return z; default: return x; }}; + f = i => { switch (i) { case 0: return z; default: return x; }}; // 6 f = i => { switch (i) { case 0: return z; default: return y; }}; f = i => { switch (i) { case 0: return z; default: return z; }}; - f = i => { switch (i) { case 0: return x; case 1: return y; default: return z; }}; - f = i => { switch (i) { case 0: return z; case 1: return y; default: return x; }}; - var g = CreateFunc(z)/*Func>*/; + f = i => { switch (i) { case 0: return x; case 1: return y; default: return z; }}; // 7 + f = i => { switch (i) { case 0: return z; case 1: return y; default: return x; }}; // 8 + var g = CreateFunc(z)/*Func!>!*/; g = i => { switch (i) { case 0: return x; default: return x; }}; g = i => { switch (i) { case 0: return x; default: return y; }}; g = i => { switch (i) { case 0: return x; default: return z; }}; @@ -27546,30 +27262,31 @@ static void F(B x, B y) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( + // (9,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // f = i => { switch (i) { case 0: return x; default: return x; }}; // 1 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(9, 48), + // (9,67): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // f = i => { switch (i) { case 0: return x; default: return x; }}; // 1 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(9, 67), + // (10,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // f = i => { switch (i) { case 0: return x; default: return y; }}; // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(10, 48), // (11,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // f = i => { switch (i) { case 0: return x; default: return x; }}; + // f = i => { switch (i) { case 0: return x; default: return z; }}; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(11, 48), - // (11,67): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // f = i => { switch (i) { case 0: return x; default: return x; }}; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(11, 67), - // (12,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // f = i => { switch (i) { case 0: return x; default: return y; }}; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(12, 48), - // (13,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // f = i => { switch (i) { case 0: return x; default: return z; }}; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(13, 48), - // (14,67): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // f = i => { switch (i) { case 0: return y; default: return x; }}; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(14, 67), - // (17,67): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // f = i => { switch (i) { case 0: return z; default: return x; }}; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(17, 67), - // (20,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // f = i => { switch (i) { case 0: return x; case 1: return y; default: return z; }}; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(20, 48), - // (21,85): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // f = i => { switch (i) { case 0: return z; case 1: return y; default: return x; }}; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(21, 85)); + // (12,67): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // f = i => { switch (i) { case 0: return y; default: return x; }}; // 5 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(12, 67), + // (15,67): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // f = i => { switch (i) { case 0: return z; default: return x; }}; // 6 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(15, 67), + // (18,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // f = i => { switch (i) { case 0: return x; case 1: return y; default: return z; }}; // 7 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(18, 48), + // (19,85): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // f = i => { switch (i) { case 0: return z; case 1: return y; default: return x; }}; // 8 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(19, 85) + ); comp.VerifyTypes(); } @@ -27671,6 +27388,27 @@ static void G(object? x) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(9, 45)); } + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33645")] + [WorkItem(33645, "https://github.com/dotnet/roslyn/issues/33645")] + public void ReinferLambdaReturnType() + { + var source = +@"using System; +class C +{ + static T F(Func f) => f(); + static void G(object? x) + { + F(() => x)/*T:object?*/; + if (x == null) return; + F(() => x)/*T:object!*/; + } +}"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + comp.VerifyDiagnostics(); + comp.VerifyTypes(); + } + [Fact] public void IdentityConversion_LambdaReturnType() { @@ -28150,9 +27888,6 @@ static void Main() " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (14,14): hidden CS8607: Expression is probably never null. - // x2 = new T2() ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new T2()").WithLocation(14, 14) ); } @@ -28207,9 +27942,6 @@ public CL0(long x) {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (14,14): hidden CS8607: Expression is probably never null. - // x2 = new CL0((dynamic)0) ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new CL0((dynamic)0)").WithLocation(14, 14) ); } @@ -28293,11 +28025,7 @@ public CL0 this[long x] } " }, options: WithNonNullTypesTrue()); - c.VerifyDiagnostics( - // (14,14): hidden CS8607: Expression is probably never null. - // x2 = x2[(dynamic)0] ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2[(dynamic)0]").WithLocation(14, 14) - ); + c.VerifyDiagnostics(); } [Fact] @@ -28466,9 +28194,6 @@ public int this[long x] " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (14,14): hidden CS8607: Expression is probably never null. - // x2 = x2[(dynamic)0] ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2[(dynamic)0]").WithLocation(14, 14) ); } @@ -28509,9 +28234,6 @@ public long this[long x] " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (14,14): hidden CS8607: Expression is probably never null. - // x2 = x2[(dynamic)0] ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2[(dynamic)0]").WithLocation(14, 14) ); } @@ -28577,9 +28299,9 @@ public long this[long x] " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (22,22): warning CS8603: Possible null reference return. + // (22,22): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // get { return default(T); } - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T)").WithLocation(22, 22) + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(22, 22) ); } @@ -28720,9 +28442,6 @@ public CL0 M1(long x) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (14,14): hidden CS8607: Expression is probably never null. - // x2 = x2.M1((dynamic)0) ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2.M1((dynamic)0)").WithLocation(14, 14) ); } @@ -28884,9 +28603,6 @@ public int M1(long x) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (14,14): hidden CS8607: Expression is probably never null. - // x2 = x2.M1((dynamic)0) ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2.M1((dynamic)0)").WithLocation(14, 14) ); } @@ -28925,9 +28641,6 @@ public long M1(long x) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (14,14): hidden CS8607: Expression is probably never null. - // x2 = x2.M1((dynamic)0) ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2.M1((dynamic)0)").WithLocation(14, 14) ); } @@ -28990,9 +28703,9 @@ public long M1(long x) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (22,16): warning CS8603: Possible null reference return. + // (22,16): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // return default(T); - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T)").WithLocation(22, 16) + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(22, 16) ); } @@ -29081,14 +28794,18 @@ public void DynamicMemberAccess_02() { static void M(dynamic x) { - x.F/*T:dynamic*/.ToString(); + x.F/*T:dynamic!*/.ToString(); var y = x.F; - y/*T:dynamic*/.ToString(); + y/*T:dynamic!*/.ToString(); y = null; } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNonNullTypesTrue()); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // y = null; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 13) + ); comp.VerifyTypes(); } @@ -29127,9 +28844,6 @@ public CL0(long x) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (16,18): hidden CS8607: Expression is probably never null. - // CL0 z2 = new CL0(x2) ?? y2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new CL0(x2)").WithLocation(16, 18) ); } @@ -29179,9 +28893,6 @@ void Test2(string x2, string? y2) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (16,14): hidden CS8607: Expression is probably never null. - // x2 = z2 ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z2").WithLocation(16, 14) ); } @@ -29208,9 +28919,6 @@ void Test2(string x2, string? y2) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (15,14): hidden CS8607: Expression is probably never null. - // x2 = $"{y2}" ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, @"$""{y2}""").WithLocation(15, 14) ); } @@ -29237,9 +28945,6 @@ void Test2(System.Action x2) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (15,14): hidden CS8607: Expression is probably never null. - // x2 = new System.Action(Main) ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new System.Action(Main)").WithLocation(15, 14) ); } @@ -29421,9 +29126,9 @@ static void G() var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29844: Should not warn for `b`, `e`, `h`. comp.VerifyDiagnostics( - // (7,37): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (7,37): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // static void F(out T t) { t = default; } - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(7, 37), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(7, 37), // (10,23): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(out object? t)' doesn't match the target delegate 'D'. // D a = F; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t", "void C.F(out object? t)", "D").WithLocation(10, 23), @@ -29447,7 +29152,8 @@ static void G() Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(out IOut t)", "D>").WithLocation(16, 29), // (17,30): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(out IOut t)' doesn't match the target delegate 'D>'. // D> h = F>; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(out IOut t)", "D>").WithLocation(17, 30)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(out IOut t)", "D>").WithLocation(17, 30) + ); } [Fact] @@ -29550,9 +29256,6 @@ void Test2(System.Type x2) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (15,14): hidden CS8607: Expression is probably never null. - // x2 = typeof(C) ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "typeof(C)").WithLocation(15, 14) ); } @@ -29669,7 +29372,8 @@ static void Main() comp.VerifyDiagnostics( // (6,9): warning CS8602: Possible dereference of a null reference. // s.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9) + ); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); @@ -29701,15 +29405,22 @@ static void F() new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( + // (5,17): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // var s = default(T); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(5, 17), // (6,9): warning CS8602: Possible dereference of a null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9), + // (7,17): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // var t = default(T?); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T?)").WithArguments("T").WithLocation(7, 17), // (7,25): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // var t = default(T?); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(7, 25), // (8,9): warning CS8602: Possible dereference of a null reference. // t.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(8, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(8, 9) + ); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); @@ -29818,7 +29529,8 @@ static void Main() comp.VerifyDiagnostics( // (6,9): warning CS8602: Possible dereference of a null reference. // s.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9) + ); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); @@ -29849,12 +29561,13 @@ static void F() parseOptions: TestOptions.Regular8); // https://github.com/dotnet/roslyn/issues/29895: Improve this diagnostic. default is the cause of the error, but is not mentioned in the diagnostic. comp.VerifyDiagnostics( - // (5,15): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (5,15): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // T s = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(5, 15), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(5, 15), // (6,9): warning CS8602: Possible dereference of a null reference. // s.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9) + ); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); @@ -30146,15 +29859,64 @@ public void Discard_02() " + NonNullTypesOn() + @" void F(object o1, object? o2, C o3, C o4) { - _ /*T:object*/ = o1; - _ /*T:object*/ = o2; - _ /*T:C*/ = o3; - _ /*T:C*/ = o4; + _ /*T:object?*/ = o1; + _ /*T:object?*/ = o2; + _ /*T:C?*/ = o3; + _ /*T:C?*/ = o4; } " + NonNullTypesOff() + @" void F(C o) { - _ /*T:C*/ = o; + _ /*T:C?*/ = o; + } +}"; + var comp = CreateCompilation(new[] { source }); + comp.VerifyDiagnostics(); + comp.VerifyTypes(); + } + + [Fact] + public void Discard_03() + { + // https://github.com/dotnet/roslyn/issues/33393 Need to re-infer discards. + // The types below should have non-oblivious type arguments in the expected results. + var source = +@"class C +{ +" + NonNullTypesOn() + @" + void F(bool b, object o1, object? o2, C o3, C o4) + { + _ /*T:object?*/ = (b ? o1 : o2); + _ /*T:C?*/ = (b ? o3 : o4); // 1 + _ /*T:C?*/ = (b ? o4 : o3); // 2 + _ /*T:C?*/ = (b ? o3 : o5); + _ /*T:C?*/ = (b ? o4 : o5); + } +" + NonNullTypesOff() + @" + static C o5 = null; +}"; + var comp = CreateCompilation(new[] { source }); + comp.VerifyDiagnostics( + // (7,40): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. + // _ /*T:C?*/ = (b ? o3 : o4); // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "o4").WithArguments("C", "C").WithLocation(7, 40), + // (8,35): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. + // _ /*T:C?*/ = (b ? o4 : o3); // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "o4").WithArguments("C", "C").WithLocation(8, 35) + ); + comp.VerifyTypes(); + } + + [Fact] + public void Discard_04() + { + var source = +@"class C +{ +" + NonNullTypesOn() + @" + void F(bool b, object o1) + { + (_ /*T:object?*/ = o1) /*T:object!*/.ToString(); } }"; var comp = CreateCompilation(new[] { source }); @@ -30185,9 +29947,6 @@ void Test2(string? x2, string? y2) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (15,21): hidden CS8607: Expression is probably never null. - // string z2 = x2 + y2 ?? ""; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2 + y2").WithLocation(15, 21) ); } @@ -30283,24 +30042,21 @@ class CL2 " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (10,24): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator +(string? x, CL0 y)'. - // CL0? z1 = x1 + y1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y1").WithArguments("y", "CL0 CL0.operator +(string? x, CL0 y)").WithLocation(10, 24), - // (11,18): hidden CS8607: Expression is probably never null. - // CL0 u1 = z1 ?? new CL0(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z1").WithLocation(11, 18), - // (16,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1? CL1.operator +(string x, CL1? y)'. - // CL1 z2 = x2 + y2; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL1? CL1.operator +(string x, CL1? y)").WithLocation(16, 18), - // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. - // CL1 z2 = x2 + y2; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2 + y2").WithLocation(16, 18), - // (21,23): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator +(string? x, CL0 y)'. - // CL2 u3 = x3 + y3 + z3; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y3").WithArguments("y", "CL0 CL0.operator +(string? x, CL0 y)").WithLocation(21, 23), - // (26,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL2 CL2.operator +(CL1 x, CL2 y)'. - // CL2 u4 = x4 + y4 + z4; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4 + y4").WithArguments("x", "CL2 CL2.operator +(CL1 x, CL2 y)").WithLocation(26, 18) + // (10,24): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator +(string? x, CL0 y)'. + // CL0? z1 = x1 + y1; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y1").WithArguments("y", "CL0 CL0.operator +(string? x, CL0 y)").WithLocation(10, 24), + // (16,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1? CL1.operator +(string x, CL1? y)'. + // CL1 z2 = x2 + y2; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL1? CL1.operator +(string x, CL1? y)").WithLocation(16, 18), + // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // CL1 z2 = x2 + y2; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2 + y2").WithLocation(16, 18), + // (21,23): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator +(string? x, CL0 y)'. + // CL2 u3 = x3 + y3 + z3; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y3").WithArguments("y", "CL0 CL0.operator +(string? x, CL0 y)").WithLocation(21, 23), + // (26,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL2 CL2.operator +(CL1 x, CL2 y)'. + // CL2 u4 = x4 + y4 + z4; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4 + y4").WithArguments("x", "CL2 CL2.operator +(CL1 x, CL2 y)").WithLocation(26, 18) ); } @@ -30347,15 +30103,12 @@ public static bool operator false(CL0 x) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'bool CL0.operator false(CL0 x)'. - // CL0? z1 = x1 && y1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "bool CL0.operator false(CL0 x)").WithLocation(10, 19), - // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator &(CL0 x, CL0? y)'. - // CL0? z1 = x1 && y1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL0 CL0.operator &(CL0 x, CL0? y)").WithLocation(10, 19), - // (17,18): hidden CS8607: Expression is probably never null. - // CL0 u2 = z2 ?? new CL0(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z2").WithLocation(17, 18) + // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'bool CL0.operator false(CL0 x)'. + // CL0? z1 = x1 && y1; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "bool CL0.operator false(CL0 x)").WithLocation(10, 19), + // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator &(CL0 x, CL0? y)'. + // CL0? z1 = x1 && y1; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL0 CL0.operator &(CL0 x, CL0? y)").WithLocation(10, 19) ); } @@ -30676,15 +30429,6 @@ void Test8(System.Action x8, System.Action y8) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (15,28): hidden CS8607: Expression is probably never null. - // System.Action u2 = x2 + y2 ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2 + y2").WithLocation(15, 28), - // (25,28): hidden CS8607: Expression is probably never null. - // System.Action u4 = x4 + y4 ?? y4; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x4 + y4").WithLocation(25, 28), - // (35,28): hidden CS8607: Expression is probably never null. - // System.Action u6 = x6 + y6 ?? x6; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x6 + y6").WithLocation(35, 28), // (40,28): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action u7 = x7 + y7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7 + y7").WithLocation(40, 28), @@ -31324,18 +31068,12 @@ class CL4 : CL3 {} // (22,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL2 u3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(22, 18), - // (28,18): hidden CS8607: Expression is probably never null. - // CL3 v4 = u4 ?? new CL3(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u4").WithLocation(28, 18), // (33,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL3 u5 = x5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5").WithLocation(33, 18), // (44,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // dynamic u7 = x7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7").WithLocation(44, 22), - // (50,22): hidden CS8607: Expression is probably never null. - // dynamic v8 = u8 ?? x8; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u8").WithLocation(50, 22), // (55,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object u9 = x9; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x9").WithLocation(55, 21), @@ -31348,9 +31086,6 @@ class CL4 : CL3 {} // (70,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL4 u12 = (CL4)x12; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(CL4)x12").WithLocation(70, 19), - // (76,22): hidden CS8607: Expression is probably never null. - // object v13 = u13 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u13").WithLocation(76, 22), // (81,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // object u14 = x14; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x14").WithLocation(81, 22), @@ -31359,10 +31094,7 @@ class CL4 : CL3 {} Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)x14").WithLocation(82, 23), // (87,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // object u15 = x15; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x15").WithLocation(87, 22), - // (93,22): hidden CS8607: Expression is probably never null. - // object v16 = u16 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u16").WithLocation(93, 22) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x15").WithLocation(87, 22) ); } @@ -31846,9 +31578,6 @@ static void G(ref I x, ref IIn y, ref IOut z) // (8,15): warning CS8620: Argument of type 'I' cannot be used as an input of type 'I' for parameter 'x' in 'void C.G(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // G(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "void C.G(ref I x, ref IIn y, ref IOut z)").WithLocation(8, 15), - // (8,15): warning CS8624: Argument of type 'I' cannot be used as an output of type 'I' for parameter 'x' in 'void C.G(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. - // G(ref x, ref y, ref z); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "x").WithArguments("I", "I", "x", "void C.G(ref I x, ref IIn y, ref IOut z)").WithLocation(8, 15), // (8,22): warning CS8620: Argument of type 'IIn' cannot be used as an input of type 'IIn' for parameter 'y' in 'void C.G(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // G(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn", "IIn", "y", "void C.G(ref I x, ref IIn y, ref IOut z)").WithLocation(8, 22), @@ -31858,16 +31587,12 @@ static void G(ref I x, ref IIn y, ref IOut z) // (12,15): warning CS8620: Argument of type 'I' cannot be used as an input of type 'I' for parameter 'x' in 'void C.F(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // F(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "void C.F(ref I x, ref IIn y, ref IOut z)").WithLocation(12, 15), - // (12,15): warning CS8624: Argument of type 'I' cannot be used as an output of type 'I' for parameter 'x' in 'void C.F(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. - // F(ref x, ref y, ref z); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "x").WithArguments("I", "I", "x", "void C.F(ref I x, ref IIn y, ref IOut z)").WithLocation(12, 15), // (12,22): warning CS8624: Argument of type 'IIn' cannot be used as an output of type 'IIn' for parameter 'y' in 'void C.F(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // F(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "y").WithArguments("IIn", "IIn", "y", "void C.F(ref I x, ref IIn y, ref IOut z)").WithLocation(12, 22), // (12,29): warning CS8620: Argument of type 'IOut' cannot be used as an input of type 'IOut' for parameter 'z' in 'void C.F(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // F(ref x, ref y, ref z); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IOut", "IOut", "z", "void C.F(ref I x, ref IIn y, ref IOut z)").WithLocation(12, 29) - ); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IOut", "IOut", "z", "void C.F(ref I x, ref IIn y, ref IOut z)").WithLocation(12, 29)); } [Fact] @@ -32119,21 +31844,12 @@ class CL1 // (10,21): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0? u1 = ++x1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(10, 21), - // (11,18): hidden CS8607: Expression is probably never null. - // CL0 v1 = u1 ?? new CL0(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 18), - // (12,18): hidden CS8607: Expression is probably never null. - // CL0 w1 = x1 ?? new CL0(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1").WithLocation(12, 18), // (16,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0 u2 = x2++; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(16, 18), // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 u2 = x2++; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2++").WithLocation(16, 18), - // (17,18): hidden CS8607: Expression is probably never null. - // CL0 v2 = x2 ?? new CL0(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2").WithLocation(17, 18), // (21,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u3 = --x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x3").WithLocation(21, 18), @@ -32143,9 +31859,6 @@ class CL1 // (26,19): warning CS8601: Possible null reference assignment. // CL1? u4 = x4--; // Result of increment is nullable, storing it in not nullable parameter. Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x4--").WithLocation(26, 19), - // (27,18): hidden CS8607: Expression is probably never null. - // CL1 v4 = u4 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u4").WithLocation(27, 18), // (32,18): warning CS8601: Possible null reference assignment. // CL1 u5 = --x5; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "--x5").WithLocation(32, 18), @@ -32153,11 +31866,14 @@ class CL1 // CL1 u5 = --x5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x5").WithLocation(32, 18), // (37,9): warning CS8601: Possible null reference assignment. - // x6--; + // x6--; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x6--").WithLocation(37, 9), // (43,9): error CS0165: Use of unassigned local variable 'x7' - // x7--; - Diagnostic(ErrorCode.ERR_UseDefViolation, "x7").WithArguments("x7").WithLocation(43, 9) + // x7--; + Diagnostic(ErrorCode.ERR_UseDefViolation, "x7").WithArguments("x7").WithLocation(43, 9), + // (43,9): warning CS8601: Possible null reference assignment. + // x7--; + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x7--").WithLocation(43, 9) ); } @@ -32227,9 +31943,6 @@ class CL1 // (10,21): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0? u1 = ++x1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(10, 21), - // (11,18): hidden CS8607: Expression is probably never null. - // CL0 v1 = u1 ?? new CL0(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 18), // (16,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0 u2 = x2++; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(16, 18), @@ -32242,9 +31955,6 @@ class CL1 // (26,19): warning CS8601: Possible null reference assignment. // CL1? u4 = x4--; // Result of increment is nullable, storing it in not nullable property. Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x4--").WithLocation(26, 19), - // (27,18): hidden CS8607: Expression is probably never null. - // CL1 v4 = u4 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u4").WithLocation(27, 18), // (32,18): warning CS8601: Possible null reference assignment. // CL1 u5 = --x5; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "--x5").WithLocation(32, 18), @@ -32340,9 +32050,6 @@ public CL1 this[int x] // (10,21): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0? u1 = ++x1[0]; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1[0]").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(10, 21), - // (11,18): hidden CS8607: Expression is probably never null. - // CL0 v1 = u1 ?? new CL0(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 18), // (16,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0 u2 = x2[0]++; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2[0]").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(16, 18), @@ -32355,9 +32062,6 @@ public CL1 this[int x] // (26,19): warning CS8601: Possible null reference assignment. // CL1? u4 = x4[0]--; // Result of increment is nullable, storing it in not nullable parameter. Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x4[0]--").WithLocation(26, 19), - // (27,18): hidden CS8607: Expression is probably never null. - // CL1 v4 = u4 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u4").WithLocation(27, 18), // (32,18): warning CS8601: Possible null reference assignment. // CL1 u5 = --x5[0]; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "--x5[0]").WithLocation(32, 18), @@ -32412,10 +32116,7 @@ void Test5(dynamic x5) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2++").WithLocation(16, 22), // (21,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // dynamic u3 = --x3; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x3").WithLocation(21, 22), - // (27,22): hidden CS8607: Expression is probably never null. - // dynamic v4 = u4 ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u4").WithLocation(27, 22) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x3").WithLocation(21, 22) ); } @@ -32463,10 +32164,7 @@ class B : A Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "C? A.operator ++(A x)").WithLocation(10, 19), // (10,17): warning CS8604: Possible null reference argument for parameter 'x' in 'C.implicit operator B(C x)'. // B? u1 = ++x1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "++x1").WithArguments("x", "C.implicit operator B(C x)").WithLocation(10, 17), - // (11,16): hidden CS8607: Expression is probably never null. - // B v1 = u1 ?? new B(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 16) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "++x1").WithArguments("x", "C.implicit operator B(C x)").WithLocation(10, 17) ); } @@ -32561,10 +32259,7 @@ public static implicit operator Convertible(int i) c.VerifyDiagnostics( // (10,29): warning CS8604: Possible null reference argument for parameter 'c' in 'Convertible.implicit operator int(Convertible c)'. // Convertible? u1 = ++x1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("c", "Convertible.implicit operator int(Convertible c)").WithLocation(10, 29), - // (11,26): hidden CS8607: Expression is probably never null. - // Convertible v1 = u1 ?? new Convertible(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 26) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("c", "Convertible.implicit operator int(Convertible c)").WithLocation(10, 29) ); } @@ -32606,13 +32301,7 @@ public static implicit operator CL0(CL1 x) c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // CL1? u1 = x1 += y1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19), - // (11,18): hidden CS8607: Expression is probably never null. - // CL1 v1 = u1 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 18), - // (12,18): hidden CS8607: Expression is probably never null. - // CL1 w1 = x1 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1").WithLocation(12, 18) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19) ); } @@ -32654,13 +32343,7 @@ public static implicit operator CL0(CL1? x) c.VerifyDiagnostics( // (10,25): warning CS8604: Possible null reference argument for parameter 'y' in 'CL1 CL0.operator +(CL0 x, CL0 y)'. // CL1? u1 = x1 += y1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y1").WithArguments("y", "CL1 CL0.operator +(CL0 x, CL0 y)").WithLocation(10, 25), - // (11,18): hidden CS8607: Expression is probably never null. - // CL1 v1 = u1 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 18), - // (12,18): hidden CS8607: Expression is probably never null. - // CL1 w1 = x1 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1").WithLocation(12, 18) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y1").WithArguments("y", "CL1 CL0.operator +(CL0 x, CL0 y)").WithLocation(10, 25) ); } @@ -32723,12 +32406,6 @@ class CL1 // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0? y)'. // CL1? u1 = x1 += y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0? y)").WithLocation(10, 19), - // (11,18): hidden CS8607: Expression is probably never null. - // CL1 v1 = u1 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 18), - // (12,18): hidden CS8607: Expression is probably never null. - // CL1 w1 = x1 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1").WithLocation(12, 18), // (17,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0? y)'. // CL0 u2 = x2 += y2; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0? y)").WithLocation(17, 18), @@ -32840,12 +32517,6 @@ public static implicit operator CL0(CL1 x) // (29,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // CL0? u4 = x4 += y4; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4 += y4").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(29, 19), - // (30,18): hidden CS8607: Expression is probably never null. - // CL0 v4 = u4 ?? new CL0(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u4").WithLocation(30, 18), - // (31,18): hidden CS8607: Expression is probably never null. - // CL0 w4 = x4 ?? new CL0(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x4").WithLocation(31, 18), // (36,9): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // x5 += y5; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x5 += y5").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(36, 9), @@ -32944,19 +32615,7 @@ public static implicit operator CL0(CL1 x) c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // CL1? u1 = x1 += y1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19), - // (11,18): hidden CS8607: Expression is probably never null. - // CL1 v1 = u1 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 18), - // (12,18): hidden CS8607: Expression is probably never null. - // CL1 w1 = x1 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1").WithLocation(12, 18), - // (18,18): hidden CS8607: Expression is probably never null. - // CL1 v2 = u2 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u2").WithLocation(18, 18), - // (19,18): hidden CS8607: Expression is probably never null. - // CL1 w2 = x2 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2").WithLocation(19, 18) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19) ); } @@ -33023,16 +32682,7 @@ public CL1 this[int x] c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // CL1? u1 = x1[0] += y1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1[0]").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19), - // (11,18): hidden CS8607: Expression is probably never null. - // CL1 v1 = u1 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u1").WithLocation(11, 18), - // (18,18): hidden CS8607: Expression is probably never null. - // CL1 v2 = u2 ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "u2").WithLocation(18, 18), - // (19,18): hidden CS8607: Expression is probably never null. - // CL1 w2 = x2[0] ?? new CL1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2[0]").WithLocation(19, 18) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1[0]").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19) ); } @@ -33199,18 +32849,6 @@ void Test3(System.Action x3) " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (16,28): hidden CS8607: Expression is probably never null. - // System.Action y1 = E1 ?? x1; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "E1").WithLocation(16, 28), - // (20,14): hidden CS8607: Expression is probably never null. - // y1 = z1.E1 ?? x1; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z1.E1").WithLocation(20, 14), - // (27,28): hidden CS8607: Expression is probably never null. - // System.Action y3 = s3.E1 ?? x3; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "s3.E1").WithLocation(27, 28), - // (31,14): hidden CS8607: Expression is probably never null. - // y3 = z3.E1 ?? x3; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z3.E1").WithLocation(31, 14) ); } @@ -33434,27 +33072,21 @@ class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (10,21): hidden CS8607: Expression is probably never null. - // object y1 = x1 as object ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1 as object").WithLocation(10, 21), - // (15,21): hidden CS8607: Expression is probably never null. - // object y2 = x2 as object ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2 as object").WithLocation(15, 21), - // (20,21): warning CS8600: Converting null literal or possible null value to non-nullable type. - // object y3 = x3 as object; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 as object").WithLocation(20, 21), - // (25,21): warning CS8600: Converting null literal or possible null value to non-nullable type. - // object y4 = x4 as object; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x4 as object").WithLocation(25, 21), - // (30,18): warning CS8600: Converting null literal or possible null value to non-nullable type. - // CL1 y5 = x5 as CL1; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5 as CL1").WithLocation(30, 18), - // (35,18): warning CS8600: Converting null literal or possible null value to non-nullable type. - // CL1 y6 = null as CL1; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null as CL1").WithLocation(35, 18), - // (40,18): warning CS8600: Converting null literal or possible null value to non-nullable type. - // CL1 y7 = x7 as CL1; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7 as CL1").WithLocation(40, 18) + // (20,21): warning CS8600: Converting null literal or possible null value to non-nullable type. + // object y3 = x3 as object; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 as object").WithLocation(20, 21), + // (25,21): warning CS8600: Converting null literal or possible null value to non-nullable type. + // object y4 = x4 as object; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x4 as object").WithLocation(25, 21), + // (30,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // CL1 y5 = x5 as CL1; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5 as CL1").WithLocation(30, 18), + // (35,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // CL1 y6 = null as CL1; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null as CL1").WithLocation(35, 18), + // (40,18): warning CS8600: Converting null literal or possible null value to non-nullable type. + // CL1 y7 = x7 as CL1; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7 as CL1").WithLocation(40, 18) ); } @@ -33600,15 +33232,15 @@ System.Collections.Generic.IEnumerable M2() where T : class? } }"; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,22): warning CS8603: Possible null reference return. + // (6,22): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // yield return default; // 1 - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(6, 22), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 22), // (10,22): warning CS8603: Possible null reference return. // yield return default; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(10, 22), - // (14,22): warning CS8603: Possible null reference return. + // (14,22): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // yield return default; // 3 - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(14, 22) + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(14, 22) ); } @@ -33652,9 +33284,6 @@ static System.Collections.Generic.IEnumerable M(object? x) // (6,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // yield return (C)x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)x").WithLocation(6, 22), - // (6,22): warning CS8603: Possible null reference return. - // yield return (C)x; - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(C)x").WithLocation(6, 22), // (8,60): error CS0111: Type 'C' already defines a member called 'M' with the same parameter types // static System.Collections.Generic.IEnumerable M(object? y) Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M").WithArguments("M", "C").WithLocation(8, 60), @@ -33898,9 +33527,6 @@ public void OnCompleted(Action x) { } public bool IsCompleted { get { return true; } } }"; CreateCompilationWithMscorlib45(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (10,20): hidden CS8607: Expression is probably never null. - // object x = await new D() ?? new object(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "await new D()").WithLocation(10, 20) ); } @@ -34185,9 +33811,6 @@ void Test2(ITest28 x2) options: WithNonNullTypesTrue(TestOptions.DebugExe)); compilation.VerifyDiagnostics( - // (15,14): hidden CS8607: Expression is probably never null. - // x2 = new ITest28() ?? x2; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "new ITest28()").WithLocation(15, 14) ); } @@ -34679,9 +34302,6 @@ void Test23(CL0.CL1 c, Action x23) // (18,18): warning CS8601: Possible null reference assignment. // E1 = x11; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x11").WithLocation(18, 18), - // (24,19): hidden CS8607: Expression is probably never null. - // x12 = E1 ?? x12; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "E1").WithLocation(24, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(30, 19), @@ -34694,15 +34314,6 @@ void Test23(CL0.CL1 c, Action x23) // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), - // (21,19): hidden CS8607: Expression is probably never null. - // x22 = c.F1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.F1").WithLocation(21, 19), - // (22,19): hidden CS8607: Expression is probably never null. - // x22 = c.P1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.P1").WithLocation(22, 19), - // (23,19): hidden CS8607: Expression is probably never null. - // x22 = c.M1() ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.M1()").WithLocation(23, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), @@ -34730,15 +34341,6 @@ void Test23(CL0.CL1 c, Action x23) // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), - // (21,19): hidden CS8607: Expression is probably never null. - // x22 = c.F1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.F1").WithLocation(21, 19), - // (22,19): hidden CS8607: Expression is probably never null. - // x22 = c.P1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.P1").WithLocation(22, 19), - // (23,19): hidden CS8607: Expression is probably never null. - // x22 = c.M1() ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.M1()").WithLocation(23, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), @@ -34904,15 +34506,6 @@ void Test23(CL0.CL1 c, Action x23) // (12,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(12, 18), - // (17,19): hidden CS8607: Expression is probably never null. - // x22 = c.F1 ?? x22; // 8 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.F1").WithLocation(17, 19), - // (18,19): hidden CS8607: Expression is probably never null. - // x22 = c.P1 ?? x22; // 9 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.P1").WithLocation(18, 19), - // (19,19): hidden CS8607: Expression is probably never null. - // x22 = c.M1() ?? x22; // 10 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.M1()").WithLocation(19, 19), // (24,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(24, 19), @@ -35042,9 +34635,6 @@ void Test23(CL0.CL1 c, Action x23) // (15,18): warning CS8601: Possible null reference assignment. // E1 = x11; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x11").WithLocation(15, 18), - // (20,19): hidden CS8607: Expression is probably never null. - // x12 = E1 ?? x12; // 3 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "E1").WithLocation(20, 19), // (25,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(25, 19) @@ -35183,9 +34773,6 @@ void Test23(CL0.CL1 c, Action x23) // (15,18): warning CS8601: Possible null reference assignment. // E1 = x11; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x11").WithLocation(15, 18), - // (20,19): hidden CS8607: Expression is probably never null. - // x12 = E1 ?? x12; // 3 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "E1").WithLocation(20, 19), // (25,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(25, 19) @@ -35867,9 +35454,6 @@ void Test23(CL0.CL1 c, Action x23) // (18,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // E1 = x11; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x11").WithLocation(18, 18), - // (24,19): hidden CS8607: Expression is probably never null. - // x12 = E1 ?? x12; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "E1").WithLocation(24, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(30, 19), @@ -35882,15 +35466,6 @@ void Test23(CL0.CL1 c, Action x23) // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), - // (21,19): hidden CS8607: Expression is probably never null. - // x22 = c.F1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.F1").WithLocation(21, 19), - // (22,19): hidden CS8607: Expression is probably never null. - // x22 = c.P1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.P1").WithLocation(22, 19), - // (23,19): hidden CS8607: Expression is probably never null. - // x22 = c.M1() ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.M1()").WithLocation(23, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), @@ -35911,31 +35486,22 @@ void Test23(CL0.CL1 c, Action x23) var expected = new[] { // (13,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.F1 = x21; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(13, 20), + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(13, 20), // (14,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.P1 = x21; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(14, 20), + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(14, 20), // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), - // (21,19): hidden CS8607: Expression is probably never null. - // x22 = c.F1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.F1").WithLocation(21, 19), - // (22,19): hidden CS8607: Expression is probably never null. - // x22 = c.P1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.P1").WithLocation(22, 19), - // (23,19): hidden CS8607: Expression is probably never null. - // x22 = c.M1() ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.M1()").WithLocation(23, 19), + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), // (31,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) }; c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.ToMetadataReference() }, @@ -36060,9 +35626,6 @@ void Test23(CL0.CL1 c, Action x23) // (18,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // E1 = x11; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x11").WithLocation(18, 18), - // (24,19): hidden CS8607: Expression is probably never null. - // x12 = E1 ?? x12; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "E1").WithLocation(24, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(30, 19), @@ -36075,15 +35638,6 @@ void Test23(CL0.CL1 c, Action x23) // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), - // (21,19): hidden CS8607: Expression is probably never null. - // x22 = c.F1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.F1").WithLocation(21, 19), - // (22,19): hidden CS8607: Expression is probably never null. - // x22 = c.P1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.P1").WithLocation(22, 19), - // (23,19): hidden CS8607: Expression is probably never null. - // x22 = c.M1() ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.M1()").WithLocation(23, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), @@ -36111,15 +35665,6 @@ void Test23(CL0.CL1 c, Action x23) // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), - // (21,19): hidden CS8607: Expression is probably never null. - // x22 = c.F1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.F1").WithLocation(21, 19), - // (22,19): hidden CS8607: Expression is probably never null. - // x22 = c.P1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.P1").WithLocation(22, 19), - // (23,19): hidden CS8607: Expression is probably never null. - // x22 = c.M1() ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.M1()").WithLocation(23, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), @@ -36253,9 +35798,6 @@ void Test23(CL0.CL1 c, Action x23) // (18,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // E1 = x11; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x11").WithLocation(18, 18), - // (24,19): hidden CS8607: Expression is probably never null. - // x12 = E1 ?? x12; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "E1").WithLocation(24, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(30, 19), @@ -36268,15 +35810,6 @@ void Test23(CL0.CL1 c, Action x23) // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), - // (21,19): hidden CS8607: Expression is probably never null. - // x22 = c.F1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.F1").WithLocation(21, 19), - // (22,19): hidden CS8607: Expression is probably never null. - // x22 = c.P1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.P1").WithLocation(22, 19), - // (23,19): hidden CS8607: Expression is probably never null. - // x22 = c.M1() ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.M1()").WithLocation(23, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), @@ -36304,15 +35837,6 @@ void Test23(CL0.CL1 c, Action x23) // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), - // (21,19): hidden CS8607: Expression is probably never null. - // x22 = c.F1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.F1").WithLocation(21, 19), - // (22,19): hidden CS8607: Expression is probably never null. - // x22 = c.P1 ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.P1").WithLocation(22, 19), - // (23,19): hidden CS8607: Expression is probably never null. - // x22 = c.M1() ?? x22; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c.M1()").WithLocation(23, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), @@ -36436,6 +35960,7 @@ void Test4() { M4().P1 = null; var x4 = M4().P1 ?? """"; + M4().P1.ToString(); } } @@ -36450,15 +35975,12 @@ class CL1 options: TestOptions.ReleaseDll); c.VerifyDiagnostics( - // (39,9): warning CS8602: Possible dereference of a null reference. - // M3().P1.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3().P1").WithLocation(39, 9), - // (50,19): warning CS8600: Converting null literal or possible null value to non-nullable type. - // M4().P1 = null; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(50, 19), - // (51,18): hidden CS8607: Expression is probably never null. - // var x4 = M4().P1 ?? ""; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "M4().P1").WithLocation(51, 18) + // (39,9): warning CS8602: Possible dereference of a null reference. + // M3().P1.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3().P1").WithLocation(39, 9), + // (50,19): warning CS8600: Converting null literal or possible null value to non-nullable type. + // M4().P1 = null; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(50, 19) ); } @@ -36709,10 +36231,7 @@ class CL1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3.P1").WithLocation(30, 9), // (38,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // M4.P1 = null; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(38, 17), - // (39,18): hidden CS8607: Expression is probably never null. - // var x4 = M4.P1 ?? ""; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "M4.P1").WithLocation(39, 18) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(38, 17) ); } @@ -36816,15 +36335,12 @@ class CL1 options: TestOptions.ReleaseDll); c.VerifyDiagnostics( - // (30,9): warning CS8602: Possible dereference of a null reference. - // M3.P1.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3.P1").WithLocation(30, 9), - // (38,17): warning CS8600: Converting null literal or possible null value to non-nullable type. - // M4.P1 = null; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(38, 17), - // (39,18): hidden CS8607: Expression is probably never null. - // var x4 = M4.P1 ?? ""; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "M4.P1").WithLocation(39, 18) + // (30,9): warning CS8602: Possible dereference of a null reference. + // M3.P1.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3.P1").WithLocation(30, 9), + // (38,17): warning CS8600: Converting null literal or possible null value to non-nullable type. + // M4.P1 = null; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(38, 17) ); } @@ -36903,6 +36419,7 @@ void Test3() void Test4() { var x4 = M4() ?? """"; + M4().ToString(); } [System.Runtime.CompilerServices.NonNullTypes(false)] @@ -36923,10 +36440,7 @@ void Assign() c.VerifyDiagnostics( // (29,9): warning CS8602: Possible dereference of a null reference. // M3().ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3()").WithLocation(29, 9), - // (37,18): hidden CS8607: Expression is probably never null. - // var x4 = M4() ?? ""; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "M4()").WithLocation(37, 18) + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3()").WithLocation(29, 9) ); } @@ -37025,18 +36539,12 @@ class CL1 // (44,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // M4(a4 => {a4.P1 = null;}); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(44, 27), - // (45,28): hidden CS8607: Expression is probably never null. - // M4(b4 => {var x4 = b4.P1 ?? "";}); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "b4.P1").WithLocation(45, 28), // (64,25): warning CS8602: Possible dereference of a null reference. // D3 v31 = b31 => b31.P1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b31.P1").WithLocation(64, 25), // (70,35): warning CS8600: Converting null literal or possible null value to non-nullable type. // D4 u41 = a41 => {a41.P1 = null;}; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(70, 35), - // (71,36): hidden CS8607: Expression is probably never null. - // D4 v41 = b41 => {var x41 = b41.P1 ?? "";}; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "b41.P1").WithLocation(71, 36) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(70, 35) ); } @@ -37554,10 +37062,7 @@ static void F(Person p) // (15,22): warning CS8601: Possible null reference assignment. // p.LastName = null as string; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "null as string").WithLocation(15, 22), - // (16,22): warning CS8601: Possible null reference assignment. - // p.LastName = null as string?; - Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "null as string?").WithLocation(16, 22), - // (16,30): error CS8651: It is not legal to use nullable type 'string?' in an as expression; use the underlying type 'string' instead. + // (16,30): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. // p.LastName = null as string?; Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(16, 30), // (17,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. @@ -37628,9 +37133,6 @@ internal static void F(this string s) // (16,9): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // default(string).F(); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(string)").WithLocation(16, 9), - // (17,11): hidden CS8605: Result of the comparison is possibly always true. - // ((p != null) ? p.MiddleName : null).F(); - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "p != null").WithLocation(17, 11), // (17,10): warning CS8604: Possible null reference argument for parameter 's' in 'void Extensions.F(string s)'. // ((p != null) ? p.MiddleName : null).F(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(p != null) ? p.MiddleName : null").WithArguments("s", "void Extensions.F(string s)").WithLocation(17, 10), @@ -37698,9 +37200,6 @@ static void G(string name) // (18,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // G(default); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(18, 11), - // (19,12): hidden CS8605: Result of the comparison is possibly always true. - // G((p != null) ? p.MiddleName : null); - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "p != null").WithLocation(19, 12), // (19,11): warning CS8604: Possible null reference argument for parameter 'name' in 'void Program.G(string name)'. // G((p != null) ? p.MiddleName : null); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(p != null) ? p.MiddleName : null").WithArguments("name", "void Program.G(string name)").WithLocation(19, 11), @@ -37753,21 +37252,15 @@ class Program // (13,27): warning CS8603: Possible null reference return. // static string F4() => null as string; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null as string").WithLocation(13, 27), - // (14,35): error CS8651: It is not legal to use nullable type 'string?' in an as expression; use the underlying type 'string' instead. + // (14,35): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. // static string F5() => null as string?; Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(14, 35), - // (14,27): warning CS8603: Possible null reference return. - // static string F5() => null as string?; - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null as string?").WithLocation(14, 27), // (15,27): warning CS8603: Possible null reference return. // static string F6() => default(string); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(string)").WithLocation(15, 27), // (16,27): warning CS8603: Possible null reference return. // static string F7() => default; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(16, 27), - // (17,36): hidden CS8605: Result of the comparison is possibly always true. - // static string F8(Person p) => (p != null) ? p.MiddleName : null; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "p != null").WithLocation(17, 36), // (17,35): warning CS8603: Possible null reference return. // static string F8(Person p) => (p != null) ? p.MiddleName : null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(p != null) ? p.MiddleName : null").WithLocation(17, 35), @@ -38036,11 +37529,11 @@ class C static void F(C? x, C y) { var t1 = x ?? y; // 1 - var t2 = y ?? x; // 2 and 3 - var t3 = x! ?? y; // 4 and 5 - var t4 = y! ?? x; // 6 and 7 + var t2 = y ?? x; // 2 + var t3 = x! ?? y; // 3 + var t4 = y! ?? x; // 4 var t5 = x ?? y!; - var t6 = y ?? x!; // 8 + var t6 = y ?? x!; var t7 = x! ?? y!; var t8 = y! ?? x!; } @@ -38050,37 +37543,20 @@ static void F(C? x, C y) // (6,23): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var t1 = x ?? y; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(6, 23), - // (7,18): hidden CS8607: Expression is probably never null. - // var t2 = y ?? x; // 2 and 3 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y").WithLocation(7, 18), // (7,23): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. - // var t2 = y ?? x; // 2 and 3 + // var t2 = y ?? x; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(7, 23), - // (8,18): hidden CS8607: Expression is probably never null. - // var t3 = x! ?? y; // 4 and 5 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x").WithLocation(8, 18), // (8,24): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. - // var t3 = x! ?? y; // 4 and 5 + // var t3 = x! ?? y; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(8, 24), - // (9,18): hidden CS8607: Expression is probably never null. - // var t4 = y! ?? x; // 6 and 7 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y").WithLocation(9, 18), // (9,24): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. - // var t4 = y! ?? x; // 6 and 7 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(9, 24), - // (11,18): hidden CS8607: Expression is probably never null. - // var t6 = y ?? x!; // 8 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y").WithLocation(11, 18), - // (12,18): hidden CS8607: Expression is probably never null. - // var t7 = x! ?? y!; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x").WithLocation(12, 18), - // (13,18): hidden CS8607: Expression is probably never null. - // var t8 = y! ?? x!; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y").WithLocation(13, 18) - ); + // var t4 = y! ?? x; // 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(9, 24)); } - [Fact, WorkItem(30151, "https://github.com/dotnet/roslyn/issues/30151")] + [Fact] + [WorkItem(30151, "https://github.com/dotnet/roslyn/issues/30151")] + [WorkItem(33346, "https://github.com/dotnet/roslyn/issues/33346")] public void SuppressNullableWarning_ArrayInitializer() { var source = @@ -38107,8 +37583,7 @@ static void F(C? x, C y) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(6, 29), // (8,30): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var a2 = new[] { x!, y }; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(8, 30) - ); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(8, 30)); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] @@ -38473,25 +37948,12 @@ static void F2(ref List a, ref List? b, ref List c, ref // (10,22): warning CS8620: Argument of type 'List' cannot be used as an input of type 'List' for parameter 'b' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. // F(ref b, ref c, ref d, ref a); // warn 1, 2, 3 and 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "c").WithArguments("List", "List", "b", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(10, 22), - // (10,22): warning CS8601: Possible null reference assignment. - // F(ref b, ref c, ref d, ref a); // warn 1, 2, 3 and 4 - Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "c").WithLocation(10, 22), - // (10,22): warning CS8624: Argument of type 'List' cannot be used as an output of type 'List' for parameter 'b' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. - // F(ref b, ref c, ref d, ref a); // warn 1, 2, 3 and 4 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "c").WithArguments("List", "List", "b", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(10, 22), // (10,29): warning CS8604: Possible null reference argument for parameter 'c' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)'. // F(ref b, ref c, ref d, ref a); // warn 1, 2, 3 and 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "d").WithArguments("c", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(10, 29), // (10,36): warning CS8620: Argument of type 'List' cannot be used as an input of type 'List' for parameter 'd' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. // F(ref b, ref c, ref d, ref a); // warn 1, 2, 3 and 4 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "a").WithArguments("List", "List", "d", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(10, 36), - // (10,36): warning CS8601: Possible null reference assignment. - // F(ref b, ref c, ref d, ref a); // warn 1, 2, 3 and 4 - Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "a").WithLocation(10, 36), - // (10,36): warning CS8624: Argument of type 'List' cannot be used as an output of type 'List' for parameter 'd' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. - // F(ref b, ref c, ref d, ref a); // warn 1, 2, 3 and 4 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "a").WithArguments("List", "List", "d", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(10, 36) - ); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "a").WithArguments("List", "List", "d", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(10, 36)); } [Fact] @@ -38536,12 +37998,6 @@ static void F2() // (15,22): warning CS8620: Argument of type 'List' cannot be used as an input of type 'List' for parameter 'b' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "c").WithArguments("List", "List", "b", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(15, 22), - // (15,22): warning CS8600: Converting null literal or possible null value to non-nullable type. - // F(ref b, ref c, ref d, ref a); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c").WithLocation(15, 22), - // (15,22): warning CS8624: Argument of type 'List' cannot be used as an output of type 'List' for parameter 'b' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. - // F(ref b, ref c, ref d, ref a); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "c").WithArguments("List", "List", "b", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(15, 22), // (15,29): error CS0165: Use of unassigned local variable 'd' // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.ERR_UseDefViolation, "d").WithArguments("d").WithLocation(15, 29), @@ -38551,12 +38007,6 @@ static void F2() // (15,36): warning CS8620: Argument of type 'List' cannot be used as an input of type 'List' for parameter 'd' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "a").WithArguments("List", "List", "d", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(15, 36), - // (15,36): warning CS8600: Converting null literal or possible null value to non-nullable type. - // F(ref b, ref c, ref d, ref a); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "a").WithLocation(15, 36), - // (15,36): warning CS8624: Argument of type 'List' cannot be used as an output of type 'List' for parameter 'd' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. - // F(ref b, ref c, ref d, ref a); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "a").WithArguments("List", "List", "d", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(15, 36), // (23,15): error CS0165: Use of unassigned local variable 'b' // F(ref b!, ref c!, ref d!, ref a!); Diagnostic(ErrorCode.ERR_UseDefViolation, "b").WithArguments("b").WithLocation(23, 15), @@ -38915,6 +38365,9 @@ static void F3(T3 t3) where T3 : struct }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( + // (5,9): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. + // default(T1).ToString(); // 1 + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T1)").WithArguments("T1").WithLocation(5, 9), // (5,9): warning CS8602: Possible dereference of a null reference. // default(T1).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(T1)").WithLocation(5, 9), @@ -39361,7 +38814,7 @@ static void G(int? i) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // i.Value.ToString(); // warn - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "i.Value").WithLocation(11, 13) + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "i").WithLocation(11, 13) ); } @@ -39393,10 +38846,10 @@ static void G(S? s) comp.VerifyDiagnostics( // (17,13): warning CS8629: Nullable value type may be null. // s.Value.ToString(); // warn - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s.Value").WithLocation(17, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s").WithLocation(17, 13), // (18,13): warning CS8629: Nullable value type may be null. // s.Value.field.Value.ToString(); // warn - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s.Value.field.Value").WithLocation(18, 13) + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s.Value.field").WithLocation(18, 13) ); } @@ -39504,7 +38957,7 @@ static void F1(object x1) if (x1 is string y1) { x1/*T:object!*/.ToString(); - y1/*T:string*/.ToString(); + y1/*T:string!*/.ToString(); } x1/*T:object!*/.ToString(); } @@ -39513,7 +38966,7 @@ static void F2(object? x2) if (x2 is string y2) { x2/*T:object!*/.ToString(); - y2/*T:string*/.ToString(); + y2/*T:string!*/.ToString(); } x2/*T:object?*/.ToString(); // 1 } @@ -39523,7 +38976,7 @@ static void F3(object x3) if (x3 is string y3) { x3/*T:object!*/.ToString(); - y3/*T:string*/.ToString(); + y3/*T:string!*/.ToString(); } x3/*T:object?*/.ToString(); // 3 } @@ -39533,7 +38986,7 @@ static void F4(object? x4) if (x4 is string y4) { x4/*T:object!*/.ToString(); - y4/*T:string*/.ToString(); + y4/*T:string!*/.ToString(); } x4/*T:object!*/.ToString(); } @@ -39661,33 +39114,31 @@ static void F1(object x1) { if (x1 is string y1) { - x1?.ToString(); // 1 - y1?.ToString(); // 2 + x1.ToString(); + x1?.ToString(); + y1.ToString(); + y1?.ToString(); } - x1?.ToString(); // 3 + x1.ToString(); } static void F2(object? x2) { if (x2 is string y2) { - x2?.ToString(); // 4 - y2?.ToString(); // 5 + x2.ToString(); + x2?.ToString(); + y2.ToString(); + y2?.ToString(); } - x2?.ToString(); + x2.ToString(); // 1 } }"; // https://github.com/dotnet/roslyn/issues/30952: `is` declaration does not set not nullable for declared local. var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (7,13): hidden CS8607: Expression is probably never null. - // x1?.ToString(); // 1 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1").WithLocation(7, 13), - // (10,9): hidden CS8607: Expression is probably never null. - // x1?.ToString(); // 3 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1").WithLocation(10, 9), - // (16,13): hidden CS8607: Expression is probably never null. - // x2?.ToString(); // 4 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2").WithLocation(16, 13)); + // (23,9): warning CS8602: Possible dereference of a null reference. + // x2.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(23, 9)); } [Fact] @@ -39722,15 +39173,7 @@ static void F2(T t2) // https://github.com/dotnet/roslyn/issues/30952: `is` declaration does not set not nullable for declared local. var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (9,13): hidden CS8607: Expression is probably never null. - // t1?.ToString(); // 1 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "t1").WithLocation(9, 13), - // (12,9): hidden CS8607: Expression is probably never null. - // t1?.ToString(); // 3 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "t1").WithLocation(12, 9), - // (20,13): hidden CS8607: Expression is probably never null. - // t2?.ToString(); // 4 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "t2").WithLocation(20, 13)); + ); } [Fact] @@ -40376,7 +39819,6 @@ static void G6() where T : U } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); - // https://github.com/dotnet/roslyn/issues/29910: Duplicate WRN_NullAsNonNullable diagnostics at some locations comp.VerifyDiagnostics( // (6,29): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // static void F1(T t = null) where T : class { } @@ -40402,12 +39844,12 @@ static void G6() where T : U // (33,28): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // F6(default); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(33, 28), - // (39,15): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (39,15): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F0(default); // 0 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(39, 15), - // (41,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(39, 15), + // (41,18): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F6(default); // 0 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(41, 18), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(41, 18), // (46,15): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // F0(default); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(46, 15), @@ -40417,15 +39859,15 @@ static void G6() where T : U // (50,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // F6(default); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(50, 18), - // (66,15): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (66,15): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F0(default); // 3 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(66, 15), - // (69,15): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(66, 15), + // (69,15): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F3(default); // 3 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(69, 15), - // (72,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(69, 15), + // (72,18): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F6(default); // 3 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(72, 18), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(72, 18), // (78,15): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // F0(default); // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(78, 15), @@ -40441,21 +39883,21 @@ static void G6() where T : U // (86,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // F6(default); // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(86, 18), - // (91,15): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (91,15): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F0(default); // 5 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(91, 15), - // (93,15): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(91, 15), + // (93,15): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F5(default); // 5 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(93, 15), - // (95,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(93, 15), + // (95,18): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F6(default); // 5 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(95, 18), - // (100,15): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(95, 18), + // (100,15): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F0(default); // 6 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(100, 15), - // (102,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(100, 15), + // (102,18): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // F6(default); // 6 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(102, 18) + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(102, 18) ); // No warnings with C#7.3. @@ -40649,7 +40091,14 @@ class Program comp.VerifyDiagnostics( // (4,37): error CS0266: Cannot implicitly convert type 'T' to 'System.Collections.Generic.IEnumerator'. An explicit conversion exists (are you missing a cast?) // static IEnumerator M() => default(T); - Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "default(T)").WithArguments("T", "System.Collections.Generic.IEnumerator").WithLocation(4, 37)); + Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "default(T)").WithArguments("T", "System.Collections.Generic.IEnumerator").WithLocation(4, 37), + // (4,37): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // static IEnumerator M() => default(T); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(4, 37), + // (4,37): warning CS8603: Possible null reference return. + // static IEnumerator M() => default(T); + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T)").WithLocation(4, 37) + ); } [Fact] @@ -40844,7 +40293,14 @@ static void G(out S s) Diagnostic(ErrorCode.ERR_UseDefViolationField, "s.F").WithArguments("F").WithLocation(7, 20), // (5,17): error CS0177: The out parameter 's' must be assigned to before control leaves the current method // static void G(out S s) - Diagnostic(ErrorCode.ERR_ParamUnassigned, "G").WithArguments("s").WithLocation(5, 17)); + Diagnostic(ErrorCode.ERR_ParamUnassigned, "G").WithArguments("s").WithLocation(5, 17), + // (7,20): warning CS8600: Converting null literal or possible null value to non-nullable type. + // object o = s.F; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s.F").WithLocation(7, 20), + // (8,9): warning CS8602: Possible dereference of a null reference. + // s.F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.F").WithLocation(8, 9) + ); } [Fact] @@ -40870,9 +40326,16 @@ struct S // (7,13): error CS0170: Use of possibly unassigned field 'F' // c = s.F; Diagnostic(ErrorCode.ERR_UseDefViolationField, "s.F").WithArguments("F").WithLocation(7, 13), + // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // c = s.F; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s.F").WithLocation(7, 13), + // (8,9): warning CS8602: Possible dereference of a null reference. + // s.F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.F").WithLocation(8, 9), // (13,17): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value null // internal C? F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "null").WithLocation(13, 17)); + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "null").WithLocation(13, 17) + ); } [Fact] @@ -40907,9 +40370,16 @@ struct S // (14,17): error CS0170: Use of possibly unassigned field 'F' // o = s.F; Diagnostic(ErrorCode.ERR_UseDefViolationField, "s.F").WithArguments("F").WithLocation(14, 17), + // (14,17): warning CS8600: Converting null literal or possible null value to non-nullable type. + // o = s.F; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s.F").WithLocation(14, 17), // (16,13): error CS0170: Use of possibly unassigned field 'G' // o = s.G; - Diagnostic(ErrorCode.ERR_UseDefViolationField, "s.G").WithArguments("G").WithLocation(16, 13)); + Diagnostic(ErrorCode.ERR_UseDefViolationField, "s.G").WithArguments("G").WithLocation(16, 13), + // (16,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // o = s.G; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s.G").WithLocation(16, 13) + ); } [Fact] @@ -41029,7 +40499,14 @@ public void UnassignedStructAutoProperty_Constructor() Diagnostic(ErrorCode.ERR_UseDefViolationProperty, "P").WithArguments("P").WithLocation(6, 13), // (4,5): error CS0843: Auto-implemented property 'S.P' must be fully assigned before control is returned to the caller. // S(out object o) - Diagnostic(ErrorCode.ERR_UnassignedThisAutoProperty, "S").WithArguments("S.P").WithLocation(4, 5)); + Diagnostic(ErrorCode.ERR_UnassignedThisAutoProperty, "S").WithArguments("S.P").WithLocation(4, 5), + // (6,13): warning CS8601: Possible null reference assignment. + // o = P; + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "P").WithLocation(6, 13), + // (7,9): warning CS8602: Possible dereference of a null reference. + // P.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "P").WithLocation(7, 9) + ); } [Fact] @@ -41091,10 +40568,7 @@ void M() comp.VerifyDiagnostics( // (7,9): error CS0120: An object reference is required for the non-static field, method, or property 'S.F' // S.F.ToString(); - Diagnostic(ErrorCode.ERR_ObjectRequired, "S.F").WithArguments("S.F").WithLocation(7, 9), - // (7,9): warning CS8602: Possible dereference of a null reference. - // S.F.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "S.F").WithLocation(7, 9)); + Diagnostic(ErrorCode.ERR_ObjectRequired, "S.F").WithArguments("S.F").WithLocation(7, 9)); } [Fact] @@ -41235,12 +40709,12 @@ class C // (6,39): warning CS8603: Possible null reference return. // static async Task F1() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(6, 39), - // (8,43): warning CS8603: Possible null reference return. + // (8,43): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // static async Task F3() { return default; } - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(8, 43), - // (9,43): warning CS8603: Possible null reference return. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(8, 43), + // (9,43): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // static async Task F4() { return default(T); } - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T)").WithLocation(9, 43), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(9, 43), // (10,59): warning CS8603: Possible null reference return. // static async Task F5() where T : class { return null; } Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(10, 59), @@ -41250,9 +40724,9 @@ class C // (13,40): warning CS8603: Possible null reference return. // static async Task? G1() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(13, 40), - // (14,44): warning CS8603: Possible null reference return. + // (14,44): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // static async Task? G3() { return default; } - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(14, 44) + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(14, 44) ); } @@ -41298,6 +40772,62 @@ static void M() Diagnostic(ErrorCode.ERR_ValueCantBeNull, "(S)null").WithArguments("S").WithLocation(6, 15)); } + [Fact] + public void NullCastToUnannotatableReferenceTypedTypeParameter() + { + var source = +@"struct S { } +class C +{ + static T M1() where T: class? + { + return (T)null; // 1 + } + static T M2() where T: C? + { + return (T)null; // 2 + } + static T M3() where T: class? + { + return null; // 3 + } + static T M4() where T: C? + { + return null; // 4 + } + static T M5() where T: class? + { + return (T)null!; + } + static T M6() where T: C? + { + return (T)null!; + } + static T M7() where T: class? + { + return null!; + } + static T M8() where T: C? + { + return null!; + } +}"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + comp.VerifyDiagnostics( + // (6,16): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. + // return (T)null; // 1 + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "(T)null").WithArguments("T").WithLocation(6, 16), + // (10,16): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. + // return (T)null; // 2 + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "(T)null").WithArguments("T").WithLocation(10, 16), + // (14,16): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. + // return null; // 3 + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(14, 16), + // (18,16): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. + // return null; // 4 + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(18, 16)); + } + [Fact] public void LiftedUserDefinedConversion() { @@ -41328,6 +40858,30 @@ static void F(A? x, A? y) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, ".F").WithLocation(17, 11)); } + [Fact] + public void LiftedBinaryOperator() + { + var source = +@"struct A +{ + public static A operator +(A a1, A a2) => throw null!; +} +class C2 +{ + static void F(A? x, A? y) + { + var sum1 = (x + y)/*T:A?*/; + sum1.ToString(); + if (x == null || y == null) return; + var sum2 = (x + y)/*T:A?*/; + sum2.ToString(); + } +}"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + comp.VerifyTypes(); + comp.VerifyDiagnostics(); + } + [Fact] public void GroupBy() { @@ -41865,9 +41419,19 @@ static void F5(U u) where U : T // (64,22): warning CS8619: Nullability of reference types in value of type '(T u, T)' doesn't match target type '(T, T)'. // (T, T) t5 = (u, default(T)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(u, default(T))").WithArguments("(T u, T)", "(T, T)").WithLocation(64, 22), + // (64,26): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // (T, T) t5 = (u, default(T)); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(64, 26), // (65,31): warning CS8619: Nullability of reference types in value of type '(object?, object? u)' doesn't match target type '(object, object)'. // (object, object) v5 = (default(T), u); // 21 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default(T), u)").WithArguments("(object?, object? u)", "(object, object)").WithLocation(65, 31)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default(T), u)").WithArguments("(object?, object? u)", "(object, object)").WithLocation(65, 31), + // (65,32): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // (object, object) v5 = (default(T), u); // 21 + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(65, 32), + // (66,34): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // (object?, object?) w5 = (default(T), u); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(66, 34) + ); } [Fact] @@ -41943,9 +41507,19 @@ static void F5(U u) where U : T // (36,23): warning CS8619: Nullability of reference types in value of type '(T u, T)' doesn't match target type '(T, T)?'. // (T, T)? t5 = (u, default(T)); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(u, default(T))").WithArguments("(T u, T)", "(T, T)?").WithLocation(36, 23), + // (36,27): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // (T, T)? t5 = (u, default(T)); // 9 + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(36, 27), // (37,32): warning CS8619: Nullability of reference types in value of type '(object?, object? u)' doesn't match target type '(object, object)?'. // (object, object)? v5 = (default(T), u); // 10 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default(T), u)").WithArguments("(object?, object? u)", "(object, object)?").WithLocation(37, 32)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default(T), u)").WithArguments("(object?, object? u)", "(object, object)?").WithLocation(37, 32), + // (37,33): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // (object, object)? v5 = (default(T), u); // 10 + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(37, 33), + // (38,35): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // (object?, object?)? w5 = (default(T), u); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(38, 35) + ); } [Fact] @@ -42099,21 +41673,31 @@ static void F5(T t) where U : T // (36,18): warning CS8619: Nullability of reference types in value of type '(U t, U)' doesn't match target type '(U, U)'. // var t5 = ((U, U))(t, default(T)); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((U, U))(t, default(T))").WithArguments("(U t, U)", "(U, U)").WithLocation(36, 18), - // (36,27): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (36,27): warning CS8601: Possible null reference assignment. + // var t5 = ((U, U))(t, default(T)); // 9 + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t").WithLocation(36, 27), + // (36,30): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // var t5 = ((U, U))(t, default(T)); // 9 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(36, 27), - // (36,30): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(36, 30), + // (36,30): warning CS8601: Possible null reference assignment. // var t5 = ((U, U))(t, default(T)); // 9 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(36, 30), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "default(T)").WithLocation(36, 30), // (37,18): warning CS8619: Nullability of reference types in value of type '(object?, object? t)' doesn't match target type '(object, object)'. // var v5 = ((object, object))(default(T), t); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((object, object))(default(T), t)").WithArguments("(object?, object? t)", "(object, object)").WithLocation(37, 18), + // (37,37): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // var v5 = ((object, object))(default(T), t); // 10 + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(37, 37), // (37,37): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v5 = ((object, object))(default(T), t); // 10 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(37, 37), // (37,49): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v5 = ((object, object))(default(T), t); // 10 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(37, 49)); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(37, 49), + // (38,39): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // var w5 = ((object?, object?))(default(T), t); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(38, 39) + ); } [Fact] @@ -42195,21 +41779,31 @@ static void F5(T t) where U : T // (36,18): warning CS8619: Nullability of reference types in value of type '(U t, U)' doesn't match target type '(U, U)?'. // var t5 = ((U, U)?)(t, default(T)); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((U, U)?)(t, default(T))").WithArguments("(U t, U)", "(U, U)?").WithLocation(36, 18), - // (36,28): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (36,28): warning CS8601: Possible null reference assignment. // var t5 = ((U, U)?)(t, default(T)); // 9 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(36, 28), - // (36,31): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t").WithLocation(36, 28), + // (36,31): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // var t5 = ((U, U)?)(t, default(T)); // 9 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(36, 31), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(36, 31), + // (36,31): warning CS8601: Possible null reference assignment. + // var t5 = ((U, U)?)(t, default(T)); // 9 + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "default(T)").WithLocation(36, 31), // (37,18): warning CS8619: Nullability of reference types in value of type '(object?, object? t)' doesn't match target type '(object, object)?'. // var v5 = ((object, object)?)(default(T), t); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((object, object)?)(default(T), t)").WithArguments("(object?, object? t)", "(object, object)?").WithLocation(37, 18), + // (37,38): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // var v5 = ((object, object)?)(default(T), t); // 10 + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(37, 38), // (37,38): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v5 = ((object, object)?)(default(T), t); // 10 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(37, 38), // (37,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v5 = ((object, object)?)(default(T), t); // 10 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(37, 50)); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(37, 50), + // (38,40): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // var w5 = ((object?, object?)?)(default(T), t); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(38, 40) + ); } [Fact] @@ -42600,22 +42194,12 @@ static void G(string x, string? y) // (7,15): warning CS8620: Argument of type '(string, string)' cannot be used as an input of type '(string, string?)' for parameter 't' in 'string C.F(ref (string, string?) t)' due to differences in the nullability of reference types. // F(ref t1).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t1").WithArguments("(string, string)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(7, 15), - // (7,15): warning CS8624: Argument of type '(string, string)' cannot be used as an output of type '(string, string?)' for parameter 't' in 'string C.F(ref (string, string?) t)' due to differences in the nullability of reference types. - // F(ref t1).ToString(); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "t1").WithArguments("(string, string)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(7, 15), // (11,15): warning CS8620: Argument of type '(string?, string)' cannot be used as an input of type '(string, string?)' for parameter 't' in 'string C.F(ref (string, string?) t)' due to differences in the nullability of reference types. // F(ref t3).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t3").WithArguments("(string?, string)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(11, 15), - // (11,15): warning CS8624: Argument of type '(string?, string)' cannot be used as an output of type '(string, string?)' for parameter 't' in 'string C.F(ref (string, string?) t)' due to differences in the nullability of reference types. - // F(ref t3).ToString(); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "t3").WithArguments("(string?, string)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(11, 15), // (13,15): warning CS8620: Argument of type '(string?, string?)' cannot be used as an input of type '(string, string?)' for parameter 't' in 'string C.F(ref (string, string?) t)' due to differences in the nullability of reference types. // F(ref t4).ToString(); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t4").WithArguments("(string?, string?)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(13, 15), - // (13,15): warning CS8624: Argument of type '(string?, string?)' cannot be used as an output of type '(string, string?)' for parameter 't' in 'string C.F(ref (string, string?) t)' due to differences in the nullability of reference types. - // F(ref t4).ToString(); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "t4").WithArguments("(string?, string?)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(13, 15) - ); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t4").WithArguments("(string?, string?)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(13, 15)); } [Fact] @@ -42643,8 +42227,7 @@ static void G() Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "(string?, string) t3").WithArguments("(string?, string)", "(string, string?)", "t", "string C.F(out (string, string?) t)").WithLocation(8, 15), // (9,15): warning CS8624: Argument of type '(string?, string?)' cannot be used as an output of type '(string, string?)' for parameter 't' in 'string C.F(out (string, string?) t)' due to differences in the nullability of reference types. // F(out (string?, string?) t4).ToString(); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "(string?, string?) t4").WithArguments("(string?, string?)", "(string, string?)", "t", "string C.F(out (string, string?) t)").WithLocation(9, 15) - ); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "(string?, string?) t4").WithArguments("(string?, string?)", "(string, string?)", "t", "string C.F(out (string, string?) t)").WithLocation(9, 15)); } [Fact] @@ -43686,7 +43269,10 @@ static void F() comp.VerifyDiagnostics( // (5,31): error CS0165: Use of unassigned local variable 't' // (string, string?) t = t; - Diagnostic(ErrorCode.ERR_UseDefViolation, "t").WithArguments("t").WithLocation(5, 31)); + Diagnostic(ErrorCode.ERR_UseDefViolation, "t").WithArguments("t").WithLocation(5, 31), + // (7,9): warning CS8602: Possible dereference of a null reference. + // t.Item2.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(7, 9)); } [Fact] @@ -43843,17 +43429,16 @@ static void F(C x) if (x.G != null) return; C y = x; x.F.ToString(); - x.G.ToString(); // 1 + x.G.ToString(); // missing warning; see below y.F.ToString(); - y.G.ToString(); // 2 + y.G.ToString(); // missing warning; see below } }"; + // https://github.com/dotnet/roslyn/issues/32703: Not inferring nullability of non-nullable value compared to null + // two warnings should appear once 32703 is fixed. + var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); - // https://github.com/dotnet/roslyn/issues/32703: Not inferring nullability of non-nullable value compared to null (see // 1, 2). - comp.VerifyDiagnostics( - // (13,13): hidden CS8605: Result of the comparison is possibly always true. - // if (x.G != null) return; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "x.G != null").WithLocation(13, 13)); + comp.VerifyDiagnostics(); } [Fact] @@ -43883,9 +43468,7 @@ static void F(S x) var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/32703: Not inferring nullability of non-nullable value compared to null (see // 1, 2). comp.VerifyDiagnostics( - // (12,13): hidden CS8605: Result of the comparison is possibly always true. - // if (x.G != null) return; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "x.G != null").WithLocation(12, 13)); + ); } [Fact] @@ -43915,10 +43498,7 @@ static void F(S? x) }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/32703: Not inferring nullability of non-nullable value compared to null (see //1, 2). - comp.VerifyDiagnostics( - // (13,13): hidden CS8605: Result of the comparison is possibly always true. - // if (x.Value.G != null) return; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "x.Value.G != null").WithLocation(13, 13)); + comp.VerifyDiagnostics(); } [Fact] @@ -43977,7 +43557,8 @@ static void F(int? x) comp.VerifyDiagnostics( // (9,9): warning CS8629: Nullable value type may be null. // y.Value.ToString(); // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(9, 9)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(9, 9) + ); } [Fact] @@ -44033,10 +43614,11 @@ static void F3(long? x3) Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x2").WithArguments("long?", "int?").WithLocation(10, 19), // (11,9): warning CS8629: Nullable value type may be null. // y2.Value.ToString(); // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2.Value").WithLocation(11, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2").WithLocation(11, 9), // (16,19): error CS0266: Cannot implicitly convert type 'long?' to 'int?'. An explicit conversion exists (are you missing a cast?) // int? y3 = x3; // 4 - Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x3").WithArguments("long?", "int?").WithLocation(16, 19)); + Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x3").WithArguments("long?", "int?").WithLocation(16, 19) + ); } [Fact] @@ -44095,10 +43677,11 @@ static void F3(A? a3) Diagnostic(ErrorCode.ERR_NoImplicitConv, "a3").WithArguments("A?", "B?").WithLocation(28, 17), // (29,13): warning CS8629: Nullable value type may be null. // _ = b3.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b3.Value").WithLocation(29, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b3").WithLocation(29, 13), // (30,9): warning CS8602: Possible dereference of a null reference. // b3.Value.F.ToString(); // 7 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b3.Value.F").WithLocation(30, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b3.Value.F").WithLocation(30, 9) + ); } [Fact] @@ -44182,7 +43765,8 @@ static void F(int? x) comp.VerifyDiagnostics( // (9,9): warning CS8629: Nullable value type may be null. // y.Value.ToString(); // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(9, 9)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(9, 9) + ); } [Fact] @@ -44206,7 +43790,8 @@ static void F(long? x) comp.VerifyDiagnostics( // (9,9): warning CS8629: Nullable value type may be null. // y.Value.ToString(); // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(9, 9)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(9, 9) + ); } [Fact] @@ -44280,28 +43865,29 @@ static void F() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1.F").WithLocation(14, 9), // (16,9): warning CS8629: Nullable value type may be null. // u.x.Value.F.ToString(); // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.x.Value").WithLocation(16, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.x").WithLocation(16, 9), // (16,9): warning CS8602: Possible dereference of a null reference. // u.x.Value.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.x.Value.F").WithLocation(16, 9), // (17,9): warning CS8629: Nullable value type may be null. // u.y.Value.F.ToString(); - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.y.Value").WithLocation(17, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.y").WithLocation(17, 9), // (17,9): warning CS8602: Possible dereference of a null reference. // u.y.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.y.Value.F").WithLocation(17, 9), // (18,9): warning CS8629: Nullable value type may be null. // v.Item1.Value.F.ToString(); // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "v.Item1.Value").WithLocation(18, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "v.Item1").WithLocation(18, 9), // (18,9): warning CS8602: Possible dereference of a null reference. // v.Item1.Value.F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v.Item1.Value.F").WithLocation(18, 9), // (19,9): warning CS8629: Nullable value type may be null. // v.Item2.Value.F.ToString(); - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "v.Item2.Value").WithLocation(19, 9), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "v.Item2").WithLocation(19, 9), // (19,9): warning CS8602: Possible dereference of a null reference. // v.Item2.Value.F.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v.Item2.Value.F").WithLocation(19, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v.Item2.Value.F").WithLocation(19, 9) + ); } [Fact] @@ -44447,7 +44033,8 @@ static void F() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(S).F").WithLocation(13, 9), // (14,13): warning CS8629: Nullable value type may be null. // _ = default(S).F/*T:V?*/.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "default(S).F/*T:V?*/.Value").WithLocation(14, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "default(S).F").WithLocation(14, 13) + ); comp.VerifyTypes(); } @@ -44482,7 +44069,8 @@ static void F() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new S().F").WithLocation(13, 9), // (14,13): warning CS8629: Nullable value type may be null. // _ = new S().F/*T:V?*/.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new S().F/*T:V?*/.Value").WithLocation(14, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new S().F").WithLocation(14, 13) + ); comp.VerifyTypes(); } @@ -44540,10 +44128,11 @@ static void F() comp.VerifyDiagnostics( // (12,13): warning CS8629: Nullable value type may be null. // _ = x.F.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.F.Value").WithLocation(12, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.F").WithLocation(12, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = y.F.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.F.Value").WithLocation(13, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.F").WithLocation(13, 13) + ); } [Fact] @@ -44600,10 +44189,11 @@ static void F() comp.VerifyDiagnostics( // (12,13): warning CS8629: Nullable value type may be null. // _ = x.F.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.F.Value").WithLocation(12, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.F").WithLocation(12, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = y.F.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.F.Value").WithLocation(13, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.F").WithLocation(13, 13) + ); } [Fact] @@ -44754,10 +44344,11 @@ static void F3(S x3 = default) where T3 : struct Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2.F").WithLocation(18, 9), // (23,13): warning CS8629: Nullable value type may be null. // _ = x3.F/*T:T3?*/.Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3.F/*T:T3?*/.Value").WithLocation(23, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3.F").WithLocation(23, 13), // (24,13): warning CS8629: Nullable value type may be null. // _ = y3.F/*T:T3?*/.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3.F/*T:T3?*/.Value").WithLocation(24, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3.F").WithLocation(24, 13) + ); comp.VerifyTypes(); } @@ -44840,7 +44431,7 @@ class Program { if (x == null) return; var y = x.Value; - y.F/*T:T*/.ToString(); + y.F/*T:T!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); @@ -45030,7 +44621,8 @@ static void F() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default((object?, string))/*T:(object?, string!)*/.Item2").WithLocation(5, 9), // (6,13): warning CS8629: Nullable value type may be null. // _ = default((int, int?))/*T:(int, int?)*/.Item2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "default((int, int?))/*T:(int, int?)*/.Item2.Value").WithLocation(6, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "default((int, int?))/*T:(int, int?)*/.Item2").WithLocation(6, 13) + ); comp.VerifyTypes(); } @@ -45055,7 +44647,8 @@ static void F1() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new ValueTuple()/*T:(object?, string!)*/.Item2").WithLocation(6, 9), // (7,13): warning CS8629: Nullable value type may be null. // _ = new ValueTuple()/*T:(int, int?)*/.Item2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new ValueTuple()/*T:(int, int?)*/.Item2.Value").WithLocation(7, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new ValueTuple()/*T:(int, int?)*/.Item2").WithLocation(7, 13) + ); comp.VerifyTypes(); } @@ -45111,10 +44704,11 @@ static void F() comp.VerifyDiagnostics( // (7,13): warning CS8629: Nullable value type may be null. // _ = t.Item2.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2.Value").WithLocation(7, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2").WithLocation(7, 13), // (8,13): warning CS8629: Nullable value type may be null. // _ = u.Item2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.Item2.Value").WithLocation(8, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.Item2").WithLocation(8, 13) + ); comp.VerifyTypes(); } @@ -45173,10 +44767,11 @@ static void F1() comp.VerifyDiagnostics( // (8,13): warning CS8629: Nullable value type may be null. // _ = t.Item2.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2.Value").WithLocation(8, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2").WithLocation(8, 13), // (9,13): warning CS8629: Nullable value type may be null. // _ = u.Item2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.Item2.Value").WithLocation(9, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.Item2").WithLocation(9, 13) + ); comp.VerifyTypes(); } @@ -45233,7 +44828,7 @@ static void F((T x, U y, V? z) t = default) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.y").WithLocation(9, 9), // (10,13): warning CS8629: Nullable value type may be null. // _ = t.z/*T:V?*/.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.z/*T:V?*/.Value").WithLocation(10, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.z").WithLocation(10, 13), // (11,9): warning CS8602: Possible dereference of a null reference. // u.x/*T:T*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.x").WithLocation(11, 9), @@ -45242,7 +44837,8 @@ static void F((T x, U y, V? z) t = default) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.y").WithLocation(12, 9), // (13,13): warning CS8629: Nullable value type may be null. // _ = u.z/*T:V?*/.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.z/*T:V?*/.Value").WithLocation(13, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.z").WithLocation(13, 13) + ); comp.VerifyTypes(); } @@ -45287,19 +44883,20 @@ static void F( Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item2").WithLocation(11, 9), // (12,13): warning CS8629: Nullable value type may be null. // _ = x.Item3/*T:V?*/.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.Item3/*T:V?*/.Value").WithLocation(12, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.Item3").WithLocation(12, 13), // (13,9): warning CS8602: Possible dereference of a null reference. // y.Item1/*T:T*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(13, 9), // (15,13): warning CS8629: Nullable value type may be null. // _ = y.Item3/*T:V?*/.Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Item3/*T:V?*/.Value").WithLocation(15, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Item3").WithLocation(15, 13), // (16,9): warning CS8602: Possible dereference of a null reference. // z.Item1/*T:T*/.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.Item1").WithLocation(16, 9), // (18,13): warning CS8629: Nullable value type may be null. // _ = z.Item3/*T:V?*/.Value; // 7 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z.Item3/*T:V?*/.Value").WithLocation(18, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z.Item3").WithLocation(18, 13) + ); comp.VerifyTypes(); } @@ -45465,6 +45062,7 @@ static void F(object? x) [Fact] public void Tuple_OtherMembers_02() { + // https://github.com/dotnet/roslyn/issues/33578 // Cannot test Derived since tuple types are considered sealed and the base type // is dropped: "error CS0509: 'Derived': cannot derive from sealed type '(T, T)'". var source = @@ -45496,8 +45094,8 @@ class C static void F(object? x) { var y = (x, x); - y.F.ToString(); - y.Item2.ToString(); + y.F.ToString(); // 1 + y.Item2.ToString(); // 2 if (x == null) return; var z = (x, x); z.F.ToString(); @@ -45507,10 +45105,10 @@ static void F(object? x) var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), targetFramework: TargetFramework.Mscorlib46); comp.VerifyDiagnostics( // (29,9): warning CS8602: Possible dereference of a null reference. - // y.F.ToString(); + // y.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(29, 9), // (30,9): warning CS8602: Possible dereference of a null reference. - // y.Item2.ToString(); + // y.Item2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item2").WithLocation(30, 9)); } @@ -45877,13 +45475,7 @@ static void M(C c) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.F").WithLocation(12, 9), // (13,9): warning CS8602: Possible dereference of a null reference. // c.P.ToString(); // 4 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.P").WithLocation(13, 9), - // (14,13): hidden CS8606: Result of the comparison is possibly always false. - // if (c.F == null) return; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "c.F == null").WithLocation(14, 13), - // (15,13): hidden CS8606: Result of the comparison is possibly always false. - // if (c.P == null) return; - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "c.P == null").WithLocation(15, 13)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.P").WithLocation(13, 9)); } [Fact] @@ -45906,8 +45498,8 @@ static void F1(object? x1) static void F2() { C c2; - c2 = new C() { F = default }; // 3 - c2 = new C() { F = c2.F }; // 4 + c2 = new C() { F = default }; // 4 + c2 = new C() { F = c2.F }; c2.F.ToString(); // 5 } }"; @@ -45922,12 +45514,9 @@ static void F2() // (12,9): warning CS8602: Possible dereference of a null reference. // c1.F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1.F").WithLocation(12, 9), - // (17,31): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // c2 = new C() { F = default }; // 3 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(17, 31), - // (18,31): warning CS8601: Possible null reference assignment. - // c2 = new C() { F = c2.F }; // 4 - Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "c2.F").WithLocation(18, 31), + // (17,31): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. + // c2 = new C() { F = default }; // 4 + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(17, 31), // (19,9): warning CS8602: Possible dereference of a null reference. // c2.F.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2.F").WithLocation(19, 9)); @@ -46171,6 +45760,9 @@ static void F4(B2 x4, B2? y4) // (19,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B2'. // ((B2?)x1).F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B2?)x1").WithArguments("A", "B2").WithLocation(19, 10), + // (19,10): warning CS8602: Possible dereference of a null reference. + // ((B2?)x1).F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(B2?)x1").WithLocation(19, 10), // (19,9): warning CS8602: Possible dereference of a null reference. // ((B2?)x1).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((B2?)x1).F").WithLocation(19, 9), @@ -46189,6 +45781,9 @@ static void F4(B2 x4, B2? y4) // (24,10): warning CS8619: Nullability of reference types in value of type 'B1' doesn't match target type 'A'. // ((A?)x2).F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A?)x2").WithArguments("B1", "A").WithLocation(24, 10), + // (24,10): warning CS8602: Possible dereference of a null reference. + // ((A?)x2).F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A?)x2").WithLocation(24, 10), // (24,9): warning CS8602: Possible dereference of a null reference. // ((A?)x2).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((A?)x2).F").WithLocation(24, 9), @@ -46204,6 +45799,9 @@ static void F4(B2 x4, B2? y4) // (25,9): warning CS8602: Possible dereference of a null reference. // ((A)y2).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((A)y2).F").WithLocation(25, 9), + // (29,10): warning CS8602: Possible dereference of a null reference. + // ((B2?)x3).F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(B2?)x3").WithLocation(29, 10), // (29,9): warning CS8602: Possible dereference of a null reference. // ((B2?)x3).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((B2?)x3).F").WithLocation(29, 9), @@ -46219,6 +45817,9 @@ static void F4(B2 x4, B2? y4) // (34,10): warning CS8619: Nullability of reference types in value of type 'B2' doesn't match target type 'A'. // ((A?)x4).F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A?)x4").WithArguments("B2", "A").WithLocation(34, 10), + // (34,10): warning CS8602: Possible dereference of a null reference. + // ((A?)x4).F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A?)x4").WithLocation(34, 10), // (35,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((A)y4).F.ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(A)y4").WithLocation(35, 10), @@ -46227,7 +45828,8 @@ static void F4(B2 x4, B2? y4) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A)y4").WithArguments("B2", "A").WithLocation(35, 10), // (35,10): warning CS8602: Possible dereference of a null reference. // ((A)y4).F.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A)y4").WithLocation(35, 10)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A)y4").WithLocation(35, 10) + ); } [Fact] @@ -46619,12 +46221,10 @@ public void ExplicitCast_StaticType() // (3,35): warning CS8600: Converting null literal or possible null value to non-nullable type. // static object F(object? x) => (C)x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)x").WithLocation(3, 35), - // (3,35): warning CS8603: Possible null reference return. - // static object F(object? x) => (C)x; - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(C)x").WithLocation(3, 35), // (4,36): error CS0716: Cannot convert to static type 'C' // static object? G(object? y) => (C?)y; - Diagnostic(ErrorCode.ERR_ConvertToStaticClass, "(C?)y").WithArguments("C").WithLocation(4, 36)); + Diagnostic(ErrorCode.ERR_ConvertToStaticClass, "(C?)y").WithArguments("C").WithLocation(4, 36) + ); } [Fact] @@ -47115,10 +46715,8 @@ static void F(IEnumerable e) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(16, 13), // (19,13): warning CS8602: Possible dereference of a null reference. // z.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(19, 13), - // (20,17): hidden CS8605: Result of the comparison is possibly always true. - // if (z != null) z.ToString(); - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "z != null").WithLocation(20, 17)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(19, 13) + ); } [WorkItem(23493, "https://github.com/dotnet/roslyn/issues/23493")] @@ -47352,7 +46950,17 @@ static void F5(T t2) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IEnumerable)t1").WithLocation(22, 27), // (22,27): warning CS8602: Possible dereference of a null reference. // foreach (var v in (IEnumerable)t1) // 3 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable)t1").WithLocation(22, 27)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable)t1").WithLocation(22, 27), + // (28,27): warning CS8602: Possible dereference of a null reference. + // foreach (var y in (IEnumerable?)t2) // 4 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable?)t2").WithLocation(28, 27), + // (34,27): warning CS8600: Converting null literal or possible null value to non-nullable type. + // foreach (var z in (IEnumerable)t2) // 5 + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IEnumerable)t2").WithLocation(34, 27), + // (34,27): warning CS8602: Possible dereference of a null reference. + // foreach (var z in (IEnumerable)t2) // 5 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable)t2").WithLocation(34, 27) + ); } [Fact] @@ -47372,7 +46980,7 @@ static void F(Enumerable e) foreach (var x in e) // 1 { } - foreach (var y in (IEnumerable?)e) + foreach (var y in (IEnumerable?)e) // 2 { } foreach (var z in (IEnumerable)e) @@ -47381,8 +46989,15 @@ static void F(Enumerable e) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + // Missing diagnostic at `// 1` // https://github.com/dotnet/roslyn/issues/29972: Should report WRN_NullReferenceReceiver using Enumerable.GetEnumerator. - comp.VerifyDiagnostics(); + + comp.VerifyDiagnostics( + // (13,27): warning CS8602: Possible dereference of a null reference. + // foreach (var y in (IEnumerable?)e) // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable?)e").WithLocation(13, 27) + ); } [Fact] @@ -47520,10 +47135,10 @@ static void G(A? x, A y) F(x, z)/*T:A?*/; F(y, x)/*T:A?*/; F(y, y)/*T:A!*/; - F(y, z)/*T:A*/; + F(y, z)/*T:A!*/; F(z, x)/*T:A?*/; - F(z, y)/*T:A*/; - F(z, z)/*T:A*/; + F(z, y)/*T:A!*/; + F(z, z)/*T:A!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); @@ -47574,22 +47189,18 @@ static void G(A? x, A y) { var z = A.F; F(out x, out x)/*T:A?*/; - F(out x, out y)/*T:A!*/; // 1 - F(out x, out z)/*T:A?*/; - F(out y, out x)/*T:A!*/; // 2 + F(out x, out y)/*T:A!*/; + F(out x, out z)/*T:A!*/; + F(out y, out x)/*T:A!*/; F(out y, out y)/*T:A!*/; F(out y, out z)/*T:A!*/; - F(out z, out x)/*T:A?*/; + F(out z, out x)/*T:A!*/; F(out z, out y)/*T:A!*/; - F(out z, out z)/*T:A*/; + F(out z, out z)/*T:A!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); - - // Missing conversion diagnostics - // Tracked by https://github.com/dotnet/roslyn/issues/29958 - comp.VerifyDiagnostics(); } @@ -47600,23 +47211,25 @@ public void TypeInference_LowerBounds_NestedNullability_Variant_01() var source0 = @"public class A { - public static string F; -}"; + public static I F; + public static IIn FIn; + public static IOut FOut; +} +public interface I { } +public interface IIn { } +public interface IOut { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface I { } -interface IIn { } -interface IOut { } -class C +@"class C { static T F(T x, T y) => throw null!; - static I CreateI(T t) => throw null!; static void G1(I x1, I y1) { - var z1 = CreateI(A.F)/*T:I!*/; + var z1 = A.F/*T:I!*/; F(x1, x1)/*T:I!*/; F(x1, y1)/*T:I!*/; // 1 F(x1, z1)/*T:I!*/; @@ -47627,10 +47240,9 @@ static void G1(I x1, I y1) F(z1, y1)/*T:I!*/; F(z1, z1)/*T:I!*/; } - static IIn CreateIIn(T t) => throw null!; static void G2(IIn x2, IIn y2) { - var z2 = CreateIIn(A.F)/*T:IIn!*/; + var z2 = A.FIn/*T:IIn!*/; F(x2, x2)/*T:IIn!*/; F(x2, y2)/*T:IIn!*/; F(x2, z2)/*T:IIn!*/; @@ -47641,10 +47253,9 @@ static void G2(IIn x2, IIn y2) F(z2, y2)/*T:IIn!*/; F(z2, z2)/*T:IIn!*/; } - static IOut CreateIOut(T t) => throw null!; static void G3(IOut x3, IOut y3) { - var z3 = CreateIOut(A.F)/*T:IOut!*/; + var z3 = A.FOut/*T:IOut!*/; F(x3, x3)/*T:IOut!*/; F(x3, y3)/*T:IOut!*/; F(x3, z3)/*T:IOut!*/; @@ -47659,12 +47270,13 @@ static void G3(IOut x3, IOut y3) var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( - // (12,15): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'I C.F>(I x, I y)'. + // (8,15): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'I C.F>(I x, I y)'. // F(x1, y1)/*T:I!*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "y", "I C.F>(I x, I y)").WithLocation(12, 15), - // (14,11): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'I C.F>(I x, I y)'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "y", "I C.F>(I x, I y)").WithLocation(8, 15), + // (10,11): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'I C.F>(I x, I y)'. // F(y1, x1)/*T:I!*/; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "x", "I C.F>(I x, I y)").WithLocation(14, 11)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "x", "I C.F>(I x, I y)").WithLocation(10, 11) + ); } [Fact] @@ -47674,27 +47286,32 @@ public void TypeInference_LowerBounds_NestedNullability_Variant_02() var source0 = @"public class A { - public static string F; -}"; + public static B F; +} +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface IOut { } +@"public interface IOut { } class C { static T F(T x, T y) => throw null!; static T F(T x, T y, T z) => throw null!; - static IOut CreateIOut(T t, U u) => throw null!; - static void G(string x, string? y) - { - var z = A.F/*T:string*/; - F(CreateIOut(x, x), CreateIOut(x, y))/*T:IOut!*/; - F(CreateIOut(x, x), CreateIOut(x, z))/*T:IOut!*/; - F(CreateIOut(y, x), CreateIOut(x, x))/*T:IOut!*/; + static IOut CreateIOut(B t, B u) => throw null!; + static void G(B x, B y) + { + var z = A.F/*T:B!*/; + var xx = CreateIOut(x, x)/*T:IOut!*/; + var xy = CreateIOut(x, y)/*T:IOut!*/; + var xz = CreateIOut(x, z)/*T:IOut!*/; + F(xx, xy)/*T:IOut!*/; + F(xx, xz)/*T:IOut!*/; + F(CreateIOut(y, x), xx)/*T:IOut!*/; F(CreateIOut(y, z), CreateIOut(z, x))/*T:IOut!*/; - F(CreateIOut(x, x), CreateIOut(x, y), CreateIOut(x, z))/*T:IOut!*/; + F(xx, xy, xz)/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); @@ -47709,23 +47326,26 @@ public void TypeInference_LowerBounds_NestedNullability_Variant_03() var source0 = @"public class A { - public static string F; -}"; + public static I F; + public static IIn FIn; + public static IOut FOut; +} +public interface I { } +public interface IIn { } +public interface IOut { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface I { } -interface IIn { } -interface IOut { } -class C +@"class C { static T F(T x, T y) => throw null!; - static I> Create1(T t) => throw null!; + static I Create1(T t) => throw null!; static void G1(I> x1, I> y1) { - var z1 = Create1(A.F)/*T:I!>!*/; + var z1 = Create1(A.FOut)/*T:I!>!*/; F(x1, x1)/*T:I!>!*/; F(x1, y1)/*T:I!>!*/; // 1 F(x1, z1)/*T:I!>!*/; @@ -47736,10 +47356,10 @@ static void G1(I> x1, I> y1) F(z1, y1)/*T:I!>!*/; F(z1, z1)/*T:I!>!*/; } - static IOut> Create2(T t) => throw null!; + static IOut Create2(T t) => throw null!; static void G2(IOut> x2, IOut> y2) { - var z2 = Create2(A.F)/*T:IOut!>!*/; + var z2 = Create2(A.FIn)/*T:IOut!>!*/; F(x2, x2)/*T:IOut!>!*/; F(x2, y2)/*T:IOut!>!*/; F(x2, z2)/*T:IOut!>!*/; @@ -47750,10 +47370,10 @@ static void G2(IOut> x2, IOut> y2) F(z2, y2)/*T:IOut!>!*/; F(z2, z2)/*T:IOut!>!*/; } - static IIn> Create3(T t) => throw null!; + static IIn Create3(T t) => throw null!; static void G3(IIn> x3, IIn> y3) { - var z3 = Create3(A.F)/*T:IIn!>!*/; + var z3 = Create3(A.FOut)/*T:IIn!>!*/; F(x3, x3)/*T:IIn!>!*/; F(x3, y3)/*T:IIn!>!*/; F(x3, z3)/*T:IIn!>!*/; @@ -47766,14 +47386,15 @@ static void G3(IIn> x3, IIn> y3) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); - comp.VerifyDiagnostics( - // (12,11): warning CS8620: Nullability of reference types in argument of type 'I>' doesn't match target type 'I>' for parameter 'x' in 'I> C.F>>(I> x, I> y)'. - // F(x1, y1)/*T:I!>!*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("I>", "I>", "x", "I> C.F>>(I> x, I> y)").WithLocation(12, 11), - // (14,15): warning CS8620: Nullability of reference types in argument of type 'I>' doesn't match target type 'I>' for parameter 'y' in 'I> C.F>>(I> x, I> y)'. - // F(y1, x1)/*T:I!>!*/; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("I>", "I>", "y", "I> C.F>>(I> x, I> y)").WithLocation(14, 15)); comp.VerifyTypes(); + comp.VerifyDiagnostics( + // (9,11): warning CS8620: Nullability of reference types in argument of type 'I>' doesn't match target type 'I>' for parameter 'x' in 'I> C.F>>(I> x, I> y)'. + // F(x1, y1)/*T:I!>!*/; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("I>", "I>", "x", "I> C.F>>(I> x, I> y)").WithLocation(9, 11), + // (11,15): warning CS8620: Nullability of reference types in argument of type 'I>' doesn't match target type 'I>' for parameter 'y' in 'I> C.F>>(I> x, I> y)'. + // F(y1, x1)/*T:I!>!*/; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("I>", "I>", "y", "I> C.F>>(I> x, I> y)").WithLocation(11, 15) + ); } [Fact] @@ -47782,21 +47403,21 @@ public void TypeInference_ExactBounds_TopLevelNullability_02() var source0 = @"public class A { - public static string F; -}"; + public static B F; +} +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"class B { } -class C +@"class C { static T F(B x, B y) => throw null!; - static B CreateB(T t) => throw null!; static void G(B x, B y) { - var z = CreateB(A.F)/*T:B!*/; + var z = A.F/*T:B!*/; F(x, x)/*T:string?*/; F(x, y)/*T:string!*/; // 1 F(x, z)/*T:string?*/; @@ -47805,18 +47426,19 @@ static void G(B x, B y) F(y, z)/*T:string!*/; F(z, x)/*T:string?*/; F(z, y)/*T:string!*/; - F(z, z)/*T:string*/; + F(z, z)/*T:string!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( - // (10,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'string C.F(B x, B y)'. + // (8,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'string C.F(B x, B y)'. // F(x, y)/*T:string!*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "string C.F(B x, B y)").WithLocation(10, 11), - // (12,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'string C.F(B x, B y)'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "string C.F(B x, B y)").WithLocation(8, 11), + // (10,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'string C.F(B x, B y)'. // F(y, x)/*T:string!*/; // 2 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "string C.F(B x, B y)").WithLocation(12, 14)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "string C.F(B x, B y)").WithLocation(10, 14) + ); } [Fact] @@ -47825,43 +47447,43 @@ public void TypeInference_ExactBounds_NestedNullability() var source0 = @"public class A { - public static object F; -}"; + public static B F; +} +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"class B { } -class Program +@"class Program { static T F(T x, T y, T z) => throw null!; - static B CreateB(T t) => throw null!; static void G(B x, B y) { - var z = CreateB(A.F)/*T:B!*/; + var z = A.F/*T:B!*/; F(x, x, x)/*T:B!*/; - F(x, x, y)/*T:B!*/; + F(x, x, y)/*T:B!*/; // 1 2 F(x, x, z)/*T:B!*/; - F(x, y, x)/*T:B!*/; - F(x, y, y)/*T:B!*/; - F(x, y, z)/*T:B!*/; + F(x, y, x)/*T:B!*/; // 3 4 + F(x, y, y)/*T:B!*/; // 5 + F(x, y, z)/*T:B!*/; // 6 F(x, z, x)/*T:B!*/; - F(x, z, y)/*T:B!*/; + F(x, z, y)/*T:B!*/; // 7 F(x, z, z)/*T:B!*/; - F(y, x, x)/*T:B!*/; - F(y, x, y)/*T:B!*/; - F(y, x, z)/*T:B!*/; - F(y, y, x)/*T:B!*/; + F(y, x, x)/*T:B!*/; // 8 9 + F(y, x, y)/*T:B!*/; // 10 + F(y, x, z)/*T:B!*/; // 11 + F(y, y, x)/*T:B!*/; // 12 F(y, y, y)/*T:B!*/; F(y, y, z)/*T:B!*/; - F(y, z, x)/*T:B!*/; + F(y, z, x)/*T:B!*/; // 13 F(y, z, y)/*T:B!*/; F(y, z, z)/*T:B!*/; F(z, x, x)/*T:B!*/; - F(z, x, y)/*T:B!*/; + F(z, x, y)/*T:B!*/; // 14 F(z, x, z)/*T:B!*/; - F(z, y, x)/*T:B!*/; + F(z, y, x)/*T:B!*/; // 15 F(z, y, y)/*T:B!*/; F(z, y, z)/*T:B!*/; F(z, z, x)/*T:B!*/; @@ -47871,51 +47493,52 @@ static void G(B x, B y) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( + // (8,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. + // F(x, x, y)/*T:B!*/; // 1 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(8, 11), + // (8,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. + // F(x, x, y)/*T:B!*/; // 1 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(8, 14), // (10,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. - // F(x, x, y)/*T:B!*/; + // F(x, y, x)/*T:B!*/; // 3 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(10, 11), - // (10,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. - // F(x, x, y)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(10, 14), + // (10,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. + // F(x, y, x)/*T:B!*/; // 3 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(10, 17), + // (11,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. + // F(x, y, y)/*T:B!*/; // 5 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(11, 11), // (12,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. - // F(x, y, x)/*T:B!*/; + // F(x, y, z)/*T:B!*/; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(12, 11), - // (12,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. - // F(x, y, x)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(12, 17), - // (13,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. - // F(x, y, y)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(13, 11), // (14,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. - // F(x, y, z)/*T:B!*/; + // F(x, z, y)/*T:B!*/; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(14, 11), - // (16,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. - // F(x, z, y)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(16, 11), + // (16,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. + // F(y, x, x)/*T:B!*/; // 8 9 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(16, 14), + // (16,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. + // F(y, x, x)/*T:B!*/; // 8 9 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(16, 17), + // (17,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. + // F(y, x, y)/*T:B!*/; // 10 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(17, 14), // (18,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. - // F(y, x, x)/*T:B!*/; + // F(y, x, z)/*T:B!*/; // 11 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(18, 14), - // (18,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. - // F(y, x, x)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(18, 17), - // (19,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. - // F(y, x, y)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(19, 14), - // (20,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. - // F(y, x, z)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(20, 14), - // (21,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. - // F(y, y, x)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(21, 17), - // (24,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. - // F(y, z, x)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(24, 17), - // (28,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. - // F(z, x, y)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(28, 14), - // (30,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. - // F(z, y, x)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(30, 17)); + // (19,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. + // F(y, y, x)/*T:B!*/; // 12 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(19, 17), + // (22,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. + // F(y, z, x)/*T:B!*/; // 13 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(22, 17), + // (26,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. + // F(z, x, y)/*T:B!*/; // 14 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(26, 14), + // (28,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. + // F(z, y, x)/*T:B!*/; // 15 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(28, 17) + ); comp.VerifyTypes(); } @@ -47925,38 +47548,37 @@ public void TypeInference_ExactAndLowerBounds_TopLevelNullability() var source0 = @"public class A { - public static string F; -}"; + public static B F; +} +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"class B { } -class C +@"class C { static T F(T x, B y) => throw null!; static B CreateB(T t) => throw null!; static void G(string? x, string y) { - var z = A.F/*T:string*/; + var z = A.F /*T:B!*/; F(x, CreateB(x))/*T:string?*/; F(x, CreateB(y))/*T:string?*/; // 1 - F(x, CreateB(z))/*T:string?*/; + F(x, z)/*T:string?*/; F(y, CreateB(x))/*T:string?*/; F(y, CreateB(y))/*T:string!*/; - F(y, CreateB(z))/*T:string*/; - F(z, CreateB(x))/*T:string?*/; - F(z, CreateB(y))/*T:string*/; - F(z, CreateB(z))/*T:string*/; + F(y, z)/*T:string!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( - // (10,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'string? C.F(string? x, B y)'. + // (9,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'string? C.F(string? x, B y)'. // F(x, CreateB(y))/*T:string?*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateB(y)").WithArguments("B", "B", "y", "string? C.F(string? x, B y)").WithLocation(10, 14)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateB(y)").WithArguments("B", "B", "y", "string? C.F(string? x, B y)").WithLocation(9, 14) + ); } [Fact] @@ -47965,40 +47587,44 @@ public void TypeInference_ExactAndUpperBounds_TopLevelNullability() var source0 = @"public class A { - public static string F; -}"; + public static IIn FIn; + public static B FB; +} +public interface IIn { } +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface IIn { } -class B { } -class C +@"class C { static T F(IIn x, B y) => throw null!; static IIn CreateIIn(T t) => throw null!; static B CreateB(T t) => throw null!; static void G(string? x, string y) { - var z = A.F/*T:string*/; + var zin = A.FIn/*T:IIn!*/; + var zb = A.FB/*T:B!*/; F(CreateIIn(x), CreateB(x))/*T:string?*/; F(CreateIIn(x), CreateB(y))/*T:string!*/; - F(CreateIIn(x), CreateB(z))/*T:string*/; + F(CreateIIn(x), zb)/*T:string!*/; F(CreateIIn(y), CreateB(x))/*T:string!*/; // 1 F(CreateIIn(y), CreateB(y))/*T:string!*/; - F(CreateIIn(y), CreateB(z))/*T:string!*/; - F(CreateIIn(z), CreateB(x))/*T:string*/; - F(CreateIIn(z), CreateB(y))/*T:string!*/; - F(CreateIIn(z), CreateB(z))/*T:string*/; + F(CreateIIn(y), zb)/*T:string!*/; + F(zin, CreateB(x))/*T:string!*/; + F(zin, CreateB(y))/*T:string!*/; + F(zin, zb)/*T:string!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); - comp.VerifyTypes(); comp.VerifyDiagnostics( - // (14,25): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'string C.F(IIn x, B y)'. - // F(CreateIIn(y), CreateB(x))/*T:string*/; // 1 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateB(x)").WithArguments("B", "B", "y", "string C.F(IIn x, B y)").WithLocation(14, 25)); + // (13,25): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'string C.F(IIn x, B y)'. + // F(CreateIIn(y), CreateB(x))/*T:string!*/; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateB(x)").WithArguments("B", "B", "y", "string C.F(IIn x, B y)").WithLocation(13, 25) + ); + comp.VerifyTypes(); } [Fact] @@ -48008,41 +47634,40 @@ public void TypeInference_MixedBounds_NestedNullability() var source0 = @"public class A { - public static object F1; - public static string F2; -}"; + public static IIn F1; + public static IOut F2; +} +public interface IIn { } +public interface IOut { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface IIn { } -interface IOut { } -class C +@"class C { static T F(T x, T y) => throw null!; - static IIn CreateIIn(T t, U u) => throw null!; static void F1(bool b, IIn x1, IIn y1) { - var z1 = CreateIIn(A.F1, A.F2)/*T:IIn!*/; + var z1 = A.F1/*T:IIn!*/; F(x1, x1)/*T:IIn!*/; - F(x1, y1)/*T:IIn!*/; + F(x1, y1)/*T:IIn!*/; // 1 F(x1, z1)/*T:IIn!*/; - F(y1, x1)/*T:IIn!*/; + F(y1, x1)/*T:IIn!*/; // 2 F(y1, y1)/*T:IIn!*/; F(y1, z1)/*T:IIn!*/; F(z1, x1)/*T:IIn!*/; F(z1, y1)/*T:IIn!*/; F(z1, z1)/*T:IIn!*/; } - static IOut CreateIOut(T t, U u) => throw null!; static void F2(bool b, IOut x2, IOut y2) { - var z2 = CreateIOut(A.F1, A.F2)/*T:IOut!*/; + var z2 = A.F2/*T:IOut!*/; F(x2, x2)/*T:IOut!*/; - F(x2, y2)/*T:IOut!*/; + F(x2, y2)/*T:IOut!*/; // 3 F(x2, z2)/*T:IOut!*/; - F(y2, x2)/*T:IOut!*/; + F(y2, x2)/*T:IOut!*/; // 4 F(y2, y2)/*T:IOut!*/; F(y2, z2)/*T:IOut!*/; F(z2, x2)/*T:IOut!*/; @@ -48051,22 +47676,21 @@ static void F2(bool b, IOut x2, IOut y2) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); + comp.VerifyTypes(); comp.VerifyDiagnostics( - // (11,15): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'y' in 'IIn C.F>(IIn x, IIn y)'. - // F(x1, y1)/*T:IIn!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("IIn", "IIn", "y", "IIn C.F>(IIn x, IIn y)").WithLocation(11, 15), - // (13,11): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'x' in 'IIn C.F>(IIn x, IIn y)'. - // F(y1, x1)/*T:IIn!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("IIn", "IIn", "x", "IIn C.F>(IIn x, IIn y)").WithLocation(13, 11), - // (25,15): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'y' in 'IOut C.F>(IOut x, IOut y)'. - // F(x2, y2)/*T:IOut!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y2").WithArguments("IOut", "IOut", "y", "IOut C.F>(IOut x, IOut y)").WithLocation(25, 15), - // (27,11): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'x' in 'IOut C.F>(IOut x, IOut y)'. - // F(y2, x2)/*T:IOut!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y2").WithArguments("IOut", "IOut", "x", "IOut C.F>(IOut x, IOut y)").WithLocation(27, 11) - + // (8,15): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'y' in 'IIn C.F>(IIn x, IIn y)'. + // F(x1, y1)/*T:IIn!*/; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("IIn", "IIn", "y", "IIn C.F>(IIn x, IIn y)").WithLocation(8, 15), + // (10,11): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'x' in 'IIn C.F>(IIn x, IIn y)'. + // F(y1, x1)/*T:IIn!*/; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("IIn", "IIn", "x", "IIn C.F>(IIn x, IIn y)").WithLocation(10, 11), + // (21,15): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'y' in 'IOut C.F>(IOut x, IOut y)'. + // F(x2, y2)/*T:IOut!*/; // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y2").WithArguments("IOut", "IOut", "y", "IOut C.F>(IOut x, IOut y)").WithLocation(21, 15), + // (23,11): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'x' in 'IOut C.F>(IOut x, IOut y)'. + // F(y2, x2)/*T:IOut!*/; // 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y2").WithArguments("IOut", "IOut", "x", "IOut C.F>(IOut x, IOut y)").WithLocation(23, 11) ); - comp.VerifyTypes(); } [Fact] @@ -48205,23 +47829,25 @@ public void TypeInference_LowerBounds_NestedNullability_MismatchedNullability() var source0 = @"public class A { - public static object F; - public static string G; -}"; + public static A F; + public static A G; +} +public class A { } +public class B { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"class B { } -class C +@"class C { static T F(T x, T y) => throw null!; - static B CreateB(T t, U u) => throw null!; - static void G(object? t1, object t2, string? u1, string u2) + static B CreateB(A t, A u) => throw null!; + static void G(A t1, A t2, A u1, A u2) { - var t3 = A.F/*T:object*/; - var u3 = A.G/*T:string*/; + var t3 = A.F/*T:A!*/; + var u3 = A.G/*T:A!*/; var x = CreateB(t1, u2)/*T:B!*/; var y = CreateB(t2, u1)/*T:B!*/; var z = CreateB(t1, u3)/*T:B!*/; @@ -48237,18 +47863,19 @@ static void G(object? t1, object t2, string? u1, string u2) var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( - // (14,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B C.F>(B x, B y)'. + // (13,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B C.F>(B x, B y)'. // F(x, y)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B C.F>(B x, B y)").WithLocation(14, 11), - // (14,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B C.F>(B x, B y)'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B C.F>(B x, B y)").WithLocation(13, 11), + // (13,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B C.F>(B x, B y)'. // F(x, y)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "B", "y", "B C.F>(B x, B y)").WithLocation(14, 14), - // (17,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B C.F>(B x, B y)'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "B", "y", "B C.F>(B x, B y)").WithLocation(13, 14), + // (16,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B C.F>(B x, B y)'. // F(y, z)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("B", "B", "y", "B C.F>(B x, B y)").WithLocation(17, 14), - // (18,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B C.F>(B x, B y)'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("B", "B", "y", "B C.F>(B x, B y)").WithLocation(16, 14), + // (17,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B C.F>(B x, B y)'. // F(y, w)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "B", "x", "B C.F>(B x, B y)").WithLocation(18, 11)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "B", "x", "B C.F>(B x, B y)").WithLocation(17, 11) + ); } [Fact] @@ -48257,51 +47884,54 @@ public void TypeInference_UpperBounds_NestedNullability_MismatchedNullability() var source0 = @"public class A { - public static object F; - public static string G; -}"; + public static X F; + public static X G; +} +public interface IIn { } +public class B { } +public class X { } +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = -@"interface IIn { } -class B { } -class C +@"class C { static T F(IIn x, IIn y) => throw null!; - static IIn> CreateB(T t, U u) => throw null!; - static void G(object? t1, object t2, string? u1, string u2) + static IIn> CreateB(X t, X u) => throw null!; + static void G(X t1, X t2, X u1, X u2) { - var t3 = A.F/*T:object*/; - var u3 = A.G/*T:string*/; + var t3 = A.F/*T:X!*/; + var u3 = A.G/*T:X!*/; var x = CreateB(t1, u2)/*T:IIn!>!*/; var y = CreateB(t2, u1)/*T:IIn!>!*/; var z = CreateB(t1, u3)/*T:IIn!>!*/; var w = CreateB(t3, u2)/*T:IIn!>!*/; - F(x, y)/*T:B!*/; + F(x, y)/*T:B!*/; // 1 2 F(x, z)/*T:B!*/; F(x, w)/*T:B!*/; - F(y, z)/*T:B!*/; - F(y, w)/*T:B!*/; + F(y, z)/*T:B!*/; // 3 + F(y, w)/*T:B!*/; // 4 F(w, z)/*T:B!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( - // (15,11): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'x' in 'B C.F>(IIn> x, IIn> y)'. - // F(x, y)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("IIn>", "IIn>", "x", "B C.F>(IIn> x, IIn> y)").WithLocation(15, 11), - // (15,14): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'y' in 'B C.F>(IIn> x, IIn> y)'. - // F(x, y)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn>", "IIn>", "y", "B C.F>(IIn> x, IIn> y)").WithLocation(15, 14), - // (18,14): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'y' in 'B C.F>(IIn> x, IIn> y)'. - // F(y, z)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IIn>", "IIn>", "y", "B C.F>(IIn> x, IIn> y)").WithLocation(18, 14), - // (19,11): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'x' in 'B C.F>(IIn> x, IIn> y)'. - // F(y, w)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn>", "IIn>", "x", "B C.F>(IIn> x, IIn> y)").WithLocation(19, 11)); + // (13,11): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'x' in 'B C.F>(IIn> x, IIn> y)'. + // F(x, y)/*T:B!*/; // 1 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("IIn>", "IIn>", "x", "B C.F>(IIn> x, IIn> y)").WithLocation(13, 11), + // (13,14): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'y' in 'B C.F>(IIn> x, IIn> y)'. + // F(x, y)/*T:B!*/; // 1 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn>", "IIn>", "y", "B C.F>(IIn> x, IIn> y)").WithLocation(13, 14), + // (16,14): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'y' in 'B C.F>(IIn> x, IIn> y)'. + // F(y, z)/*T:B!*/; // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IIn>", "IIn>", "y", "B C.F>(IIn> x, IIn> y)").WithLocation(16, 14), + // (17,11): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'x' in 'B C.F>(IIn> x, IIn> y)'. + // F(y, w)/*T:B!*/; // 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn>", "IIn>", "x", "B C.F>(IIn> x, IIn> y)").WithLocation(17, 11) + ); } [Fact] @@ -48326,12 +47956,13 @@ static void G(IOut x, IOut y) where T : class } [Fact] + [WorkItem(33346, "https://github.com/dotnet/roslyn/issues/33346")] public void TypeInference_LowerBounds_NestedNullability_Arrays() { var source0 = @"public class A { - public static string F; + public static string[] F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); @@ -48343,27 +47974,21 @@ public void TypeInference_LowerBounds_NestedNullability_Arrays() static T F(T x, T y) => throw null!; static void G(string?[] x, string[] y) { - var z = (new[] { A.F })/*T:string[]!*/; + var z = A.F/*T:string[]!*/; F(x, x)/*T:string?[]!*/; - F(x, y)/*T:string![]!*/; + F(x, y)/*T:string?[]!*/; F(x, z)/*T:string?[]!*/; - F(y, x)/*T:string![]!*/; + F(y, x)/*T:string?[]!*/; F(y, y)/*T:string![]!*/; - F(y, z)/*T:string![]!*/; + F(y, z)/*T:string[]!*/; F(z, x)/*T:string?[]!*/; - F(z, y)/*T:string![]!*/; + F(z, y)/*T:string[]!*/; F(z, z)/*T:string[]!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); - comp.VerifyDiagnostics( - // (8,11): warning CS8620: Nullability of reference types in argument of type 'string?[]' doesn't match target type 'string[]' for parameter 'x' in 'string[] C.F(string[] x, string[] y)'. - // F(x, y)/*T:string![]!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("string?[]", "string[]", "x", "string[] C.F(string[] x, string[] y)").WithLocation(8, 11), - // (10,14): warning CS8620: Nullability of reference types in argument of type 'string?[]' doesn't match target type 'string[]' for parameter 'y' in 'string[] C.F(string[] x, string[] y)'. - // F(y, x)/*T:string![]!*/; - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("string?[]", "string[]", "y", "string[] C.F(string[] x, string[] y)").WithLocation(10, 14)); + comp.VerifyDiagnostics(); } [Fact] @@ -48390,73 +48015,68 @@ static void G(IOut x, IOut y) [Fact] public void TypeInference_LowerBounds_NestedNullability_Pointers() { - var source0 = -@"public class A -{ - public static object F; -}"; - var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); - comp0.VerifyDiagnostics(); - var ref0 = comp0.EmitToImageReference(); - var source = @"unsafe class C { static T F(T x, T y) => throw null!; - static T* CreatePointer(T t) => throw null!; - static void G(object?* x, object* y) - { - var z = CreatePointer(A.F)/*T:object**/; - F(x, x)/*T:object?**/; - F(x, y)/*T:object!**/; - F(x, z)/*T:object?**/; - F(y, x)/*T:object!**/; - F(y, y)/*T:object!**/; - F(y, z)/*T:object!**/; - F(z, x)/*T:object?**/; - F(z, y)/*T:object!**/; - F(z, z)/*T:object**/; - } -}"; - var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(TestOptions.UnsafeDebugDll), references: new[] { ref0 }); + static void G(object?* x, object* y) // 1 + { + _ = z/*T:object**/; + F(x, x)/*T:object?**/; // 2 + F(x, y)/*T:object!**/; // 3 + F(x, z)/*T:object?**/; // 4 + F(y, x)/*T:object!**/; // 5 + F(y, y)/*T:object!**/; // 6 + F(y, z)/*T:object!**/; // 7 + F(z, x)/*T:object?**/; // 8 + F(z, y)/*T:object!**/; // 9 + F(z, z)/*T:object**/; // 10 + } + +#nullable disable + + public static object* z = null; // 11 +}"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(TestOptions.UnsafeDebugDll)); comp.VerifyTypes(); comp.VerifyDiagnostics( - // (4,12): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('T') - // static T* CreatePointer(T t) => throw null!; - Diagnostic(ErrorCode.ERR_ManagedAddr, "T*").WithArguments("T").WithLocation(4, 12), - // (5,19): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') + // (4,19): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') // static void G(object?* x, object* y) - Diagnostic(ErrorCode.ERR_ManagedAddr, "object?*").WithArguments("object").WithLocation(5, 19), - // (5,31): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') + Diagnostic(ErrorCode.ERR_ManagedAddr, "object?*").WithArguments("object").WithLocation(4, 19), + // (4,31): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') // static void G(object?* x, object* y) - Diagnostic(ErrorCode.ERR_ManagedAddr, "object*").WithArguments("object").WithLocation(5, 31), - // (8,9): error CS0306: The type 'object*' may not be used as a type argument + Diagnostic(ErrorCode.ERR_ManagedAddr, "object*").WithArguments("object").WithLocation(4, 31), + // (7,9): error CS0306: The type 'object*' may not be used as a type argument // F(x, x)/*T:object?**/; + Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(7, 9), + // (8,9): error CS0306: The type 'object*' may not be used as a type argument + // F(x, y)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(8, 9), // (9,9): error CS0306: The type 'object*' may not be used as a type argument - // F(x, y)/*T:object!**/; + // F(x, z)/*T:object?**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(9, 9), // (10,9): error CS0306: The type 'object*' may not be used as a type argument - // F(x, z)/*T:object?**/; + // F(y, x)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(10, 9), // (11,9): error CS0306: The type 'object*' may not be used as a type argument - // F(y, x)/*T:object!**/; + // F(y, y)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(11, 9), // (12,9): error CS0306: The type 'object*' may not be used as a type argument - // F(y, y)/*T:object!**/; + // F(y, z)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(12, 9), // (13,9): error CS0306: The type 'object*' may not be used as a type argument - // F(y, z)/*T:object!**/; + // F(z, x)/*T:object?**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(13, 9), // (14,9): error CS0306: The type 'object*' may not be used as a type argument - // F(z, x)/*T:object?**/; + // F(z, y)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(14, 9), // (15,9): error CS0306: The type 'object*' may not be used as a type argument - // F(z, y)/*T:object!**/; - Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(15, 9), - // (16,9): error CS0306: The type 'object*' may not be used as a type argument // F(z, z)/*T:object**/; - Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(16, 9)); + Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(15, 9), + // (20,19): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') + // public static object* z = null; + Diagnostic(ErrorCode.ERR_ManagedAddr, "object*").WithArguments("object").WithLocation(20, 19) + ); } [Fact] @@ -48465,9 +48085,13 @@ public void TypeInference_LowerBounds_NestedNullability_Tuples() var source0 = @"public class A { - public static object F; - public static string G; -}"; + public static B F; + public static B G; +} +public class B +{ +} +"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); @@ -48476,17 +48100,18 @@ public void TypeInference_LowerBounds_NestedNullability_Tuples() @"class C { static T F(T x, T y) => throw null!; - static void G(object? t1, object t2, string? u1, string u2) - { - var t3 = A.F/*T:object*/; - var u3 = A.G/*T:string*/; - var x = (t1, u2)/*T:(object? t1, string! u2)*/; - var y = (t2, u1)/*T:(object! t2, string? u1)*/; - var z = (t1, u3)/*T:(object? t1, string u3)*/; - var w = (t3, u2)/*T:(object t3, string! u2)*/; + static (T, U) Create(B t, B u) => throw null!; + static void G(B t1, B t2, B u1, B u2) + { + var t3 = A.F/*T:B!*/; + var u3 = A.G/*T:B!*/; + var x = Create(t1, u2)/*T:(object?, string!)*/; + var y = Create(t2, u1)/*T:(object!, string?)*/; + var z = Create(t1, u3)/*T:(object?, string)*/; + var w = Create(t3, u2)/*T:(object, string!)*/; F(x, y)/*T:(object?, string?)*/; - F(x, z)/*T:(object? t1, string)*/; - F(x, w)/*T:(object?, string! u2)*/; + F(x, z)/*T:(object?, string)*/; + F(x, w)/*T:(object?, string!)*/; F(y, z)/*T:(object?, string?)*/; F(y, w)/*T:(object, string?)*/; F(w, z)/*T:(object?, string)*/; @@ -48602,22 +48227,22 @@ class C static B CreateB(T t, U u) => throw null!; static void G(object? t1, object t2, string? u1, string u2) { - var t3 = A.F/*T:object*/; - var u3 = A.G/*T:string*/; + var t3 = A.F/*T:object!*/; + var u3 = A.G/*T:string!*/; var x0 = CreateB(t1, u2)/*T:B!*/; var y0 = CreateB(t2, u1)/*T:B!*/; - var z0 = CreateB(t1, u3)/*T:B!*/; - var w0 = CreateB(t3, u2)/*T:B!*/; + var z0 = CreateB(t1, u3)/*T:B!*/; + var w0 = CreateB(t3, u2)/*T:B!*/; var x = x0; var y = y0; var z = z0; var w = w0; x = y0; // 1 x = z0; - x = w0; - y = z0; // 2 - y = w0; // 3 - w = z0; + x = w0; // 2 + y = z0; // 3 + y = w0; // 4 + w = z0; // 5 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); @@ -48626,12 +48251,19 @@ static void G(object? t1, object t2, string? u1, string u2) // (17,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // x = y0; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y0").WithArguments("B", "B").WithLocation(17, 13), + // (19,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // x = w0; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w0").WithArguments("B", "B").WithLocation(19, 13), // (20,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // y = z0; // 2 + // y = z0; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "z0").WithArguments("B", "B").WithLocation(20, 13), // (21,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. - // y = w0; // 3 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w0").WithArguments("B", "B").WithLocation(21, 13)); + // y = w0; // 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w0").WithArguments("B", "B").WithLocation(21, 13), + // (22,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. + // w = z0; // 5 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "z0").WithArguments("B", "B").WithLocation(22, 13) + ); } [Fact] @@ -48820,15 +48452,15 @@ public class NotNull static T F(T x, T y) => throw null!; static void F1(UnknownNull x1, UnknownNull y1) { - F(x1.A1, y1.A1)/*T:A*/.F.ToString(); + F(x1.A1, y1.A1)/*T:A!*/.F.ToString(); } static void F2(UnknownNull x2, MaybeNull y2) { - F(x2.A1, y2.A2)/*T:A*/.F.ToString(); + F(x2.A1, y2.A2)/*T:A!*/.F.ToString(); } static void F3(MaybeNull x3, UnknownNull y3) { - F(x3.A2, y3.A1)/*T:A*/.F.ToString(); + F(x3.A2, y3.A1)/*T:A!*/.F.ToString(); } static void F4(MaybeNull x4, MaybeNull y4) { @@ -48836,11 +48468,11 @@ static void F4(MaybeNull x4, MaybeNull y4) } static void F5(UnknownNull x5, NotNull y5) { - F(x5.A1, y5.A3)/*T:A*/.F.ToString(); + F(x5.A1, y5.A3)/*T:A!*/.F.ToString(); } static void F6(NotNull x6, UnknownNull y6) { - F(x6.A3, y6.A1)/*T:A*/.F.ToString(); + F(x6.A3, y6.A1)/*T:A!*/.F.ToString(); } static void F7(MaybeNull x7, NotNull y7) { @@ -48859,11 +48491,11 @@ static void F9(NotNull x9, NotNull y9) comp.VerifyTypes(); comp.VerifyDiagnostics( // (10,9): warning CS8602: Possible dereference of a null reference. - // F(x2.A1, y2.A2)/*T:A*/.F.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x2.A1, y2.A2)/*T:A*/.F").WithLocation(10, 9), + // F(x2.A1, y2.A2)/*T:A!*/.F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x2.A1, y2.A2)/*T:A!*/.F").WithLocation(10, 9), // (14,9): warning CS8602: Possible dereference of a null reference. - // F(x3.A2, y3.A1)/*T:A*/.F.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x3.A2, y3.A1)/*T:A*/.F").WithLocation(14, 9), + // F(x3.A2, y3.A1)/*T:A!*/.F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x3.A2, y3.A1)/*T:A!*/.F").WithLocation(14, 9), // (18,9): warning CS8602: Possible dereference of a null reference. // F(x4.A2, y4.A2)/*T:A!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x4.A2, y4.A2)/*T:A!*/.F").WithLocation(18, 9), @@ -48872,7 +48504,8 @@ static void F9(NotNull x9, NotNull y9) Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x7.A2").WithArguments("A", "A", "x", "A C.F>(A x, A y)").WithLocation(30, 11), // (34,18): warning CS8620: Nullability of reference types in argument of type 'A' doesn't match target type 'A' for parameter 'y' in 'A C.F>(A x, A y)'. // F(x8.A3, y8.A2)/*T:A!*/.F.ToString(); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y8.A2").WithArguments("A", "A", "y", "A C.F>(A x, A y)").WithLocation(34, 18)); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y8.A2").WithArguments("A", "A", "y", "A C.F>(A x, A y)").WithLocation(34, 18) + ); } [Fact] @@ -49245,12 +48878,6 @@ static void G(object x, object? y) new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( - // (6,11): hidden CS8607: Expression is probably never null. - // F(x ?? x).ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x").WithLocation(6, 11), - // (7,11): hidden CS8607: Expression is probably never null. - // F(x ?? y).ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x").WithLocation(7, 11), // (9,9): warning CS8602: Possible dereference of a null reference. // F(y ?? y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y ?? y)").WithLocation(9, 9)); @@ -49300,25 +48927,24 @@ class C static void F(C a, bool c) { - if (c) a.field.ToString(); + if (c) a.field.ToString(); // 1 else if (a.field != null) a.field.ToString(); C b = new C(); - if (c) b.field.ToString(); + if (c) b.field.ToString(); // 2 else if (b.field != null) b.field.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (4,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (4,24): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // internal T field = default; - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(4, 24), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(4, 24), // (8,16): warning CS8602: Possible dereference of a null reference. - // if (c) a.field.ToString(); + // if (c) a.field.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.field").WithLocation(8, 16), // (11,16): warning CS8602: Possible dereference of a null reference. - // if (c) b.field.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.field").WithLocation(11, 16) - ); + // if (c) b.field.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.field").WithLocation(11, 16)); } [Fact] @@ -50445,30 +50071,33 @@ static void F5(T t5) where T : I // (15,9): warning CS8602: Possible dereference of a null reference. // t2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(15, 9), - // (16,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (16,14): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // t2 = default; // 3 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(16, 14), - // (21,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(16, 14), + // (21,14): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // t3 = default; // 6 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(21, 14), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(21, 14), // (25,9): warning CS8602: Possible dereference of a null reference. // t4.P.ToString(); // 7 and 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4").WithLocation(25, 9), // (25,9): warning CS8602: Possible dereference of a null reference. // t4.P.ToString(); // 7 and 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4.P").WithLocation(25, 9), - // (26,16): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (26,16): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // t4.P = default; // 9 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(26, 16), - // (27,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(26, 16), + // (27,14): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // t4 = default; // 10 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(27, 14), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(27, 14), // (31,9): warning CS8602: Possible dereference of a null reference. // t5.P.ToString(); // 11 and 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5.P").WithLocation(31, 9), - // (33,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (32,16): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // t5.P = default; + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(32, 16), + // (33,14): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // t5 = default; // 15 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(33, 14) + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(33, 14) ); } @@ -56600,52 +56229,52 @@ class A var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29981: missing warnings comp.VerifyDiagnostics( - // (45,23): warning CS8603: Possible null reference return. - // static T5 F1() => default; // warn: return type T5 may be non-null - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(45, 23), - // (29,16): warning CS8600: Converting null literal or possible null value to non-nullable type. - // T3 t = (T3)NullableObject(); // warn: T3 may be non-null - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T3)NullableObject()").WithLocation(29, 16), - // (35,23): warning CS8603: Possible null reference return. - // static T4 F1() => default; // warn: return type T4 may be non-null - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(35, 23), - // (24,23): warning CS8603: Possible null reference return. - // static T3 F1() => default; // warn: return type T3 may be non-null - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(24, 23), // (14,23): warning CS8603: Possible null reference return. // static T2 F1() => default; // warn: return type T2 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(14, 23), - // (4,23): warning CS8603: Possible null reference return. + // (4,23): warning CS8652: A default expression introduces a null value when 'T1' is a non-nullable reference type. // static T1 F1() => default; // warn: return type T1 may be non-null - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(4, 23), - // (39,17): warning CS8600: Converting null literal or possible null value to non-nullable type. - // T4 t4 = (T4)NullableObject(); // warn: T4 may be non-null - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T4)NullableObject()").WithLocation(39, 17), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(4, 23), + // (24,23): warning CS8652: A default expression introduces a null value when 'T3' is a non-nullable reference type. + // static T3 F1() => default; // warn: return type T3 may be non-null + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T3").WithLocation(24, 23), + // (35,23): warning CS8652: A default expression introduces a null value when 'T4' is a non-nullable reference type. + // static T4 F1() => default; // warn: return type T4 may be non-null + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T4").WithLocation(35, 23), + // (45,23): warning CS8603: Possible null reference return. + // static T5 F1() => default; // warn: return type T5 may be non-null + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(45, 23), + // (25,23): warning CS8652: A default expression introduces a null value when 'T3' is a non-nullable reference type. + // static T3 F2() => default(T3); // warn: return type T3 may be non-null + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T3)").WithArguments("T3").WithLocation(25, 23), // (46,23): warning CS8603: Possible null reference return. // static T5 F2() => default(T5); // warn: return type T5 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T5)").WithLocation(46, 23), - // (25,23): warning CS8603: Possible null reference return. - // static T3 F2() => default(T3); // warn: return type T3 may be non-null - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T3)").WithLocation(25, 23), - // (36,23): warning CS8603: Possible null reference return. - // static T4 F2() => default(T4); // warn: return type T4 may be non-null - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T4)").WithLocation(36, 23), - // (5,23): warning CS8603: Possible null reference return. - // static T1 F2() => default(T1); // warn: return type T1 may be non-null - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T1)").WithLocation(5, 23), // (15,23): warning CS8603: Possible null reference return. // static T2 F2() => default(T2); // warn: return type T2 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T2)").WithLocation(15, 23), + // (36,23): warning CS8652: A default expression introduces a null value when 'T4' is a non-nullable reference type. + // static T4 F2() => default(T4); // warn: return type T4 may be non-null + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T4)").WithArguments("T4").WithLocation(36, 23), + // (5,23): warning CS8652: A default expression introduces a null value when 'T1' is a non-nullable reference type. + // static T1 F2() => default(T1); // warn: return type T1 may be non-null + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T1)").WithArguments("T1").WithLocation(5, 23), + // (8,17): warning CS8601: Possible null reference assignment. + // T1 t1 = (T1)NullableObject(); // warn: T1 may be non-null + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T1)NullableObject()").WithLocation(8, 17), + // (39,17): warning CS8601: Possible null reference assignment. + // T4 t4 = (T4)NullableObject(); // warn: T4 may be non-null + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T4)NullableObject()").WithLocation(39, 17), + // (29,16): warning CS8601: Possible null reference assignment. + // T3 t = (T3)NullableObject(); // warn: T3 may be non-null + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T3)NullableObject()").WithLocation(29, 16), // (49,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // T5 t5 = (T5)NullableObject(); // warn: T5 may be non-null Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T5)NullableObject()").WithLocation(49, 17), - // (8,17): warning CS8600: Converting null literal or possible null value to non-nullable type. - // T1 t1 = (T1)NullableObject(); // warn: T1 may be non-null - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T1)NullableObject()").WithLocation(8, 17), // (18,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // T2 t2 = (T2)NullableObject(); // warn: T2 may be non-null Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T2)NullableObject()").WithLocation(18, 17) - ); + ); } [Fact] @@ -56878,43 +56507,34 @@ public void UnconstrainedTypeParameter_Return_03() static T F14(U u) where U : class, T => (T)u; static T F15(U u) where U : struct, T => (T)u; static T F16(U u) where U : T, new() => (T)u; - static U F17(T t) where U : T => (U)t; - static U F18(T t) where U : class, T => (U)t; + static U F17(T t) where U : T => (U)t; // W on cast + static U F18(T t) where U : class, T => (U)t; // W on cast, W on return static U F19(T t) where U : struct, T => (U)t; - static U F20(T t) where U : T, new() => (U)t; - static U F21(T t) => (U)(object)t; + static U F20(T t) where U : T, new() => (U)t; // W on cast + static U F21(T t) => (U)(object)t; // W on cast, W on cast }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (19,44): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static U F17(T t) where U : T => (U)t; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)t").WithLocation(19, 44), - // (19,44): warning CS8603: Possible null reference return. - // static U F17(T t) where U : T => (U)t; - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(U)t").WithLocation(19, 44), + // (19,44): warning CS8601: Possible null reference assignment. + // static U F17(T t) where U : T => (U)t; // W on cast + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)t").WithLocation(19, 44), // (20,51): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static U F18(T t) where U : class, T => (U)t; + // static U F18(T t) where U : class, T => (U)t; // W on cast, W on return Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)t").WithLocation(20, 51), // (20,51): warning CS8603: Possible null reference return. - // static U F18(T t) where U : class, T => (U)t; + // static U F18(T t) where U : class, T => (U)t; // W on cast, W on return Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(U)t").WithLocation(20, 51), - // (22,51): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static U F20(T t) where U : T, new() => (U)t; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)t").WithLocation(22, 51), - // (22,51): warning CS8603: Possible null reference return. - // static U F20(T t) where U : T, new() => (U)t; - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(U)t").WithLocation(22, 51), - // (23,32): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static U F21(T t) => (U)(object)t; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)(object)t").WithLocation(23, 32), - // (23,32): warning CS8603: Possible null reference return. - // static U F21(T t) => (U)(object)t; - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(U)(object)t").WithLocation(23, 32), + // (22,51): warning CS8601: Possible null reference assignment. + // static U F20(T t) where U : T, new() => (U)t; // W on cast + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)t").WithLocation(22, 51), + // (23,32): warning CS8601: Possible null reference assignment. + // static U F21(T t) => (U)(object)t; // W on cast, W on cast + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)(object)t").WithLocation(23, 32), // (23,35): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static U F21(T t) => (U)(object)t; + // static U F21(T t) => (U)(object)t; // W on cast, W on cast Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(23, 35) - ); + ); } [Fact] @@ -56959,28 +56579,22 @@ class C var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (4,39): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (4,39): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // static void F1(out T t) => t = default; // 1 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(4, 39), - // (5,39): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(4, 39), + // (5,39): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // static void F2(out T t) => t = default(T); // 2 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T)").WithLocation(5, 39), - // (8,59): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static void F5(U u, out T t) where T : U => t = (T)u; // 3 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)u").WithLocation(8, 59), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(5, 39), // (8,59): warning CS8601: Possible null reference assignment. // static void F5(U u, out T t) where T : U => t = (T)u; // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)u").WithLocation(8, 59), - // (9,47): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static void F6(U u, out T t) => t = (T)(object)u; // 4 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)(object)u").WithLocation(9, 47), // (9,47): warning CS8601: Possible null reference assignment. // static void F6(U u, out T t) => t = (T)(object)u; // 4 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)(object)u").WithLocation(9, 47), // (9,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // static void F6(U u, out T t) => t = (T)(object)u; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)u").WithLocation(9, 50) - ); + ); } [Fact] @@ -57021,13 +56635,16 @@ static void F1(object o, T tin) var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( + // (12,18): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // t1 = default; // 1 + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(12, 18), // (15,9): warning CS8602: Possible dereference of a null reference. // t1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(15, 9), // (25,9): warning CS8602: Possible dereference of a null reference. // t2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(25, 9) - ); + ); } [Fact] @@ -57105,7 +56722,7 @@ class C { static U F1(T t) => (U)(object)t; // 1 and 2 static U F2(T t) where U : class => (U)(object)t; // 3, 4 and 5 - static U F3(T t) where U : struct => (U)(object)t; // 5 + static U F3(T t) where U : struct => (U)(object)t; // 6 static U F4(T t) where T : class => (U)(object)t; static U F5(T t) where T : struct => (U)(object)t; }"; @@ -57114,25 +56731,22 @@ class C // https://github.com/dotnet/roslyn/issues/29993: Errors are different than expected. comp.VerifyDiagnostics( // (4,34): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static U F1(T t) => (U)(object)t; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(4, 34), - // (4,31): warning CS8600: Converting null literal or possible null value to non-nullable type. // static U F1(T t) => (U)(object)t; // 1 and 2 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)(object)t").WithLocation(4, 31), - // (4,31): warning CS8603: Possible null reference return. + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(4, 34), + // (4,31): warning CS8601: Possible null reference assignment. // static U F1(T t) => (U)(object)t; // 1 and 2 - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(U)(object)t").WithLocation(4, 31), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)(object)t").WithLocation(4, 31), // (5,50): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static U F2(T t) where U : class => (U)(object)t; + // static U F2(T t) where U : class => (U)(object)t; // 3, 4 and 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(5, 50), // (5,47): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static U F2(T t) where U : class => (U)(object)t; + // static U F2(T t) where U : class => (U)(object)t; // 3, 4 and 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)(object)t").WithLocation(5, 47), // (5,47): warning CS8603: Possible null reference return. - // static U F2(T t) where U : class => (U)(object)t; + // static U F2(T t) where U : class => (U)(object)t; // 3, 4 and 5 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(U)(object)t").WithLocation(5, 47), // (6,51): warning CS8600: Converting null literal or possible null value to non-nullable type. - // static U F3(T t) where U : struct => (U)(object)t; + // static U F3(T t) where U : struct => (U)(object)t; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(6, 51) ); } @@ -57184,36 +56798,31 @@ static T F4(T x4) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( + // (5,9): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // default(T).ToString(); // warn 1 + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(5, 9), // (5,9): warning CS8602: Possible dereference of a null reference. // default(T).ToString(); // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(T)").WithLocation(5, 9), - // (10,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,9): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // default(T)?.ToString(); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(6, 9), + // (10,16): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // T x1 = default; // warn 2 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(10, 16), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(10, 16), // (11,9): warning CS8602: Possible dereference of a null reference. // x1.ToString(); // warn 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(11, 9), - // (13,9): hidden CS8607: Expression is probably never null. - // x1?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x1").WithLocation(13, 9), - // (14,13): hidden CS8605: Result of the comparison is possibly always true. - // if (x1 != null) x1.ToString(); - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "x1 != null").WithLocation(14, 13), // (20,9): warning CS8602: Possible dereference of a null reference. // x2.ToString(); // warn 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(20, 9), - // (22,9): hidden CS8607: Expression is probably never null. - // x2?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x2").WithLocation(22, 9), - // (23,13): hidden CS8605: Result of the comparison is possibly always true. - // if (x2 != null) x2.ToString(); - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "x2 != null").WithLocation(23, 13), // (26,9): warning CS8602: Possible dereference of a null reference. // a2[0].ToString(); // warn 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a2[0]").WithLocation(26, 9), // (34,9): warning CS8602: Possible dereference of a null reference. // a3[0].ToString(); // warn 6 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a3[0]").WithLocation(34, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a3[0]").WithLocation(34, 9) + ); } [Fact] @@ -57243,10 +56852,8 @@ static void F2(T2 t2) where T2 : class Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t1").WithLocation(8, 11), // (8,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.F(object o)'. // F((object)t1); - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(object)t1").WithArguments("o", "void C.F(object o)").WithLocation(8, 11), - // (14,13): hidden CS8605: Result of the comparison is possibly always true. - // if (t2 != null) F((object)t2); - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "t2 != null").WithLocation(14, 13)); + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(object)t1").WithArguments("o", "void C.F(object o)").WithLocation(8, 11) + ); } [Fact] @@ -57518,6 +57125,9 @@ static void M() // (7,24): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // var u = typeof(U?); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(7, 24), + // (8,21): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. + // object? o = default(T?); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T?)").WithArguments("T").WithLocation(8, 21), // (8,29): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // object? o = default(T?); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 29), @@ -59945,22 +59555,21 @@ void M5() // (8,8): warning CS0414: The field 'A.F' is assigned but its value is never used // T1 F; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "F").WithArguments("A.F").WithLocation(8, 8), - // (15,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (15,17): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 1 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(15, 17), - // (22,13): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(15, 17), + // (22,13): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 2 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(22, 13), + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(22, 13), // (30,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // F = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(30, 17), - // (39,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (39,17): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 4 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(39, 17), - // (48,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(39, 17), + // (48,17): warning CS8654: A null literal introduces a null value when 'T2' is a non-nullable reference type. // F = null; // 5 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(48, 17) - ); + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T2").WithLocation(48, 17)); var b = comp.GetTypeByMetadataName("A`2+B"); Assert.NotNull(b); @@ -60145,19 +59754,21 @@ void M3() // (7,8): warning CS0414: The field 'A.F' is assigned but its value is never used // T1 F; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "F").WithArguments("A.F").WithLocation(7, 8), - // (14,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (14,17): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 1 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 17), + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(14, 17), + // (21,13): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. + // F = null; // 2 + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(21, 13), // (29,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // F = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(29, 17), - // (38,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (38,17): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 4 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(38, 17), - // (47,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(38, 17), + // (47,17): warning CS8654: A null literal introduces a null value when 'T2' is a non-nullable reference type. // F = null; // 5 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(47, 17) - ); + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T2").WithLocation(47, 17)); var b = comp.GetTypeByMetadataName("A`2+B"); Assert.NotNull(b); @@ -62070,15 +61681,24 @@ public static void Test(T x) where T : object "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( - // (29,17): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (20,14): warning CS8652: A default expression introduces a null value when 'T1' is a non-nullable reference type. + // F1 = default; + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(20, 14), + // (21,14): warning CS8652: A default expression introduces a null value when 'T2' is a non-nullable reference type. + // F2 = default; + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T2").WithLocation(21, 14), + // (22,14): warning CS8652: A default expression introduces a null value when 'T3' is a non-nullable reference type. + // F3 = default; + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T3").WithLocation(22, 14), + // (29,17): warning CS8652: A default expression introduces a null value when 'T1' is a non-nullable reference type. // T1 x2 = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(29, 17), - // (30,17): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(29, 17), + // (30,17): warning CS8652: A default expression introduces a null value when 'T2' is a non-nullable reference type. // T2 y2 = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(30, 17), - // (31,17): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T2").WithLocation(30, 17), + // (31,17): warning CS8652: A default expression introduces a null value when 'T3' is a non-nullable reference type. // T3 z2 = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(31, 17), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T3").WithLocation(31, 17), // (37,9): warning CS8631: The type 'T1' cannot be used as type parameter 'T' in the generic type or method 'C.Test()'. Nullability of type argument 'T1' doesn't match constraint type 'object'. // C.Test(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "C.Test").WithArguments("C.Test()", "object", "T", "T1").WithLocation(37, 9), @@ -62087,7 +61707,16 @@ public static void Test(T x) where T : object Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "C.Test").WithArguments("C.Test()", "object", "T", "T2").WithLocation(38, 9), // (39,9): warning CS8631: The type 'T3' cannot be used as type parameter 'T' in the generic type or method 'C.Test()'. Nullability of type argument 'T3' doesn't match constraint type 'object'. // C.Test(); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "C.Test").WithArguments("C.Test()", "object", "T", "T3").WithLocation(39, 9) + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "C.Test").WithArguments("C.Test()", "object", "T", "T3").WithLocation(39, 9), + // (45,9): warning CS8631: The type 'T1' cannot be used as type parameter 'T' in the generic type or method 'D.Test(T)'. Nullability of type argument 'T1' doesn't match constraint type 'object'. + // D.Test(F1); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "D.Test").WithArguments("D.Test(T)", "object", "T", "T1").WithLocation(45, 9), + // (46,9): warning CS8631: The type 'T2' cannot be used as type parameter 'T' in the generic type or method 'D.Test(T)'. Nullability of type argument 'T2' doesn't match constraint type 'object'. + // D.Test(F2); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "D.Test").WithArguments("D.Test(T)", "object", "T", "T2").WithLocation(46, 9), + // (47,9): warning CS8631: The type 'T3' cannot be used as type parameter 'T' in the generic type or method 'D.Test(T)'. Nullability of type argument 'T3' doesn't match constraint type 'object'. + // D.Test(F3); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "D.Test").WithArguments("D.Test(T)", "object", "T", "T3").WithLocation(47, 9) ); } @@ -62197,10 +61826,8 @@ static void F(object? x) Diagnostic(ErrorCode.ERR_UseDefViolation, "y").WithArguments("y").WithLocation(7, 9), // (9,9): warning CS8602: Possible dereference of a null reference. // y.ToString(); // 2 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9), - // (13,13): hidden CS8605: Result of the comparison is possibly always true. - // if (y != null) - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "y != null").WithLocation(13, 13)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9) + ); } [Fact] @@ -62235,15 +61862,13 @@ static void F(T x) // (7,9): error CS0165: Use of unassigned local variable 'y' // y.ToString(); Diagnostic(ErrorCode.ERR_UseDefViolation, "y").WithArguments("y").WithLocation(7, 9), - // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (8,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // y = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(8, 13), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(8, 13), // (9,9): warning CS8602: Possible dereference of a null reference. // y.ToString(); // 2 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9), - // (13,13): hidden CS8605: Result of the comparison is possibly always true. - // if (y != null) - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "y != null").WithLocation(13, 13)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9) + ); } [Fact] @@ -62471,10 +62096,10 @@ static void G(C? x, C y) { object z; z = x[x = null]; // 1 - z = x[x.F]; // 2, 3 + z = x[x.F]; // 2 z = x[x.F]; - y[y = null] = 1; - y[y.F] = 2; // 4, 5 + y[y = null] = 1; // 3 + y[y.F] = 2; // 4 y[y.F] = 3; } }"; @@ -62485,14 +62110,15 @@ static void G(C? x, C y) // z = x[x = null]; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 13), // (14,13): warning CS8602: Possible dereference of a null reference. - // z = x[x.F]; // 2, 3 + // z = x[x.F]; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(14, 13), // (16,15): warning CS8600: Converting null literal or possible null value to non-nullable type. - // y[y = null] = 1; + // y[y = null] = 1; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(16, 15), // (17,9): warning CS8602: Possible dereference of a null reference. - // y[y.F] = 2; // 4, 5 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(17, 9)); + // y[y.F] = 2; // 4 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(17, 9) + ); } [Fact] @@ -62719,6 +62345,61 @@ internal static void F(this C x) { } Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(12, 12)); } + [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] + [Fact] + public void MethodGroupReinferredAfterReceiver() + { + var source = +@"public class C +{ + G CreateG(T t) => new G(); + void Main(string? s1, string? s2) + { + Run(CreateG(s1).M, s2)/*T:(string?, string?)!*/; + if (s1 == null) return; + Run(CreateG(s1).M, s2)/*T:(string!, string?)!*/; + if (s2 == null) return; + Run(CreateG(s1).M, s2)/*T:(string!, string!)!*/; + } + (T, U) Run(MyDelegate del, U u) => del(u); +} +public class G +{ + public T t = default(T)!; + public (T, U) M(U u) => (t, u)!; +} +public delegate (T, U) MyDelegate(U u); +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + comp.VerifyDiagnostics(); + // https://github.com/dotnet/roslyn/issues/33637 + // comp.VerifyTypes(); + } + + [WorkItem(33638, "https://github.com/dotnet/roslyn/issues/33638")] + [Fact] + public void TupleFromNestedGenerics() + { + var source = +@"public class G +{ + public (T, U) M(T t, U u) => (t, u); +} +public class C +{ + public (T, U) M(T t, U u) => (t, u); +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + comp.VerifyDiagnostics( + // (3,37): warning CS8619: Nullability of reference types in value of type '(T t, U u)' doesn't match target type '(T, U)'. + // public (T, U) M(T t, U u) => (t, u); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(t, u)").WithArguments("(T t, U u)", "(T, U)").WithLocation(3, 37), + // (7,40): warning CS8619: Nullability of reference types in value of type '(T t, U u)' doesn't match target type '(T, U)'. + // public (T, U) M(T t, U u) => (t, u); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(t, u)").WithArguments("(T t, U u)", "(T, U)").WithLocation(7, 40)); + } + [WorkItem(30562, "https://github.com/dotnet/roslyn/issues/30562")] [Fact] public void NotNullAfterDereference_ForEach() @@ -63913,15 +63594,15 @@ void M(object? x, object y) // (7,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("object", "T").WithLocation(7, 13), - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,13): warning CS8601: Possible null reference assignment. // z = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = y; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y").WithArguments("object", "T").WithLocation(8, 13), - // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)x").WithLocation(9, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Possible dereference of a null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) @@ -63938,10 +63619,10 @@ class Outer void M(dynamic? x, dynamic y) { T z; - z = x; + z = x; // 1 z = y; - z = (T)x; - z.ToString(); // 1 + z = (T)x; // 2 + z.ToString(); // 3 z = (T)y; z.ToString(); } @@ -63949,14 +63630,14 @@ void M(dynamic? x, dynamic y) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. - // z = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), - // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. - // z = (T)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)x").WithLocation(9, 13), + // (7,13): warning CS8601: Possible null reference assignment. + // z = x; // 1 + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), + // (9,13): warning CS8601: Possible null reference assignment. + // z = (T)x; // 2 + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Possible dereference of a null reference. - // z.ToString(); // 1 + // z.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) ); } @@ -63986,15 +63667,15 @@ interface I1{} // (7,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("object", "T").WithLocation(7, 13), - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,13): warning CS8601: Possible null reference assignment. // z = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = y; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y").WithArguments("object", "T").WithLocation(8, 13), - // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)x").WithLocation(9, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Possible dereference of a null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) @@ -64023,12 +63704,12 @@ interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,13): warning CS8601: Possible null reference assignment. // z = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), - // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), + // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)x").WithLocation(9, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Possible dereference of a null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) @@ -64060,15 +63741,15 @@ interface I1{} // (7,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("object", "T").WithLocation(7, 13), - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,13): warning CS8601: Possible null reference assignment. // z = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = y; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y").WithArguments("object", "T").WithLocation(8, 13), - // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)x").WithLocation(9, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Possible dereference of a null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) @@ -64097,12 +63778,12 @@ interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,13): warning CS8601: Possible null reference assignment. // z = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), - // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), + // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)x").WithLocation(9, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Possible dereference of a null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) @@ -64129,12 +63810,12 @@ void M(T x) where U : T // (7,13): error CS0266: Cannot implicitly convert type 'T' to 'U'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("T", "U").WithLocation(7, 13), - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,13): warning CS8601: Possible null reference assignment. // y = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), - // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), + // (8,13): warning CS8601: Possible null reference assignment. // y = (U)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)x").WithLocation(8, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x").WithLocation(8, 13), // (9,9): warning CS8602: Possible dereference of a null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9) @@ -64163,12 +63844,12 @@ interface I1 {} // (7,13): error CS0266: Cannot implicitly convert type 'T' to 'U'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("T", "U").WithLocation(7, 13), - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,13): warning CS8601: Possible null reference assignment. // y = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), - // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), + // (8,13): warning CS8601: Possible null reference assignment. // y = (U)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)x").WithLocation(8, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x").WithLocation(8, 13), // (9,9): warning CS8602: Possible dereference of a null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9) @@ -64197,12 +63878,12 @@ interface I1 {} // (7,13): error CS0266: Cannot implicitly convert type 'T' to 'U'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("T", "U").WithLocation(7, 13), - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,13): warning CS8601: Possible null reference assignment. // y = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), - // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), + // (8,13): warning CS8601: Possible null reference assignment. // y = (U)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)x").WithLocation(8, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x").WithLocation(8, 13), // (9,9): warning CS8602: Possible dereference of a null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9) @@ -64277,12 +63958,12 @@ void M(dynamic? x) "; // https://github.com/dotnet/roslyn/issues/30939 - ErrorCode.WRN_ConvertingNullableToNonNullable/ErrorCode.WRN_NullReferenceReceiver warnings are not expected CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (8,13): warning CS8601: Possible null reference assignment. // y = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(8, 13), - // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(8, 13), + // (9,13): warning CS8601: Possible null reference assignment. // y = (T)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)x").WithLocation(9, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Possible dereference of a null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(10, 9) @@ -64314,15 +63995,15 @@ void M(Outer? x, Outer y) where T : Outer? // (7,13): error CS0266: Cannot implicitly convert type 'Outer' to 'T'. An explicit conversion exists (are you missing a cast?) // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("Outer", "T").WithLocation(7, 13), - // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,13): warning CS8601: Possible null reference assignment. // z = x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): error CS0266: Cannot implicitly convert type 'Outer' to 'T'. An explicit conversion exists (are you missing a cast?) // z = y; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y").WithArguments("Outer", "T").WithLocation(8, 13), - // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)x").WithLocation(9, 13), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Possible dereference of a null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) @@ -64454,9 +64135,9 @@ void M0(T x) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Possible dereference of a null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) @@ -64478,9 +64159,9 @@ void M0(T x) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default(T); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Possible dereference of a null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) @@ -64504,9 +64185,9 @@ interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Possible dereference of a null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) @@ -64530,9 +64211,9 @@ interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default(T); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Possible dereference of a null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) @@ -64604,9 +64285,9 @@ interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Possible dereference of a null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) @@ -64630,9 +64311,9 @@ interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default(T); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Possible dereference of a null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) @@ -64865,13 +64546,12 @@ void M0(T x) where T : class? "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,13): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // x = null; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Possible dereference of a null reference. // x.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) - ); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9)); } [Fact] @@ -64913,13 +64593,12 @@ void M0(T x) where T : Outer? "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,13): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // x = null; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Possible dereference of a null reference. // x.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) - ); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9)); } [Fact] @@ -66131,8 +65810,11 @@ void M0(T x0, object? z0) } "; - // https://github.com/dotnet/roslyn/issues/30952 - Expect WRN_NullReferenceAssignment for [M2(y0) = z0;] - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); + CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( + // (8,22): warning CS8601: Possible null reference assignment. + // M2(y0) = z0; + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "z0").WithLocation(8, 22) + ); } [Fact] @@ -66251,15 +65933,12 @@ class Outer void M0(T x0, T y0) { if (y0 == null) return; - (x0 ?? y0)?.ToString(); + (x0 ?? y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,10): hidden CS8607: Expression is probably never null. - // (x0 ?? y0)?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0 ?? y0").WithLocation(7, 10) ); } @@ -66315,7 +65994,10 @@ void M0(T x0, T z0) CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,13): warning CS8602: Possible dereference of a null reference. // M2(x0).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0)").WithLocation(10, 13) + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0)").WithLocation(10, 13), + // (11,13): warning CS8602: Possible dereference of a null reference. + // M2(y0).ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(y0)").WithLocation(11, 13) ); } @@ -66493,12 +66175,12 @@ interface I1 {} // (4,35): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void M0(T x0) where T : I1 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(4, 35), - // (6,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,14): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x0 = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(6, 14), - // (11,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 14), + // (11,14): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x1 = default; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(11, 14) + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(11, 14) ); } @@ -66523,15 +66205,9 @@ void M0(T x0, T y0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): hidden CS8607: Expression is probably never null. - // T z0 = x0 ?? y0; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // M1(z0).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(8, 9), - // (11,9): hidden CS8607: Expression is probably never null. - // z0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z0").WithLocation(11, 9) + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(8, 9) ); } @@ -66556,12 +66232,6 @@ void M0(T x0, T y0, T a0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,16): hidden CS8607: Expression is probably never null. - // T z0 = x0 ?? y0; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(8, 16), - // (10,9): hidden CS8607: Expression is probably never null. - // z0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z0").WithLocation(10, 9), // (11,9): warning CS8602: Possible dereference of a null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(11, 9) @@ -66583,11 +66253,7 @@ void M0(T x0, T y0) } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // z0 = y0; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y0").WithLocation(8, 14) - ); + CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] @@ -67129,13 +66795,9 @@ void F(T y0) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (8,14): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (8,14): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // x0 = null; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 14), - // (10,15): warning CS8604: Possible null reference argument for parameter 'x' in 'C C.M1(T x)'. - // M2(M1(x0), M1(y0)) = - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x0").WithArguments("x", "C C.M1(T x)").WithLocation(10, 15) - ); + Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(8, 14)); } [Fact] @@ -67214,9 +66876,6 @@ void M0(T x0, T y0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): hidden CS8607: Expression is probably never null. - // T z0 = y0 ?? M2(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 16), // (11,9): warning CS8602: Possible dereference of a null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(11, 9) @@ -67266,11 +66925,7 @@ void M0(T x0, T y0) } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,9): warning CS8602: Possible dereference of a null reference. - // z0.ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) - ); + CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] @@ -67456,9 +67111,6 @@ void M0(bool b, T x0, T y0, T a0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (10,9): hidden CS8607: Expression is probably never null. - // z0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z0").WithLocation(10, 9), // (11,9): warning CS8602: Possible dereference of a null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(11, 9) @@ -67693,10 +67345,7 @@ void M0(T x0, T y0, T a0) CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Possible dereference of a null reference. // M1(z0).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(10, 9), - // (11,9): hidden CS8607: Expression is probably never null. - // z0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z0").WithLocation(11, 9) + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(10, 9) ); } @@ -67751,10 +67400,7 @@ void M0(T x0, T y0) CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Possible dereference of a null reference. // M1(z0).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(9, 9), - // (10,9): hidden CS8607: Expression is probably never null. - // z0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z0").WithLocation(10, 9) + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(9, 9) ); } @@ -67916,10 +67562,7 @@ void M0(T x0, T y0, T a0) CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Possible dereference of a null reference. // M1(z0).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(10, 9), - // (11,9): hidden CS8607: Expression is probably never null. - // z0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z0").WithLocation(11, 9) + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(10, 9) ); } @@ -67949,10 +67592,7 @@ void M0(T x0, T y0) CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Possible dereference of a null reference. // M1(z0).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(9, 9), - // (10,9): hidden CS8607: Expression is probably never null. - // z0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z0").WithLocation(10, 9) + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(9, 9) ); } @@ -68076,12 +67716,9 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8601: Possible null reference assignment. // U y0 = (U)x0; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)x0").WithLocation(6, 16), - // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. - // U z0 = y0; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y0").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x0").WithLocation(6, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), @@ -68110,12 +67747,9 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8601: Possible null reference assignment. // U y0 = (U)x0; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)x0").WithLocation(6, 16), - // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. - // U z0 = y0; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y0").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x0").WithLocation(6, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), @@ -68146,6 +67780,9 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( + // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. + // T z0 = x0?.M1(); + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), @@ -68174,11 +67811,13 @@ void M0(T x0) T M1() => throw null!; } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. + // T z0 = x0?.M1(); + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), + // (7,16): warning CS8601: Possible null reference assignment. // U y0 = (U)z0; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)z0").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)z0").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), @@ -68210,9 +67849,9 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): hidden CS8607: Expression is probably never null. + // (7,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(7, 16), // (10,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(10, 9), @@ -68243,12 +67882,9 @@ void M0(Outer? x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(6, 16), - // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. - // U y0 = z0; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z0").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), @@ -68277,11 +67913,10 @@ void M0(Outer x0) T M1() => throw null!; } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): hidden CS8607: Expression is probably never null. + // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), @@ -68337,12 +67972,12 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,23): hidden CS8607: Expression is probably never null. + // (7,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer z0 = x0?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 23), - // (8,9): hidden CS8607: Expression is probably never null. - // z0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z0").WithLocation(8, 9) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(7, 23), + // (9,9): warning CS8602: Possible dereference of a null reference. + // z0.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } @@ -68392,9 +68027,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,23): hidden CS8607: Expression is probably never null. - // Outer z0 = x0?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 23), // (7,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(7, 23), @@ -68422,6 +68054,9 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( + // (6,16): warning CS8638: Conditional access may produce a null value when 'U' is a non-nullable reference type. + // U z0 = x0?.M1(); + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("U").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) @@ -68447,9 +68082,9 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): hidden CS8607: Expression is probably never null. + // (7,16): warning CS8638: Conditional access may produce a null value when 'U' is a non-nullable reference type. // U z0 = x0?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("U").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) @@ -68474,6 +68109,9 @@ void M0(U x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( + // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. + // U z0 = x0?.M1(); + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) @@ -68496,16 +68134,10 @@ void M0(U x0) T M1() => throw null!; } "; - // Strictly speaking, we should warn on assignment (โ€œT z0 = x0?.M1();โ€) because T - // could be not-nullable reference type and U can be nullable reference type at - // the same time, making result of conditional access nullable of T. However, - // assigning the same value to U (the previous unit-test) should not warn. If U is - // not-nullable reference type, T is also not nullable, the result of conditional - // access is not nullable T. - // At the moment, we donโ€™t have a way to track this complex dependency between nullable - // state and possible target type. During implementation the preference is given to - // suppression of incorrect warning for the scenario from the previous unit-test. CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( + // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. + // T z0 = x0?.M1(); + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) @@ -68531,9 +68163,9 @@ void M0(U x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): hidden CS8607: Expression is probably never null. + // (7,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // U z0 = x0?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) @@ -68559,9 +68191,9 @@ void M0(U x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): hidden CS8607: Expression is probably never null. + // (7,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) @@ -68586,9 +68218,9 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8638: Conditional access may produce a null value when 'U' is a non-nullable reference type. // U z0 = x0?.M1(); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("U").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) @@ -68614,9 +68246,9 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): hidden CS8607: Expression is probably never null. + // (7,16): warning CS8638: Conditional access may produce a null value when 'U' is a non-nullable reference type. // U z0 = x0?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("U").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) @@ -68669,12 +68301,12 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): hidden CS8607: Expression is probably never null. + // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // U z0 = x0?.M1(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 16), - // (8,9): hidden CS8607: Expression is probably never null. - // z0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "z0").WithLocation(8, 9) + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(7, 16), + // (9,9): warning CS8602: Possible dereference of a null reference. + // z0.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } @@ -68720,9 +68352,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(8, 9) ); } @@ -68768,9 +68397,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(8, 9) ); } @@ -68788,11 +68414,10 @@ void M0(object x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -68813,11 +68438,10 @@ void M0(object? x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -68839,11 +68463,10 @@ void M0(object? x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) @@ -68864,11 +68487,10 @@ void M0(dynamic x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -68889,11 +68511,10 @@ void M0(dynamic? x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -68915,11 +68536,10 @@ void M0(dynamic? x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) @@ -68942,9 +68562,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 9) ); } @@ -68964,9 +68581,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 9) ); } @@ -69187,11 +68801,10 @@ void M0(Outer? x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -69213,11 +68826,10 @@ void M0(Outer? x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) @@ -69238,11 +68850,10 @@ void M0(Outer x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -69392,9 +69003,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(8, 9) ); } @@ -69412,11 +69020,10 @@ void M0(Outer x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -69439,9 +69046,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 9) ); } @@ -69567,9 +69171,6 @@ interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(8, 9) ); } @@ -69589,11 +69190,10 @@ void M0(I1 x0) interface I1{} "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -69618,9 +69218,6 @@ interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 9) ); } @@ -69745,9 +69342,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(8, 9) ); } @@ -69767,9 +69361,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 9) ); } @@ -69812,9 +69403,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(8, 9) ); } @@ -69834,9 +69422,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 9) ); } @@ -69856,9 +69441,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 9) ); } @@ -69901,9 +69483,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(8, 9) ); } @@ -69923,9 +69502,6 @@ void M0(T x0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // y0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 9) ); } @@ -70019,11 +69595,10 @@ void M0(U x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -70045,11 +69620,10 @@ void M0(U x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) @@ -70095,11 +69669,10 @@ void M0(U x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) @@ -70121,11 +69694,10 @@ void M0(U x0) } } "; - CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), + Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) @@ -70243,9 +69815,6 @@ void M0(T x0, T y0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,10): hidden CS8607: Expression is probably never null. - // (x0 ??= y0)?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0 ??= y0").WithLocation(7, 10) ); } @@ -70270,15 +69839,10 @@ void M0(T x0, T y0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // x0 ??= y0; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(7, 9), // (8,9): warning CS8602: Possible dereference of a null reference. // M1(x0).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x0)").WithLocation(8, 9), - // (10,9): hidden CS8607: Expression is probably never null. - // x0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(10, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x0)").WithLocation(8, 9) + ); } [Fact] @@ -70302,12 +69866,6 @@ void M0(T x0, T y0, T a0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (8,9): hidden CS8607: Expression is probably never null. - // x0 ??= y0; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(8, 9), - // (10,9): hidden CS8607: Expression is probably never null. - // x0?.ToString(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "x0").WithLocation(10, 9), // (11,9): warning CS8602: Possible dereference of a null reference. // M1(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x0)").WithLocation(11, 9)); @@ -70338,9 +69896,6 @@ void M0(T x0, T y0) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (7,9): hidden CS8607: Expression is probably never null. - // y0 ??= M2(); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "y0").WithLocation(7, 9), // (11,9): warning CS8602: Possible dereference of a null reference. // M1(y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(y0)").WithLocation(11, 9)); @@ -70386,15 +69941,9 @@ void M0(T1 t1, T2 t2) "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( - // (6,9): hidden CS8607: Expression is probably never null. - // t1 ??= t2 as T1; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "t1").WithLocation(6, 9), // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // t1 ??= t2 as T1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t2 as T1").WithLocation(6, 16), - // (7,9): hidden CS8607: Expression is probably never null. - // M1(t1) ??= t2 as T1; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "M1(t1)").WithLocation(7, 9), // (7,20): warning CS8601: Possible null reference assignment. // M1(t1) ??= t2 as T1; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2 as T1").WithLocation(7, 20)); @@ -70603,10 +70152,7 @@ static void M(object x) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 13), // (14,9): error CS0176: Member 'C.F()' cannot be accessed with an instance reference; qualify it with a type name instead // c2.F().ToString(); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "c2.F").WithArguments("C.F()").WithLocation(14, 9), - // (14,9): warning CS8602: Possible dereference of a null reference. - // c2.F().ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2.F()").WithLocation(14, 9)); + Diagnostic(ErrorCode.ERR_ObjectProhibited, "c2.F").WithArguments("C.F()").WithLocation(14, 9)); } [Fact] @@ -74177,6 +73723,7 @@ static void F(C x, C? y) private readonly static NullableAnnotation[] s_AllNullableAnnotations = (NullableAnnotation[])Enum.GetValues(typeof(NullableAnnotation)); private readonly static NullableAnnotation[] s_AllSpeakableNullableAnnotations = new[] { NullableAnnotation.Unknown, NullableAnnotation.NotAnnotated, NullableAnnotation.Annotated }; + private readonly static NullableFlowState[] s_AllNullableFlowStates = (NullableFlowState[])Enum.GetValues(typeof(NullableFlowState)); [Fact] public void TestJoinForFixingLowerBounds() @@ -74195,42 +73742,16 @@ public void TestJoinForFixingLowerBounds() } [Fact] - public void TestJoinForFlowAnalysisBranches_IsPossiblyNullableReferenceTypeTypeParameterFalse() + public void TestJoinForFlowAnalysisBranches() { - var inputs = new[] { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }; + var inputs = new[] { NullableFlowState.NotNull, NullableFlowState.MaybeNull }; - Func getResult = - (i, j) => NullableAnnotationExtensions.JoinForFlowAnalysisBranches( - inputs[i], inputs[j], type: null, isPossiblyNullableReferenceTypeTypeParameter: _ => false); - - var expected = new NullableAnnotation[5, 5] - { - { NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.Annotated }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Nullable, NullableAnnotation.Nullable, NullableAnnotation.Nullable }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.Unknown, NullableAnnotation.Unknown }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, - }; + Func getResult = (i, j) => inputs[i].JoinForFlowAnalysisBranches(inputs[j]); - AssertEqual(expected, getResult, inputs.Length); - } - - [Fact] - public void TestJoinForFlowAnalysisBranches_IsPossiblyNullableReferenceTypeTypeParameterTrue() - { - var inputs = new[] { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }; - - Func getResult = - (i, j) => NullableAnnotationExtensions.JoinForFlowAnalysisBranches( - inputs[i], inputs[j], type: null, isPossiblyNullableReferenceTypeTypeParameter: _ => true); - - var expected = new NullableAnnotation[5, 5] + var expected = new NullableFlowState[2, 2] { - { NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.Annotated }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Nullable, NullableAnnotation.Nullable, NullableAnnotation.Nullable }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.Unknown, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, + { NullableFlowState.NotNull, NullableFlowState.MaybeNull }, + { NullableFlowState.MaybeNull, NullableFlowState.MaybeNull }, }; AssertEqual(expected, getResult, inputs.Length); @@ -74253,18 +73774,15 @@ public void TestMeetForFixingUpperBounds() } [Fact] - public void TestJoinMeetForFlowAnalysisFinally() + public void TestMeetForFlowAnalysisFinally() { - var inputs = new[] { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }; - Func getResult = (i, j) => NullableAnnotationExtensions.MeetForFlowAnalysisFinally(inputs[i], inputs[j]); + var inputs = new[] { NullableFlowState.NotNull, NullableFlowState.MaybeNull }; + Func getResult = (i, j) => inputs[i].MeetForFlowAnalysisFinally(inputs[j]); - var expected = new NullableAnnotation[5, 5] + var expected = new NullableFlowState[2, 2] { - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.Nullable, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.Unknown, NullableAnnotation.Unknown, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.NotNullable, NullableAnnotation.NotNullable, NullableAnnotation.NotNullable, NullableAnnotation.NotNullable, NullableAnnotation.NotNullable }, - { NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, + { NullableFlowState.NotNull, NullableFlowState.NotNull }, + { NullableFlowState.NotNull, NullableFlowState.MaybeNull }, }; AssertEqual(expected, getResult, inputs.Length); @@ -74291,46 +73809,28 @@ public void TestEnsureCompatibleForTuples_IsPossiblyNullableReferenceTypeTypePar { var inputs = new[] { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }; - Func getResult = - (i, j) => NullableAnnotationExtensions.EnsureCompatibleForTuples( - inputs[i], inputs[j], type: null, isPossiblyNullableReferenceTypeTypeParameter: _ => false); + Func getResult = (i, j) => inputs[i].EnsureCompatibleForTuples(inputs[j]); var expected = new NullableAnnotation[5, 5] { - { NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Nullable, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, + { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Annotated, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, + { NullableAnnotation.Nullable, NullableAnnotation.Nullable, NullableAnnotation.Nullable, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotNullable, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, + { NullableAnnotation.NotNullable, NullableAnnotation.NotNullable, NullableAnnotation.NotNullable, NullableAnnotation.NotNullable, NullableAnnotation.NotNullable }, + { NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, }; AssertEqual(expected, getResult, inputs.Length); } - [Fact] - public void TestEnsureCompatibleForTuples_IsPossiblyNullableReferenceTypeTypeParameterTrue() + private static void AssertEqual(NullableAnnotation[,] expected, Func getResult, int size) { - var inputs = new[] { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }; - - Func getResult = - (i, j) => NullableAnnotationExtensions.EnsureCompatibleForTuples( - inputs[i], inputs[j], type: null, isPossiblyNullableReferenceTypeTypeParameter: _ => true); - - var expected = new NullableAnnotation[5, 5] - { - { NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Nullable, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.Annotated, NullableAnnotation.Nullable, NullableAnnotation.Unknown, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotNullable, NullableAnnotation.NotNullable, NullableAnnotation.NotAnnotated }, - { NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, - }; - - AssertEqual(expected, getResult, inputs.Length); + AssertEx.Equal(expected, getResult, (na1, na2) => na1 == na2, na => $"NullableAnnotation.{na}", "{0,-32:G}", size); } - private static void AssertEqual(NullableAnnotation[,] expected, Func getResult, int size) + private static void AssertEqual(NullableFlowState[,] expected, Func getResult, int size) { - AssertEx.Equal(expected, getResult, (na1, na2) => na1 == na2, na => $"NullableAnnotation.{na}", "{0,-32:G}", size); + AssertEx.Equal(expected, getResult, (na1, na2) => na1 == na2, na => $"NullableFlowState.{na}", "{0,-32:G}", size); } [Fact] @@ -74353,19 +73853,15 @@ public void TestJoinForFixingLowerBoundsIsAssociative() [Fact] public void TestJoinForFlowAnalysisBranchesIsAssociative() { - Func identity = x => x; - foreach (var a in s_AllNullableAnnotations) + foreach (var a in s_AllNullableFlowStates) { - foreach (var b in s_AllNullableAnnotations) + foreach (var b in s_AllNullableFlowStates) { - foreach (var c in s_AllNullableAnnotations) + foreach (var c in s_AllNullableFlowStates) { - foreach (bool isPossiblyNullableReferenceTypeTypeParameter in new[] { true, false }) - { - var leftFirst = a.JoinForFlowAnalysisBranches(b, isPossiblyNullableReferenceTypeTypeParameter, identity).JoinForFlowAnalysisBranches(c, isPossiblyNullableReferenceTypeTypeParameter, identity); - var rightFirst = a.JoinForFlowAnalysisBranches(b.JoinForFlowAnalysisBranches(c, isPossiblyNullableReferenceTypeTypeParameter, identity), isPossiblyNullableReferenceTypeTypeParameter, identity); - Assert.Equal(leftFirst, rightFirst); - } + var leftFirst = a.JoinForFlowAnalysisBranches(b).JoinForFlowAnalysisBranches(c); + var rightFirst = a.JoinForFlowAnalysisBranches(b.JoinForFlowAnalysisBranches(c)); + Assert.Equal(leftFirst, rightFirst); } } } @@ -74391,11 +73887,11 @@ public void TestMeetForFixingUpperBoundsIsAssociative() [Fact] public void TestMeetForFlowAnalysisFinallyIsAssociative() { - foreach (var a in s_AllNullableAnnotations) + foreach (var a in s_AllNullableFlowStates) { - foreach (var b in s_AllNullableAnnotations) + foreach (var b in s_AllNullableFlowStates) { - foreach (var c in s_AllNullableAnnotations) + foreach (var c in s_AllNullableFlowStates) { var leftFirst = a.MeetForFlowAnalysisFinally(b).MeetForFlowAnalysisFinally(c); var rightFirst = a.MeetForFlowAnalysisFinally(b.MeetForFlowAnalysisFinally(c)); @@ -74444,14 +73940,14 @@ public void TestJoinForFixingLowerBoundsIsCommutative() public void TestJoinForFlowAnalysisBranchesIsCommutative() { Func identity = x => x; - foreach (var a in s_AllNullableAnnotations) + foreach (var a in s_AllNullableFlowStates) { - foreach (var b in s_AllNullableAnnotations) + foreach (var b in s_AllNullableFlowStates) { foreach (bool isPossiblyNullableReferenceTypeTypeParameter in new[] { true, false }) { - var leftFirst = a.JoinForFlowAnalysisBranches(b, isPossiblyNullableReferenceTypeTypeParameter, identity); - var rightFirst = b.JoinForFlowAnalysisBranches(a, isPossiblyNullableReferenceTypeTypeParameter, identity); + var leftFirst = a.JoinForFlowAnalysisBranches(b); + var rightFirst = b.JoinForFlowAnalysisBranches(a); Assert.Equal(leftFirst, rightFirst); } } @@ -74475,16 +73971,13 @@ public void TestMeetForFixingUpperBoundsIsCommutative() [Fact] public void TestMeetForFlowAnalysisFinallyIsCommutative() { - foreach (var a in s_AllNullableAnnotations) + foreach (var a in s_AllNullableFlowStates) { - foreach (var b in s_AllNullableAnnotations) + foreach (var b in s_AllNullableFlowStates) { - foreach (var c in s_AllNullableAnnotations) - { - var leftFirst = a.MeetForFlowAnalysisFinally(b); - var rightFirst = b.MeetForFlowAnalysisFinally(a); - Assert.Equal(leftFirst, rightFirst); - } + var leftFirst = a.MeetForFlowAnalysisFinally(b); + var rightFirst = b.MeetForFlowAnalysisFinally(a); + Assert.Equal(leftFirst, rightFirst); } } } @@ -74492,51 +73985,13 @@ public void TestMeetForFlowAnalysisFinallyIsCommutative() [Fact] public void TestEnsureCompatibleIsCommutative() { - Func identity = x => x; foreach (var a in s_AllSpeakableNullableAnnotations) { foreach (var b in s_AllSpeakableNullableAnnotations) { - foreach (bool isPossiblyNullableReferenceTypeTypeParameter in new[] { true, false }) - { - var leftFirst = a.EnsureCompatible(b); - var rightFirst = b.EnsureCompatible(a); - Assert.Equal(leftFirst, rightFirst); - } - } - } - } - - // Tracked by https://github.com/dotnet/roslyn/issues/31160 - [Fact(Skip = "Two different implementations of NullableAnnotation Join do not agree")] - public void TestJoinsAgree() - { - Func identity = x => x; - foreach (var a in s_AllNullableAnnotations) - { - foreach (var b in s_AllNullableAnnotations) - { - foreach (bool isPossiblyNullableReferenceTypeTypeParameter in new[] { true, false }) - { - var result1 = a.JoinForFixingLowerBounds(b); - var result2 = a.JoinForFlowAnalysisBranches(b, isPossiblyNullableReferenceTypeTypeParameter, identity); - Assert.Equal(result1, result2); - } - } - } - } - - // Tracked by https://github.com/dotnet/roslyn/issues/31160 - [Fact(Skip = "Two different implementations of NullableAnnotation Meet do not agree")] - public void TestMeetsAgree() - { - foreach (var a in s_AllNullableAnnotations) - { - foreach (var b in s_AllNullableAnnotations) - { - var result1 = a.MeetForFixingUpperBounds(b); - var result2 = a.MeetForFlowAnalysisFinally(b); - Assert.Equal(result1, result2); + var leftFirst = a.EnsureCompatible(b); + var rightFirst = b.EnsureCompatible(a); + Assert.Equal(leftFirst, rightFirst); } } } @@ -74592,7 +74047,8 @@ static void F(T? x) where T : struct comp.VerifyDiagnostics( // (5,13): warning CS8629: Nullable value type may be null. // _ = x.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.Value").WithLocation(5, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(5, 13) + ); } [Fact] @@ -74760,10 +74216,11 @@ static void F(T t) where T : struct comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = x.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.Value").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(6, 13), // (8,13): warning CS8629: Nullable value type may be null. // _ = y.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(8, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(8, 13) + ); } [WorkItem(31502, "https://github.com/dotnet/roslyn/issues/31502")] @@ -74789,10 +74246,10 @@ static void F(T t) where T : struct comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = x.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.Value").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(6, 13), // (10,13): warning CS8629: Nullable value type may be null. // _ = z.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z.Value").WithLocation(10, 13) + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z").WithLocation(10, 13) ); } @@ -74821,10 +74278,11 @@ static void F2(T? t2) comp.VerifyDiagnostics( // (8,17): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1.Value").WithLocation(8, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(8, 17), // (13,17): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2.Value").WithLocation(13, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(13, 17) + ); } [Fact] @@ -74852,10 +74310,11 @@ static void F2(T? t2) comp.VerifyDiagnostics( // (8,17): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1.Value").WithLocation(8, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(8, 17), // (13,17): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2.Value").WithLocation(13, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(13, 17) + ); } [Fact] @@ -74960,10 +74419,11 @@ static void F4(T? t4) comp.VerifyDiagnostics( // (24,22): warning CS8629: Nullable value type may be null. // else _ = t3.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3.Value").WithLocation(24, 22), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3").WithLocation(24, 22), // (31,33): warning CS8629: Nullable value type may be null. // if (t4 == null) _ = t4.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4.Value").WithLocation(31, 33)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4").WithLocation(31, 33) + ); } [Fact] @@ -75001,19 +74461,20 @@ static void F4(T? x4, T? y4) comp.VerifyDiagnostics( // (7,13): warning CS8629: Nullable value type may be null. // y1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1.Value").WithLocation(7, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1").WithLocation(7, 13), // (12,13): warning CS8629: Nullable value type may be null. // y2.Value : // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2.Value").WithLocation(12, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2").WithLocation(12, 13), // (18,13): warning CS8629: Nullable value type may be null. // x3.Value : // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3.Value").WithLocation(18, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3").WithLocation(18, 13), // (19,13): warning CS8629: Nullable value type may be null. // y3.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3.Value").WithLocation(19, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3").WithLocation(19, 13), // (25,13): warning CS8629: Nullable value type may be null. // (T)y4; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)y4").WithLocation(25, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)y4").WithLocation(25, 13) + ); } [Fact] @@ -75051,19 +74512,20 @@ static void F4(T? x4, T? y4) comp.VerifyDiagnostics( // (7,13): warning CS8629: Nullable value type may be null. // y1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1.Value").WithLocation(7, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1").WithLocation(7, 13), // (12,13): warning CS8629: Nullable value type may be null. // y2.Value : // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2.Value").WithLocation(12, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2").WithLocation(12, 13), // (18,13): warning CS8629: Nullable value type may be null. // x3.Value : // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3.Value").WithLocation(18, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3").WithLocation(18, 13), // (19,13): warning CS8629: Nullable value type may be null. // y3.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3.Value").WithLocation(19, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3").WithLocation(19, 13), // (25,13): warning CS8629: Nullable value type may be null. // (T)y4; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)y4").WithLocation(25, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)y4").WithLocation(25, 13) + ); } [Fact] @@ -75106,9 +74568,9 @@ static void F2(T? x2, T? y2) { if (y2 == null) return; object? z2 = x2 != null ? (object?)x2 : y2; - _ = z2/*T:object!*/.ToString(); + _ = z2/*T:object?*/.ToString(); // 3 dynamic? w2 = x2 != null ? (dynamic?)x2 : y2; - _ = w2/*T:dynamic!*/.ToString(); + _ = w2/*T:dynamic?*/.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); @@ -75118,7 +74580,14 @@ static void F2(T? x2, T? y2) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1").WithLocation(6, 13), // (8,13): warning CS8602: Possible dereference of a null reference. // _ = w1/*T:dynamic?*/.ToString(); // 2 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w1").WithLocation(8, 13)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w1").WithLocation(8, 13), + // (14,13): warning CS8602: Possible dereference of a null reference. + // _ = z2/*T:object!*/.ToString(); // 3 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z2").WithLocation(14, 13), + // (16,13): warning CS8602: Possible dereference of a null reference. + // _ = w2/*T:dynamic!*/.ToString(); // 4 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w2").WithLocation(16, 13) + ); comp.VerifyTypes(); } @@ -75171,13 +74640,13 @@ static void F2(A? na2) comp.VerifyDiagnostics( // (23,20): warning CS8629: Nullable value type may be null. // A a1 = na1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "na1.Value").WithLocation(23, 20), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "na1").WithLocation(23, 20), // (24,20): warning CS8629: Nullable value type may be null. // B b1 = a1.B.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "a1.B.Value").WithLocation(24, 20), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "a1.B").WithLocation(24, 20), // (25,20): warning CS8629: Nullable value type may be null. // C c1 = b1.C.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b1.C.Value").WithLocation(25, 20), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b1.C").WithLocation(25, 20), // (36,20): warning CS8629: Nullable value type may be null. // A a2 = (A)na2; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(A)na2").WithLocation(36, 20), @@ -75186,7 +74655,8 @@ static void F2(A? na2) Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(B)a2.B").WithLocation(37, 20), // (38,20): warning CS8629: Nullable value type may be null. // C c2 = (C)b2.C; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(C)b2.C").WithLocation(38, 20)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(C)b2.C").WithLocation(38, 20) + ); } [Fact] @@ -75407,7 +74877,7 @@ static void F2(C? nc) comp.VerifyDiagnostics( // (20,21): warning CS8629: Nullable value type may be null. // var s = ns.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns.Value").WithLocation(20, 21), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns").WithLocation(20, 21), // (22,13): warning CS8602: Possible dereference of a null reference. // c.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(22, 13), @@ -75416,7 +74886,8 @@ static void F2(C? nc) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "nc").WithLocation(34, 22), // (35,17): warning CS8629: Nullable value type may be null. // _ = ns.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns.Value").WithLocation(35, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns").WithLocation(35, 17) + ); } [Fact] @@ -75471,13 +74942,14 @@ static void F3(int? ni) comp.VerifyDiagnostics( // (27,17): warning CS8629: Nullable value type may be null. // _ = nl3.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl3.Value").WithLocation(27, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl3").WithLocation(27, 17), // (29,17): warning CS8629: Nullable value type may be null. // _ = nl4.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl4.Value").WithLocation(29, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl4").WithLocation(29, 17), // (41,17): warning CS8629: Nullable value type may be null. // _ = (long)ni; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(long)ni").WithLocation(41, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(long)ni").WithLocation(41, 17) + ); } [Fact] @@ -75536,13 +75008,14 @@ static void F3(int? ni) comp.VerifyDiagnostics( // (31,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3.Value").WithLocation(31, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(31, 17), // (33,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4.Value").WithLocation(33, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17), // (45,20): warning CS8629: Nullable value type may be null. // _ = (S)ni; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ni").WithLocation(45, 20)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ni").WithLocation(45, 20) + ); } [Fact] @@ -75589,25 +75062,26 @@ static void F2(int? ni) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(13, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13), // (16,13): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3.Value").WithLocation(16, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(16, 13), // (24,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(24, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(24, 17), // (26,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(26, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(26, 17), // (31,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3.Value").WithLocation(31, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(31, 17), // (33,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 7 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4.Value").WithLocation(33, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17) + ); } [Fact] @@ -75686,16 +75160,17 @@ static void F2(int? ni) Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(S)i").WithLocation(10, 13), // (18,17): warning CS8629: Nullable value type may be null. // _ = ns1.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns1.Value").WithLocation(18, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns1").WithLocation(18, 17), // (20,17): warning CS8629: Nullable value type may be null. // _ = ns2.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns2.Value").WithLocation(20, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns2").WithLocation(20, 17), // (25,17): warning CS8629: Nullable value type may be null. // _ = ns3.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns3.Value").WithLocation(25, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns3").WithLocation(25, 17), // (27,17): warning CS8629: Nullable value type may be null. // _ = ns4.Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns4.Value").WithLocation(27, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns4").WithLocation(27, 17) + ); } [Fact] @@ -75739,10 +75214,11 @@ static void F2(S? ns) comp.VerifyDiagnostics( // (28,17): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1.Value").WithLocation(28, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2.Value").WithLocation(30, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(30, 17) + ); } [Fact] @@ -75786,22 +75262,23 @@ static void F2(S? ns) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2.Value").WithLocation(13, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1.Value").WithLocation(21, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2.Value").WithLocation(23, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1.Value").WithLocation(28, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2.Value").WithLocation(30, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(30, 17) + ); } [Fact] @@ -75898,22 +75375,23 @@ static void F2(S? ns) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2.Value").WithLocation(13, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1.Value").WithLocation(21, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2.Value").WithLocation(23, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = nl3.Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl3.Value").WithLocation(28, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = nl4.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl4.Value").WithLocation(30, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl4").WithLocation(30, 17) + ); } [Fact] @@ -76226,28 +75704,29 @@ static void F2(C? nc) comp.VerifyDiagnostics( // (14,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(14, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(14, 13), // (16,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(16, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(16, 13), // (24,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(24, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(24, 17), // (26,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(26, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(26, 17), // (30,26): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S?(C c)'. // var s3 = (S?)nc; // 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S?(C c)").WithLocation(30, 26), // (31,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3.Value").WithLocation(31, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(31, 17), // (32,21): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S?(C c)'. // S? s4 = nc; // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S?(C c)").WithLocation(32, 21), // (33,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 8 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4.Value").WithLocation(33, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17) + ); } [Fact] @@ -76336,22 +75815,23 @@ static void F2(C? nc) comp.VerifyDiagnostics( // (14,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(14, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(14, 13), // (16,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(16, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(16, 13), // (24,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(24, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(24, 17), // (26,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(26, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(26, 17), // (31,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3.Value").WithLocation(31, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(31, 17), // (33,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4.Value").WithLocation(33, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17) + ); } // https://github.com/dotnet/roslyn/issues/31675: Add similar tests for @@ -76401,12 +75881,13 @@ static void F2(S? ns) // (21,17): warning CS8602: Possible dereference of a null reference. // _ = t1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(21, 17), - // (25,22): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (25,22): warning CS8601: Possible null reference assignment. // var t2 = (T)ns; // 4 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)ns").WithLocation(25, 22), + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)ns").WithLocation(25, 22), // (26,17): warning CS8602: Possible dereference of a null reference. // _ = t2.ToString(); // 5 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(26, 17)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(26, 17) + ); } [Fact] @@ -76587,10 +76068,11 @@ static void F2(S? ns) comp.VerifyDiagnostics( // (28,17): warning CS8629: Nullable value type may be null. // _ = t3.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3.Value").WithLocation(28, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = t4.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4.Value").WithLocation(30, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4").WithLocation(30, 17) + ); } [Fact] @@ -76675,22 +76157,23 @@ static void F2(S? ns) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2.Value").WithLocation(13, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1.Value").WithLocation(21, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2.Value").WithLocation(23, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = t3.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3.Value").WithLocation(28, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = t4.Value; // 8 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4.Value").WithLocation(30, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4").WithLocation(30, 17) + ); } [Fact] @@ -76734,22 +76217,23 @@ static void F2(S? ns) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2.Value").WithLocation(13, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1.Value").WithLocation(21, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2.Value").WithLocation(23, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = t3.Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3.Value").WithLocation(28, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = t4.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4.Value").WithLocation(30, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4").WithLocation(30, 17) + ); } [Fact] @@ -76796,10 +76280,11 @@ static void F1(T t) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(13, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13) + ); } [Fact] @@ -76888,28 +76373,29 @@ static void F2(T? nt) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(13, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(21, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(23, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(23, 17), // (27,29): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S?(T t)'. // var s3 = (S?)nt; // 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S?(T t)").WithLocation(27, 29), // (28,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3.Value").WithLocation(28, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(28, 17), // (29,24): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S?(T t)'. // S? s4 = nt; // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S?(T t)").WithLocation(29, 24), // (30,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 8 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4.Value").WithLocation(30, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(30, 17) + ); } [Fact] @@ -76951,10 +76437,11 @@ static void F2(T? nt) comp.VerifyDiagnostics( // (26,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3.Value").WithLocation(26, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(26, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4.Value").WithLocation(28, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(28, 17) + ); } [Fact] @@ -76998,22 +76485,23 @@ static void F2(T? nt) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(13, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(21, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(23, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3.Value").WithLocation(28, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 8 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4.Value").WithLocation(30, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(30, 17) + ); } [Fact] @@ -77096,22 +76584,23 @@ static void F2(T? nt) comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(13, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1.Value").WithLocation(21, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2.Value").WithLocation(23, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3.Value").WithLocation(28, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4.Value").WithLocation(30, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(30, 17) + ); } [Fact] @@ -77127,8 +76616,8 @@ class B1 : A internal override void F(U x) { int? y = x; - _ = y.Value; // 1 - _ = ((int?)x).Value; // 2 + _ = y.Value; + _ = ((int?)x).Value; } } class B2 : A @@ -77136,8 +76625,8 @@ class B2 : A internal override void F(U x) { int? y = x; - _ = y.Value; // 3 - _ = ((int?)x).Value; // 4 + _ = y.Value; // 1 + _ = ((int?)x).Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); @@ -77147,26 +76636,17 @@ internal override void F(U x) // (9,18): error CS0029: Cannot implicitly convert type 'U' to 'int?' // int? y = x; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("U", "int?").WithLocation(9, 18), - // (10,13): warning CS8629: Nullable value type may be null. - // _ = y.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(10, 13), - // (11,13): warning CS8629: Nullable value type may be null. - // _ = ((int?)x).Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "((int?)x).Value").WithLocation(11, 13), // (11,14): error CS0030: Cannot convert type 'U' to 'int?' - // _ = ((int?)x).Value; // 2 + // _ = ((int?)x).Value; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(int?)x").WithArguments("U", "int?").WithLocation(11, 14), // (18,18): error CS0029: Cannot implicitly convert type 'U' to 'int?' // int? y = x; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("U", "int?").WithLocation(18, 18), // (19,13): warning CS8629: Nullable value type may be null. - // _ = y.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(19, 13), - // (20,13): warning CS8629: Nullable value type may be null. - // _ = ((int?)x).Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "((int?)x).Value").WithLocation(20, 13), + // _ = y.Value; // 1 + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(19, 13), // (20,14): error CS0030: Cannot convert type 'U' to 'int?' - // _ = ((int?)x).Value; // 4 + // _ = ((int?)x).Value; // 2 Diagnostic(ErrorCode.ERR_NoExplicitConv, "(int?)x").WithArguments("U", "int?").WithLocation(20, 14)); } @@ -77234,14 +76714,18 @@ internal override void F(int? t) if (t == null) return; U u = (U)(object?)t; object? o = u; - o.ToString(); + o.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Possible dereference of a null reference. // o.ToString(); // 1 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(11, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(11, 9), + // (21,9): warning CS8602: Possible dereference of a null reference. + // o.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(21, 9) + ); } [Fact] @@ -77253,8 +76737,8 @@ public void NullableT_Box() static void F1(T? x1, T? y1) where T : struct { if (x1 == null) return; - ((object?)x1).ToString(); - ((object?)y1).ToString(); // 1 + ((object?)x1).ToString(); // 1 + ((object?)y1).ToString(); // 2 } static void F2(T? x2, T? y2) where T : struct { @@ -77262,17 +76746,21 @@ static void F2(T? x2, T? y2) where T : struct object? z2 = x2; z2.ToString(); object? w2 = y2; - w2.ToString(); // 2 + w2.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( + // (6,10): warning CS8602: Possible dereference of a null reference. + // ((object?)x1).ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object?)x1").WithLocation(6, 10), // (7,10): warning CS8602: Possible dereference of a null reference. - // ((object?)y1).ToString(); // 1 + // ((object?)y1).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object?)y1").WithLocation(7, 10), // (15,9): warning CS8602: Possible dereference of a null reference. - // w2.ToString(); // 2 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w2").WithLocation(15, 9)); + // w2.ToString(); // 3 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w2").WithLocation(15, 9) + ); } [Fact] @@ -77287,7 +76775,7 @@ class B1 : A { internal override void F(U x) { - ((object?)x).ToString(); + ((object?)x).ToString(); // 1 object y = x; y.ToString(); } @@ -77296,19 +76784,23 @@ class B2 : A { internal override void F(U x) { - ((object?)x).ToString(); // 1 + ((object?)x).ToString(); // 2 object? y = x; - y.ToString(); // 2 + y.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (18,10): warning CS8602: Possible dereference of a null reference. + // (9,10): warning CS8602: Possible dereference of a null reference. // ((object?)x).ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object?)x").WithLocation(9, 10), + // (18,10): warning CS8602: Possible dereference of a null reference. + // ((object?)x).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object?)x").WithLocation(18, 10), // (20,9): warning CS8602: Possible dereference of a null reference. - // y.ToString(); // 2 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(20, 9)); + // y.ToString(); // 3 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(20, 9) + ); } [Fact] @@ -77332,12 +76824,13 @@ static void F2(object x2, object? y2) where T : struct }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (6,13): warning CS8629: Nullable value type may be null. + // (6,14): warning CS8629: Nullable value type may be null. // _ = ((T?)y1).Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "((T?)y1).Value").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T?)y1").WithLocation(6, 14), // (13,13): warning CS8629: Nullable value type may be null. // _ = w2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "w2.Value").WithLocation(13, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "w2").WithLocation(13, 13) + ); } [Fact] @@ -77373,12 +76866,13 @@ internal override void F(object? x) // (16,20): error CS1061: 'U' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'U' could be found (are you missing a using directive or an assembly reference?) // _ = ((U)x).Value; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Value").WithArguments("U", "Value").WithLocation(16, 20), - // (17,13): warning CS8629: Nullable value type may be null. + // (17,14): warning CS8629: Nullable value type may be null. // _ = ((int?)(object)(U)x).Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "((int?)(object)(U)x).Value").WithLocation(17, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(int?)(object)(U)x").WithLocation(17, 14), // (17,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // _ = ((int?)(object)(U)x).Value; // 1 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)(U)x").WithLocation(17, 20)); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)(U)x").WithLocation(17, 20) + ); } [Fact] @@ -77406,10 +76900,11 @@ static void F2(dynamic x2, dynamic? y2) where T : struct comp.VerifyDiagnostics( // (8,13): warning CS8629: Nullable value type may be null. // _ = w1.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "w1.Value").WithLocation(8, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "w1").WithLocation(8, 13), // (15,13): warning CS8629: Nullable value type may be null. // _ = w2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "w2.Value").WithLocation(15, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "w2").WithLocation(15, 13) + ); } [Fact] @@ -77430,14 +76925,18 @@ static void F(S? x, S? y) ni = x?.F; _ = ni.Value; // 1 ni = y?.F; - _ = ni.Value; + _ = ni.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8629: Nullable value type may be null. // _ = ni.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ni.Value").WithLocation(13, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ni").WithLocation(13, 13), + // (15,13): warning CS8629: Nullable value type may be null. + // _ = ni.Value; // 2 + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ni").WithLocation(15, 13) + ); } [Fact] @@ -77463,13 +76962,14 @@ static void F(bool b, int? x, int? y) comp.VerifyDiagnostics( // (7,17): warning CS8629: Nullable value type may be null. // _ = x.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.Value").WithLocation(7, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(7, 17), // (8,17): warning CS8629: Nullable value type may be null. // _ = y.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(8, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(8, 17), // (12,17): warning CS8629: Nullable value type may be null. // _ = x.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.Value").WithLocation(12, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(12, 17) + ); } [Fact] @@ -77493,10 +76993,11 @@ static void F2(int x, int? y) comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = y.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(6, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(6, 13), // (11,13): warning CS8629: Nullable value type may be null. // _ = z.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z.Value").WithLocation(11, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z").WithLocation(11, 13) + ); } [WorkItem(31500, "https://github.com/dotnet/roslyn/issues/31500")] @@ -77521,13 +77022,7 @@ static void F2(int x, int? y) }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/31500: Track nullable state across lifted conversions. - comp.VerifyDiagnostics( - // (7,13): warning CS8629: Nullable value type may be null. - // _ = y.Value; - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(7, 13), - // (13,13): warning CS8629: Nullable value type may be null. - // _ = z.Value; - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z.Value").WithLocation(13, 13)); + comp.VerifyDiagnostics(); } [WorkItem(31500, "https://github.com/dotnet/roslyn/issues/31500")] @@ -77567,10 +77062,11 @@ static void F2(A? a) comp.VerifyDiagnostics( // (13,13): warning CS8629: Nullable value type may be null. // _ = b.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b.Value").WithLocation(13, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b").WithLocation(13, 13), // (25,17): warning CS8629: Nullable value type may be null. // _ = b2.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b2.Value").WithLocation(25, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b2").WithLocation(25, 17) + ); } [Fact] @@ -77606,9 +77102,7 @@ static void F(T? t) where T : struct }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (6,13): hidden CS8607: Expression is probably never null. - // _ = t ?? default(T); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "t").WithLocation(6, 13)); + ); } [Fact] @@ -77633,7 +77127,8 @@ static void F(T? t) where T : struct Diagnostic(ErrorCode.ERR_AssgReadonlyProp, "t.Value").WithArguments("T?.Value").WithLocation(6, 9), // (6,9): warning CS8629: Nullable value type may be null. // t.Value = default(T); - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Value").WithLocation(6, 9)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t").WithLocation(6, 9) + ); } [Fact] @@ -77646,17 +77141,14 @@ class Program static void F() { var s = (S?)F; - _ = s.Value; // 1 + _ = s.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,18): error CS0030: Cannot convert type 'method' to 'S?' // var s = (S?)F; - Diagnostic(ErrorCode.ERR_NoExplicitConv, "(S?)F").WithArguments("method", "S?").WithLocation(6, 18), - // (7,13): warning CS8629: Nullable value type may be null. - // _ = s.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s.Value").WithLocation(7, 13)); + Diagnostic(ErrorCode.ERR_NoExplicitConv, "(S?)F").WithArguments("method", "S?").WithLocation(6, 18)); } [Fact] @@ -77699,33 +77191,7 @@ static void F4(T? t4) where T : struct } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); - // https://github.com/dotnet/roslyn/issues/31516: Report HDN_NullCheckIsProbablyAlwaysTrue/False - // when HasValue check is unnecessary. - comp.VerifyDiagnostics( - // (8,13): hidden CS8605: Result of the comparison is possibly always true. - // if (t1 != null) { } // always false - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "t1 != null").WithLocation(8, 13), - // (9,13): hidden CS8606: Result of the comparison is possibly always false. - // if (t1 == null) { } // always true - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "t1 == null").WithLocation(9, 13), - // (14,13): hidden CS8606: Result of the comparison is possibly always false. - // if (t2 == null) { } // always false - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "t2 == null").WithLocation(14, 13), - // (15,13): hidden CS8605: Result of the comparison is possibly always true. - // if (t2 != null) { } // always true - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "t2 != null").WithLocation(15, 13), - // (24,13): hidden CS8606: Result of the comparison is possibly always false. - // if (t3 == null) { } // always true - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "t3 == null").WithLocation(24, 13), - // (25,13): hidden CS8605: Result of the comparison is possibly always true. - // if (t3 != null) { } // always false - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "t3 != null").WithLocation(25, 13), - // (30,13): hidden CS8605: Result of the comparison is possibly always true. - // if (t4 != null) { } // always true - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue, "t4 != null").WithLocation(30, 13), - // (31,13): hidden CS8606: Result of the comparison is possibly always false. - // if (t4 == null) { } // always false - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "t4 == null").WithLocation(31, 13)); + comp.VerifyDiagnostics(); } [Fact] @@ -77765,33 +77231,34 @@ static void F6(U x6) where T : struct, U }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (5,13): warning CS8629: Nullable value type may be null. + // (5,14): warning CS8629: Nullable value type may be null. // _ = (x1 as T?).Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(x1 as T?).Value").WithLocation(5, 13), - // (6,13): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x1 as T?").WithLocation(5, 14), + // (6,14): warning CS8629: Nullable value type may be null. // _ = (y1 as T?).Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(y1 as T?).Value").WithLocation(6, 13), - // (11,13): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1 as T?").WithLocation(6, 14), + // (11,14): warning CS8629: Nullable value type may be null. // _ = (y2 as T?).Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(y2 as T?).Value").WithLocation(11, 13), - // (15,13): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2 as T?").WithLocation(11, 14), + // (15,14): warning CS8629: Nullable value type may be null. // _ = (x3 as T?).Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(x3 as T?).Value").WithLocation(15, 13), - // (19,13): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3 as T?").WithLocation(15, 14), + // (19,14): warning CS8629: Nullable value type may be null. // _ = (x4 as T?).Value; // 5 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(x4 as T?).Value").WithLocation(19, 13), - // (20,13): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x4 as T?").WithLocation(19, 14), + // (20,14): warning CS8629: Nullable value type may be null. // _ = (y4 as T?).Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(y4 as T?).Value").WithLocation(20, 13), - // (24,13): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y4 as T?").WithLocation(20, 14), + // (24,14): warning CS8629: Nullable value type may be null. // _ = (x5 as T?).Value; // 7 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(x5 as T?).Value").WithLocation(24, 13), - // (25,13): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x5 as T?").WithLocation(24, 14), + // (25,14): warning CS8629: Nullable value type may be null. // _ = (y5 as T?).Value; // 8 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(y5 as T?).Value").WithLocation(25, 13), - // (29,13): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y5 as T?").WithLocation(25, 14), + // (29,14): warning CS8629: Nullable value type may be null. // _ = (x6 as T?).Value; // 9 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(x6 as T?).Value").WithLocation(29, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x6 as T?").WithLocation(29, 14) + ); } [Fact] @@ -77849,12 +77316,12 @@ static void F5(T? t5) where T : struct // (9,18): warning CS8602: Possible dereference of a null reference. // _ = (t1 as object).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1 as object").WithLocation(9, 18), - // (13,13): warning CS8629: Nullable value type may be null. + // (13,14): warning CS8629: Nullable value type may be null. // _ = (t2 as T?).Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(t2 as T?).Value").WithLocation(13, 13), - // (17,17): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2 as T?").WithLocation(13, 14), + // (17,18): warning CS8629: Nullable value type may be null. // _ = (t2 as T?).Value; // 4 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(t2 as T?).Value").WithLocation(17, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2 as T?").WithLocation(17, 18), // (21,14): warning CS8602: Possible dereference of a null reference. // _ = (t3 as U).ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3 as U").WithLocation(21, 14), @@ -77864,21 +77331,22 @@ static void F5(T? t5) where T : struct // (25,18): warning CS8602: Possible dereference of a null reference. // _ = (t3 as U).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3 as U").WithLocation(25, 18), - // (29,13): warning CS8629: Nullable value type may be null. + // (29,14): warning CS8629: Nullable value type may be null. // _ = (t4 as U?).Value; // 8 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(t4 as U?).Value").WithLocation(29, 13), - // (31,17): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4 as U?").WithLocation(29, 14), + // (31,18): warning CS8629: Nullable value type may be null. // _ = (t4 as U?).Value; // 9 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(t4 as U?).Value").WithLocation(31, 17), - // (33,17): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4 as U?").WithLocation(31, 18), + // (33,18): warning CS8629: Nullable value type may be null. // _ = (t4 as U?).Value; // 10 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(t4 as U?).Value").WithLocation(33, 17), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4 as U?").WithLocation(33, 18), // (37,14): warning CS8602: Possible dereference of a null reference. // _ = (t5 as dynamic).ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5 as dynamic").WithLocation(37, 14), // (41,18): warning CS8602: Possible dereference of a null reference. // _ = (t5 as dynamic).ToString(); // 12 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5 as dynamic").WithLocation(41, 18)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5 as dynamic").WithLocation(41, 18) + ); } [Fact] @@ -77908,12 +77376,13 @@ internal override void F(U u) // so those conversions are not handled in NullableWalker either. var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (10,13): warning CS8629: Nullable value type may be null. + // (10,14): warning CS8629: Nullable value type may be null. // _ = (u as int?).Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(u as int?).Value").WithLocation(10, 13), - // (17,13): warning CS8629: Nullable value type may be null. + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u as int?").WithLocation(10, 14), + // (17,14): warning CS8629: Nullable value type may be null. // _ = (u as int?).Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(u as int?).Value").WithLocation(17, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u as int?").WithLocation(17, 14) + ); } [Fact] @@ -77943,18 +77412,19 @@ internal override void F(int? t) // so those conversions are not handled in NullableWalker either. var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (9,13): warning CS8629: Nullable value type may be null. + // (9,14): warning CS8629: Nullable value type may be null. // _ = (t as U?).Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(t as U?).Value").WithLocation(9, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t as U?").WithLocation(9, 14), // (16,14): error CS0413: The type parameter 'U' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint // _ = (t as U).Value; // 2 Diagnostic(ErrorCode.ERR_AsWithTypeVar, "t as U").WithArguments("U").WithLocation(16, 14), - // (17,13): warning CS8629: Nullable value type may be null. + // (17,14): warning CS8629: Nullable value type may be null. // _ = (t as U?).Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(t as U?).Value").WithLocation(17, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t as U?").WithLocation(17, 14), // (17,19): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // _ = (t as U?).Value; // 3 - Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "U?").WithArguments("System.Nullable", "T", "U").WithLocation(17, 19)); + Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "U?").WithArguments("System.Nullable", "T", "U").WithLocation(17, 19) + ); } [WorkItem(31501, "https://github.com/dotnet/roslyn/issues/31501")] @@ -78004,7 +77474,8 @@ static void F(T x, T? y, T? z) where T : struct comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = z.Value!; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z.Value").WithLocation(11, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z").WithLocation(11, 13) + ); } [Fact] @@ -78030,7 +77501,8 @@ static void G(T? t) where T : struct comp.VerifyDiagnostics( // (13,17): warning CS8629: Nullable value type may be null. // _ = t.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Value").WithLocation(13, 17)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t").WithLocation(13, 17) + ); } [Fact] @@ -78090,7 +77562,8 @@ static void F6(T? t6) comp.VerifyDiagnostics( // (9,13): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2.Value").WithLocation(9, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(9, 13) + ); } [Fact] @@ -78119,10 +77592,11 @@ static void F2(T? t) where T : struct, IDisposable comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s.Value").WithLocation(11, 13), + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s").WithLocation(11, 13), // (16,13): warning CS8629: Nullable value type may be null. // _ = t.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Value").WithLocation(16, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t").WithLocation(16, 13) + ); } [WorkItem(31503, "https://github.com/dotnet/roslyn/issues/31503")] @@ -78458,7 +77932,7 @@ static void F(T? x, object y) comp.VerifyTypes(); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33344")] [WorkItem(32575, "https://github.com/dotnet/roslyn/issues/32575")] public void BestType_DifferentTupleNullability_10() { @@ -78468,10 +77942,10 @@ public void BestType_DifferentTupleNullability_10() static void F(bool b, T t, U u) where U : class { - var x = (b ? (t, u) : default)/*T:(T t, U u)*/; + var x = (b ? (t, u) : default)/*T:(T t, U? u)*/; x.Item1.ToString(); // 1 x.Item2.ToString(); // 2 - var y = (b ? default : (t, u))/*T:(T t, U u)*/; + var y = (b ? default : (t, u))/*T:(T t, U? u)*/; y.Item1.ToString(); // 3 y.Item2.ToString(); // 4 } @@ -78483,13 +77957,21 @@ static void F(bool b, T t, U u) // x.Item1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item1").WithLocation(7, 9), // (10,9): warning CS8602: Possible dereference of a null reference. + // x.Item2.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item2").WithLocation(8, 9), + // (10,9): warning CS8602: Possible dereference of a null reference. // y.Item1.ToString(); // 3 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(10, 9)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(10, 9), + // (10,9): warning CS8602: Possible dereference of a null reference. + // y.Item2.ToString(); // 4 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item2").WithLocation(11, 9) + ); comp.VerifyTypes(); } [Fact] [WorkItem(32575, "https://github.com/dotnet/roslyn/issues/32575")] + [WorkItem(33344, "https://github.com/dotnet/roslyn/issues/33344")] public void BestType_DifferentTupleNullability_11() { var source = @@ -78498,23 +77980,19 @@ public void BestType_DifferentTupleNullability_11() static void F(T t, U u) where U : class { - var x = new[] { (t, u), default }[0]/*T:(T t, U u)*/; + var x = new[] { (t, u), default }[0]/*T:(T t, U u)*/; // should be (T t, U? u) x.Item1.ToString(); // 1 x.Item2.ToString(); // 2 - var y = new[] { default, (t, u) }[0]/*T:(T t, U u)*/; + var y = new[] { default, (t, u) }[0]/*T:(T t, U u)*/; // should be (T t, U? u) y.Item1.ToString(); // 3 y.Item2.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); - // https://github.com/dotnet/roslyn/issues/32575: Not handling default for U. comp.VerifyDiagnostics( - // (7,9): warning CS8602: Possible dereference of a null reference. - // x.Item1.ToString(); // 1 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item1").WithLocation(7, 9), - // (10,9): warning CS8602: Possible dereference of a null reference. - // y.Item1.ToString(); // 3 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(10, 9)); + // https://github.com/dotnet/roslyn/issues/32575: Not handling default for U. + // SHOULD BE 4 diagnostics. + ); comp.VerifyTypes(); } @@ -78527,22 +78005,17 @@ public void BestType_DifferentTupleNullability_12() static void F(bool b, U? u) where U : struct { - var t = b ? (t, u) : default; + var t = b ? (1, u) : default; t.Item1.ToString(); _ = t.Item2.Value; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (6,22): error CS0841: Cannot use local variable 't' before it is declared - // var t = b ? (t, u) : default; - Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "t").WithArguments("t").WithLocation(6, 22), - // (6,22): error CS0165: Use of unassigned local variable 't' - // var t = b ? (t, u) : default; - Diagnostic(ErrorCode.ERR_UseDefViolation, "t").WithArguments("t").WithLocation(6, 22), // (8,13): warning CS8629: Nullable value type may be null. // _ = t.Item2.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2.Value").WithLocation(8, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2").WithLocation(8, 13) + ); } [Fact] @@ -78554,22 +78027,17 @@ public void BestType_DifferentTupleNullability_13() static void F(U? u) where U : struct { - var t = new[] { (t, u), default }[0]; + var t = new[] { (1, u), default }[0]; t.Item1.ToString(); _ = t.Item2.Value; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (6,26): error CS0841: Cannot use local variable 't' before it is declared - // var t = new[] { (t, u), default }[0]; - Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "t").WithArguments("t").WithLocation(6, 26), - // (6,26): error CS0165: Use of unassigned local variable 't' - // var t = new[] { (t, u), default }[0]; - Diagnostic(ErrorCode.ERR_UseDefViolation, "t").WithArguments("t").WithLocation(6, 26), // (8,13): warning CS8629: Nullable value type may be null. // _ = t.Item2.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2.Value").WithLocation(8, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2").WithLocation(8, 13) + ); } [WorkItem(32006, "https://github.com/dotnet/roslyn/issues/32006")] @@ -78951,21 +78419,13 @@ void M(C? c1, C c2, C c3) // (19,9): warning CS8602: Possible dereference of a null reference. // c1.F.ToString(); // Warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1.F").WithLocation(19, 9), - // (21,13): hidden CS8606: Result of the comparison is possibly always false. - // if (c1.F == null) return; // Hidden 3 - Diagnostic(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse, "c1.F == null").WithLocation(21, 13), - // (22,9): hidden CS8607: Expression is probably never null. - // c1 ??= c2; // Hidden 4 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c1").WithLocation(22, 9), // (23,9): warning CS8602: Possible dereference of a null reference. // c1.F.ToString(); // Warn 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1.F").WithLocation(23, 9), // (27,9): warning CS8602: Possible dereference of a null reference. // (c1 ??= c3).F.ToString(); // Warn 6, Hidden 7 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(c1 ??= c3).F").WithLocation(27, 9), - // (27,10): hidden CS8607: Expression is probably never null. - // (c1 ??= c3).F.ToString(); // Warn 6, Hidden 7 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c1").WithLocation(27, 10)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(c1 ??= c3).F").WithLocation(27, 9) + ); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] @@ -79025,16 +78485,15 @@ void M(C? c1, C c2) C c3 #nullable enable = (c1 ??= GetC()); - _ = c1/*T:C*/; - _ = c3/*T:C*/; + _ = c1/*T:C!*/; + _ = c3/*T:C!*/; // oblivious + nullable = nullable - // This one is a little weirder. The ??= on c3 forces it into either nullable or not nullable, so we must - // pick the nullable version, meaning the resulting expression is actually nullable + nullable = nullable. + // Since c3 is non-nullable, the result is non-nullable. c1 = null; var c4 = (c3 ??= c1); - _ = c3/*T:C?*/; - _ = c4/*T:C?*/; + _ = c3/*T:C!*/; + _ = c4/*T:C!*/; // oblivious + not nullable = not nullable c3 = GetC(); @@ -79050,10 +78509,7 @@ C c3 }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); - comp.VerifyDiagnostics( - // (30,19): hidden CS8607: Expression is probably never null. - // var c6 = (c2 ??= GetC()); - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c2").WithLocation(32, 19)); + comp.VerifyDiagnostics(); comp.VerifyTypes(); } @@ -79099,9 +78555,6 @@ void M1(C c1, C? c2) var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (6,9): hidden CS8607: Expression is probably never null. - // M2(c1) ??= c2; // Warn 1, 2 - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "M2(c1)").WithLocation(6, 9), // (6,20): warning CS8601: Possible null reference assignment. // M2(c1) ??= c2; // Warn 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "c2").WithLocation(6, 20), @@ -79148,9 +78601,6 @@ void M1(C? c1, C c2, C c3, C? c4) // (6,16): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // c1 ??= c2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c2").WithArguments("C", "C").WithLocation(6, 16), - // (7,9): hidden CS8607: Expression is probably never null. - // c3 ??= c4; - Diagnostic(ErrorCode.HDN_ExpressionIsProbablyNeverNull, "c3").WithLocation(7, 9), // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // c3 ??= c4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c4").WithLocation(7, 16), @@ -79244,9 +78694,9 @@ static void F() where U : class }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (5,23): warning CS8600: Converting null literal or possible null value to non-nullable type. + // (5,23): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // (T x, U y) = (default, default); // 1, 2 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(5, 23), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(5, 23), // (5,32): warning CS8600: Converting null literal or possible null value to non-nullable type. // (T x, U y) = (default, default); // 1, 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(5, 32), @@ -80554,7 +80004,7 @@ static void F(S s) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Value.F").WithLocation(13, 9), // (14,13): warning CS8629: Nullable value type may be null. // _ = z.Value; // 2 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z.Value").WithLocation(14, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z").WithLocation(14, 13)); } [Fact] @@ -80885,7 +80335,7 @@ static void F(ref int? x, ref int? y) comp.VerifyDiagnostics( // (8,13): warning CS8629: Nullable value type may be null. // _ = y.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(8, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(8, 13)); } [Fact] @@ -80909,7 +80359,7 @@ static void F(int? px, int? py) comp.VerifyDiagnostics( // (10,13): warning CS8629: Nullable value type may be null. // _ = y.Value; // 1 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Value").WithLocation(10, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(10, 13)); } [Fact] @@ -81260,7 +80710,7 @@ static void F4() where T4 : struct Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F").WithLocation(15, 9), // (25,13): warning CS8629: Nullable value type may be null. // _ = C.F.Value; // 3 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "C.F.Value").WithLocation(25, 13)); + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "C.F").WithLocation(25, 13)); } [Fact] @@ -81318,9 +80768,9 @@ static void F8() }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (10,19): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (10,19): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // C.F = default; // 1 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(10, 19), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(10, 19), // (11,9): warning CS8602: Possible dereference of a null reference. // C.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F").WithLocation(11, 9), @@ -81396,9 +80846,9 @@ static void F8() }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (13,19): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (13,19): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // C.P = default; // 1 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(13, 19), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(13, 19), // (14,9): warning CS8602: Possible dereference of a null reference. // C.P.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.P").WithLocation(14, 9), @@ -81446,9 +80896,9 @@ static void F3() where T3 : class }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (10,19): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (10,19): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // S.F = default; // 1 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(10, 19), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(10, 19), // (11,9): warning CS8602: Possible dereference of a null reference. // S.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "S.F").WithLocation(11, 9), @@ -81489,9 +80939,9 @@ static void F3() where T3 : class }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (9,19): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (9,19): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // S.P = default; // 1 - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(9, 19), + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(9, 19), // (10,9): warning CS8602: Possible dereference of a null reference. // S.P.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "S.P").WithLocation(10, 9), @@ -81632,5 +81082,118 @@ static void F() // return (null, string.Empty); Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithLocation(9, 13)); } + + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33347")] + public void NestedNullConditionalAccess() + { + var source = +@"class Node +{ + public Node? Next = null; + void M(Node node) { } + private static void Test(Node? node) + { + node?.Next?.Next?.M(node.Next); + } +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + comp.VerifyDiagnostics(); + } + + [Fact] + public void ConditionalAccess() + { + var source = +@"class C +{ + void M1(C c, C[] a) + { + _ = (c?.S).Length; + _ = (a?[0]).P; + } + void M2(T t) where T : I + { + if (t == null) return; + _ = (t?.S).Length; + _ = (t?[0]).P; + } + int P { get => 0; } + string S => throw null!; +} +interface I +{ + string S { get; } + C this[int i] { get; } +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + comp.VerifyDiagnostics( + // (5,14): warning CS8602: Possible dereference of a null reference. + // _ = (c?.S).Length; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c?.S").WithLocation(5, 14), + // (6,14): warning CS8602: Possible dereference of a null reference. + // _ = (a?[0]).P; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a?[0]").WithLocation(6, 14), + // (11,14): warning CS8602: Possible dereference of a null reference. + // _ = (t?.S).Length; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t?.S").WithLocation(11, 14), + // (12,14): warning CS8602: Possible dereference of a null reference. + // _ = (t?[0]).P; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t?[0]").WithLocation(12, 14) + ); + } + + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33615")] + public void TestSubsituteMemberOfTuple() + { + var source = +@"using System; + +class C +{ + static void Main() + { + Console.WriteLine(Test(42)); + } + + public static Test(object? a) + { + if (a == null) return; + var x = (f1: a, f2: a); + Func f = () => x.Test(a); + f(); } } + +namespace System +{ + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + + public U Test(U val) + { + return val; + } + } +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + comp.VerifyDiagnostics(); + } + } +} + diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UninitializedNonNullableFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UninitializedNonNullableFieldTests.cs index 8f8daf1596fa7..5e3299cd2aadf 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UninitializedNonNullableFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UninitializedNonNullableFieldTests.cs @@ -42,12 +42,12 @@ public void UnconstrainedGenericType() // (3,16): warning CS0649: Field 'C.F1' is never assigned to, and will always have its default value // internal T F1; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("C.F1", "").WithLocation(3, 16), - // (5,21): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // (5,21): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // internal T F3 = default; - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(5, 21), - // (6,21): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(5, 21), + // (6,21): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // internal T F4 = default(T); - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T)").WithLocation(6, 21)); + Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(6, 21)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs index 94f9e5c6449e3..f8d2ef83d1bec 100644 --- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs +++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs @@ -297,6 +297,10 @@ public void WarningLevel_2() case ErrorCode.WRN_CaseConstantNamedUnderscore: case ErrorCode.ERR_FeatureInPreview: case ErrorCode.WRN_PossibleNull: + case ErrorCode.WRN_ConditionalAccessMayReturnNull: + case ErrorCode.WRN_AsOperatorMayReturnNull: + case ErrorCode.WRN_DefaultExpressionMayIntroduceNullT: + case ErrorCode.WRN_NullLiteralMayIntroduceNullT: Assert.Equal(1, ErrorFacts.GetWarningLevel(errorCode)); break; case ErrorCode.WRN_InvalidVersionFormat: diff --git a/src/Compilers/Test/Utilities/CSharp/CompilationTestUtils.cs b/src/Compilers/Test/Utilities/CSharp/CompilationTestUtils.cs index 12563d2dae4c3..669a27db13a6b 100644 --- a/src/Compilers/Test/Utilities/CSharp/CompilationTestUtils.cs +++ b/src/Compilers/Test/Utilities/CSharp/CompilationTestUtils.cs @@ -322,7 +322,7 @@ internal static void VerifyTypes(this CSharpCompilation compilation, SyntaxTree // Consider reporting the correct source with annotations on mismatch. AssertEx.Equal(expectedTypes, actualTypes, message: method.ToTestDisplayString()); - foreach (var entry in dictionary.Values.Where(v => !v.IsNull)) + foreach (var entry in dictionary.Values.Where(v => v.HasType)) { // Result types cannot have nested types that are unspeakables Assert.Null(entry.VisitType(typeOpt: null, @@ -335,9 +335,9 @@ string toDisplayString(SyntaxNode syntaxOpt) // We don't support VerifyTypes on suppressions at the moment Assert.NotEqual(syntaxOpt.Kind(), SyntaxKind.SuppressNullableWarningExpression); - return (syntaxOpt != null) && dictionary.TryGetValue(syntaxOpt, out var type) - ? (type.IsNull ? "" : type.ToDisplayString(TypeSymbolWithAnnotations.TestDisplayFormat)) - : null; + return (syntaxOpt != null) && dictionary.TryGetValue(syntaxOpt, out var type) ? + (!type.HasType ? "" : type.ToDisplayString(TypeSymbolWithAnnotations.TestDisplayFormat)) : + null; } } diff --git a/src/Compilers/Test/Utilities/CSharp/UsesIsNullableVisitor.cs b/src/Compilers/Test/Utilities/CSharp/UsesIsNullableVisitor.cs index bb1fed49f63e4..df026a0729e31 100644 --- a/src/Compilers/Test/Utilities/CSharp/UsesIsNullableVisitor.cs +++ b/src/Compilers/Test/Utilities/CSharp/UsesIsNullableVisitor.cs @@ -146,7 +146,7 @@ private bool AddIfUsesIsNullable(Symbol symbol, TypeSymbol type, ConsList inProgress) { - if (type.IsNull) + if (!type.HasType) { return false; }