From 0610c79807fa59d0815f2b89e5283cf6d630b71e Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Mon, 10 Dec 2018 14:14:48 -0800 Subject: [PATCH] Remove remaining artifacts of symbol-centric NonNullTypes context. (#31607) Closes #30171. Closes #29838. --- ...spaceOrTypeOrAliasSymbolWithAnnotations.cs | 32 +- .../CSharp/Portable/Binder/Binder.cs | 22 +- .../Portable/Binder/Binder_Constraints.cs | 17 +- .../Portable/Binder/Binder_Deconstruct.cs | 4 +- .../CSharp/Portable/Binder/Binder_Patterns.cs | 4 +- .../CSharp/Portable/Binder/Binder_Symbols.cs | 97 +- .../Portable/Binder/Binder_TupleOperators.cs | 2 +- .../Portable/Binder/BuckStopsHereBinder.cs | 5 + .../Binder/Semantics/INonNullTypesContext.cs | 27 - .../Binder/WithNullableContextBinder.cs | 26 + .../OutDeconstructVarPendingInference.cs | 2 +- .../Portable/BoundTree/UnboundLambda.cs | 2 +- .../BoundTree/VariablePendingInference.cs | 2 +- .../Compilation/CSharpSemanticModel.cs | 2 + ...issingNonNullTypesContextDiagnosticInfo.cs | 18 +- .../LazyNullAsNonNullableDiagnosticInfo.cs | 26 - ...zyNullableContraintChecksDiagnosticInfo.cs | 45 - .../SymbolDisplayVisitor.Types.cs | 18 +- .../Portable/Symbols/ErrorTypeSymbol.cs | 2 - .../CSharp/Portable/Symbols/EventSymbol.cs | 9 - .../CSharp/Portable/Symbols/FieldSymbol.cs | 9 - .../CSharp/Portable/Symbols/LocalSymbol.cs | 8 - .../Symbols/Metadata/PE/PEEventSymbol.cs | 8 - .../Symbols/Metadata/PE/PEFieldSymbol.cs | 8 - .../Symbols/Metadata/PE/PEMethodSymbol.cs | 8 - .../Symbols/Metadata/PE/PEModuleSymbol.cs | 8 - .../Symbols/Metadata/PE/PENamedTypeSymbol.cs | 8 - .../Symbols/Metadata/PE/PEPropertySymbol.cs | 8 - .../Symbols/Metadata/PE/SymbolFactory.cs | 5 +- .../CSharp/Portable/Symbols/MethodSymbol.cs | 8 - .../Portable/Symbols/MissingModuleSymbol.cs | 2 - .../Portable/Symbols/NamedTypeSymbol.cs | 38 +- .../Portable/Symbols/ParameterSymbol.cs | 9 - .../CSharp/Portable/Symbols/PropertySymbol.cs | 9 - .../Retargeting/RetargetingEventSymbol.cs | 8 - .../Retargeting/RetargetingFieldSymbol.cs | 8 - .../Retargeting/RetargetingMethodSymbol.cs | 8 - .../Retargeting/RetargetingModuleSymbol.cs | 8 - .../Retargeting/RetargetingNamedTypeSymbol.cs | 8 - .../Retargeting/RetargetingPropertySymbol.cs | 8 - .../Symbols/SignatureOnlyMethodSymbol.cs | 2 - .../FieldSymbolWithAttributesAndModifiers.cs | 8 - .../Source/GlobalExpressionVariable.cs | 2 +- .../Portable/Symbols/Source/LambdaSymbol.cs | 2 +- .../Symbols/Source/SourceAssemblySymbol.cs | 8 - .../Source/SourceComplexParameterSymbol.cs | 4 +- .../Symbols/Source/SourceConstructorSymbol.cs | 2 +- .../Source/SourceDelegateMethodSymbol.cs | 8 +- .../Source/SourceEventAccessorSymbol.cs | 8 +- .../Symbols/Source/SourceEventSymbol.cs | 8 - .../Symbols/Source/SourceMemberFieldSymbol.cs | 4 +- .../Source/SourceMemberMethodSymbol.cs | 8 - .../Symbols/Source/SourceModuleSymbol.cs | 8 - .../Symbols/Source/SourceNamedTypeSymbol.cs | 8 - .../Source/SourcePropertyAccessorSymbol.cs | 2 +- .../Symbols/Source/SourcePropertySymbol.cs | 8 - .../Source/SourceTypeParameterSymbol.cs | 12 +- .../Source/TypeParameterConstraintClause.cs | 15 + .../Symbols/SubstitutedMethodSymbol.cs | 2 - .../Symbols/SubstitutedNamedTypeSymbol.cs | 2 - .../CSharp/Portable/Symbols/Symbol.cs | 40 +- .../SynthesizedEntryPointSymbol.cs | 6 +- .../SynthesizedImplementationMethod.cs | 2 - ...SynthesizedInteractiveInitializerMethod.cs | 4 +- .../Symbols/Tuples/TupleMethodSymbol.cs | 2 - .../CSharp/Portable/Symbols/TypeMap.cs | 6 +- .../Portable/Symbols/TypeParameterSymbol.cs | 8 - .../Symbols/TypeSymbolWithAnnotations.cs | 10 +- .../Semantics/NullableReferenceTypesTests.cs | 1254 ++++++++++++++--- 69 files changed, 1300 insertions(+), 699 deletions(-) delete mode 100644 src/Compilers/CSharp/Portable/Binder/Semantics/INonNullTypesContext.cs create mode 100644 src/Compilers/CSharp/Portable/Binder/WithNullableContextBinder.cs delete mode 100644 src/Compilers/CSharp/Portable/Errors/LazyNullAsNonNullableDiagnosticInfo.cs delete mode 100644 src/Compilers/CSharp/Portable/Errors/LazyNullableContraintChecksDiagnosticInfo.cs diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.NamespaceOrTypeOrAliasSymbolWithAnnotations.cs b/src/Compilers/CSharp/Portable/Binder/Binder.NamespaceOrTypeOrAliasSymbolWithAnnotations.cs index 2bf5f668741..3ae271a9e6e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.NamespaceOrTypeOrAliasSymbolWithAnnotations.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.NamespaceOrTypeOrAliasSymbolWithAnnotations.cs @@ -11,13 +11,22 @@ internal struct NamespaceOrTypeOrAliasSymbolWithAnnotations { private readonly TypeSymbolWithAnnotations _type; private readonly Symbol _symbol; + private readonly bool _isNullableEnabled; - private NamespaceOrTypeOrAliasSymbolWithAnnotations(TypeSymbolWithAnnotations type, Symbol symbol) + private NamespaceOrTypeOrAliasSymbolWithAnnotations(TypeSymbolWithAnnotations type) { - Debug.Assert(type.IsNull != (symbol is null)); - Debug.Assert(!(symbol is TypeSymbol)); + Debug.Assert(!type.IsNull); _type = type; + _symbol = null; + _isNullableEnabled = false; // Not meaningful for a TypeSymbolWithAnnotations, it already baked the fact into its content. + } + + private NamespaceOrTypeOrAliasSymbolWithAnnotations(Symbol symbol, bool isNullableEnabled) + { + Debug.Assert(!(symbol is TypeSymbol)); + _type = default; _symbol = symbol; + _isNullableEnabled = isNullableEnabled; } internal TypeSymbolWithAnnotations Type => _type; @@ -27,7 +36,16 @@ private NamespaceOrTypeOrAliasSymbolWithAnnotations(TypeSymbolWithAnnotations ty internal NamespaceOrTypeSymbol NamespaceOrTypeSymbol => Symbol as NamespaceOrTypeSymbol; internal bool IsDefault => _type.IsNull && _symbol is null; - internal static NamespaceOrTypeOrAliasSymbolWithAnnotations CreateUnannotated(INonNullTypesContext nonNullTypesContext, Symbol symbol) + internal bool IsNullableEnabled + { + get + { + Debug.Assert(_symbol?.Kind == SymbolKind.Alias); // Not meaningful to use this property otherwise + return _isNullableEnabled; + } + } + + internal static NamespaceOrTypeOrAliasSymbolWithAnnotations CreateUnannotated(bool isNullableEnabled, Symbol symbol) { if (symbol is null) { @@ -35,13 +53,13 @@ internal static NamespaceOrTypeOrAliasSymbolWithAnnotations CreateUnannotated(IN } var type = symbol as TypeSymbol; return type is null ? - new NamespaceOrTypeOrAliasSymbolWithAnnotations(default, symbol) : - new NamespaceOrTypeOrAliasSymbolWithAnnotations(TypeSymbolWithAnnotations.Create(nonNullTypesContext, type), null); + new NamespaceOrTypeOrAliasSymbolWithAnnotations(symbol, isNullableEnabled) : + new NamespaceOrTypeOrAliasSymbolWithAnnotations(TypeSymbolWithAnnotations.Create(isNullableEnabled, type)); } public static implicit operator NamespaceOrTypeOrAliasSymbolWithAnnotations(TypeSymbolWithAnnotations type) { - return new NamespaceOrTypeOrAliasSymbolWithAnnotations(type, null); + return new NamespaceOrTypeOrAliasSymbolWithAnnotations(type); } } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.cs b/src/Compilers/CSharp/Portable/Binder/Binder.cs index 288004f8380..2504c72c95f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.cs @@ -216,7 +216,27 @@ internal virtual Symbol ContainingMemberOrLambda /// /// Are we in a context where un-annotated types should be interpreted as non-null? /// - internal INonNullTypesContext NonNullTypesContext => (Flags & BinderFlags.InEEMethodBinder) == 0 ? ContainingMember().OriginalDefinition : NonNullTypesTrueContext.Instance; + internal bool IsNullableEnabled(SyntaxTree syntaxTree, int position) + { + bool? fromTree = ((CSharpSyntaxTree)syntaxTree).GetNullableDirectiveState(position); + + if (fromTree != null) + { + return fromTree.GetValueOrDefault(); + } + + return IsNullableGloballyEnabled(); + } + + internal bool IsNullableEnabled(SyntaxToken token) + { + return IsNullableEnabled(token.SyntaxTree, token.SpanStart); + } + + internal virtual bool IsNullableGloballyEnabled() + { + return Next.IsNullableGloballyEnabled(); + } /// /// Is the contained code within a member method body? diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs index d465325058c..3dbc626fd7c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs @@ -116,13 +116,24 @@ internal partial class Binder diagnostics.Add(ErrorCode.ERR_RefValBoundMustBeFirst, syntax.GetFirstToken().GetLocation()); } - SyntaxToken questionToken = ((ClassOrStructConstraintSyntax)syntax).QuestionToken; + var constraintSyntax = (ClassOrStructConstraintSyntax)syntax; + SyntaxToken questionToken = constraintSyntax.QuestionToken; if (questionToken.IsKind(SyntaxKind.QuestionToken)) { constraints |= TypeParameterConstraintKind.NullableReferenceType; - diagnostics.Add(new LazyMissingNonNullTypesContextDiagnosticInfo(Compilation, NonNullTypesContext, type: default), questionToken.GetLocation()); + + DiagnosticInfo info = LazyMissingNonNullTypesContextDiagnosticInfo.ReportNullableReferenceTypesIfNeeded(Compilation, IsNullableEnabled(questionToken)); + + if (!(info is null)) + { + diagnostics.Add(info, questionToken.GetLocation()); + } + } + else if (IsNullableEnabled(constraintSyntax.ClassOrStructKeyword)) + { + constraints |= TypeParameterConstraintKind.NotNullableReferenceType; } - else + else { constraints |= TypeParameterConstraintKind.ReferenceType; } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs index f05b5e137c7..9c1c74e9f6e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs @@ -340,13 +340,13 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t case BoundKind.DeconstructionVariablePendingInference: { var pending = (DeconstructionVariablePendingInference)expression; - return pending.SetInferredType(TypeSymbolWithAnnotations.Create(NonNullTypesContext, type), this, diagnostics); + return pending.SetInferredType(TypeSymbolWithAnnotations.Create(type), this, diagnostics); } case BoundKind.DiscardExpression: { var pending = (BoundDiscardExpression)expression; Debug.Assert((object)pending.Type == null); - return pending.SetInferredType(TypeSymbolWithAnnotations.Create(NonNullTypesContext, type)); + return pending.SetInferredType(TypeSymbolWithAnnotations.Create(type)); } default: throw ExceptionUtilities.UnexpectedValue(expression.Kind); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index 120d118e41c..ecf341b708b 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -250,13 +250,13 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy TypeSymbolWithAnnotations declType = BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar, out aliasOpt); if (isVar) { - declType = TypeSymbolWithAnnotations.Create(NonNullTypesContext, operandType); + declType = TypeSymbolWithAnnotations.Create(operandType); } if (declType.IsNull) { Debug.Assert(hasErrors); - declType = TypeSymbolWithAnnotations.Create(NonNullTypesContext, this.CreateErrorType("var")); + declType = TypeSymbolWithAnnotations.Create(this.CreateErrorType("var")); } var boundDeclType = new BoundTypeExpression(typeSyntax, aliasOpt, inferredType: isVar, type: declType.TypeSymbol); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 9c69963c205..f14a0d33fa1 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -102,14 +102,14 @@ private NamespaceOrTypeOrAliasSymbolWithAnnotations BindTypeOrAliasOrVarKeyword( { if (syntax.IsVar) { - var symbol = BindTypeOrAliasOrKeyword(syntax, diagnostics, out isVar); + var symbol = BindTypeOrAliasOrKeyword((IdentifierNameSyntax)syntax, diagnostics, out isVar); if (isVar) { CheckFeatureAvailability(syntax, MessageID.IDS_FeatureImplicitLocal, diagnostics); } - return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(NonNullTypesContext, symbol); + return symbol; } else { @@ -122,14 +122,14 @@ private NamespaceOrTypeOrAliasSymbolWithAnnotations BindTypeOrAliasOrUnmanagedKe { if (syntax.IsUnmanaged) { - var symbol = BindTypeOrAliasOrKeyword(syntax, diagnostics, out isUnmanaged); + var symbol = BindTypeOrAliasOrKeyword((IdentifierNameSyntax)syntax, diagnostics, out isUnmanaged); if (isUnmanaged) { CheckFeatureAvailability(syntax, MessageID.IDS_FeatureUnmanagedGenericTypeConstraint, diagnostics); } - return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(NonNullTypesContext, symbol); + return symbol; } else { @@ -144,10 +144,10 @@ private NamespaceOrTypeOrAliasSymbolWithAnnotations BindTypeOrAliasOrUnmanagedKe /// PREREQUISITE: syntax should be checked to match the keyword, like or . /// Otherwise, call instead. /// - private Symbol BindTypeOrAliasOrKeyword(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isKeyword) + private NamespaceOrTypeOrAliasSymbolWithAnnotations BindTypeOrAliasOrKeyword(IdentifierNameSyntax syntax, DiagnosticBag diagnostics, out bool isKeyword) { // Keywords can only be IdentifierNameSyntax - var identifierValueText = ((IdentifierNameSyntax)syntax).Identifier.ValueText; + var identifierValueText = syntax.Identifier.ValueText; Symbol symbol = null; // Perform name lookup without generating diagnostics as it could possibly be a keyword in the current context. @@ -240,7 +240,8 @@ private Symbol BindTypeOrAliasOrKeyword(TypeSyntax syntax, DiagnosticBag diagnos } lookupResult.Free(); - return symbol; + + return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(IsNullableEnabled(syntax.Identifier), symbol); } // Binds the given expression syntax as Type. @@ -355,11 +356,6 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS var type = (NamedTypeSymbol)constructedType.TypeSymbol; var location = syntax.Location; var conversions = this.Conversions.WithNullability(includeNullability: true); - if (!ShouldCheckConstraintsNullability) - { - diagnostics.Add(new LazyNullableContraintChecksDiagnosticInfo(type, conversions, this.Compilation), location); - conversions = this.Conversions.WithNullability(includeNullability: false); - } type.CheckConstraints(this.Compilation, conversions, location, diagnostics); } else if (constructedType.TypeSymbol.IsUnconstrainedTypeParameter()) @@ -372,17 +368,16 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS case SyntaxKind.PredefinedType: { - var type = BindPredefinedTypeSymbol((PredefinedTypeSyntax)syntax, diagnostics); - return TypeSymbolWithAnnotations.Create(NonNullTypesContext, type); + var predefinedType = (PredefinedTypeSyntax)syntax; + var type = BindPredefinedTypeSymbol(predefinedType, diagnostics); + return TypeSymbolWithAnnotations.Create(IsNullableEnabled(predefinedType.Keyword), type); } case SyntaxKind.IdentifierName: - return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(NonNullTypesContext, - BindNonGenericSimpleNamespaceOrTypeOrAliasSymbol((IdentifierNameSyntax)syntax, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics, qualifierOpt: null)); + return BindNonGenericSimpleNamespaceOrTypeOrAliasSymbol((IdentifierNameSyntax)syntax, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics, qualifierOpt: null); case SyntaxKind.GenericName: - return TypeSymbolWithAnnotations.Create(NonNullTypesContext, - BindGenericSimpleNamespaceOrTypeOrAliasSymbol((GenericNameSyntax)syntax, diagnostics, basesBeingResolved, qualifierOpt: null)); + return BindGenericSimpleNamespaceOrTypeOrAliasSymbol((GenericNameSyntax)syntax, diagnostics, basesBeingResolved, qualifierOpt: null); case SyntaxKind.AliasQualifiedName: { @@ -396,19 +391,19 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS return TypeSymbolWithAnnotations.Create(new ExtendedErrorTypeSymbol(left, LookupResultKind.NotATypeOrNamespace, diagnostics.Add(ErrorCode.ERR_ColColWithTypeAlias, node.Alias.Location, node.Alias.Identifier.Text))); } - return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(NonNullTypesContext, this.BindSimpleNamespaceOrTypeOrAliasSymbol(node.Name, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics, left)); + return this.BindSimpleNamespaceOrTypeOrAliasSymbol(node.Name, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics, left); } case SyntaxKind.QualifiedName: { var node = (QualifiedNameSyntax)syntax; - return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(NonNullTypesContext, BindQualifiedName(node.Left, node.Right, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics)); + return BindQualifiedName(node.Left, node.Right, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics); } case SyntaxKind.SimpleMemberAccessExpression: { var node = (MemberAccessExpressionSyntax)syntax; - return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(NonNullTypesContext, BindQualifiedName(node.Expression, node.Name, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics)); + return BindQualifiedName(node.Expression, node.Name, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics); } case SyntaxKind.ArrayType: @@ -446,7 +441,7 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS } else { - type = TypeSymbolWithAnnotations.Create(NonNullTypesContext, array); + type = TypeSymbolWithAnnotations.Create(IsNullableEnabled(a.CloseBracketToken), array); } } @@ -481,7 +476,8 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS case SyntaxKind.TupleType: { - return TypeSymbolWithAnnotations.Create(NonNullTypesContext, BindTupleType((TupleTypeSyntax)syntax, diagnostics)); + var tupleTypeSyntax = (TupleTypeSyntax)syntax; + return TypeSymbolWithAnnotations.Create(IsNullableEnabled(tupleTypeSyntax.CloseParenToken), BindTupleType(tupleTypeSyntax, diagnostics)); } case SyntaxKind.RefType: @@ -503,15 +499,16 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS void reportNullableReferenceTypesIfNeeded(SyntaxToken questionToken, TypeSymbolWithAnnotations typeArgument = default) { - // Inside a method body or other executable code, we can pull on NonNullTypes symbol or question IsValueType without causing cycles. - // We still need to delay that check when binding in an attribute argument - if (!InExecutableBinder || !ShouldCheckConstraintsNullability) + bool isNullableEnabled = IsNullableEnabled(questionToken); + + // Inside a method body or other executable code, we can question IsValueType without causing cycles. + if (!typeArgument.IsNull && !ShouldCheckConstraints) { - diagnostics.Add(new LazyMissingNonNullTypesContextDiagnosticInfo(Compilation, NonNullTypesContext, typeArgument), questionToken.GetLocation()); + diagnostics.Add(new LazyMissingNonNullTypesContextDiagnosticInfo(Compilation, isNullableEnabled, typeArgument), questionToken.GetLocation()); } else { - DiagnosticInfo info = LazyMissingNonNullTypesContextDiagnosticInfo.ReportNullableReferenceTypesIfNeeded(Compilation, NonNullTypesContext, typeArgument); + DiagnosticInfo info = LazyMissingNonNullTypesContextDiagnosticInfo.ReportNullableReferenceTypesIfNeeded(Compilation, isNullableEnabled, typeArgument); if (!(info is null)) { @@ -651,7 +648,7 @@ private NamedTypeSymbol BindPredefinedTypeSymbol(PredefinedTypeSyntax node, Diag /// /// Binds a simple name or the simple name portion of a qualified name. /// - private Symbol BindSimpleNamespaceOrTypeOrAliasSymbol( + private NamespaceOrTypeOrAliasSymbolWithAnnotations BindSimpleNamespaceOrTypeOrAliasSymbol( SimpleNameSyntax syntax, DiagnosticBag diagnostics, ConsList basesBeingResolved, @@ -668,7 +665,7 @@ private NamedTypeSymbol BindPredefinedTypeSymbol(PredefinedTypeSyntax node, Diag switch (syntax.Kind()) { default: - return new ExtendedErrorTypeSymbol(qualifierOpt ?? this.Compilation.Assembly.GlobalNamespace, string.Empty, arity: 0, errorInfo: null); + return TypeSymbolWithAnnotations.Create(new ExtendedErrorTypeSymbol(qualifierOpt ?? this.Compilation.Assembly.GlobalNamespace, string.Empty, arity: 0, errorInfo: null)); case SyntaxKind.IdentifierName: return BindNonGenericSimpleNamespaceOrTypeOrAliasSymbol((IdentifierNameSyntax)syntax, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics, qualifierOpt); @@ -701,7 +698,7 @@ private static bool IsViableType(LookupResult result) return false; } - protected Symbol BindNonGenericSimpleNamespaceOrTypeOrAliasSymbol( + protected NamespaceOrTypeOrAliasSymbolWithAnnotations BindNonGenericSimpleNamespaceOrTypeOrAliasSymbol( IdentifierNameSyntax node, DiagnosticBag diagnostics, ConsList basesBeingResolved, @@ -717,15 +714,15 @@ private static bool IsViableType(LookupResult result) if (string.IsNullOrWhiteSpace(identifierValueText)) { - return new ExtendedErrorTypeSymbol( + return TypeSymbolWithAnnotations.Create(new ExtendedErrorTypeSymbol( Compilation.Assembly.GlobalNamespace, identifierValueText, 0, - new CSDiagnosticInfo(ErrorCode.ERR_SingleTypeNameNotFound)); + new CSDiagnosticInfo(ErrorCode.ERR_SingleTypeNameNotFound))); } var errorResult = CreateErrorIfLookupOnTypeParameter(node.Parent, qualifierOpt, identifierValueText, 0, diagnostics); if ((object)errorResult != null) { - return errorResult; + return TypeSymbolWithAnnotations.Create(errorResult); } var result = LookupResult.GetInstance(); @@ -765,7 +762,7 @@ private static bool IsViableType(LookupResult result) } result.Free(); - return bindingResult; + return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(IsNullableEnabled(node.Identifier), bindingResult); } private void ReportUseSiteDiagnosticForDynamic(DiagnosticBag diagnostics, IdentifierNameSyntax node) @@ -834,7 +831,7 @@ private NamespaceOrTypeOrAliasSymbolWithAnnotations UnwrapAlias(NamespaceOrTypeO if (symbol.IsAlias) { AliasSymbol discarded; - return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(NonNullTypesContext, (NamespaceOrTypeSymbol)UnwrapAlias(symbol.Symbol, out discarded, diagnostics, syntax, basesBeingResolved)); + return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(symbol.IsNullableEnabled, (NamespaceOrTypeSymbol)UnwrapAlias(symbol.Symbol, out discarded, diagnostics, syntax, basesBeingResolved)); } return symbol; @@ -844,7 +841,7 @@ private NamespaceOrTypeOrAliasSymbolWithAnnotations UnwrapAlias(NamespaceOrTypeO { if (symbol.IsAlias) { - return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(NonNullTypesContext, (NamespaceOrTypeSymbol)UnwrapAlias(symbol.Symbol, out alias, diagnostics, syntax, basesBeingResolved)); + return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(symbol.IsNullableEnabled, (NamespaceOrTypeSymbol)UnwrapAlias(symbol.Symbol, out alias, diagnostics, syntax, basesBeingResolved)); } alias = null; @@ -885,7 +882,7 @@ private Symbol UnwrapAlias(Symbol symbol, out AliasSymbol alias, DiagnosticBag d return symbol; } - private NamedTypeSymbol BindGenericSimpleNamespaceOrTypeOrAliasSymbol( + private TypeSymbolWithAnnotations BindGenericSimpleNamespaceOrTypeOrAliasSymbol( GenericNameSyntax node, DiagnosticBag diagnostics, ConsList basesBeingResolved, @@ -995,7 +992,7 @@ private Symbol UnwrapAlias(Symbol symbol, out AliasSymbol alias, DiagnosticBag d LookupResultKind.NotAnAttributeType, errorInfo: null); } - return resultType; + return TypeSymbolWithAnnotations.Create(IsNullableEnabled(node.TypeArgumentList.GreaterThanToken), resultType); } private NamedTypeSymbol LookupGenericTypeName( @@ -1194,11 +1191,6 @@ private NamedTypeSymbol ConstructNamedTypeUnlessTypeArgumentOmitted(SyntaxNode t { bool includeNullability = Compilation.IsFeatureEnabled(MessageID.IDS_FeatureNullableReferenceTypes); var conversions = this.Conversions.WithNullability(includeNullability); - if (includeNullability && !ShouldCheckConstraintsNullability) - { - diagnostics.Add(new LazyNullableContraintChecksDiagnosticInfo(type, conversions, this.Compilation), typeSyntax.GetLocation()); - conversions = this.Conversions.WithNullability(includeNullability: false); - } type.CheckConstraintsForNonTuple(conversions, typeSyntax, typeArgumentsSyntax, this.Compilation, basesBeingResolved, diagnostics); } @@ -1219,15 +1211,7 @@ private bool ShouldCheckConstraints } } - private bool ShouldCheckConstraintsNullability - { - get - { - return ShouldCheckConstraints && !this.Flags.Includes(BinderFlags.AttributeArgument); - } - } - - private NamespaceOrTypeSymbol BindQualifiedName( + private NamespaceOrTypeOrAliasSymbolWithAnnotations BindQualifiedName( ExpressionSyntax leftName, SimpleNameSyntax rightName, DiagnosticBag diagnostics, @@ -1249,17 +1233,18 @@ private bool ShouldCheckConstraintsNullability } // since the name is qualified, it cannot result in a using alias symbol, only a type or namespace - var right = this.BindSimpleNamespaceOrTypeOrAliasSymbol(rightName, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics, left) as NamespaceOrTypeSymbol; + var right = this.BindSimpleNamespaceOrTypeOrAliasSymbol(rightName, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics, left); // If left name bound to an unbound generic type // and right name bound to a generic type, we must // convert right to an unbound generic type. if (isLeftUnboundGenericType) { - var namedTypeRight = right as NamedTypeSymbol; + var namedTypeRight = right.Symbol as NamedTypeSymbol; if ((object)namedTypeRight != null && namedTypeRight.IsGenericType) { - right = namedTypeRight.AsUnboundGenericType(); + TypeSymbolWithAnnotations type = right.Type; + right = type.WithTypeAndModifiers(namedTypeRight.AsUnboundGenericType(), type.CustomModifiers); } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_TupleOperators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_TupleOperators.cs index cb59cd483c1..1259e212d80 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_TupleOperators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_TupleOperators.cs @@ -411,7 +411,7 @@ private static (ImmutableArray Elements, ImmutableArray ImmutableArray elementLocations = elements.SelectAsArray(e => e.Syntax.Location); var tuple = TupleTypeSymbol.Create(locationOpt: null, - elementTypes: convertedTypes.SelectAsArray((t, m) => TypeSymbolWithAnnotations.Create(nonNullTypesContext: m, t), compilation.SourceModule), + elementTypes: convertedTypes.SelectAsArray(t => TypeSymbolWithAnnotations.Create(t)), elementLocations, elementNames: names, compilation, shouldCheckConstraints: true, errorPositions: default, syntax, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs b/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs index 343ba5b5012..2308b2beeea 100644 --- a/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs @@ -157,6 +157,11 @@ internal override Symbol ContainingMemberOrLambda } } + internal override bool IsNullableGloballyEnabled() + { + return Compilation.Options.Nullable; + } + internal override Binder GetBinder(SyntaxNode node) { return null; diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/INonNullTypesContext.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/INonNullTypesContext.cs deleted file mode 100644 index 1d9bc3da7eb..00000000000 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/INonNullTypesContext.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.CSharp -{ - /// - /// Instead of storing a bool to tell us if we're in a NonNullTypes context, - /// we use this interface to pull on that information lazily. - /// - internal interface INonNullTypesContext - { - bool? NonNullTypes { get; } - } - - internal sealed class NonNullTypesTrueContext : INonNullTypesContext - { - public static readonly INonNullTypesContext Instance = new NonNullTypesTrueContext(); - public bool? NonNullTypes => true; - } - - internal sealed class NonNullTypesNullContext : INonNullTypesContext - { - public static readonly INonNullTypesContext Instance = new NonNullTypesNullContext(); - public bool? NonNullTypes => null; - } -} diff --git a/src/Compilers/CSharp/Portable/Binder/WithNullableContextBinder.cs b/src/Compilers/CSharp/Portable/Binder/WithNullableContextBinder.cs new file mode 100644 index 00000000000..0ed208f956c --- /dev/null +++ b/src/Compilers/CSharp/Portable/Binder/WithNullableContextBinder.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp +{ + internal sealed class WithNullableContextBinder : Binder + { + private readonly SyntaxTree _syntaxTree; + private readonly int _position; + + internal WithNullableContextBinder(SyntaxTree syntaxTree, int position, Binder next) + : base(next) + { + Debug.Assert(syntaxTree != null); + Debug.Assert(position >= 0); + _syntaxTree = syntaxTree; + _position = position; + } + + internal override bool IsNullableGloballyEnabled() + { + return Next.IsNullableEnabled(_syntaxTree, _position); + } + } +} diff --git a/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs b/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs index 27d2f257892..bea0979d797 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/OutDeconstructVarPendingInference.cs @@ -20,7 +20,7 @@ public BoundDeconstructValuePlaceholder SetInferredType(TypeSymbolWithAnnotation public BoundDeconstructValuePlaceholder FailInference(Binder binder) { - return SetInferredType(TypeSymbolWithAnnotations.Create(binder.NonNullTypesContext, binder.CreateErrorType()), binder, success: false); + return SetInferredType(TypeSymbolWithAnnotations.Create(binder.CreateErrorType()), binder, success: false); } } } diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs index 5768defe618..ce78d50cfd5 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs @@ -604,7 +604,7 @@ private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType, Immutabl var returnType = inferredReturnType.Type; if (returnType.IsNull) { - returnType = TypeSymbolWithAnnotations.Create(NonNullTypesNullContext.Instance, LambdaSymbol.InferenceFailureReturnType); + returnType = TypeSymbolWithAnnotations.Create(LambdaSymbol.InferenceFailureReturnType); } lambdaSymbol.SetInferredReturnType(inferredReturnType.RefKind, returnType); diff --git a/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs b/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs index 9c5fe0fc2fc..ba76d9d0adf 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs @@ -38,7 +38,7 @@ internal BoundExpression SetInferredType(TypeSymbolWithAnnotations type, Binder if (inferenceFailed) { - type = TypeSymbolWithAnnotations.Create(binderOpt.NonNullTypesContext, binderOpt.CreateErrorType("var")); + type = TypeSymbolWithAnnotations.Create(binderOpt.CreateErrorType("var")); } switch (this.VariableSymbol.Kind) diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index 94451fd2618..9971f7c3299 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -215,6 +215,8 @@ internal Binder GetSpeculativeBinder(int position, ExpressionSyntax expression, binder = new TypeofBinder(expression, binder); } + binder = new WithNullableContextBinder(SyntaxTree, position, binder); + return new ExecutableCodeBinder(expression, binder.ContainingMemberOrLambda, binder).GetBinder(expression); } diff --git a/src/Compilers/CSharp/Portable/Errors/LazyMissingNonNullTypesContextDiagnosticInfo.cs b/src/Compilers/CSharp/Portable/Errors/LazyMissingNonNullTypesContextDiagnosticInfo.cs index a189db5315e..dd64057c59e 100644 --- a/src/Compilers/CSharp/Portable/Errors/LazyMissingNonNullTypesContextDiagnosticInfo.cs +++ b/src/Compilers/CSharp/Portable/Errors/LazyMissingNonNullTypesContextDiagnosticInfo.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Symbols; namespace Microsoft.CodeAnalysis.CSharp @@ -10,19 +11,20 @@ namespace Microsoft.CodeAnalysis.CSharp internal sealed class LazyMissingNonNullTypesContextDiagnosticInfo : LazyDiagnosticInfo { private readonly CSharpCompilation _compilation; - private readonly INonNullTypesContext _context; + private readonly bool _isNullableEnabled; private readonly TypeSymbolWithAnnotations _type; - internal LazyMissingNonNullTypesContextDiagnosticInfo(CSharpCompilation compilation, INonNullTypesContext context, TypeSymbolWithAnnotations type) + internal LazyMissingNonNullTypesContextDiagnosticInfo(CSharpCompilation compilation, bool isNullableEnabled, TypeSymbolWithAnnotations type) { + Debug.Assert(!type.IsNull); _compilation = compilation; - _context = context; + _isNullableEnabled = isNullableEnabled; _type = type; } protected override DiagnosticInfo ResolveInfo() { - return ReportNullableReferenceTypesIfNeeded(_compilation, _context, _type); + return ReportNullableReferenceTypesIfNeeded(_compilation, _isNullableEnabled, _type); } /// @@ -30,12 +32,12 @@ protected override DiagnosticInfo ResolveInfo() /// - an error before C# 8.0 /// - a warning outside of a NonNullTypes context /// - public static DiagnosticInfo ReportNullableReferenceTypesIfNeeded(CSharpCompilation compilation, INonNullTypesContext context, TypeSymbolWithAnnotations type) + public static DiagnosticInfo ReportNullableReferenceTypesIfNeeded(CSharpCompilation compilation, bool isNullableEnabled, TypeSymbolWithAnnotations type) { - return !type.IsNull && (type.IsValueType || type.IsErrorType()) ? null : ReportNullableReferenceTypesIfNeeded(compilation, context); + return !type.IsNull && (type.IsValueType || type.IsErrorType()) ? null : ReportNullableReferenceTypesIfNeeded(compilation, isNullableEnabled); } - private static DiagnosticInfo ReportNullableReferenceTypesIfNeeded(CSharpCompilation compilation, INonNullTypesContext nonNullTypesContext) + public static DiagnosticInfo ReportNullableReferenceTypesIfNeeded(CSharpCompilation compilation, bool isNullableEnabled) { var featureID = MessageID.IDS_FeatureNullableReferenceTypes; if (!compilation.IsFeatureEnabled(featureID)) @@ -45,7 +47,7 @@ private static DiagnosticInfo ReportNullableReferenceTypesIfNeeded(CSharpCompila return new CSDiagnosticInfo(availableVersion.GetErrorCode(), featureID.Localize(), new CSharpRequiredLanguageVersion(requiredVersion)); } - else if (nonNullTypesContext.NonNullTypes != true) + else if (!isNullableEnabled) { return new CSDiagnosticInfo(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation); } diff --git a/src/Compilers/CSharp/Portable/Errors/LazyNullAsNonNullableDiagnosticInfo.cs b/src/Compilers/CSharp/Portable/Errors/LazyNullAsNonNullableDiagnosticInfo.cs deleted file mode 100644 index e252f9e0ec5..00000000000 --- a/src/Compilers/CSharp/Portable/Errors/LazyNullAsNonNullableDiagnosticInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.CSharp.Symbols; - -namespace Microsoft.CodeAnalysis.CSharp -{ - internal sealed class LazyNullAsNonNullableDiagnosticInfo : LazyDiagnosticInfo - { - private readonly TypeSymbolWithAnnotations _possiblyNullableType; - - internal LazyNullAsNonNullableDiagnosticInfo(TypeSymbolWithAnnotations possiblyNullableType) - { - _possiblyNullableType = possiblyNullableType; - } - - protected override DiagnosticInfo ResolveInfo() - { - if (_possiblyNullableType.NullableAnnotation.IsAnyNotNullable()) - { - return new CSDiagnosticInfo(ErrorCode.WRN_NullAsNonNullable); - } - - return null; - } - } -} diff --git a/src/Compilers/CSharp/Portable/Errors/LazyNullableContraintChecksDiagnosticInfo.cs b/src/Compilers/CSharp/Portable/Errors/LazyNullableContraintChecksDiagnosticInfo.cs deleted file mode 100644 index 97484fdc862..00000000000 --- a/src/Compilers/CSharp/Portable/Errors/LazyNullableContraintChecksDiagnosticInfo.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.CSharp.Symbols; -using Microsoft.CodeAnalysis.PooledObjects; - -namespace Microsoft.CodeAnalysis.CSharp -{ - /// - /// A lazily calculated diagnostic for constraint check nullability. - /// - internal sealed class LazyNullableContraintChecksDiagnosticInfo : LazyDiagnosticInfo - { - private readonly NamedTypeSymbol _type; - private readonly ConversionsBase _conversions; - private readonly Compilation _compilation; - - internal LazyNullableContraintChecksDiagnosticInfo(NamedTypeSymbol type, ConversionsBase conversions, Compilation compilation) - { - _type = type; - _conversions = conversions; - _compilation = compilation; - } - - protected override DiagnosticInfo ResolveInfo() - { - var diagnosticsBuilder = ArrayBuilder.GetInstance(); - var warningsBuilder = ArrayBuilder.GetInstance(); - ArrayBuilder useSiteDiagnosticsBuilder = null; - // CheckTypeConstraints should only add nullability warnings to warningsBuilder. - ConstraintsHelper.CheckTypeConstraints( - _type, - _conversions, - _compilation, - diagnosticsBuilder, - warningsBuilder, - ref useSiteDiagnosticsBuilder); - // If there are multiple constraint check warnings, we'll report the first one only. - var diagnostic = (warningsBuilder.Count == 0) ? null : warningsBuilder[0].DiagnosticInfo; - useSiteDiagnosticsBuilder?.Free(); - warningsBuilder.Free(); - diagnosticsBuilder.Free(); - return diagnostic; - } - } -} diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs index de57333705b..18d60f7733b 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs @@ -786,10 +786,22 @@ private void AddTypeParameterConstraints(ImmutableArray typeArgumen if (typeParam.HasReferenceTypeConstraint) { AddKeyword(SyntaxKind.ClassKeyword); - if (format.MiscellaneousOptions.IncludesOption(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier) && - typeParameterSymbol?.ReferenceTypeConstraintIsNullable == true) // https://github.com/dotnet/roslyn/issues/26198 Switch to public API when we will have one. + + switch (typeParameterSymbol?.ReferenceTypeConstraintIsNullable) // https://github.com/dotnet/roslyn/issues/26198 Switch to public API when we will have one. { - AddPunctuation(SyntaxKind.QuestionToken); + case true: + if (format.MiscellaneousOptions.IncludesOption(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier)) + { + AddPunctuation(SyntaxKind.QuestionToken); + } + break; + + case false: + if (format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier)) + { + AddPunctuation(SyntaxKind.ExclamationToken); + } + break; } needComma = true; diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs index 7ab3015b9bb..2e6c44042a6 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs @@ -591,8 +591,6 @@ public override int GetHashCode() } return _hashCode; } - - public override bool? NonNullTypes => false; } internal sealed class ConstructedErrorTypeSymbol : SubstitutedErrorTypeSymbol diff --git a/src/Compilers/CSharp/Portable/Symbols/EventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/EventSymbol.cs index 6e4fee0760d..551b9299fcd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/EventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/EventSymbol.cs @@ -91,15 +91,6 @@ internal bool HasAssociatedField /// internal abstract bool HasSpecialName { get; } - public override bool? NonNullTypes - { - get - { - Debug.Assert(IsDefinition); - return ContainingType?.NonNullTypes; - } - } - /// /// Gets the attributes on event's associated field, if any. /// Returns an empty if diff --git a/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs index c577cf6bf25..263b9cfd780 100644 --- a/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs @@ -157,15 +157,6 @@ public virtual object ConstantValue internal abstract ConstantValue GetConstantValue(ConstantFieldsInProgress inProgress, bool earlyDecodingWellKnownAttributes); - public override bool? NonNullTypes - { - get - { - Debug.Assert(IsDefinition); - return (AssociatedSymbol ?? ContainingType)?.NonNullTypes; - } - } - /// /// Gets the kind of this symbol. /// diff --git a/src/Compilers/CSharp/Portable/Symbols/LocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/LocalSymbol.cs index 4a01f358477..43e9981ba28 100644 --- a/src/Compilers/CSharp/Portable/Symbols/LocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/LocalSymbol.cs @@ -155,14 +155,6 @@ public sealed override Accessibility DeclaredAccessibility } } - public override bool? NonNullTypes - { - get - { - throw ExceptionUtilities.Unreachable; - } - } - /// /// Returns value 'Local' of the /// diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs index 883b62712a8..a79510c9fc7 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs @@ -473,13 +473,5 @@ internal override ObsoleteAttributeData ObsoleteAttributeData { get { return null; } } - - public override bool? NonNullTypes - { - get - { - throw ExceptionUtilities.Unreachable; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs index 3e52ae3197f..378554d9238 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs @@ -506,13 +506,5 @@ internal override ObsoleteAttributeData ObsoleteAttributeData { get { return null; } } - - public override bool? NonNullTypes - { - get - { - throw ExceptionUtilities.Unreachable; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs index 56e5ba52b35..ffd9198e6e6 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs @@ -711,14 +711,6 @@ public override bool IsExtensionMethod } } - public override bool? NonNullTypes - { - get - { - throw ExceptionUtilities.Unreachable; - } - } - public override ImmutableArray Locations => _containingType.ContainingPEModule.MetadataLocation.Cast(); public override ImmutableArray DeclaringSyntaxReferences => ImmutableArray.Empty; diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs index 7425742ddb6..a33cfe60edf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs @@ -696,13 +696,5 @@ internal IEnumerable GetForwardedTypes() } public override ModuleMetadata GetMetadata() => _module.GetNonDisposableMetadata(); - - public override bool? NonNullTypes - { - get - { - throw ExceptionUtilities.Unreachable; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index 45f02313843..a077fce2d46 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs @@ -1986,14 +1986,6 @@ internal string DefaultMemberName } } - public override bool? NonNullTypes - { - get - { - throw ExceptionUtilities.Unreachable; - } - } - internal override bool IsComImport { get diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs index 3473c8b20e6..f5b24d5f3b5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs @@ -735,14 +735,6 @@ internal override bool HasRuntimeSpecialName get { return null; } } - public override bool? NonNullTypes - { - get - { - throw ExceptionUtilities.Unreachable; - } - } - private sealed class PEPropertySymbolWithCustomModifiers : PEPropertySymbol { private readonly ImmutableArray _refCustomModifiers; diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/SymbolFactory.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/SymbolFactory.cs index 7dece0b6443..13432117b39 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/SymbolFactory.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/SymbolFactory.cs @@ -172,9 +172,8 @@ internal override TypeSymbol MakeUnboundIfGeneric(PEModuleSymbol moduleSymbol, T private static TypeSymbolWithAnnotations CreateType(TypeSymbol type, ImmutableArray> customModifiers) { - // NonNullTypesContext is unset because the actual context will - // be set when these types are transformed by the caller. - return TypeSymbolWithAnnotations.Create(NonNullTypesNullContext.Instance, type, customModifiers: CSharpCustomModifier.Convert(customModifiers)); + // The actual annotation will be set when these types are transformed by the caller. + return TypeSymbolWithAnnotations.Create(type, NullableAnnotation.Unknown, CSharpCustomModifier.Convert(customModifiers)); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs index 30f985d341e..1fe40eaab52 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs @@ -954,14 +954,6 @@ internal virtual bool SynthesizesLoweredBoundBody /// internal abstract int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree); - public override bool? NonNullTypes - { - get - { - return (AssociatedSymbol ?? ContainingSymbol)?.NonNullTypes; - } - } - #region IMethodSymbol Members MethodKind IMethodSymbol.MethodKind diff --git a/src/Compilers/CSharp/Portable/Symbols/MissingModuleSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/MissingModuleSymbol.cs index 84d3ab30d87..c6e75d93070 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MissingModuleSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MissingModuleSymbol.cs @@ -185,8 +185,6 @@ internal override bool HasAssemblyRuntimeCompatibilityAttribute } public override ModuleMetadata GetMetadata() => null; - - public override bool? NonNullTypes => false; } internal sealed class MissingModuleSymbolWithName : MissingModuleSymbol diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index 5ac9afc8057..f2683a3b93a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs @@ -962,30 +962,19 @@ private static VarianceKind GetTypeArgumentVariance(VarianceKind typeVariance, V /// parameters in the type. public NamedTypeSymbol Construct(params TypeSymbol[] typeArguments) { - // https://github.com/dotnet/roslyn/issues/30064: We should fix the callers to pass an explicit context. - return ConstructWithoutModifiers(typeArguments.AsImmutableOrNull(), false, NonNullTypesNullContext.Instance); + // https://github.com/dotnet/roslyn/issues/30064: We should fix the callers to pass TypeSymbolWithAnnotations[] instead of TypeSymbol[]. + return ConstructWithoutModifiers(typeArguments.AsImmutableOrNull(), false); } /// /// Returns a constructed type given its type arguments. /// - /// This context indicates how to interpret un-annotated types. /// The immediate type arguments to be replaced for type /// parameters in the type. - public NamedTypeSymbol Construct(INonNullTypesContext nonNullTypesContext, params TypeSymbol[] typeArguments) + public NamedTypeSymbol Construct(ImmutableArray typeArguments) { - return ConstructWithoutModifiers(typeArguments.AsImmutableOrNull(), false, nonNullTypesContext); - } - - /// - /// Returns a constructed type given its type arguments. - /// - /// The immediate type arguments to be replaced for type - /// parameters in the type. - public NamedTypeSymbol Construct(ImmutableArray typeArguments, INonNullTypesContext nonNullTypesContext = null) - { - // https://github.com/dotnet/roslyn/issues/30064: We should fix the callers to pass an explicit context. - return ConstructWithoutModifiers(typeArguments, false, nonNullTypesContext ?? NonNullTypesNullContext.Instance); + // https://github.com/dotnet/roslyn/issues/30064: We should fix the callers to pass ImmutableArray instead of ImmutableArray. + return ConstructWithoutModifiers(typeArguments, false); } /// @@ -994,8 +983,8 @@ public NamedTypeSymbol Construct(ImmutableArray typeArguments, INonN /// public NamedTypeSymbol Construct(IEnumerable typeArguments) { - // https://github.com/dotnet/roslyn/issues/30064: We should fix the callers to pass an explicit context. - return ConstructWithoutModifiers(typeArguments.AsImmutableOrNull(), false, NonNullTypesNullContext.Instance); + // https://github.com/dotnet/roslyn/issues/30064: We should fix the callers to pass IEnumerable instead of IEnumerable. + return ConstructWithoutModifiers(typeArguments.AsImmutableOrNull(), false); } /// @@ -1025,7 +1014,7 @@ internal NamedTypeSymbol GetUnboundGenericTypeOrSelf() internal static readonly Func TypeSymbolIsErrorType = type => !type.IsNull && type.IsErrorType(); - private NamedTypeSymbol ConstructWithoutModifiers(ImmutableArray typeArguments, bool unbound, INonNullTypesContext nonNullTypesContext) + private NamedTypeSymbol ConstructWithoutModifiers(ImmutableArray typeArguments, bool unbound) { ImmutableArray modifiedArguments; @@ -1035,7 +1024,7 @@ private NamedTypeSymbol ConstructWithoutModifiers(ImmutableArray typ } else { - modifiedArguments = typeArguments.SelectAsArray((t, c) => t == null ? default : TypeSymbolWithAnnotations.Create(c, t), nonNullTypesContext); + modifiedArguments = typeArguments.SelectAsArray(t => TypeSymbolWithAnnotations.Create(t)); } return Construct(modifiedArguments, unbound); @@ -1406,15 +1395,6 @@ protected CharSet DefaultMarshallingCharSet } } - public override bool? NonNullTypes - { - get - { - Debug.Assert(IsDefinition); - return ((Symbol)ContainingType ?? base.ContainingModule)?.NonNullTypes; - } - } - /// /// Marshalling charset of string data fields within the type (string formatting flags in metadata). /// diff --git a/src/Compilers/CSharp/Portable/Symbols/ParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ParameterSymbol.cs index 3c07d8693e6..61d1c22275a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ParameterSymbol.cs @@ -230,15 +230,6 @@ public object ExplicitDefaultValue /// internal abstract ConstantValue ExplicitDefaultConstantValue { get; } - public override bool? NonNullTypes - { - get - { - Debug.Assert(IsDefinition); - return ContainingSymbol?.NonNullTypes; - } - } - /// /// Gets the kind of this symbol. /// diff --git a/src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs index f031921c5ea..02553f25296 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs @@ -169,15 +169,6 @@ public bool IsWriteOnly /// internal abstract bool HasSpecialName { get; } - public override bool? NonNullTypes - { - get - { - Debug.Assert(IsDefinition); - return ContainingType?.NonNullTypes; - } - } - /// /// The 'get' accessor of the property, or null if the property is write-only. /// diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs index 827edb43719..2bb1bef0987 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs @@ -185,13 +185,5 @@ internal override DiagnosticInfo GetUseSiteDiagnostic() { get { return null; } } - - public override bool? NonNullTypes - { - get - { - return _underlyingEvent.NonNullTypes; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs index d8786be7712..525a46d35e7 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs @@ -125,13 +125,5 @@ internal override DiagnosticInfo GetUseSiteDiagnostic() { get { return null; } } - - public override bool? NonNullTypes - { - get - { - return _underlyingField.NonNullTypes; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs index 2e9c525cd47..2b08b452e33 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs @@ -310,13 +310,5 @@ internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree l // retargeting symbols refer to a symbol from another compilation, they don't define locals in the current compilation throw ExceptionUtilities.Unreachable; } - - public override bool? NonNullTypes - { - get - { - return _underlyingMethod.NonNullTypes; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingModuleSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingModuleSymbol.cs index 01b588f0924..81fc953d142 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingModuleSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingModuleSymbol.cs @@ -285,13 +285,5 @@ internal override bool HasAssemblyRuntimeCompatibilityAttribute } public override ModuleMetadata GetMetadata() => _underlyingModule.GetMetadata(); - - public override bool? NonNullTypes - { - get - { - return _underlyingModule.NonNullTypes; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs index e549352d086..bfd47ad60c7 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs @@ -357,13 +357,5 @@ internal override bool IsComImport { get { return null; } } - - public override bool? NonNullTypes - { - get - { - return _underlyingType.NonNullTypes; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs index eb3a315e95b..f1a573e77bb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs @@ -242,13 +242,5 @@ internal override DiagnosticInfo GetUseSiteDiagnostic() { get { return null; } } - - public override bool? NonNullTypes - { - get - { - return _underlyingProperty.NonNullTypes; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/SignatureOnlyMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SignatureOnlyMethodSymbol.cs index a0a23c3c7fa..f06a75b85ab 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SignatureOnlyMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SignatureOnlyMethodSymbol.cs @@ -77,8 +77,6 @@ internal sealed class SignatureOnlyMethodSymbol : MethodSymbol public override string Name { get { return _name; } } - public override bool? NonNullTypes => false; - #region Not used by MethodSignatureComparer internal override bool GenerateDebugInfo { get { throw ExceptionUtilities.Unreachable; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs index c6d202c9a72..c66a5ae1dab 100755 --- a/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs @@ -336,14 +336,6 @@ internal sealed override bool HasSpecialName } } - public sealed override bool? NonNullTypes - { - get - { - return GetNonNullTypesFromSyntax() ?? (AssociatedSymbol ?? ContainingModule)?.NonNullTypes; - } - } - internal sealed override bool IsNotSerialized { get diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs b/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs index 2d43ec42fc1..138e6f00e0b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs @@ -91,7 +91,7 @@ internal override TypeSymbolWithAnnotations GetFieldType(ConsList f if (isVar) { diagnostics.Add(ErrorCode.ERR_RecursivelyTypedVariable, this.ErrorLocation, this); - type = TypeSymbolWithAnnotations.Create(binder.NonNullTypesContext, binder.CreateErrorType("var")); + type = TypeSymbolWithAnnotations.Create(binder.CreateErrorType("var")); } SetType(compilation, diagnostics, type); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs index d102a5e8eac..4791d5771ed 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs @@ -47,7 +47,7 @@ internal sealed class LambdaSymbol : SourceMethodSymbol _messageID = unboundLambda.Data.MessageID; _syntax = unboundLambda.Syntax; _refKind = refKind; - _returnType = returnType.IsNull ? TypeSymbolWithAnnotations.Create(NonNullTypesNullContext.Instance, ReturnTypeIsBeingInferred) : returnType; + _returnType = returnType.IsNull ? 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. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs index 7fbbe3e137b..a366f2dc04f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs @@ -871,14 +871,6 @@ internal SourceModuleSymbol SourceModule get { return (SourceModuleSymbol)this.Modules[0]; } } - public override bool? NonNullTypes - { - get - { - return SourceModule.NonNullTypes; - } - } - internal override bool RequiresCompletion { get { return true; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index ab7a294232f..e86651533eb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -235,12 +235,12 @@ protected ConstantValue MakeDefaultExpression(DiagnosticBag diagnostics, Binder } if (parameterType.IsReferenceType && + parameterType.NullableAnnotation.IsAnyNotNullable() && convertedExpression.ConstantValue?.IsNull == true && !suppressNullableWarning(convertedExpression) && DeclaringCompilation.LanguageVersion >= MessageID.IDS_FeatureNullableReferenceTypes.RequiredVersion()) { - // Note: Eagerly calling IsNullable causes a cycle, so we delay the check - diagnostics.Add(new LazyNullAsNonNullableDiagnosticInfo(parameterType), parameterSyntax.Default.Value.Location); + diagnostics.Add(ErrorCode.WRN_NullAsNonNullable, parameterSyntax.Default.Value.Location); } // represent default(struct) by a Null constant: diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs index 9c2069d2679..fa85d3f739c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs @@ -93,7 +93,7 @@ protected override void MethodChecks(DiagnosticBag diagnostics) diagnostics: diagnostics); _lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); - _lazyReturnType = TypeSymbolWithAnnotations.Create(nonNullTypesContext: this, bodyBinder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax)); + _lazyReturnType = TypeSymbolWithAnnotations.Create(bodyBinder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax)); var location = this.Locations[0]; if (MethodKind == MethodKind.StaticConstructor && (_lazyParameters.Length != 0)) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs index a5c2c481493..d66a0267d5f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs @@ -50,8 +50,8 @@ protected void InitializeParameters(ImmutableArray parameters) // reuse types to avoid reporting duplicate errors if missing: var voidType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax)); - // https://github.com/dotnet/roslyn/issues/30079: Should the 'object' parameter be considered nullable? - var objectType = TypeSymbolWithAnnotations.Create(nonNullTypesContext: delegateType, binder.GetSpecialType(SpecialType.System_Object, diagnostics, syntax)); + // https://github.com/dotnet/roslyn/issues/30079: Should the 'object', IAsyncResult and AsyncCallback parameters be considered nullable or not nullable? + var objectType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_Object, diagnostics, syntax)); var intPtrType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_IntPtr, diagnostics, syntax)); if (returnType.IsRestrictedType(ignoreSpanLikeTypes: true)) @@ -74,8 +74,8 @@ protected void InitializeParameters(ImmutableArray parameters) // WinRT delegates don't have Begin/EndInvoke methods !delegateType.IsCompilationOutputWinMdObj()) { - var iAsyncResultType = TypeSymbolWithAnnotations.Create(nonNullTypesContext: delegateType, binder.GetSpecialType(SpecialType.System_IAsyncResult, diagnostics, syntax)); - var asyncCallbackType = TypeSymbolWithAnnotations.Create(nonNullTypesContext: delegateType, binder.GetSpecialType(SpecialType.System_AsyncCallback, diagnostics, syntax)); + var iAsyncResultType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_IAsyncResult, diagnostics, syntax)); + var asyncCallbackType = TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_AsyncCallback, diagnostics, syntax)); // (3) BeginInvoke symbols.Add(new BeginInvokeMethod(invoke, iAsyncResultType, objectType, asyncCallbackType, syntax)); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs index 3fceeaac868..ff4ef49887e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs @@ -64,7 +64,7 @@ protected sealed override void MethodChecks(DiagnosticBag diagnostics) // EventRegistrationToken add_E(EventDelegate d); // Leave the returns void bit in this.flags false. - _lazyReturnType = TypeSymbolWithAnnotations.Create(nonNullTypesContext: this, eventTokenType); + _lazyReturnType = TypeSymbolWithAnnotations.Create(eventTokenType); var parameter = new SynthesizedAccessorValueParameterSymbol(this, _event.Type, 0); _lazyParameters = ImmutableArray.Create(parameter); @@ -77,10 +77,10 @@ protected sealed override void MethodChecks(DiagnosticBag diagnostics) TypeSymbol voidType = compilation.GetSpecialType(SpecialType.System_Void); Binder.ReportUseSiteDiagnostics(voidType, diagnostics, this.Location); - _lazyReturnType = TypeSymbolWithAnnotations.Create(nonNullTypesContext: this, voidType); + _lazyReturnType = TypeSymbolWithAnnotations.Create(voidType); this.SetReturnsVoid(returnsVoid: true); - var parameter = new SynthesizedAccessorValueParameterSymbol(this, TypeSymbolWithAnnotations.Create(nonNullTypesContext: this, eventTokenType), 0); + var parameter = new SynthesizedAccessorValueParameterSymbol(this, TypeSymbolWithAnnotations.Create(eventTokenType), 0); _lazyParameters = ImmutableArray.Create(parameter); } } @@ -91,7 +91,7 @@ protected sealed override void MethodChecks(DiagnosticBag diagnostics) TypeSymbol voidType = compilation.GetSpecialType(SpecialType.System_Void); Binder.ReportUseSiteDiagnostics(voidType, diagnostics, this.Location); - _lazyReturnType = TypeSymbolWithAnnotations.Create(nonNullTypesContext: this, voidType); + _lazyReturnType = TypeSymbolWithAnnotations.Create(voidType); this.SetReturnsVoid(returnsVoid: true); var parameter = new SynthesizedAccessorValueParameterSymbol(this, _event.Type, 0); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs index 82ab484b6ee..b3738c6af8d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs @@ -338,14 +338,6 @@ internal sealed override bool HasSpecialName } } - public override bool? NonNullTypes - { - get - { - return GetNonNullTypesFromSyntax() ?? ContainingModule?.NonNullTypes; - } - } - public sealed override bool IsAbstract { get { return (_modifiers & DeclarationModifiers.Abstract) != 0; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index e1274bf6e69..eac916a0de1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -473,7 +473,7 @@ internal sealed override TypeSymbolWithAnnotations GetFieldType(ConsList Diagnostics get { return _cachedDiagnostics; } } - public override bool? NonNullTypes - { - get - { - return GetNonNullTypesFromSyntax() ?? (AssociatedSymbol ?? ContainingModule)?.NonNullTypes; - } - } - internal ImmutableArray SetDiagnostics(ImmutableArray newSet, out bool diagsWritten) { //return the diagnostics that were actually saved in the event that there were two threads racing. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceModuleSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceModuleSymbol.cs index 4168ec02aa9..25ef81310af 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceModuleSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceModuleSymbol.cs @@ -513,14 +513,6 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu } } - public override bool? NonNullTypes - { - get - { - return _assemblySymbol.DeclaringCompilation.Options.Nullable; - } - } - internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { base.AddSynthesizedAttributes(moduleBuilder, ref attributes); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index c4fa056aef7..7ff646e7824 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs @@ -919,14 +919,6 @@ internal override bool HasSpecialName } } - public override bool? NonNullTypes - { - get - { - return GetNonNullTypesFromSyntax() ?? ContainingModule?.NonNullTypes; - } - } - internal override bool HasCodeAnalysisEmbeddedAttribute { get diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs index 9fd80e8b08e..ff4f0ea15b1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs @@ -373,7 +373,7 @@ private TypeSymbolWithAnnotations ComputeReturnType(DiagnosticBag diagnostics) else { var binder = GetBinder(); - return TypeSymbolWithAnnotations.Create(nonNullTypesContext: _property, binder.GetSpecialType(SpecialType.System_Void, diagnostics, this.GetSyntax())); + return TypeSymbolWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_Void, diagnostics, this.GetSyntax())); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index a41eb0f770e..bdd37b8e953 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -1524,13 +1524,5 @@ private static BaseParameterListSyntax GetParameterListSyntax(BasePropertyDeclar { return (syntax.Kind() == SyntaxKind.IndexerDeclaration) ? ((IndexerDeclarationSyntax)syntax).ParameterList : null; } - - public override bool? NonNullTypes - { - get - { - return GetNonNullTypesFromSyntax() ?? ContainingModule?.NonNullTypes; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs index 23f06cf70e2..8ad3b5b66e0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs @@ -400,14 +400,12 @@ internal override sealed void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib return false; } - if ((constraints & TypeParameterConstraintKind.NullableReferenceType) == TypeParameterConstraintKind.NullableReferenceType) + switch (constraints & (TypeParameterConstraintKind.NullableReferenceType | TypeParameterConstraintKind.NotNullableReferenceType)) { - return true; - } - - if (NonNullTypes == true) - { - return false; + case TypeParameterConstraintKind.NullableReferenceType: + return true; + case TypeParameterConstraintKind.NotNullableReferenceType: + return false; } return null; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterConstraintClause.cs b/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterConstraintClause.cs index 9cb7e97df5d..d2ccbc601dd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterConstraintClause.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterConstraintClause.cs @@ -6,6 +6,7 @@ using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols { @@ -18,6 +19,7 @@ internal enum TypeParameterConstraintKind Constructor = 0x04, Unmanaged = 0x08, NullableReferenceType = ReferenceType | 0x10, + NotNullableReferenceType = ReferenceType | 0x20, } /// @@ -52,6 +54,19 @@ internal sealed class TypeParameterConstraintClause ImmutableArray typeConstraintsSyntax, ImmutableArray otherPartialDeclarations) { +#if DEBUG + switch (constraints & (TypeParameterConstraintKind.NullableReferenceType | TypeParameterConstraintKind.NotNullableReferenceType)) + { + case TypeParameterConstraintKind.None: + case TypeParameterConstraintKind.ReferenceType: + case TypeParameterConstraintKind.NullableReferenceType: + case TypeParameterConstraintKind.NotNullableReferenceType: + break; + default: + ExceptionUtilities.UnexpectedValue(constraints); // This call asserts. + break; + } +#endif this.Constraints = constraints; this.ConstraintTypes = constraintTypes; this.TypeConstraintsSyntax = typeConstraintsSyntax; diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs index a0fea4a0786..634dfd65e1f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs @@ -358,8 +358,6 @@ internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree l throw ExceptionUtilities.Unreachable; } - public sealed override bool? NonNullTypes => false; - private int ComputeHashCode() { int code = this.OriginalDefinition.GetHashCode(); diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs index e7ebb866889..961e7235a36 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs @@ -361,7 +361,5 @@ internal override IEnumerable GetCustomAttributesToEmit(PEM { throw ExceptionUtilities.Unreachable; } - - public sealed override bool? NonNullTypes => false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs index 6c96d169adc..e12598be422 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs @@ -23,7 +23,7 @@ namespace Microsoft.CodeAnalysis.CSharp /// exposed by the compiler. /// [DebuggerDisplay("{GetDebuggerDisplay(), nq}")] - internal abstract partial class Symbol : ISymbol, IFormattable, INonNullTypesContext + internal abstract partial class Symbol : ISymbol, IFormattable { // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Changes to the public interface of this class should remain synchronized with the VB version of Symbol. @@ -836,44 +836,6 @@ public virtual bool HasUnsupportedMetadata } } - /// - /// Is module/type/method/field/property/event/parameter definition opted-in/out of treating un-annotated types as non-null. - /// This is determined by the presence of the `[NonNullTypes]` attribute. - /// Returns null if no attribute was set. - /// Not valid to call on non-definitions. - /// - public virtual bool? NonNullTypes - { - get - { - throw ExceptionUtilities.Unreachable; - } - } - - internal bool? GetNonNullTypesFromSyntax() - { - bool? result = null; - foreach (Location location in Locations) - { - SyntaxTree tree = location.SourceTree; - if (tree == null) - { - continue; - } - bool? state = ((CSharpSyntaxTree)tree).GetNullableDirectiveState(location.SourceSpan.Start); - if (state == null) - { - continue; - } - if (state == true) - { - return true; - } - result = false; - } - return result; - } - internal DiagnosticInfo GetUseSiteDiagnosticForSymbolOrContainingType() { var info = this.GetUseSiteDiagnostic(); diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEntryPointSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEntryPointSymbol.cs index bd281a8fd5b..f94ec1ee8f4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEntryPointSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEntryPointSymbol.cs @@ -37,7 +37,7 @@ internal static SynthesizedEntryPointSymbol Create(SynthesizedInteractiveInitial else { var systemVoid = Binder.GetSpecialType(compilation, SpecialType.System_Void, DummySyntax(), diagnostics); - return new ScriptEntryPoint(containingType, TypeSymbolWithAnnotations.Create(nonNullTypesContext: containingType, systemVoid)); + return new ScriptEntryPoint(containingType, TypeSymbolWithAnnotations.Create(systemVoid)); } } @@ -349,7 +349,7 @@ internal sealed class AsyncForwardEntryPoint : SynthesizedEntryPointSymbol public override ImmutableArray Parameters => _parameters; - public override TypeSymbolWithAnnotations ReturnType => TypeSymbolWithAnnotations.Create(nonNullTypesContext: ContainingModule, _getAwaiterGetResultCall.Type); + public override TypeSymbolWithAnnotations ReturnType => TypeSymbolWithAnnotations.Create(_getAwaiterGetResultCall.Type); internal override BoundBlock CreateBody(DiagnosticBag diagnostics) { @@ -496,7 +496,7 @@ private sealed class SubmissionEntryPoint : SynthesizedEntryPointSymbol Debug.Assert(containingType.IsSubmissionClass); Debug.Assert(returnType.SpecialType != SpecialType.System_Void); _parameters = ImmutableArray.Create(SynthesizedParameterSymbol.Create(this, - TypeSymbolWithAnnotations.Create(nonNullTypesContext: ContainingModule, submissionArrayType), 0, RefKind.None, "submissionArray")); + TypeSymbolWithAnnotations.Create(submissionArrayType), 0, RefKind.None, "submissionArray")); _returnType = returnType; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedImplementationMethod.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedImplementationMethod.cs index 7925c6254da..eba2ee89836 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedImplementationMethod.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedImplementationMethod.cs @@ -259,7 +259,5 @@ internal override ImmutableArray GetAppliedConditionalSymbols() { return ImmutableArray.Empty; } - - public override bool? NonNullTypes => false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInteractiveInitializerMethod.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInteractiveInitializerMethod.cs index 14f0651ed6c..11b5bff8172 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInteractiveInitializerMethod.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInteractiveInitializerMethod.cs @@ -137,7 +137,7 @@ public override bool ReturnsVoid public override TypeSymbolWithAnnotations ReturnType { - get { return TypeSymbolWithAnnotations.Create(nonNullTypesContext: ContainingSymbol, _returnType); } + get { return TypeSymbolWithAnnotations.Create(_returnType); } } public override ImmutableArray RefCustomModifiers @@ -251,7 +251,7 @@ internal TypeSymbol ResultType resultType = (object)submissionReturnTypeOpt == null ? compilation.GetSpecialType(SpecialType.System_Object) : compilation.GetTypeByReflectionType(submissionReturnTypeOpt, diagnostics); - returnType = taskT.Construct(nonNullTypesContext: containingType, resultType); + returnType = taskT.Construct(resultType); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleMethodSymbol.cs index a3f96fb87dd..65805793b1e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleMethodSymbol.cs @@ -172,8 +172,6 @@ internal override DiagnosticInfo GetUseSiteDiagnostic() return result; } - public override bool? NonNullTypes => false; - public override int GetHashCode() { return _underlyingMethod.ConstructedFrom.GetHashCode(); diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeMap.cs b/src/Compilers/CSharp/Portable/Symbols/TypeMap.cs index 0ff7335e04d..ace3f7aad8e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeMap.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeMap.cs @@ -20,9 +20,7 @@ internal sealed class TypeMap : AbstractTypeParameterMap internal static ImmutableArray TypeParametersAsTypeSymbolsWithAnnotations(ImmutableArray typeParameters) { - return typeParameters.SelectAsArray((tp) => - TypeSymbolWithAnnotations.Create(NonNullTypesNullContext.Instance, tp, isAnnotated: false, customModifiers: ImmutableArray.Empty) - ); + return typeParameters.SelectAsArray((tp) => TypeSymbolWithAnnotations.Create(tp)); } internal static ImmutableArray AsTypeSymbols(ImmutableArray typesOpt) @@ -119,7 +117,7 @@ private TypeMap WithAlphaRename(ImmutableArray oldTypeParam var newTp = synthesized ? new SynthesizedSubstitutedTypeParameterSymbol(newOwner, result, tp, ordinal) : new SubstitutedTypeParameterSymbol(newOwner, result, tp, ordinal); - result.Mapping.Add(tp, TypeSymbolWithAnnotations.Create(NonNullTypesNullContext.Instance, newTp)); + result.Mapping.Add(tp, TypeSymbolWithAnnotations.Create(newTp)); newTypeParametersBuilder.Add(newTp); ordinal++; } diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs index 37f3c63106d..03e0f129b5e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs @@ -689,14 +689,6 @@ internal override TypeSymbol MergeNullability(TypeSymbol other, VarianceKind var return this; } - public override sealed bool? NonNullTypes - { - get - { - return ContainingSymbol.NonNullTypes; - } - } - #region ITypeParameterTypeSymbol Members TypeParameterKind ITypeParameterSymbol.TypeParameterKind diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs index d45baf58ea4..cf3cadd2959 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs @@ -338,7 +338,6 @@ private TypeSymbolWithAnnotations(TypeSymbol defaultType, NullableAnnotation nul public string Name => TypeSymbol.Name; public SymbolKind Kind => TypeSymbol.Kind; - // Note: We cannot pull on NonNullTypes while debugging, as that causes cycles, so we only display annotated vs. un-annotated. internal static readonly SymbolDisplayFormat DebuggerDisplayFormat = new SymbolDisplayFormat( typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, @@ -350,19 +349,14 @@ private TypeSymbolWithAnnotations(TypeSymbol defaultType, NullableAnnotation nul miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier, compilerInternalOptions: SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier); - internal static TypeSymbolWithAnnotations Create(INonNullTypesContext nonNullTypesContext, TypeSymbol typeSymbol, bool isAnnotated = false, ImmutableArray customModifiers = default) + internal static TypeSymbolWithAnnotations Create(bool isNullableEnabled, TypeSymbol typeSymbol, bool isAnnotated = false, ImmutableArray customModifiers = default) { - Debug.Assert(nonNullTypesContext != null); - Debug.Assert((nonNullTypesContext as Symbol)?.IsDefinition != false); -#if DEBUG - _ = nonNullTypesContext.NonNullTypes; // Should be able to ask this question right away. -#endif if (typeSymbol is null) { return default; } - return Create(typeSymbol, nullableAnnotation: isAnnotated ? NullableAnnotation.Annotated : nonNullTypesContext.NonNullTypes == true ? NullableAnnotation.NotAnnotated : NullableAnnotation.Unknown, + return Create(typeSymbol, nullableAnnotation: isAnnotated ? NullableAnnotation.Annotated : isNullableEnabled ? NullableAnnotation.NotAnnotated : NullableAnnotation.Unknown, customModifiers.NullToEmpty()); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 5c000550f60..5d45a160fab 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -261,18 +261,12 @@ partial class C9 { } // -nullable (default): var comp = CreateCompilation(new[] { source0, source1, source2 }, options: TestOptions.DebugDll); comp.VerifyDiagnostics( - // (12,11): warning CS8620: Nullability of reference types in argument of type 'C3' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. - // F(new C3()); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C3()").WithArguments("C3", "Base", "b", "void Program.F(Base b)").WithLocation(12, 11), // (15,11): warning CS8620: Nullability of reference types in argument of type 'C6' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C6()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C6()").WithArguments("C6", "Base", "b", "void Program.F(Base b)").WithLocation(15, 11), // (16,11): warning CS8620: Nullability of reference types in argument of type 'C7' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C7()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C7()").WithArguments("C7", "Base", "b", "void Program.F(Base b)").WithLocation(16, 11), - // (17,11): warning CS8620: Nullability of reference types in argument of type 'C8' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. - // F(new C8()); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C8()").WithArguments("C8", "Base", "b", "void Program.F(Base b)").WithLocation(17, 11), // (18,11): warning CS8620: Nullability of reference types in argument of type 'C9' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C9()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C9()").WithArguments("C9", "Base", "b", "void Program.F(Base b)").WithLocation(18, 11)); @@ -280,18 +274,12 @@ partial class C9 { } // -nullable-: comp = CreateCompilation(new[] { source0, source1, source2 }, options: TestOptions.DebugDll.WithNullable(false)); comp.VerifyDiagnostics( - // (12,11): warning CS8620: Nullability of reference types in argument of type 'C3' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. - // F(new C3()); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C3()").WithArguments("C3", "Base", "b", "void Program.F(Base b)").WithLocation(12, 11), // (15,11): warning CS8620: Nullability of reference types in argument of type 'C6' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C6()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C6()").WithArguments("C6", "Base", "b", "void Program.F(Base b)").WithLocation(15, 11), // (16,11): warning CS8620: Nullability of reference types in argument of type 'C7' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C7()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C7()").WithArguments("C7", "Base", "b", "void Program.F(Base b)").WithLocation(16, 11), - // (17,11): warning CS8620: Nullability of reference types in argument of type 'C8' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. - // F(new C8()); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C8()").WithArguments("C8", "Base", "b", "void Program.F(Base b)").WithLocation(17, 11), // (18,11): warning CS8620: Nullability of reference types in argument of type 'C9' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C9()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C9()").WithArguments("C9", "Base", "b", "void Program.F(Base b)").WithLocation(18, 11)); @@ -305,15 +293,15 @@ partial class C9 { } // (12,11): warning CS8620: Nullability of reference types in argument of type 'C3' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C3()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C3()").WithArguments("C3", "Base", "b", "void Program.F(Base b)").WithLocation(12, 11), + // (13,11): warning CS8620: Nullability of reference types in argument of type 'C4' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. + // F(new C4()); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C4()").WithArguments("C4", "Base", "b", "void Program.F(Base b)").WithLocation(13, 11), // (15,11): warning CS8620: Nullability of reference types in argument of type 'C6' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C6()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C6()").WithArguments("C6", "Base", "b", "void Program.F(Base b)").WithLocation(15, 11), // (16,11): warning CS8620: Nullability of reference types in argument of type 'C7' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C7()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C7()").WithArguments("C7", "Base", "b", "void Program.F(Base b)").WithLocation(16, 11), - // (17,11): warning CS8620: Nullability of reference types in argument of type 'C8' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. - // F(new C8()); - Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C8()").WithArguments("C8", "Base", "b", "void Program.F(Base b)").WithLocation(17, 11), // (18,11): warning CS8620: Nullability of reference types in argument of type 'C9' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C9()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C9()").WithArguments("C9", "Base", "b", "void Program.F(Base b)").WithLocation(18, 11)); @@ -1271,8 +1259,6 @@ public void Nullable_False_InCSharp7() { var comp = CreateCompilation("", options: WithNonNullTypesFalse(), parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); - - Assert.False(comp.SourceModule.NonNullTypes); } [Fact] @@ -2303,7 +2289,6 @@ public class External // public static string? fns; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 25) ); - verifyExternal(libComp); var source = @" @@ -2409,43 +2394,6 @@ public void M() // OuterD.D.s /*T:string!*/ = null; // warn 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(73, 36) ); - - var outerA = (NamedTypeSymbol)compilation.GetMember("OuterA"); - Assert.False(outerA.NonNullTypes); - - var a = (NamedTypeSymbol)outerA.GetMember("A"); - VerifyNonNullTypes(a, true); - - var b = (NamedTypeSymbol)compilation.GetMember("B"); - VerifyNonNullTypes(b, true); - - var c = (NamedTypeSymbol)compilation.GetMember("C"); - Assert.False(c.NonNullTypes); - VerifyNonNullTypes(c.GetMember("s"), true); - VerifyNonNullTypes(c.GetMember("ns"), true); - - var outerD = (NamedTypeSymbol)compilation.GetMember("OuterD"); - Assert.False(outerD.NonNullTypes); - - var d = (NamedTypeSymbol)outerD.GetMember("D"); - Assert.False(d.NonNullTypes); - VerifyNonNullTypes(d.GetMember("s"), true); - VerifyNonNullTypes(d.GetMember("ns"), true); - - var oblivious2 = (NamedTypeSymbol)compilation.GetMember("Oblivious2"); - Assert.True(oblivious2.NonNullTypes); - VerifyNonNullTypes(oblivious2.GetMember("s"), false); - VerifyNonNullTypes(oblivious2.GetMember("ns"), false); - - void verifyExternal(Compilation comp) - { - var external = (NamedTypeSymbol)comp.GetMember("External"); - Assert.True(external.NonNullTypes); - Assert.True(external.GetMember("s").NonNullTypes); - Assert.True(external.GetMember("ns").NonNullTypes); - Assert.False(external.GetMember("fs").NonNullTypes); - Assert.False(external.GetMember("fns").NonNullTypes); - } } [Fact] @@ -2820,7 +2768,6 @@ public class Oblivious var obliviousComp = CreateCompilation(obliviousLib, parseOptions: TestOptions.Regular7); obliviousComp.VerifyDiagnostics(); - VerifyNonNullTypes(obliviousComp.GetMember("Oblivious"), expectNonNullTypes: false); var lib = @" public class External @@ -2917,89 +2864,6 @@ public void M() // OuterD.D.s /*T:string!*/ = null; // warn 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(57, 36) ); - - var outerA = (NamedTypeSymbol)compilation.GetMember("OuterA"); - Assert.False(outerA.NonNullTypes); - - var a = (NamedTypeSymbol)outerA.GetMember("A"); - Assert.False(a.NonNullTypes); - VerifyNonNullTypes(a.GetMember("s"), true); - VerifyNonNullTypes(a.GetMember("ns"), true); - - var b = (NamedTypeSymbol)compilation.GetMember("B"); - VerifyNonNullTypes(b, true); - - var outerD = (NamedTypeSymbol)compilation.GetMember("OuterD"); - Assert.False(outerD.NonNullTypes); - - var d = (NamedTypeSymbol)outerD.GetMember("D"); - VerifyNonNullTypes(d, true); - - var oblivious2 = (NamedTypeSymbol)compilation.GetMember("Oblivious2"); - Assert.True(oblivious2.NonNullTypes); - VerifyNonNullTypes(oblivious2.GetMember("s"), false); - VerifyNonNullTypes(oblivious2.GetMember("ns"), false); - } - - /// - /// The type and all of its members should have the expected NonNullTypes value. - /// - private static void VerifyNonNullTypes(NamedTypeSymbol type, bool? expectNonNullTypes) - { - Assert.Equal(expectNonNullTypes, type.NonNullTypes); - - foreach (var member in type.GetMembers()) - { - VerifyNonNullTypes(member, expectNonNullTypes); - } - } - - private static void VerifyNonNullTypes(Symbol symbol, bool? expectNonNullTypes) - { - switch (symbol) - { - case NamedTypeSymbol type: - VerifyNonNullTypes(type, expectNonNullTypes); - break; - case PropertySymbol property: - VerifyNonNullTypes(property, expectNonNullTypes); - break; - case MethodSymbol method: - VerifyNonNullTypes(method, expectNonNullTypes); - break; - case FieldSymbol field: - Assert.Equal(expectNonNullTypes, field.NonNullTypes); - break; - } - } - - private static void VerifyNonNullTypes(PropertySymbol property, bool? expectNonNullTypes) - { - Assert.Equal(expectNonNullTypes, property.NonNullTypes); - VerifyNonNullTypes(property.GetMethod, expectNonNullTypes); - VerifyNonNullTypes(property.SetMethod, expectNonNullTypes); - } - - private static void VerifyNonNullTypes(MethodSymbol method, bool? expectNonNullTypes) - { - Assert.Equal(expectNonNullTypes, method.NonNullTypes); - - if (method.ReturnType.NullableAnnotation != NullableAnnotation.Annotated) - { - if (method is SynthesizedInstanceConstructor) - { - Assert.Equal(NullableAnnotation.Unknown, method.ReturnType.NullableAnnotation); - } - else - { - Assert.Equal(expectNonNullTypes == true, method.ReturnType.NullableAnnotation != NullableAnnotation.Unknown); - } - } - - foreach (var parameter in method.Parameters) - { - Assert.Equal(expectNonNullTypes, parameter.NonNullTypes); - } } [Fact] @@ -3013,7 +2877,6 @@ public class Oblivious "; var obliviousComp = CreateCompilation(obliviousLib, parseOptions: TestOptions.Regular7); - VerifyNonNullTypes((NamedTypeSymbol)obliviousComp.GetMember("Oblivious"), expectNonNullTypes: false); var lib = @" public class External @@ -3024,7 +2887,6 @@ public class External "; var libComp = CreateCompilation(new[] { lib }, options: WithNonNullTypesTrue()); - verifyExternal(libComp); var source = @" @@ -3113,31 +2975,6 @@ public void M() // OuterD.D.Method(null) /*T:string!*/; // warn 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(56, 25) ); - - var outerA = (NamedTypeSymbol)compilation.GetMember("OuterA"); - Assert.False(outerA.NonNullTypes); - - var a = (NamedTypeSymbol)outerA.GetMember("A"); - VerifyNonNullTypes(a, true); - - var b = (NamedTypeSymbol)compilation.GetMember("B"); - VerifyNonNullTypes(b, true); - - var outerD = (NamedTypeSymbol)compilation.GetMember("OuterD"); - Assert.False(outerD.NonNullTypes); - - var d = (NamedTypeSymbol)outerD.GetMember("D"); - Assert.False(d.NonNullTypes); - VerifyNonNullTypes(d.GetMember("Method"), true); - VerifyNonNullTypes(d.GetMember("NMethod"), true); - - var oblivious2 = (NamedTypeSymbol)compilation.GetMember("Oblivious2"); - VerifyNonNullTypes(oblivious2, false); - - void verifyExternal(Compilation comp) - { - VerifyNonNullTypes((NamedTypeSymbol)comp.GetMember("External"), true); - } } [Fact] @@ -3150,7 +2987,6 @@ public class Oblivious { } var obliviousComp = CreateCompilation(new[] { obliviousLib }); obliviousComp.VerifyDiagnostics(); - VerifyNonNullTypes(obliviousComp.GetMember("Oblivious"), expectNonNullTypes: false); var compilation = CreateCompilation("", options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular8, references: new[] { obliviousComp.EmitToImageReference() }); @@ -13045,6 +12881,7 @@ void M(T t) } [Fact] + [WorkItem(30079, "https://github.com/dotnet/roslyn/issues/30079")] public void EnsuresNotNull_BeginInvoke() { CSharpCompilation c = CreateCompilation(new[] { @" @@ -13065,12 +12902,6 @@ void M(Delegate d, string? s) // (8,32): warning CS8602: Possible dereference of a null reference. // if (s != string.Empty) s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 32), - // (9,26): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // d.BeginInvoke(s, null, null); - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(9, 26), - // (9,32): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // d.BeginInvoke(s, null, null); - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(9, 32), // (10,9): warning CS8602: Possible dereference of a null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(10, 9) @@ -24208,7 +24039,8 @@ static void G(C c) //Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c").WithArguments("C", "(IIn x, IOut y)").WithLocation(19, 18)); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/29618")] + [WorkItem(29618, "https://github.com/dotnet/roslyn/issues/29618")] public void DeconstructionTypeInference_01() { var source = @@ -24234,7 +24066,8 @@ static void M() Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(9, 13)); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/29618")] + [WorkItem(29618, "https://github.com/dotnet/roslyn/issues/29618")] public void DeconstructionTypeInference_02() { var source = @@ -24261,7 +24094,8 @@ static void G() Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 13)); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/29618")] + [WorkItem(29618, "https://github.com/dotnet/roslyn/issues/29618")] public void DeconstructionTypeInference_03() { var source = @@ -50574,8 +50408,1072 @@ class C {} Assert.Equal(2, arrays.Length); Assert.Equal("B[]", model.GetTypeInfo(arrays[0]).Type.ToTestDisplayString(includeNonNullable: true)); - // https://github.com/dotnet/roslyn/issues/30171 Expected "C![]" - Assert.Equal("C[]", model.GetTypeInfo(arrays[1]).Type.ToTestDisplayString(includeNonNullable: true)); + Assert.Equal("C![]", model.GetTypeInfo(arrays[1]).Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_02() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ +#nullable enable + B +#nullable disable + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("B!", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_03() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ +#nullable disable + B +#nullable enable + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("B", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_04() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + B +#nullable enable + ? + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("B?", f1.Type.ToTestDisplayString(includeNonNullable: true)); + + comp.VerifyDiagnostics(); + } + + [Fact] + public void NonNullTypesContext_05() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + B +#nullable disable + ? + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("B?", f1.Type.ToTestDisplayString(includeNonNullable: true)); + + comp.VerifyDiagnostics( + // (8,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. + // ? + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 6) + ); + } + + [Fact] + public void NonNullTypesContext_06() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ +#nullable enable + string +#nullable disable + F1; +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("System.String!", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_07() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ +#nullable disable + string +#nullable enable + F1; +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("System.String", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_08() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + B[ +#nullable enable + ] +#nullable disable + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("B[]!", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_09() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + B[ +#nullable disable + ] +#nullable enable + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("B![]", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_10() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + (B, B +#nullable enable + ) +#nullable disable + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal(NullableAnnotation.NotAnnotated, f1.Type.NullableAnnotation); + } + + [Fact] + public void NonNullTypesContext_11() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + (B, B +#nullable disable + ) +#nullable enable + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal(NullableAnnotation.Unknown, f1.Type.NullableAnnotation); + } + + [Fact] + public void NonNullTypesContext_12() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + B +#nullable disable + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("B!", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_13() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + B +#nullable enable + F1; +} + +class B {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("B", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_14() + { + var source = +@" +class A +{ + void M(out T x){} + + void Test() + { + M(out +#nullable enable + var +#nullable disable + local); + } +} + +class var {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + + var decl = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Equal("var!", ((LocalSymbol)model.GetDeclaredSymbol(decl.Designation)).Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_15() + { + var source = +@" +class A +{ + void M(out T x){} + + void Test() + { + M(out +#nullable disable + var +#nullable enable + local); + } +} + +class var {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + + var decl = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.Equal("var", ((LocalSymbol)model.GetDeclaredSymbol(decl.Designation)).Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_16() + { + var source = +@" +class A where T : +#nullable enable + class +#nullable disable +{ +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var a = comp.GetTypeByMetadataName("A`1"); + Assert.Equal("A where T : class!", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); + } + + [Fact] + public void NonNullTypesContext_17() + { + var source = +@" +class A where T : +#nullable disable + class +#nullable enable +{ +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var a = comp.GetTypeByMetadataName("A`1"); + Assert.Equal("A where T : class", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); + } + + [Fact] + public void NonNullTypesContext_18() + { + var source = +@" +class A where T : class +#nullable enable + ? +#nullable disable +{ +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var a = comp.GetTypeByMetadataName("A`1"); + Assert.Equal("A where T : class?", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); + + comp.VerifyDiagnostics(); + } + + [Fact] + public void NonNullTypesContext_19() + { + var source = +@" +class A where T : class +#nullable disable + ? +#nullable enable +{ +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var a = comp.GetTypeByMetadataName("A`1"); + Assert.Equal("A where T : class?", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); + + comp.VerifyDiagnostics( + // (4,5): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. + // ? + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 5) + ); + } + + [Fact] + public void NonNullTypesContext_20() + { + var source = +@" +class A where T : +#nullable enable + unmanaged +#nullable disable +{ +} + +class unmanaged {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var a = comp.GetTypeByMetadataName("A`1"); + Assert.Equal("A where T : unmanaged!", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); + } + + [Fact] + public void NonNullTypesContext_21() + { + var source = +@" +class A where T : +#nullable disable + unmanaged +#nullable enable +{ +} + +class unmanaged {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var a = comp.GetTypeByMetadataName("A`1"); + Assert.Equal("A where T : unmanaged", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); + } + + [Fact] + public void NonNullTypesContext_22() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string b; + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +A +" + ); + + AssertGetSpeculativeTypeInfo(source, WithNonNullTypesTrue(), type, "A"); + } + + private static void AssertGetSpeculativeTypeInfo(string source, CSharpCompilationOptions options, TypeSyntax type, string expected) + { + var comp = CreateCompilation(new[] { source }, options: options); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + + var decl = tree.GetRoot().DescendantNodes().OfType().Single(); + + Assert.Equal(expected, + model.GetSpeculativeTypeInfo(decl.Identifier.SpanStart, type, SpeculativeBindingOption.BindAsTypeOrNamespace).Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_23() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string b; + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +A +" + ); + + AssertGetSpeculativeTypeInfo(source, WithNonNullTypesFalse(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_24() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string b; + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +#nullable disable +A +" + ); + + AssertGetSpeculativeTypeInfo(source, WithNonNullTypesTrue(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_25() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string b; + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +#nullable enable +A +" + ); + + AssertGetSpeculativeTypeInfo(source, WithNonNullTypesFalse(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_26() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string +#nullable disable + b; +#nullable enable + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +A +" + ); + + AssertGetSpeculativeTypeInfo(source, WithNonNullTypesTrue(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_27() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string +#nullable enable + b; +#nullable disable + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +A +" + ); + + AssertGetSpeculativeTypeInfo(source, WithNonNullTypesFalse(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_28() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string +#nullable disable + b; +#nullable enable + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +#nullable enable +A +" + ); + + AssertGetSpeculativeTypeInfo(source, WithNonNullTypesTrue(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_29() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string +#nullable enable + b; +#nullable disable + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +#nullable disable +A +" + ); + + AssertGetSpeculativeTypeInfo(source, WithNonNullTypesFalse(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_30() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string b; + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +A +" + ); + + AssertTryGetSpeculativeSemanticModel(source, WithNonNullTypesTrue(), type, "A"); + } + + private static void AssertTryGetSpeculativeSemanticModel(string source, CSharpCompilationOptions options, TypeSyntax type, string expected) + { + var comp = CreateCompilation(new[] { source }, options: options); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + + var decl = tree.GetRoot().DescendantNodes().OfType().Single(); + + Assert.True(model.TryGetSpeculativeSemanticModel(decl.Identifier.SpanStart, type, out model, SpeculativeBindingOption.BindAsTypeOrNamespace)); + Assert.Equal(expected, + model.GetTypeInfo(type).Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_31() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string b; + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +A +" + ); + + AssertTryGetSpeculativeSemanticModel(source, WithNonNullTypesFalse(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_32() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string b; + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +#nullable disable +A +" + ); + + AssertTryGetSpeculativeSemanticModel(source, WithNonNullTypesTrue(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_33() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string b; + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +#nullable enable +A +" + ); + + AssertTryGetSpeculativeSemanticModel(source, WithNonNullTypesFalse(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_34() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string +#nullable disable + b; +#nullable enable + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +A +" + ); + + AssertTryGetSpeculativeSemanticModel(source, WithNonNullTypesTrue(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_35() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string +#nullable enable + b; +#nullable disable + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +A +" + ); + + AssertTryGetSpeculativeSemanticModel(source, WithNonNullTypesFalse(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_36() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string +#nullable disable + b; +#nullable enable + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +#nullable enable +A +" + ); + + AssertTryGetSpeculativeSemanticModel(source, WithNonNullTypesTrue(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_37() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + void Tests() + { + string +#nullable enable + b; +#nullable disable + } +} +"; + TypeSyntax type = SyntaxFactory.ParseTypeName( +@" +#nullable disable +A +" + ); + + AssertTryGetSpeculativeSemanticModel(source, WithNonNullTypesFalse(), type, "A"); + } + + [Fact] + public void NonNullTypesContext_38() + { + var source = +@" +using B = C; +#pragma warning disable CS0169 + +class A +{ +#nullable enable + B +#nullable disable + F1; +} + +class C {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("C!", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_39() + { + var source = +@" +using B = C; +#pragma warning disable CS0169 + +class A +{ +#nullable disable + B +#nullable enable + F1; +} + +class C {} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("C", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_40() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + C. +#nullable enable + B +#nullable disable + F1; +} + +namespace C +{ + class B {} +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("C.B!", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_41() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + C. +#nullable disable + B +#nullable enable + F1; +} + +namespace C +{ + class B {} +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("C.B", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_42() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + C.B +#nullable disable + F1; +} + +namespace C +{ + class B {} +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("C.B!", f1.Type.ToTestDisplayString(includeNonNullable: true)); + } + + [Fact] + public void NonNullTypesContext_43() + { + var source = +@" +#pragma warning disable CS0169 + +class A +{ + C.B +#nullable enable + F1; +} + +namespace C +{ + class B {} +} +"; + var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); + + var f1 = comp.GetMember("A.F1"); + Assert.Equal("C.B", f1.Type.ToTestDisplayString(includeNonNullable: true)); } [Fact] -- GitLab