未验证 提交 2566316b 编写于 作者: J Julien Couvreur 提交者: GitHub

Merge pull request #33648 from gafter/nullable-states

Revise NullableWalker to use a two-state solution
......@@ -15,7 +15,7 @@ internal struct NamespaceOrTypeOrAliasSymbolWithAnnotations
private NamespaceOrTypeOrAliasSymbolWithAnnotations(TypeSymbolWithAnnotations type)
{
Debug.Assert(!type.IsNull);
Debug.Assert(type.HasType);
_type = type;
_symbol = null;
_isNullableEnabled = false; // Not meaningful for a TypeSymbolWithAnnotations, it already baked the fact into its content.
......@@ -31,10 +31,10 @@ private NamespaceOrTypeOrAliasSymbolWithAnnotations(Symbol symbol, bool isNullab
internal TypeSymbolWithAnnotations Type => _type;
internal Symbol Symbol => _symbol ?? Type.TypeSymbol;
internal bool IsType => !_type.IsNull;
internal bool IsType => !_type.IsDefault;
internal bool IsAlias => _symbol?.Kind == SymbolKind.Alias;
internal NamespaceOrTypeSymbol NamespaceOrTypeSymbol => Symbol as NamespaceOrTypeSymbol;
internal bool IsDefault => _type.IsNull && _symbol is null;
internal bool IsDefault => !_type.HasType && _symbol is null;
internal bool IsNullableEnabled
{
......
......@@ -954,7 +954,7 @@ private bool CheckPropertyValueKind(SyntaxNode node, BoundExpression expr, BindV
// change from Dev10 which reports this error for struct types only,
// not for type parameters constrained to "struct".
Debug.Assert(!propertySymbol.Type.IsNull);
Debug.Assert(propertySymbol.Type.HasType);
Error(diagnostics, ErrorCode.ERR_ReturnNotLValue, expr.Syntax, propertySymbol);
}
else
......@@ -1665,7 +1665,7 @@ private static void ReportReadOnlyFieldError(FieldSymbol field, SyntaxNode node,
{
Debug.Assert((object)field != null);
Debug.Assert(RequiresAssignableVariable(kind));
Debug.Assert(!field.Type.IsNull);
Debug.Assert(field.Type.HasType);
// It's clearer to say that the address can't be taken than to say that the field can't be modified
// (even though the latter message gives more explanation of why).
......
......@@ -226,7 +226,7 @@ private void ValidateTypeForAttributeParameters(ImmutableArray<ParameterSymbol>
foreach (var parameter in parameters)
{
var paramType = parameter.Type;
Debug.Assert(!paramType.IsNull);
Debug.Assert(paramType.HasType);
if (!paramType.TypeSymbol.IsValidAttributeParameterType(Compilation))
{
......
......@@ -75,7 +75,7 @@ internal partial class Binder
sourceTuple.Type,
sourceTuple.Arguments,
sourceTuple.Type, // same type to keep original element names
sourceTuple.HasErrors);
sourceTuple.HasErrors).WithSuppression(sourceTuple.IsSuppressed);
}
// We need to preserve any conversion that changes the type (even identity conversions, like object->dynamic),
......
......@@ -500,7 +500,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
locationsBuilder.Add(element.Syntax.Location);
}
if (typesBuilder.Any(t => t.IsNull))
if (typesBuilder.Any(t => !t.HasType))
{
typesBuilder.Free();
locationsBuilder.Free();
......@@ -721,7 +721,7 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres
bool isConst = false;
AliasSymbol alias;
var declType = BindVariableType(component.Designation, diagnostics, component.Type, ref isConst, out isVar, out alias);
Debug.Assert(isVar == declType.IsNull);
Debug.Assert(isVar == !declType.HasType);
if (component.Designation.Kind() == SyntaxKind.ParenthesizedVariableDesignation && !isVar)
{
// An explicit is not allowed with a parenthesized designation
......@@ -819,7 +819,7 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres
// might own nested scope.
var hasErrors = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
if (!declType.IsNull)
if (declType.HasType)
{
return new BoundLocal(syntax, localSymbol, BoundLocalDeclarationKind.WithExplicitType, constantValueOpt: null, isNullableUnknown: false, type: declType.TypeSymbol, hasErrors: hasErrors);
}
......@@ -839,7 +839,7 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres
BoundThisReference receiver = ThisReference(designation, this.ContainingType, hasErrors: false,
wasCompilerGenerated: true);
if (!declType.IsNull)
if (declType.HasType)
{
var fieldType = field.GetFieldType(this.FieldsBeingBound);
Debug.Assert(TypeSymbol.Equals(declType.TypeSymbol, fieldType.TypeSymbol, TypeCompareKind.ConsiderEverything2));
......
......@@ -692,7 +692,7 @@ private BoundExpression BindDeclarationExpression(DeclarationExpressionSyntax no
/// </summary>
private BoundExpression BindDeclarationVariables(TypeSymbolWithAnnotations declType, VariableDesignationSyntax node, CSharpSyntaxNode syntax, DiagnosticBag diagnostics)
{
declType = declType.IsNull ? TypeSymbolWithAnnotations.Create(CreateErrorType("var")) : declType;
declType = declType.HasType ? declType : TypeSymbolWithAnnotations.Create(CreateErrorType("var"));
switch (node.Kind())
{
case SyntaxKind.SingleVariableDesignation:
......@@ -799,7 +799,7 @@ private BoundExpression BindTupleExpression(TupleExpressionSyntax node, Diagnost
var elementType = TypeSymbolWithAnnotations.Create(boundArgument.Type);
elementTypes.Add(elementType);
if (elementType.IsNull)
if (!elementType.HasType)
{
hasNaturalType = false;
}
......@@ -2237,7 +2237,7 @@ private BoundExpression BindCastCore(ExpressionSyntax node, BoundExpression oper
/// </summary>
private BoundExpression BindExplicitNullableCastFromNonNullable(ExpressionSyntax node, BoundExpression operand, TypeSymbolWithAnnotations targetType, DiagnosticBag diagnostics)
{
Debug.Assert(!targetType.IsNull && targetType.IsNullableType());
Debug.Assert(targetType.HasType && targetType.IsNullableType());
Debug.Assert((object)operand.Type != null && !operand.Type.IsNullableType());
// Section 6.2.3 of the spec only applies when the non-null version of the types involved have a
......@@ -2491,7 +2491,7 @@ private BoundExpression BindOutDeclarationArgument(DeclarationExpressionSyntax d
bool isConst = false;
AliasSymbol alias;
var declType = BindVariableType(designation, diagnostics, typeSyntax, ref isConst, out isVar, out alias);
Debug.Assert(isVar == declType.IsNull);
Debug.Assert(isVar != declType.HasType);
return new BoundDiscardExpression(declarationExpression, declType.TypeSymbol);
}
......@@ -2744,7 +2744,7 @@ private BoundExpression BindArgumentExpression(DiagnosticBag diagnostics, Expres
else if (argument.Kind == BoundKind.DiscardExpression && !argument.HasExpressionType())
{
TypeSymbolWithAnnotations parameterType = GetCorrespondingParameterType(ref result, parameters, arg);
Debug.Assert(!parameterType.IsNull);
Debug.Assert(parameterType.HasType);
arguments[arg] = ((BoundDiscardExpression)argument).SetInferredType(parameterType);
}
}
......
......@@ -228,7 +228,7 @@ private UnboundLambda BindAnonymousFunction(CSharpSyntaxNode syntax, DiagnosticB
foreach (var type in types)
{
// UNDONE: Where do we report improper use of pointer types?
if (!type.IsNull && type.IsStatic)
if (type.HasType && type.IsStatic)
{
Error(diagnostics, ErrorCode.ERR_ParameterIsStaticClass, syntax, type.TypeSymbol);
}
......
......@@ -377,7 +377,7 @@ private BoundPattern BindDiscardPattern(DiscardPatternSyntax node, TypeSymbol in
Debug.Assert(inputType != (object)null);
Debug.Assert(!typeSyntax.IsVar); // if the syntax had `var`, it would have been parsed as a var pattern.
TypeSymbolWithAnnotations declType = BindType(typeSyntax, diagnostics, out AliasSymbol aliasOpt);
Debug.Assert(!declType.IsNull);
Debug.Assert(declType.HasType);
Debug.Assert(typeSyntax.Kind() != SyntaxKind.NullableType); // the syntax does not permit nullable annotations
BoundTypeExpression boundDeclType = new BoundTypeExpression(typeSyntax, aliasOpt, inferredType: false, type: declType.TypeSymbol);
hasErrors |= CheckValidPatternType(typeSyntax, inputType, declType.TypeSymbol, patternTypeWasInSource: true, diagnostics: diagnostics);
......
......@@ -728,7 +728,7 @@ private TypeSymbolWithAnnotations BindVariableType(CSharpSyntaxNode declarationN
// we want to treat the declaration as an explicitly typed declaration.
TypeSymbolWithAnnotations declType = BindTypeOrVarKeyword(typeSyntax.SkipRef(out _), diagnostics, out isVar, out alias);
Debug.Assert(!declType.IsNull || isVar);
Debug.Assert(declType.HasType || isVar);
if (isVar)
{
......@@ -915,7 +915,7 @@ protected BoundExpression BindInferredVariableInitializer(DiagnosticBag diagnost
CSharpSyntaxNode associatedSyntaxNode = null)
{
Debug.Assert(declarator != null);
Debug.Assert(!declTypeOpt.IsNull || isVar);
Debug.Assert(declTypeOpt.HasType || isVar);
Debug.Assert(typeSyntax != null);
var localDiagnostics = DiagnosticBag.GetInstance();
......@@ -999,7 +999,7 @@ protected BoundExpression BindInferredVariableInitializer(DiagnosticBag diagnost
}
}
Debug.Assert(!declTypeOpt.IsNull);
Debug.Assert(declTypeOpt.HasType);
if (kind == LocalDeclarationKind.FixedVariable)
{
......@@ -2344,7 +2344,7 @@ internal BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSyn
bool isVar;
TypeSymbolWithAnnotations declType = BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar, out alias);
Debug.Assert(!declType.IsNull || isVar);
Debug.Assert(declType.HasType || isVar);
var variables = nodeOpt.Variables;
int count = variables.Count;
......@@ -2495,7 +2495,7 @@ protected virtual TypeSymbol GetCurrentReturnType(out RefKind refKind)
TypeSymbolWithAnnotations returnType = symbol.ReturnType;
if (returnType.IsNull || (object)returnType.TypeSymbol == LambdaSymbol.ReturnTypeIsBeingInferred)
if ((object)returnType.TypeSymbol == LambdaSymbol.ReturnTypeIsBeingInferred)
{
return null;
}
......
......@@ -469,7 +469,7 @@ void reportNullableReferenceTypesIfNeeded(SyntaxToken questionToken, TypeSymbolW
var location = questionToken.GetLocation();
// Inside a method body or other executable code, we can question IsValueType without causing cycles.
if (!typeArgument.IsNull && !ShouldCheckConstraints)
if (typeArgument.HasType && !ShouldCheckConstraints)
{
LazyMissingNonNullTypesContextDiagnosticInfo.AddAll(isNullableEnabled, typeArgument, location, diagnostics);
}
......
......@@ -58,7 +58,7 @@ internal bool IsAsync
BinderFlags location)
{
Debug.Assert((object)collectionType != null, "Field 'collectionType' cannot be null");
Debug.Assert(!elementType.IsNull, "Field 'elementType' cannot be null");
Debug.Assert(elementType.HasType, "Field 'elementType' cannot be null");
Debug.Assert((object)getEnumeratorMethod != null, "Field 'getEnumeratorMethod' cannot be null");
Debug.Assert((object)currentPropertyGetter != null, "Field 'currentPropertyGetter' cannot be null");
Debug.Assert((object)moveNextMethod != null, "Field 'moveNextMethod' cannot be null");
......
......@@ -244,11 +244,11 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics,
if (isVar)
{
declType = inferredType.IsNull ? TypeSymbolWithAnnotations.Create(CreateErrorType("var")) : inferredType;
declType = inferredType.HasType ? inferredType : TypeSymbolWithAnnotations.Create(CreateErrorType("var"));
}
else
{
Debug.Assert(!declType.IsNull);
Debug.Assert(declType.HasType);
}
iterationVariableType = declType.TypeSymbol;
......
......@@ -15,7 +15,7 @@ public static NullableAnnotation GetNullableAnnotation(ArrayBuilder<TypeSymbolWi
NullableAnnotation result = NullableAnnotation.NotAnnotated;
foreach (var type in types)
{
Debug.Assert(!type.IsNull);
Debug.Assert(type.HasType);
Debug.Assert(type.Equals(types[0], TypeCompareKind.AllIgnoreOptions));
// This uses the covariant merging rules.
result = result.JoinForFixingLowerBounds(type.AsSpeakable().NullableAnnotation);
......@@ -24,6 +24,18 @@ public static NullableAnnotation GetNullableAnnotation(ArrayBuilder<TypeSymbolWi
return result;
}
public static NullableAnnotation GetNullableAnnotation(ArrayBuilder<TypeWithState> types)
{
ArrayBuilder<TypeSymbolWithAnnotations> builder = ArrayBuilder<TypeSymbolWithAnnotations>.GetInstance();
foreach (var type in types)
{
builder.Add(type.ToTypeSymbolWithAnnotations());
}
var result = GetNullableAnnotation(builder);
builder.Free();
return result;
}
/// <remarks>
/// This method finds the best common type of a set of expressions as per section 7.5.2.14 of the specification.
/// NOTE: If some or all of the expressions have error types, we return error type as the inference result.
......
......@@ -212,6 +212,7 @@ internal static Conversion GetTrivialConversion(ConversionKind kind)
return new Conversion(kind);
}
internal static Conversion UnsetConversion => new Conversion(ConversionKind.UnsetConversionKind);
internal static Conversion NoConversion => new Conversion(ConversionKind.NoConversion);
internal static Conversion Identity => new Conversion(ConversionKind.Identity);
internal static Conversion ImplicitConstant => new Conversion(ConversionKind.ImplicitConstant);
......
......@@ -8,6 +8,7 @@ namespace Microsoft.CodeAnalysis.CSharp
{
internal enum ConversionKind : byte
{
UnsetConversionKind = 0,
NoConversion,
Identity,
ImplicitNumeric,
......
......@@ -1399,12 +1399,12 @@ internal bool HasTopLevelNullabilityIdentityConversion(TypeSymbolWithAnnotations
return true;
}
if (source.IsPossiblyNullableReferenceTypeTypeParameter() && !destination.IsPossiblyNullableReferenceTypeTypeParameter())
if (source.IsPossiblyNullableTypeTypeParameter() && !destination.IsPossiblyNullableTypeTypeParameter())
{
return destination.NullableAnnotation.IsAnyNullable();
}
if (destination.IsPossiblyNullableReferenceTypeTypeParameter() && !source.IsPossiblyNullableReferenceTypeTypeParameter())
if (destination.IsPossiblyNullableTypeTypeParameter() && !source.IsPossiblyNullableTypeTypeParameter())
{
return source.NullableAnnotation.IsAnyNullable();
}
......@@ -1431,7 +1431,7 @@ internal bool HasTopLevelNullabilityImplicitConversion(TypeSymbolWithAnnotations
return true;
}
if (source.IsPossiblyNullableReferenceTypeTypeParameter() && !destination.IsPossiblyNullableReferenceTypeTypeParameter())
if (source.IsPossiblyNullableTypeTypeParameter() && !destination.IsPossiblyNullableTypeTypeParameter())
{
return false;
}
......
......@@ -212,8 +212,8 @@ private enum Dependency
// the delegate.
ImmutableArray<RefKind> formalParameterRefKinds, // Optional; assume all value if missing.
ImmutableArray<BoundExpression> arguments, // Required; in scenarios like method group conversions where there are
// no arguments per se we cons up some fake arguments.
ImmutableArray<BoundExpression> arguments,// Required; in scenarios like method group conversions where there are
// no arguments per se we cons up some fake arguments.
ref HashSet<DiagnosticInfo> useSiteDiagnostics,
Func<BoundExpression, TypeSymbolWithAnnotations> getTypeWithAnnotationOpt = null)
{
......@@ -338,7 +338,7 @@ internal string Dump()
var fixedType = _fixedResults[i];
if (fixedType.IsNull)
if (!fixedType.HasType)
{
sb.Append("UNFIXED ");
}
......@@ -384,7 +384,7 @@ private ImmutableArray<TypeSymbolWithAnnotations> GetResults()
for (int i = 0; i < _methodTypeParameters.Length; i++)
{
if (!_fixedResults[i].IsNull)
if (_fixedResults[i].HasType)
{
if (!_fixedResults[i].IsErrorType())
{
......@@ -411,12 +411,12 @@ private bool ValidIndex(int index)
private bool IsUnfixed(int methodTypeParameterIndex)
{
Debug.Assert(ValidIndex(methodTypeParameterIndex));
return _fixedResults[methodTypeParameterIndex].IsNull;
return !_fixedResults[methodTypeParameterIndex].HasType;
}
private bool IsUnfixedTypeParameter(TypeSymbolWithAnnotations type)
{
Debug.Assert(!type.IsNull);
Debug.Assert(type.HasType);
if (type.TypeKind != TypeKind.TypeParameter) return false;
......@@ -1169,7 +1169,7 @@ private bool AnyDependsOn(int iParam)
private void OutputTypeInference(Binder binder, BoundExpression expression, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(expression != null);
Debug.Assert(!target.IsNull);
Debug.Assert(target.HasType);
// SPEC: An output type inference is made from an expression E to a type T
// SPEC: in the following way:
......@@ -1192,7 +1192,7 @@ private void OutputTypeInference(Binder binder, BoundExpression expression, Type
// SPEC: * Otherwise, if E is an expression with type U then a lower-bound
// SPEC: inference is made from U to T.
var sourceType = GetTypeWithAnnotations(expression);
if (!sourceType.IsNull)
if (sourceType.HasType)
{
LowerBoundInference(sourceType, target, ref useSiteDiagnostics);
}
......@@ -1202,7 +1202,7 @@ private void OutputTypeInference(Binder binder, BoundExpression expression, Type
private bool InferredReturnTypeInference(BoundExpression source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(source != null);
Debug.Assert(!target.IsNull);
Debug.Assert(target.HasType);
// SPEC: * If E is an anonymous function with inferred return type U and
// SPEC: T is a delegate type or expression tree with return type Tb
// SPEC: then a lower bound inference is made from U to Tb.
......@@ -1218,13 +1218,13 @@ private bool InferredReturnTypeInference(BoundExpression source, TypeSymbolWithA
Debug.Assert((object)delegateType.DelegateInvokeMethod != null && !delegateType.DelegateInvokeMethod.HasUseSiteError,
"This method should only be called for valid delegate types.");
var returnType = delegateType.DelegateInvokeMethod.ReturnType;
if (returnType.IsNull || returnType.SpecialType == SpecialType.System_Void)
if (!returnType.HasType || returnType.SpecialType == SpecialType.System_Void)
{
return false;
}
var inferredReturnType = InferReturnType(source, delegateType, ref useSiteDiagnostics);
if (inferredReturnType.IsNull)
if (!inferredReturnType.HasType)
{
return false;
}
......@@ -1261,7 +1261,7 @@ private bool MethodGroupReturnTypeInference(Binder binder, BoundExpression sourc
"This method should only be called for valid delegate types");
TypeSymbolWithAnnotations delegateReturnType = delegateInvokeMethod.ReturnType;
if (delegateReturnType.IsNull || delegateReturnType.SpecialType == SpecialType.System_Void)
if (!delegateReturnType.HasType || delegateReturnType.SpecialType == SpecialType.System_Void)
{
return false;
}
......@@ -1280,7 +1280,9 @@ private bool MethodGroupReturnTypeInference(Binder binder, BoundExpression sourc
return false;
}
NullableAnnotation returnIsNullable = NullableAnnotation.Unknown; // https://github.com/dotnet/roslyn/issues/27961 Review this
// https://github.com/dotnet/roslyn/issues/33635 : We should preserve the return nullability from the
// selected method of the method group, possibly turning oblivious into non-null.
NullableAnnotation returnIsNullable = NullableAnnotation.Unknown;
LowerBoundInference(TypeSymbolWithAnnotations.Create(returnType, returnIsNullable), delegateReturnType, ref useSiteDiagnostics);
return true;
......@@ -1324,7 +1326,7 @@ private bool MethodGroupReturnTypeInference(Binder binder, BoundExpression sourc
private void ExplicitParameterTypeInference(BoundExpression source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(source != null);
Debug.Assert(!target.IsNull);
Debug.Assert(target.HasType);
// SPEC: An explicit type parameter type inference is made from an expression
// SPEC: E to a type T in the following way.
......@@ -1382,8 +1384,8 @@ private void ExplicitParameterTypeInference(BoundExpression source, TypeSymbolWi
//
private void ExactInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// SPEC: An exact inference from a type U to a type V is made as follows:
......@@ -1429,8 +1431,8 @@ private void ExactInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnno
private bool ExactTypeParameterInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// SPEC: * If V is one of the unfixed Xi then U is added to the set of bounds
// SPEC: for Xi.
......@@ -1444,8 +1446,8 @@ private bool ExactTypeParameterInference(TypeSymbolWithAnnotations source, TypeS
private bool ExactArrayInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// SPEC: * Otherwise, if U is an array type UE[...] and V is an array type VE[...]
// SPEC: of the same rank then an exact inference from UE to VE is made.
......@@ -1490,8 +1492,8 @@ private void ExactOrBoundsInference(ExactOrBoundsKind kind, TypeSymbolWithAnnota
private bool ExactOrBoundsNullableInference(ExactOrBoundsKind kind, TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
if (source.IsNullableType() && target.IsNullableType())
{
......@@ -1519,8 +1521,8 @@ private bool ExactNullableInference(TypeSymbolWithAnnotations source, TypeSymbol
private bool LowerBoundTupleInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// NOTE: we are losing tuple element names when unwrapping tuple types to underlying types.
// that is ok, because we are inferring type parameters used in the matching elements,
......@@ -1546,8 +1548,8 @@ private bool LowerBoundTupleInference(TypeSymbolWithAnnotations source, TypeSymb
private bool ExactConstructedInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// SPEC: * Otherwise, if V is a constructed type C<V1...Vk> and U is a constructed
// SPEC: type C<U1...Uk> then an exact inference
......@@ -1614,8 +1616,8 @@ private void ExactTypeArgumentInference(NamedTypeSymbol source, NamedTypeSymbol
//
private void LowerBoundInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// SPEC: A lower-bound inference from a type U to a type V is made as follows:
......@@ -1696,8 +1698,8 @@ private void LowerBoundInference(TypeSymbolWithAnnotations source, TypeSymbolWit
private bool LowerBoundTypeParameterInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// SPEC: * If V is one of the unfixed Xi then U is added to the set of bounds
// SPEC: for Xi.
......@@ -1765,7 +1767,7 @@ private bool LowerBoundArrayInference(TypeSymbol source, TypeSymbol target, ref
var arraySource = (ArrayTypeSymbol)source;
var elementSource = arraySource.ElementType;
var elementTarget = GetMatchingElementType(arraySource, target, ref useSiteDiagnostics);
if (elementTarget.IsNull)
if (!elementTarget.HasType)
{
return false;
}
......@@ -2003,8 +2005,8 @@ private void LowerBoundTypeArgumentInference(NamedTypeSymbol source, NamedTypeSy
//
private void UpperBoundInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// SPEC: An upper-bound inference from a type U to a type V is made as follows:
......@@ -2059,8 +2061,8 @@ private void UpperBoundInference(TypeSymbolWithAnnotations source, TypeSymbolWit
private bool UpperBoundTypeParameterInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// SPEC: * If V is one of the unfixed Xi then U is added to the set of upper bounds
// SPEC: for Xi.
if (IsUnfixedTypeParameter(target))
......@@ -2073,8 +2075,8 @@ private bool UpperBoundTypeParameterInference(TypeSymbolWithAnnotations source,
private bool UpperBoundArrayInference(TypeSymbolWithAnnotations source, TypeSymbolWithAnnotations target, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(!source.IsNull);
Debug.Assert(!target.IsNull);
Debug.Assert(source.HasType);
Debug.Assert(target.HasType);
// SPEC: * Otherwise, if V is an array type Ve[...] and U is an array
// SPEC: type Ue[...] of the same rank, or if V is a one-dimensional array
......@@ -2091,7 +2093,7 @@ private bool UpperBoundArrayInference(TypeSymbolWithAnnotations source, TypeSymb
var arrayTarget = (ArrayTypeSymbol)target.TypeSymbol;
var elementTarget = arrayTarget.ElementType;
var elementSource = GetMatchingElementType(arrayTarget, source.TypeSymbol, ref useSiteDiagnostics);
if (elementSource.IsNull)
if (!elementSource.HasType)
{
return false;
}
......@@ -2115,8 +2117,8 @@ private bool UpperBoundNullableInference(TypeSymbolWithAnnotations source, TypeS
private bool UpperBoundConstructedInference(TypeSymbolWithAnnotations sourceWithAnnotations, TypeSymbolWithAnnotations targetWithAnnotations, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
Debug.Assert(!sourceWithAnnotations.IsNull);
Debug.Assert(!targetWithAnnotations.IsNull);
Debug.Assert(sourceWithAnnotations.HasType);
Debug.Assert(targetWithAnnotations.HasType);
var source = sourceWithAnnotations.TypeSymbol.TupleUnderlyingTypeOrSelf();
var target = targetWithAnnotations.TypeSymbol.TupleUnderlyingTypeOrSelf();
......@@ -2302,7 +2304,7 @@ private bool Fix(int iParam, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
var upper = _upperBounds[iParam];
var best = Fix(exact, lower, upper, ref useSiteDiagnostics, _conversions);
if (best.IsNull)
if (!best.HasType)
{
return false;
}
......@@ -2415,7 +2417,7 @@ private bool Fix(int iParam, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
}
}
if (best.IsNull)
if (!best.HasType)
{
best = candidate;
}
......@@ -2454,6 +2456,7 @@ internal static TypeSymbolWithAnnotations Merge(TypeSymbolWithAnnotations first,
// distinct "not computed" state from initial binding.
return merged.SetUnknownNullabilityForReferenceTypes();
}
return merged.MergeNullability(second, variance);
}
......@@ -2785,6 +2788,7 @@ private static void GetAllCandidates(Dictionary<TypeSymbolWithAnnotations, TypeS
// distinct "not computed" state from initial binding.
type = type.SetUnknownNullabilityForReferenceTypes();
}
AddOrMergeCandidate(candidates, type, variance, conversions);
}
}
......
......@@ -2248,7 +2248,7 @@ private bool ExpressionMatchExactly(BoundExpression node, TypeSymbol t, ref Hash
// - an inferred return type X exists for E in the context of the parameter list of D(§7.5.2.12), and an identity conversion exists from X to Y
var x = lambda.GetInferredReturnType(ref useSiteDiagnostics);
if (!x.IsNull && Conversions.HasIdentityConversion(x.TypeSymbol, y))
if (x.HasType && Conversions.HasIdentityConversion(x.TypeSymbol, y))
{
return true;
}
......@@ -2673,7 +2673,7 @@ private bool CanDowngradeConversionFromLambdaToNeither(BetterResult currentResul
}
var x = lambda.InferReturnType(Conversions, d1, ref useSiteDiagnostics);
if (x.IsNull)
if (!x.HasType)
{
return true;
}
......
......@@ -9,7 +9,7 @@ internal partial class BoundDiscardExpression
{
public BoundExpression SetInferredType(TypeSymbolWithAnnotations type)
{
Debug.Assert((object)Type == null && !type.IsNull);
Debug.Assert((object)Type == null && type.HasType);
return this.Update(type.TypeSymbol);
}
......
......@@ -16,15 +16,18 @@ internal partial class BoundExpression
/// </summary>
protected abstract BoundExpression ShallowClone();
internal BoundExpression WithSuppression()
internal BoundExpression WithSuppression(bool suppress = true)
{
if (this.IsSuppressed)
if (this.IsSuppressed == suppress)
{
return this;
}
// There is no scenario where suppression goes away
Debug.Assert(suppress || !this.IsSuppressed);
var result = ShallowClone();
result.IsSuppressed = true;
result.IsSuppressed = suppress;
return result;
}
......
......@@ -70,7 +70,7 @@ public bool HasAnyErrors
return true;
}
var expression = this as BoundExpression;
return expression != null && !ReferenceEquals(expression.Type, null) && expression.Type.IsErrorType();
return expression?.Type?.IsErrorType() == true;
}
}
......
......@@ -22,7 +22,7 @@ internal ConversionGroup(Conversion conversion, TypeSymbolWithAnnotations explic
/// <summary>
/// True if the conversion is an explicit conversion.
/// </summary>
internal bool IsExplicitConversion => !ExplicitType.IsNull;
internal bool IsExplicitConversion => ExplicitType.HasType;
/// <summary>
/// The conversion (from Conversions.ClassifyConversionFromExpression for
......@@ -43,7 +43,7 @@ internal ConversionGroup(Conversion conversion, TypeSymbolWithAnnotations explic
internal string GetDebuggerDisplay()
{
var str = $"#{_id} {Conversion}";
if (!ExplicitType.IsNull)
if (ExplicitType.HasType)
{
str += $" ({ExplicitType})";
}
......
......@@ -234,7 +234,7 @@ public TypeSymbolWithAnnotations GetInferredReturnType(ConversionsBase conversio
return TypeSymbolWithAnnotations.Create(resultType);
}
if (bestResultType.IsNull || bestResultType.SpecialType == SpecialType.System_Void)
if (!bestResultType.HasType || bestResultType.SpecialType == SpecialType.System_Void)
{
// If the best type was 'void', ERR_CantReturnVoid is reported while binding the "return void"
// statement(s).
......@@ -428,7 +428,7 @@ internal IEnumerable<TypeSymbol> InferredReturnTypes()
foreach (var lambda in _returnInferenceCache.Values)
{
var type = lambda.InferredReturnType.Type;
if (!type.IsNull)
if (type.HasType)
{
any = true;
yield return type.TypeSymbol;
......@@ -438,7 +438,7 @@ internal IEnumerable<TypeSymbol> InferredReturnTypes()
if (!any)
{
var type = BindForErrorRecovery().InferredReturnType.Type;
if (!type.IsNull)
if (type.HasType)
{
yield return type.TypeSymbol;
}
......@@ -528,7 +528,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
var lambdaParameters = lambdaSymbol.Parameters;
ParameterHelpers.EnsureIsReadOnlyAttributeExists(lambdaParameters, diagnostics, modifyCompilation: false);
if (!returnType.IsNull)
if (returnType.HasType)
{
if (returnType.NeedsNullableAttribute())
{
......@@ -563,7 +563,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics))
{
if (!returnType.IsNull && // Can be null if "delegateType" is not actually a delegate type.
if (returnType.HasType && // Can be null if "delegateType" is not actually a delegate type.
returnType.SpecialType != SpecialType.System_Void &&
!returnType.TypeSymbol.IsNonGenericTaskType(binder.Compilation) &&
!returnType.TypeSymbol.IsGenericTaskType(binder.Compilation))
......@@ -633,7 +633,7 @@ private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType, Immutabl
// TODO: Should InferredReturnType.UseSiteDiagnostics be merged into BoundLambda.Diagnostics?
var returnType = inferredReturnType.Type;
if (returnType.IsNull)
if (!returnType.HasType)
{
returnType = TypeSymbolWithAnnotations.Create(LambdaSymbol.InferenceFailureReturnType);
}
......@@ -842,7 +842,7 @@ private static string GetLambdaSortString(LambdaSymbol lambda)
builder.Builder.Append(parameter.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat));
}
if (!lambda.ReturnType.IsNull)
if (lambda.ReturnType.HasType)
{
builder.Builder.Append(lambda.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
}
......
......@@ -22,19 +22,19 @@ internal partial class VariablePendingInference : BoundExpression
{
internal BoundExpression SetInferredType(TypeSymbolWithAnnotations type, DiagnosticBag diagnosticsOpt)
{
Debug.Assert(!type.IsNull);
Debug.Assert(type.HasType);
return SetInferredType(type, null, diagnosticsOpt);
}
internal BoundExpression SetInferredType(TypeSymbolWithAnnotations type, Binder binderOpt, DiagnosticBag diagnosticsOpt)
{
Debug.Assert(binderOpt != null || !type.IsNull);
Debug.Assert(binderOpt != null || type.HasType);
Debug.Assert(this.Syntax.Kind() == SyntaxKind.SingleVariableDesignation ||
(this.Syntax.Kind() == SyntaxKind.DeclarationExpression &&
((DeclarationExpressionSyntax)this.Syntax).Designation.Kind() == SyntaxKind.SingleVariableDesignation));
bool inferenceFailed = type.IsNull;
bool inferenceFailed = !type.HasType;
if (inferenceFailed)
{
......
......@@ -10716,60 +10716,6 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Expression is probably never null..
/// </summary>
internal static string HDN_ExpressionIsProbablyNeverNull {
get {
return ResourceManager.GetString("HDN_ExpressionIsProbablyNeverNull", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Expression is probably never null..
/// </summary>
internal static string HDN_ExpressionIsProbablyNeverNull_Title {
get {
return ResourceManager.GetString("HDN_ExpressionIsProbablyNeverNull_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Result of the comparison is possibly always false..
/// </summary>
internal static string HDN_NullCheckIsProbablyAlwaysFalse {
get {
return ResourceManager.GetString("HDN_NullCheckIsProbablyAlwaysFalse", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Result of the comparison is possibly always false..
/// </summary>
internal static string HDN_NullCheckIsProbablyAlwaysFalse_Title {
get {
return ResourceManager.GetString("HDN_NullCheckIsProbablyAlwaysFalse_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Result of the comparison is possibly always true..
/// </summary>
internal static string HDN_NullCheckIsProbablyAlwaysTrue {
get {
return ResourceManager.GetString("HDN_NullCheckIsProbablyAlwaysTrue", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Result of the comparison is possibly always true..
/// </summary>
internal static string HDN_NullCheckIsProbablyAlwaysTrue_Title {
get {
return ResourceManager.GetString("HDN_NullCheckIsProbablyAlwaysTrue_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unused extern alias..
/// </summary>
......@@ -12400,6 +12346,24 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;as&apos; operator may produce a null value when &apos;{0}&apos; is a non-nullable reference type..
/// </summary>
internal static string WRN_AsOperatorMayReturnNull {
get {
return ResourceManager.GetString("WRN_AsOperatorMayReturnNull", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;as&apos; operator may produce a null value for a type parameter..
/// </summary>
internal static string WRN_AsOperatorMayReturnNull_Title {
get {
return ResourceManager.GetString("WRN_AsOperatorMayReturnNull_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Attribute &apos;{0}&apos; from module &apos;{1}&apos; will be ignored in favor of the instance appearing in source.
/// </summary>
......@@ -13543,6 +13507,24 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Conditional access may produce a null value when &apos;{0}&apos; is a non-nullable reference type..
/// </summary>
internal static string WRN_ConditionalAccessMayReturnNull {
get {
return ResourceManager.GetString("WRN_ConditionalAccessMayReturnNull", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Conditional access may produce a null value for a type parameter..
/// </summary>
internal static string WRN_ConditionalAccessMayReturnNull_Title {
get {
return ResourceManager.GetString("WRN_ConditionalAccessMayReturnNull_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Different checksum values given for &apos;{0}&apos;.
/// </summary>
......@@ -13615,6 +13597,24 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to A default expression introduces a null value when &apos;{0}&apos; is a non-nullable reference type..
/// </summary>
internal static string WRN_DefaultExpressionMayIntroduceNullT {
get {
return ResourceManager.GetString("WRN_DefaultExpressionMayIntroduceNullT", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A default expression introduces a null value for a type parameter..
/// </summary>
internal static string WRN_DefaultExpressionMayIntroduceNullT_Title {
get {
return ResourceManager.GetString("WRN_DefaultExpressionMayIntroduceNullT_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &apos;default&apos; is converted to &apos;null&apos;, not &apos;default({0})&apos;.
/// </summary>
......@@ -15412,6 +15412,24 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to A null literal introduces a null value when &apos;{0}&apos; is a non-nullable reference type..
/// </summary>
internal static string WRN_NullLiteralMayIntroduceNullT {
get {
return ResourceManager.GetString("WRN_NullLiteralMayIntroduceNullT", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A null literal introduces a null value for a type parameter..
/// </summary>
internal static string WRN_NullLiteralMayIntroduceNullT_Title {
get {
return ResourceManager.GetString("WRN_NullLiteralMayIntroduceNullT_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Possible null reference argument for parameter &apos;{0}&apos; in &apos;{1}&apos;..
/// </summary>
......
......@@ -5325,24 +5325,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="WRN_PossibleNull_Title" xml:space="preserve">
<value>Possible null value.</value>
</data>
<data name="HDN_NullCheckIsProbablyAlwaysTrue" xml:space="preserve">
<value>Result of the comparison is possibly always true.</value>
</data>
<data name="HDN_NullCheckIsProbablyAlwaysTrue_Title" xml:space="preserve">
<value>Result of the comparison is possibly always true.</value>
</data>
<data name="HDN_NullCheckIsProbablyAlwaysFalse" xml:space="preserve">
<value>Result of the comparison is possibly always false.</value>
</data>
<data name="HDN_NullCheckIsProbablyAlwaysFalse_Title" xml:space="preserve">
<value>Result of the comparison is possibly always false.</value>
</data>
<data name="HDN_ExpressionIsProbablyNeverNull" xml:space="preserve">
<value>Expression is probably never null.</value>
</data>
<data name="HDN_ExpressionIsProbablyNeverNull_Title" xml:space="preserve">
<value>Expression is probably never null.</value>
</data>
<data name="WRN_NullabilityMismatchInTypeOnOverride" xml:space="preserve">
<value>Nullability of reference types in type doesn't match overridden member.</value>
</data>
......@@ -5415,6 +5397,30 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="WRN_NullabilityMismatchInAssignment_Title" xml:space="preserve">
<value>Nullability of reference types in value doesn't match target type.</value>
</data>
<data name="WRN_ConditionalAccessMayReturnNull" xml:space="preserve">
<value>Conditional access may produce a null value when '{0}' is a non-nullable reference type.</value>
</data>
<data name="WRN_ConditionalAccessMayReturnNull_Title" xml:space="preserve">
<value>Conditional access may produce a null value for a type parameter.</value>
</data>
<data name="WRN_AsOperatorMayReturnNull" xml:space="preserve">
<value>The 'as' operator may produce a null value when '{0}' is a non-nullable reference type.</value>
</data>
<data name="WRN_AsOperatorMayReturnNull_Title" xml:space="preserve">
<value>The 'as' operator may produce a null value for a type parameter.</value>
</data>
<data name="WRN_DefaultExpressionMayIntroduceNullT" xml:space="preserve">
<value>A default expression introduces a null value when '{0}' is a non-nullable reference type.</value>
</data>
<data name="WRN_DefaultExpressionMayIntroduceNullT_Title" xml:space="preserve">
<value>A default expression introduces a null value for a type parameter.</value>
</data>
<data name="WRN_NullLiteralMayIntroduceNullT" xml:space="preserve">
<value>A null literal introduces a null value when '{0}' is a non-nullable reference type.</value>
</data>
<data name="WRN_NullLiteralMayIntroduceNullT_Title" xml:space="preserve">
<value>A null literal introduces a null value for a type parameter.</value>
</data>
<data name="WRN_NullabilityMismatchInArgument" xml:space="preserve">
<value>Argument of type '{0}' cannot be used as an input of type '{1}' for parameter '{2}' in '{3}' due to differences in the nullability of reference types.</value>
</data>
......
......@@ -1299,7 +1299,7 @@ internal enum ErrorCode
ERR_FeatureNotAvailableInVersion6 = 8059,
// available 8062-8069
ERR_SwitchFallOut = 8070,
// ERR_UnexpectedBoundGenericName = 8071, // for nameof - used in an early prototype
// available = 8071,
ERR_NullPropagatingOpInExpressionTree = 8072,
WRN_NubExprIsConstBool2 = 8073,
ERR_DictionaryInitializerInExpressionTree = 8074,
......@@ -1633,9 +1633,9 @@ internal enum ErrorCode
WRN_NullReferenceReceiver = 8602,
WRN_NullReferenceReturn = 8603,
WRN_NullReferenceArgument = 8604,
HDN_NullCheckIsProbablyAlwaysTrue = 8605,
HDN_NullCheckIsProbablyAlwaysFalse = 8606,
HDN_ExpressionIsProbablyNeverNull = 8607,
// Available = 8605,
// Available = 8606,
// Available = 8607,
WRN_NullabilityMismatchInTypeOnOverride = 8608,
WRN_NullabilityMismatchInReturnTypeOnOverride = 8609,
WRN_NullabilityMismatchInParameterTypeOnOverride = 8610,
......@@ -1654,7 +1654,7 @@ internal enum ErrorCode
ERR_ExplicitNullableAttribute = 8623,
WRN_NullabilityMismatchInArgumentForOutput = 8624,
WRN_NullAsNonNullable = 8625,
// Available = 8626,
WRN_AsOperatorMayReturnNull = 8626,
ERR_NullableUnconstrainedTypeParameter = 8627,
ERR_AnnotationDisallowedInObjectCreation = 8628,
WRN_NullableValueTypeMayBeNull = 8629,
......@@ -1666,7 +1666,7 @@ internal enum ErrorCode
ERR_TripleDotNotAllowed = 8635,
ERR_BadNullableContextOption = 8636,
ERR_NullableDirectiveQualifierExpected = 8637,
// Available = 8638,
WRN_ConditionalAccessMayReturnNull = 8638,
// Available = 8639,
ERR_ExpressionTreeCantContainRefStruct = 8640,
ERR_ElseCannotStartStatement = 8641,
......@@ -1681,6 +1681,8 @@ internal enum ErrorCode
ERR_IsNullableType = 8650,
ERR_AsNullableType = 8651,
ERR_FeatureInPreview = 8652,
WRN_DefaultExpressionMayIntroduceNullT = 8653,
WRN_NullLiteralMayIntroduceNullT = 8654,
#endregion diagnostics introduced for C# 8.0
......
......@@ -36,14 +36,15 @@ static ErrorFacts()
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint));
builder.Add(getId(ErrorCode.WRN_PossibleNull));
builder.Add(getId(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT));
builder.Add(getId(ErrorCode.WRN_NullLiteralMayIntroduceNullT));
builder.Add(getId(ErrorCode.WRN_ConditionalAccessMayReturnNull));
builder.Add(getId(ErrorCode.WRN_AsOperatorMayReturnNull));
NullableFlowAnalysisSafetyWarnings = builder.ToImmutable();
builder.Clear();
builder.Add(getId(ErrorCode.WRN_ConvertingNullableToNonNullable));
builder.Add(getId(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse));
builder.Add(getId(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue));
builder.Add(getId(ErrorCode.HDN_ExpressionIsProbablyNeverNull));
NullableFlowAnalysisNonSafetyWarnings = builder.ToImmutable();
......@@ -399,6 +400,10 @@ internal static int GetWarningLevel(ErrorCode code)
case ErrorCode.WRN_GivenExpressionAlwaysMatchesConstant:
case ErrorCode.WRN_CaseConstantNamedUnderscore:
case ErrorCode.WRN_PossibleNull:
case ErrorCode.WRN_DefaultExpressionMayIntroduceNullT:
case ErrorCode.WRN_NullLiteralMayIntroduceNullT:
case ErrorCode.WRN_ConditionalAccessMayReturnNull:
case ErrorCode.WRN_AsOperatorMayReturnNull:
return 1;
default:
return 0;
......
......@@ -16,7 +16,7 @@ internal sealed class LazyMissingNonNullTypesContextDiagnosticInfo : LazyDiagnos
private LazyMissingNonNullTypesContextDiagnosticInfo(TypeSymbolWithAnnotations type, DiagnosticInfo info)
{
Debug.Assert(!type.IsNull);
Debug.Assert(type.HasType);
_type = type;
_info = info;
}
......@@ -48,7 +48,7 @@ private static void GetRawDiagnosticInfos(bool isNullableEnabled, CSharpParseOpt
}
private static bool IsNullableReference(TypeSymbolWithAnnotations type)
=> type.IsNull || !(type.IsValueType || type.IsErrorType());
=> !type.HasType || !(type.IsValueType || type.IsErrorType());
protected override DiagnosticInfo ResolveInfo() => IsNullableReference(_type) ? _info : null;
......
......@@ -597,11 +597,10 @@ private void AdjustConditionalState(BoundExpression node)
/// AssignedWhenFalse.
/// </summary>
/// <param name="node"></param>
protected BoundNode VisitRvalue(BoundExpression node)
protected virtual void VisitRvalue(BoundExpression node)
{
var result = Visit(node);
Visit(node);
Unsplit();
return result;
}
/// <summary>
......@@ -1590,7 +1589,7 @@ public sealed override BoundNode VisitReturnStatement(BoundReturnStatement node)
protected virtual BoundNode VisitReturnStatementNoAdjust(BoundReturnStatement node)
{
var result = VisitRvalue(node.ExpressionOpt);
VisitRvalue(node.ExpressionOpt);
// byref return is also a potential write
if (node.RefKind != RefKind.None)
......@@ -1598,7 +1597,7 @@ protected virtual BoundNode VisitReturnStatementNoAdjust(BoundReturnStatement no
WriteArgument(node.ExpressionOpt, node.RefKind, method: null);
}
return result;
return null;
}
private void AdjustStateAfterReturnStatement(BoundReturnStatement node)
......
......@@ -210,14 +210,18 @@ public static bool IsWarning(ErrorCode code)
case ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate:
case ErrorCode.WRN_NullabilityMismatchInArgumentForOutput:
case ErrorCode.WRN_NullAsNonNullable:
case ErrorCode.WRN_AsOperatorMayReturnNull:
case ErrorCode.WRN_NullableValueTypeMayBeNull:
case ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint:
case ErrorCode.WRN_MissingNonNullTypesContextForAnnotation:
case ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation:
case ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint:
case ErrorCode.WRN_ConditionalAccessMayReturnNull:
case ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface:
case ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase:
case ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList:
case ErrorCode.WRN_DefaultExpressionMayIntroduceNullT:
case ErrorCode.WRN_NullLiteralMayIntroduceNullT:
return true;
default:
return false;
......@@ -258,9 +262,6 @@ public static bool IsHidden(ErrorCode code)
{
case ErrorCode.HDN_UnusedUsingDirective:
case ErrorCode.HDN_UnusedExternAlias:
case ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue:
case ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse:
case ErrorCode.HDN_ExpressionIsProbablyNeverNull:
return true;
default:
return false;
......
......@@ -23,7 +23,7 @@ private LambdaCapturedVariable(SynthesizedContainer frame, TypeSymbolWithAnnotat
isReadOnly: false,
isStatic: false)
{
Debug.Assert(!type.IsNull);
Debug.Assert(type.HasType);
// lifted fields do not need to have the CompilerGeneratedAttribute attached to it, the closure is already
// marked as being compiler generated.
......
......@@ -59,7 +59,7 @@ private void VisitArrayType(IArrayTypeSymbol symbol, TypeSymbolWithAnnotations t
}
while (underlyingType.Kind == SymbolKind.ArrayType && !ShouldAddNullableAnnotation(underlyingTypeWithAnnotations));
if (!underlyingTypeWithAnnotations.IsNull)
if (underlyingTypeWithAnnotations.HasType)
{
VisitTypeSymbolWithAnnotations(underlyingTypeWithAnnotations);
}
......@@ -91,7 +91,7 @@ private void AddNullableAnnotations(TypeSymbolWithAnnotations typeOpt)
private bool ShouldAddNullableAnnotation(TypeSymbolWithAnnotations typeOpt)
{
if (typeOpt.IsNull)
if (!typeOpt.HasType)
{
return false;
}
......
......@@ -28,7 +28,7 @@ public AnonymousTypeField(string name, Location location, TypeSymbolWithAnnotati
[Conditional("DEBUG")]
internal void AssertIsGood()
{
Debug.Assert(this.Name != null && this.Location != null && !this.Type.IsNull);
Debug.Assert(this.Name != null && this.Location != null && this.Type.HasType);
}
}
}
......@@ -42,7 +42,7 @@ private sealed class AnonymousTypePropertySymbol : PropertySymbol
{
Debug.Assert((object)container != null);
Debug.Assert((object)field != null);
Debug.Assert(!fieldType.IsNull);
Debug.Assert(fieldType.HasType);
Debug.Assert(index >= 0);
Debug.Assert(!locations.IsDefault);
......
......@@ -22,7 +22,7 @@ internal abstract partial class ArrayTypeSymbol : TypeSymbol, IArrayTypeSymbol
TypeSymbolWithAnnotations elementType,
NamedTypeSymbol array)
{
Debug.Assert(!elementType.IsNull);
Debug.Assert(elementType.HasType);
Debug.Assert((object)array != null);
_elementType = elementType;
......@@ -401,7 +401,7 @@ internal override TypeSymbol SetNullabilityForReferenceTypes(Func<TypeSymbolWith
internal override TypeSymbol MergeNullability(TypeSymbol other, VarianceKind variance)
{
Debug.Assert(this.Equals(other, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes));
TypeSymbolWithAnnotations elementType = ElementType.MergeNullability(((ArrayTypeSymbol)other).ElementType, VarianceKind.None);
TypeSymbolWithAnnotations elementType = ElementType.MergeNullability(((ArrayTypeSymbol)other).ElementType, variance);
return WithElementType(elementType);
}
......
......@@ -454,7 +454,7 @@ private static bool PermissionSetAttributeTypeHasRequiredProperty(NamedTypeSymbo
if (members.Length == 1 && members[0].Kind == SymbolKind.Property)
{
var property = (PropertySymbol)members[0];
if (!property.Type.IsNull && property.Type.SpecialType == SpecialType.System_String &&
if (property.Type.HasType && property.Type.SpecialType == SpecialType.System_String &&
property.DeclaredAccessibility == Accessibility.Public && property.GetMemberArity() == 0 &&
(object)property.SetMethod != null && property.SetMethod.DeclaredAccessibility == Accessibility.Public)
{
......
......@@ -18,7 +18,7 @@ internal static class NullableTypeDecoder
EntityHandle targetSymbolToken,
PEModuleSymbol containingModule)
{
Debug.Assert(!metadataType.IsNull);
Debug.Assert(metadataType.HasType);
byte defaultTransformFlag;
ImmutableArray<byte> nullableTransformFlags;
......
......@@ -89,7 +89,7 @@ private enum Flags : byte
}
TypeSymbol originalEventType = _eventType.TypeSymbol;
if (_eventType.IsNull)
if (!_eventType.HasType)
{
var metadataDecoder = new MetadataDecoder(moduleSymbol, containingType);
originalEventType = metadataDecoder.GetTypeOfToken(eventType);
......
......@@ -203,7 +203,7 @@ internal void SetAssociatedEvent(PEEventSymbol eventSymbol)
private void EnsureSignatureIsLoaded()
{
if (_lazyType.IsNull)
if (_lazyType.IsDefault)
{
var moduleSymbol = _containingType.ContainingPEModule;
bool isVolatile;
......
......@@ -199,7 +199,7 @@ public bool TryGetWellKnownAttribute(WellKnownAttributeFlags flag, out bool valu
Debug.Assert((object)moduleSymbol != null);
Debug.Assert((object)containingSymbol != null);
Debug.Assert(ordinal >= 0);
Debug.Assert(!type.IsNull);
Debug.Assert(type.HasType);
isBad = false;
_moduleSymbol = moduleSymbol;
......
......@@ -84,7 +84,7 @@ public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol m
var typeArgsForConstraintsCheck = typeArgs;
for (int i = 0; i < typeArgsForConstraintsCheck.Length; i++)
{
if (typeArgsForConstraintsCheck[i].IsNull)
if (!typeArgsForConstraintsCheck[i].HasType)
{
firstNullInTypeArgs = i;
var builder = ArrayBuilder<TypeSymbolWithAnnotations>.GetInstance();
......@@ -93,7 +93,7 @@ public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol m
for (; i < typeArgsForConstraintsCheck.Length; i++)
{
var typeArg = typeArgsForConstraintsCheck[i];
if (typeArg.IsNull)
if (!typeArg.HasType)
{
notInferredTypeParameters.Add(typeParams[i]);
builder.Add(TypeSymbolWithAnnotations.Create(ErrorTypeSymbol.UnknownResultType));
......@@ -146,7 +146,7 @@ public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol m
for (int i = firstNullInTypeArgs; i < typeArgsForConstruct.Length; i++)
{
var typeArgForConstruct = typeArgsForConstruct[i];
builder.Add(!typeArgForConstruct.IsNull ? typeArgForConstruct : TypeSymbolWithAnnotations.Create(typeParams[i]));
builder.Add(typeArgForConstruct.HasType ? typeArgForConstruct : TypeSymbolWithAnnotations.Create(typeParams[i]));
}
typeArgsForConstruct = builder.ToImmutableAndFree();
......
......@@ -1005,9 +1005,9 @@ internal NamedTypeSymbol GetUnboundGenericTypeOrSelf()
/// </summary>
internal abstract bool HasCodeAnalysisEmbeddedAttribute { get; }
internal static readonly Func<TypeSymbolWithAnnotations, bool> TypeSymbolIsNullFunction = type => type.IsNull;
internal static readonly Func<TypeSymbolWithAnnotations, bool> TypeSymbolIsNullFunction = type => !type.HasType;
internal static readonly Func<TypeSymbolWithAnnotations, bool> TypeSymbolIsErrorType = type => !type.IsNull && type.IsErrorType();
internal static readonly Func<TypeSymbolWithAnnotations, bool> TypeSymbolIsErrorType = type => type.HasType && type.IsErrorType();
private NamedTypeSymbol ConstructWithoutModifiers(ImmutableArray<TypeSymbol> typeArguments, bool unbound)
{
......
......@@ -23,7 +23,7 @@ internal sealed partial class PointerTypeSymbol : TypeSymbol, IPointerTypeSymbol
/// <param name="pointedAtType">The type being pointed at.</param>
internal PointerTypeSymbol(TypeSymbolWithAnnotations pointedAtType)
{
Debug.Assert(!pointedAtType.IsNull);
Debug.Assert(pointedAtType.HasType);
_pointedAtType = pointedAtType;
}
......
......@@ -130,7 +130,7 @@ public override TypeSymbolWithAnnotations ReturnType
{
get
{
if (_lazyReturnType.IsNull)
if (_lazyReturnType.IsDefault)
{
_lazyReturnType = this.RetargetingTranslator.Retarget(_underlyingMethod.ReturnType, RetargetOptions.RetargetPrimitiveTypesByTypeCode, this.ContainingType);
}
......
......@@ -59,7 +59,7 @@ public override TypeSymbolWithAnnotations Type
{
get
{
if (_lazyType.IsNull)
if (_lazyType.IsDefault)
{
var type = this.RetargetingTranslator.Retarget(_underlyingProperty.Type, RetargetOptions.RetargetPrimitiveTypesByTypeCode);
if (type.TypeSymbol.TryAsDynamicIfNoPia(this.ContainingType, out TypeSymbol asDynamic))
......
......@@ -66,7 +66,7 @@ internal override TypeSymbolWithAnnotations GetFieldType(ConsList<FieldSymbol> f
{
Debug.Assert(fieldsBeingBound != null);
if (!_lazyType.IsNull)
if (!_lazyType.IsDefault)
{
return _lazyType.ToType();
}
......@@ -93,12 +93,12 @@ internal override TypeSymbolWithAnnotations GetFieldType(ConsList<FieldSymbol> f
type = default;
}
Debug.Assert(!type.IsNull || isVar);
Debug.Assert(type.HasType || isVar);
if (isVar && !fieldsBeingBound.ContainsReference(this))
{
InferFieldType(fieldsBeingBound, binder);
Debug.Assert(!_lazyType.IsNull);
Debug.Assert(!_lazyType.IsDefault);
}
else
{
......
......@@ -47,7 +47,7 @@ internal sealed class LambdaSymbol : SourceMethodSymbol
_messageID = unboundLambda.Data.MessageID;
_syntax = unboundLambda.Syntax;
_refKind = refKind;
_returnType = returnType.IsNull ? TypeSymbolWithAnnotations.Create(ReturnTypeIsBeingInferred) : returnType;
_returnType = !returnType.HasType ? TypeSymbolWithAnnotations.Create(ReturnTypeIsBeingInferred) : returnType;
_isSynthesized = unboundLambda.WasCompilerGenerated;
_isAsync = unboundLambda.IsAsync;
// No point in making this lazy. We are always going to need these soon after creation of the symbol.
......@@ -166,7 +166,7 @@ internal override ImmutableArray<string> GetAppliedConditionalSymbols()
public override bool ReturnsVoid
{
get { return !this.ReturnType.IsNull && this.ReturnType.SpecialType == SpecialType.System_Void; }
get { return this.ReturnType.HasType && this.ReturnType.SpecialType == SpecialType.System_Void; }
}
public override RefKind RefKind
......@@ -185,7 +185,7 @@ public override TypeSymbolWithAnnotations ReturnType
// IDE might inspect the symbol and want to know the return type.
internal void SetInferredReturnType(RefKind refKind, TypeSymbolWithAnnotations inferredReturnType)
{
Debug.Assert(!inferredReturnType.IsNull);
Debug.Assert(inferredReturnType.HasType);
Debug.Assert((object)_returnType.TypeSymbol == ReturnTypeIsBeingInferred);
_refKind = refKind;
_returnType = inferredReturnType;
......
......@@ -208,7 +208,7 @@ public override TypeSymbolWithAnnotations ReturnType
internal void ComputeReturnType()
{
if (!_lazyReturnType.IsNull)
if (!_lazyReturnType.IsDefault)
{
return;
}
......@@ -254,7 +254,7 @@ internal void ComputeReturnType()
lock (_declarationDiagnostics)
{
if (!_lazyReturnType.IsNull)
if (!_lazyReturnType.IsDefault)
{
diagnostics.Free();
return;
......
......@@ -40,14 +40,14 @@ public sealed override Symbol AssociatedSymbol
protected sealed override void MethodChecks(DiagnosticBag diagnostics)
{
Debug.Assert(_lazyParameters.IsDefault == _lazyReturnType.IsNull);
Debug.Assert(_lazyParameters.IsDefault != _lazyReturnType.HasType);
// CONSIDER: currently, we're copying the custom modifiers of the event overridden
// by this method's associated event (by using the associated event's type, which is
// copied from the overridden event). It would be more correct to copy them from
// the specific accessor that this method is overriding (as in SourceMemberMethodSymbol).
if (_lazyReturnType.IsNull)
if (_lazyReturnType.IsDefault)
{
CSharpCompilation compilation = this.DeclaringCompilation;
Debug.Assert(compilation != null);
......@@ -105,7 +105,7 @@ public sealed override bool ReturnsVoid
get
{
LazyMethodChecks();
Debug.Assert(!_lazyReturnType.IsNull);
Debug.Assert(!_lazyReturnType.IsDefault);
return base.ReturnsVoid;
}
}
......@@ -120,7 +120,7 @@ public sealed override TypeSymbolWithAnnotations ReturnType
get
{
LazyMethodChecks();
Debug.Assert(!_lazyReturnType.IsNull);
Debug.Assert(!_lazyReturnType.IsDefault);
return _lazyReturnType;
}
}
......
......@@ -100,7 +100,7 @@ internal Binder TypeSyntaxBinder
// don't let the debugger force inference.
internal override string GetDebuggerDisplay()
{
return !_type.IsNull
return !_type.IsDefault
? base.GetDebuggerDisplay()
: $"{this.Kind} <var> ${this.Name}";
}
......@@ -287,7 +287,7 @@ public override TypeSymbolWithAnnotations Type
{
get
{
if (_type.IsNull)
if (_type.IsDefault)
{
#if DEBUG
concurrentTypeResolutions++;
......@@ -346,7 +346,7 @@ private TypeSymbolWithAnnotations GetTypeSymbol()
// If we got a valid result that was not void then use the inferred type
// else create an error type.
if (!inferredType.IsNull &&
if (inferredType.HasType &&
inferredType.SpecialType != SpecialType.System_Void)
{
declType = inferredType;
......@@ -357,7 +357,7 @@ private TypeSymbolWithAnnotations GetTypeSymbol()
}
}
Debug.Assert(!declType.IsNull);
Debug.Assert(declType.HasType);
//
// Note that we drop the diagnostics on the floor! That is because this code is invoked mainly in
......@@ -688,7 +688,7 @@ protected override TypeSymbolWithAnnotations InferTypeOfVarVariable(DiagnosticBa
throw ExceptionUtilities.UnexpectedValue(_deconstruction.Kind());
}
Debug.Assert(!this._type.IsNull);
Debug.Assert(!this._type.IsDefault);
return _type.ToType();
}
......@@ -783,7 +783,7 @@ protected override TypeSymbolWithAnnotations InferTypeOfVarVariable(DiagnosticBa
break;
}
if (this._type.IsNull)
if (this._type.IsDefault)
{
Debug.Assert(this.DeclarationKind == LocalDeclarationKind.DeclarationExpressionVariable);
SetType(TypeSymbolWithAnnotations.Create(_nodeBinder.CreateErrorType("var")));
......
......@@ -351,7 +351,7 @@ internal override bool HasPointerType
{
get
{
if (!_lazyType.IsNull)
if (!_lazyType.IsDefault)
{
Debug.Assert(_lazyType.DefaultType.IsPointerType() ==
IsPointerFieldSyntactically());
......@@ -389,7 +389,7 @@ internal sealed override TypeSymbolWithAnnotations GetFieldType(ConsList<FieldSy
{
Debug.Assert(fieldsBeingBound != null);
if (!_lazyType.IsNull)
if (!_lazyType.IsDefault)
{
return _lazyType.ToType();
}
......@@ -439,7 +439,7 @@ internal sealed override TypeSymbolWithAnnotations GetFieldType(ConsList<FieldSy
bool isVar;
type = binder.BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar);
Debug.Assert(!type.IsNull || isVar);
Debug.Assert(type.HasType || isVar);
if (isVar)
{
......@@ -480,7 +480,7 @@ internal sealed override TypeSymbolWithAnnotations GetFieldType(ConsList<FieldSy
}
}
if (type.IsNull)
if (!type.HasType)
{
type = TypeSymbolWithAnnotations.Create(binder.CreateErrorType("var"));
}
......
......@@ -474,7 +474,7 @@ public override TypeSymbolWithAnnotations Type
{
get
{
if (_lazyType.IsNull)
if (_lazyType.IsDefault)
{
var diagnostics = DiagnosticBag.GetInstance();
var binder = this.CreateBinderForTypeAndParameters();
......@@ -495,7 +495,7 @@ internal bool HasPointerType
{
get
{
if (!_lazyType.IsNull)
if (!_lazyType.IsDefault)
{
return _lazyType.DefaultType.IsPointerType();
}
......
......@@ -23,7 +23,7 @@ public override TypeSymbolWithAnnotations Type
{
get
{
if (_lazyType.IsNull)
if (_lazyType.IsDefault)
{
_lazyType.InterlockedInitialize(_containingType.TypeSubstitution.SubstituteTypeWithTupleUnification(OriginalDefinition.Type));
}
......
......@@ -22,7 +22,7 @@ internal SubstitutedFieldSymbol(SubstitutedNamedTypeSymbol containingType, Field
internal override TypeSymbolWithAnnotations GetFieldType(ConsList<FieldSymbol> fieldsBeingBound)
{
if (_lazyType.IsNull)
if (_lazyType.IsDefault)
{
_lazyType.InterlockedInitialize(_containingType.TypeSubstitution.SubstituteTypeWithTupleUnification(OriginalDefinition.GetFieldType(fieldsBeingBound)));
}
......
......@@ -230,7 +230,7 @@ public sealed override TypeSymbolWithAnnotations ReturnType
{
get
{
if (_lazyReturnType.IsNull)
if (_lazyReturnType.IsDefault)
{
var returnType = Map.SubstituteTypeWithTupleUnification(OriginalDefinition.ReturnType);
_lazyReturnType.InterlockedInitialize(returnType);
......
......@@ -23,7 +23,7 @@ public override TypeSymbolWithAnnotations Type
{
get
{
if (_lazyType.IsNull)
if (_lazyType.IsDefault)
{
_lazyType.InterlockedInitialize(_containingType.TypeSubstitution.SubstituteTypeWithTupleUnification(OriginalDefinition.Type));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册