提交 090e52e2 编写于 作者: C Charles Stoner 提交者: Julien Couvreur

Initial support for [AllowNull], [DisallowNull], [MaybeNull], [NotNull] in NullableWalker (#35955)

上级 fa358805
......@@ -305,6 +305,8 @@ private void SetAnalyzedNullability(BoundExpression expr, VisitResult result, bo
/// </summary>
private int _lastConditionalAccessSlot = -1;
private bool IsAnalyzingAttribute => methodMainNode.Kind == BoundKind.Attribute;
protected override void Free()
{
_methodGroupReceiverMapOpt?.Free();
......@@ -2765,8 +2767,8 @@ private void ReinferMethodAndVisitArguments(BoundCall node, TypeWithState receiv
ReplayReadsAndWrites(localFunc, node.Syntax, writes: true);
}
var type = method.ReturnTypeWithAnnotations;
SetLvalueResultType(node, type);
var result = GetReturnType(method);
SetResult(node, result.RValueType, result.LValueType);
}
private TypeWithState VisitCallReceiver(BoundCall node)
......@@ -2808,19 +2810,42 @@ private TypeWithState VisitCallReceiver(BoundCall node)
return receiverType;
}
private VisitResult GetReturnType(MethodSymbol method)
{
var type = method.ReturnTypeWithAnnotations;
var rvalueType = TypeWithState.Create(type, GetAnnotations(method));
return new VisitResult(rvalueType, type);
}
private FlowAnalysisAnnotations GetAnnotations(ParameterSymbol parameter)
{
// Annotations are ignored when binding an attribute to avoid cycles. (Members used
// in attributes are error scenarios, so missing warnings should not be important.)
return IsAnalyzingAttribute ?
FlowAnalysisAnnotations.None :
parameter.FlowAnalysisAnnotations;
}
private FlowAnalysisAnnotations GetAnnotations(MethodSymbol method)
{
// Annotations are ignored when binding an attribute to avoid cycles. (Members used
// in attributes are error scenarios, so missing warnings should not be important.)
return IsAnalyzingAttribute ?
FlowAnalysisAnnotations.None :
method.ReturnTypeAnnotationAttributes;
}
/// <summary>
/// For each argument, figure out if its corresponding parameter is annotated with NotNullWhenFalse or
/// NotNull.
/// For each argument, get the annotation from the corresponding parameter.
/// </summary>
private static ImmutableArray<FlowAnalysisAnnotations> GetAnnotations(int numArguments,
private ImmutableArray<FlowAnalysisAnnotations> GetAnnotations(int numArguments,
bool expanded, ImmutableArray<ParameterSymbol> parameters, ImmutableArray<int> argsToParamsOpt)
{
ArrayBuilder<FlowAnalysisAnnotations> builder = null;
for (int i = 0; i < numArguments; i++)
{
(ParameterSymbol parameter, _) = GetCorrespondingParameter(i, parameters, argsToParamsOpt, expanded);
FlowAnalysisAnnotations annotations = parameter?.FlowAnalysisAnnotations ?? FlowAnalysisAnnotations.None;
(ParameterSymbol parameter, _, FlowAnalysisAnnotations annotations) = GetCorrespondingParameter(i, parameters, argsToParamsOpt, expanded);
annotations = removeInapplicableAnnotations(parameter, annotations);
......@@ -2895,6 +2920,34 @@ FlowAnalysisAnnotations removeInapplicableNotNullWhenSense(ParameterSymbol param
}
}
private static TypeWithAnnotations ApplyLValueAnnotations(TypeWithAnnotations declaredType, FlowAnalysisAnnotations flowAnalysisAnnotations)
{
if ((flowAnalysisAnnotations & FlowAnalysisAnnotations.DisallowNull) == FlowAnalysisAnnotations.DisallowNull)
{
return declaredType.AsNotAnnotated();
}
else if ((flowAnalysisAnnotations & FlowAnalysisAnnotations.AllowNull) == FlowAnalysisAnnotations.AllowNull)
{
return declaredType.AsAnnotated();
}
return declaredType;
}
private static TypeWithAnnotations ApplyRValueAnnotations(TypeWithAnnotations declaredType, FlowAnalysisAnnotations flowAnalysisAnnotations)
{
if ((flowAnalysisAnnotations & FlowAnalysisAnnotations.NotNull) == FlowAnalysisAnnotations.NotNull)
{
return declaredType.AsNotAnnotated();
}
else if ((flowAnalysisAnnotations & FlowAnalysisAnnotations.MaybeNull) == FlowAnalysisAnnotations.MaybeNull)
{
return declaredType.AsAnnotated();
}
return declaredType;
}
// https://github.com/dotnet/roslyn/issues/29863 Record in the node whether type
// arguments were implicit, to allow for cases where the syntax is not an
// invocation (such as a synthesized call from a query interpretation).
......@@ -2990,11 +3043,8 @@ protected override void VisitArguments(ImmutableArray<BoundExpression> arguments
}
// We do a second pass through the arguments, ignoring any diagnostics produced, but honoring the annotations,
// to get the proper result state. Annotations are ignored when binding an attribute to avoid cycles.
// (Additional warnings are only expected in error scenarios, particularly calling a method in an attribute argument.)
// to get the proper result state.
ImmutableArray<FlowAnalysisAnnotations> annotations =
(this.methodMainNode.Kind == BoundKind.Attribute) ?
default :
GetAnnotations(argumentsNoConversions.Length, expanded, parameters, argsToParamsOpt);
if (!annotations.IsDefault)
......@@ -3193,7 +3243,7 @@ void visitArgumentEvaluateAndUnsplit(int argumentIndex, bool assertsTrue, bool a
{
for (int i = 0; i < argumentsNoConversions.Length; i++)
{
(ParameterSymbol parameter, TypeWithAnnotations parameterType) = GetCorrespondingParameter(i, parameters, argsToParamsOpt, expanded);
(ParameterSymbol parameter, TypeWithAnnotations parameterType, FlowAnalysisAnnotations parameterAnnotations) = GetCorrespondingParameter(i, parameters, argsToParamsOpt, expanded);
if (parameter is null)
{
continue;
......@@ -3207,6 +3257,7 @@ void visitArgumentEvaluateAndUnsplit(int argumentIndex, bool assertsTrue, bool a
GetRefKind(refKindsOpt, i),
parameter,
parameterType,
parameterAnnotations,
results[i],
invokedAsExtensionMethod && i == 0);
}
......@@ -3222,6 +3273,7 @@ void visitArgumentEvaluateAndUnsplit(int argumentIndex, bool assertsTrue, bool a
RefKind refKind,
ParameterSymbol parameter,
TypeWithAnnotations parameterType,
FlowAnalysisAnnotations parameterAnnotations,
VisitArgumentResult result,
bool extensionMethodThisArgument)
{
......@@ -3240,7 +3292,7 @@ void visitArgumentEvaluateAndUnsplit(int argumentIndex, bool assertsTrue, bool a
conversionOpt: conversionOpt,
conversionOperand: argumentNoConversion,
conversion: conversion,
targetTypeWithNullability: parameterType,
targetTypeWithNullability: ApplyLValueAnnotations(parameterType, parameterAnnotations),
operandType: resultType,
checkConversion: true,
fromExplicitCast: false,
......@@ -3264,12 +3316,12 @@ void visitArgumentEvaluateAndUnsplit(int argumentIndex, bool assertsTrue, bool a
else
{
// types match, but state would let a null in
ReportNullableAssignmentIfNecessary(argumentNoConversion, parameterType, resultType, useLegacyWarnings: false);
ReportNullableAssignmentIfNecessary(argumentNoConversion, ApplyLValueAnnotations(parameterType, parameterAnnotations), resultType, useLegacyWarnings: false);
}
}
// Check assignment from a fictional value from the parameter to the argument.
var parameterWithState = parameterType.ToTypeWithState();
var parameterWithState = TypeWithState.Create(parameterType, parameterAnnotations);
if (argumentNoConversion.IsSuppressed)
{
parameterWithState = parameterWithState.WithNotNullState();
......@@ -3285,13 +3337,15 @@ void visitArgumentEvaluateAndUnsplit(int argumentIndex, bool assertsTrue, bool a
break;
case RefKind.Out:
{
var parameterWithState = parameterType.ToTypeWithState();
var lValueType = result.LValueType;
var parameterWithAnnotations = ApplyRValueAnnotations(parameterType, parameterAnnotations);
var parameterWithState = TypeWithState.Create(parameterWithAnnotations, parameterAnnotations);
if (argumentNoConversion is BoundLocal local && local.DeclarationKind == BoundLocalDeclarationKind.WithInferredType)
{
_variableTypes[local.LocalSymbol] = parameterType;
_variableTypes[local.LocalSymbol] = parameterWithAnnotations;
lValueType = parameterWithAnnotations;
}
var lValueType = result.LValueType;
// Check assignment from a fictional value from the parameter to the argument.
var parameterValue = new BoundParameter(argumentNoConversion.Syntax, parameter);
......@@ -3370,7 +3424,7 @@ private VariableState GetVariableState(Optional<LocalState> localState)
localState.HasValue ? localState.Value : this.State.Clone());
}
private static (ParameterSymbol Parameter, TypeWithAnnotations Type) GetCorrespondingParameter(
private (ParameterSymbol Parameter, TypeWithAnnotations Type, FlowAnalysisAnnotations Annotations) GetCorrespondingParameter(
int argumentOrdinal,
ImmutableArray<ParameterSymbol> parameters,
ImmutableArray<int> argsToParamsOpt,
......@@ -3378,7 +3432,7 @@ private VariableState GetVariableState(Optional<LocalState> localState)
{
if (parameters.IsDefault)
{
return (default, default);
return default;
}
int n = parameters.Length;
......@@ -3417,16 +3471,17 @@ private VariableState GetVariableState(Optional<LocalState> localState)
if (parameter is null)
{
Debug.Assert(!expanded);
return (default, default);
return default;
}
var type = parameter.TypeWithAnnotations;
if (expanded && parameter.Ordinal == n - 1 && type.IsSZArray())
{
type = ((ArrayTypeSymbol)type.Type).ElementTypeWithAnnotations;
return (parameter, type, FlowAnalysisAnnotations.None);
}
return (parameter, type);
return (parameter, type, GetAnnotations(parameter));
}
private MethodSymbol InferMethodTypeArguments(BoundCall node, MethodSymbol method, ImmutableArray<BoundExpression> arguments)
......@@ -4303,7 +4358,6 @@ private static BoundConversion GetConversionIfApplicable(BoundExpression convers
{
Debug.Assert(!trackMembers || !IsConditionalState);
Debug.Assert(conversionOperand != null);
Debug.Assert(targetTypeWithNullability.HasType);
Debug.Assert((object)target != null || assignmentKind != AssignmentKind.Argument);
NullableFlowState resultState = NullableFlowState.NotNull;
......@@ -5211,7 +5265,7 @@ private void VisitDeconstructionArguments(ArrayBuilder<DeconstructionVariable> v
else
{
VisitArgumentConversion(
conversionOpt: null, variable.Expression, underlyingConversion, parameter.RefKind, parameter, parameter.TypeWithAnnotations,
conversionOpt: null, variable.Expression, underlyingConversion, parameter.RefKind, parameter, parameter.TypeWithAnnotations, GetAnnotations(parameter),
new VisitArgumentResult(new VisitResult(variable.Type.ToTypeWithState(), variable.Type), stateForLambda: default),
extensionMethodThisArgument: false);
}
......@@ -6606,6 +6660,7 @@ private void CheckExtensionMethodThisNullability(BoundExpression expr, Conversio
parameter.RefKind,
parameter,
parameter.TypeWithAnnotations,
GetAnnotations(parameter),
new VisitArgumentResult(new VisitResult(result, result.ToTypeWithAnnotations()),
stateForLambda: default),
extensionMethodThisArgument: true);
......
......@@ -142,6 +142,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return TypeWithAnnotations.Create(ContainingAssembly.GetSpecialType(SpecialType.System_Void)); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
get { return ImmutableArray<TypeWithAnnotations>.Empty; }
......
......@@ -139,6 +139,8 @@ public sealed override TypeWithAnnotations ReturnTypeWithAnnotations
get { return this.TypeMap.SubstituteType(this.BaseMethod.OriginalDefinition.ReturnTypeWithAnnotations); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => BaseMethod.ReturnTypeAnnotationAttributes;
public sealed override bool IsVararg
{
get { return this.BaseMethod.IsVararg; }
......
......@@ -97,6 +97,8 @@ public sealed override bool IsVararg
get { return false; }
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public sealed override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
get { return ImmutableArray<TypeWithAnnotations>.Empty; }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class ReturnTypeWellKnownAttributeData : CommonReturnTypeWellKnownAttributeData
{
private bool _hasMaybeNullAttribute;
public bool HasMaybeNullAttribute
{
get
{
VerifySealed(expected: true);
return _hasMaybeNullAttribute;
}
set
{
VerifySealed(expected: false);
_hasMaybeNullAttribute = value;
SetDataStored();
}
}
private bool _hasNotNullAttribute;
public bool HasNotNullAttribute
{
get
{
VerifySealed(expected: true);
return _hasNotNullAttribute;
}
set
{
VerifySealed(expected: false);
_hasNotNullAttribute = value;
SetDataStored();
}
}
}
}
......@@ -161,6 +161,8 @@ public override bool ReturnsVoid
get { return this.ReturnType.IsVoidType(); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override bool IsVararg
{
get { return false; }
......
......@@ -526,6 +526,8 @@ internal override int ParameterCount
public override TypeWithAnnotations ReturnTypeWithAnnotations => Signature.ReturnParam.TypeWithAnnotations;
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => Signature.ReturnParam.FlowAnalysisAnnotations;
public override ImmutableArray<CustomModifier> RefCustomModifiers => Signature.ReturnParam.RefCustomModifiers;
/// <summary>
......
......@@ -209,6 +209,8 @@ public bool ReturnsByRefReadonly
/// </summary>
public TypeSymbol ReturnType => ReturnTypeWithAnnotations.Type;
public abstract FlowAnalysisAnnotations ReturnTypeAnnotationAttributes { get; }
/// <summary>
/// Returns the type arguments that have been substituted for the type parameters.
/// If nothing has been substituted for a given type parameter,
......
......@@ -344,6 +344,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return _typeMap.SubstituteType(_reducedFrom.ReturnTypeWithAnnotations); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => _reducedFrom.ReturnTypeAnnotationAttributes;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
get { return _typeMap.SubstituteCustomModifiers(_reducedFrom.RefCustomModifiers); }
......
......@@ -65,6 +65,8 @@ internal sealed class SignatureOnlyMethodSymbol : MethodSymbol
public override TypeWithAnnotations ReturnTypeWithAnnotations { get { return _returnType; } }
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers { get { return _refCustomModifiers; } }
public override ImmutableArray<ParameterSymbol> Parameters { get { return _parameters; } }
......
......@@ -179,6 +179,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return _returnType; }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
// In error recovery and type inference scenarios we do not know the return type
// until after the body is bound, but the symbol is created before the body
// is bound. Fill in the return type post hoc in these scenarios; the
......
......@@ -204,6 +204,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override RefKind RefKind => _refKind;
internal void ComputeReturnType()
......
......@@ -41,7 +41,6 @@ protected struct Flags
private const int MethodKindMask = 0x1F;
private const int DeclarationModifiersMask = 0x7FFFFF;
private const int ReturnsVoidBit = 1 << 27;
private const int IsExtensionMethodBit = 1 << 28;
private const int IsMetadataVirtualIgnoringInterfaceChangesBit = 1 << 29;
private const int IsMetadataVirtualBit = 1 << 30;
......@@ -358,6 +357,9 @@ public override bool ReturnsVoid
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes =>
DecodeReturnTypeAnnotationAttributes(GetDecodedReturnTypeWellKnownAttributeData());
public sealed override MethodKind MethodKind
{
get
......@@ -940,7 +942,7 @@ protected CommonMethodWellKnownAttributeData GetDecodedWellKnownAttributeData()
/// <remarks>
/// Forces binding and decoding of attributes.
/// </remarks>
internal CommonReturnTypeWellKnownAttributeData GetDecodedReturnTypeWellKnownAttributeData()
internal ReturnTypeWellKnownAttributeData GetDecodedReturnTypeWellKnownAttributeData()
{
var attributesBag = _lazyReturnTypeCustomAttributesBag;
if (attributesBag == null || !attributesBag.IsDecodedWellKnownAttributeDataComputed)
......@@ -948,7 +950,7 @@ internal CommonReturnTypeWellKnownAttributeData GetDecodedReturnTypeWellKnownAtt
attributesBag = this.GetReturnTypeAttributesBag();
}
return (CommonReturnTypeWellKnownAttributeData)attributesBag.DecodedWellKnownAttributeData;
return (ReturnTypeWellKnownAttributeData)attributesBag.DecodedWellKnownAttributeData;
}
/// <summary>
......@@ -1313,7 +1315,7 @@ private void DecodeWellKnownAttributeAppliedToReturnValue(ref DecodeWellKnownAtt
if (attribute.IsTargetAttribute(this, AttributeDescription.MarshalAsAttribute))
{
// MarshalAs applied to the return value:
MarshalAsAttributeDecoder<CommonReturnTypeWellKnownAttributeData, AttributeSyntax, CSharpAttributeData, AttributeLocation>.Decode(ref arguments, AttributeTargets.ReturnValue, MessageProvider.Instance);
MarshalAsAttributeDecoder<ReturnTypeWellKnownAttributeData, AttributeSyntax, CSharpAttributeData, AttributeLocation>.Decode(ref arguments, AttributeTargets.ReturnValue, MessageProvider.Instance);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute))
{
......@@ -1344,6 +1346,14 @@ private void DecodeWellKnownAttributeAppliedToReturnValue(ref DecodeWellKnownAtt
// NullableAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.MaybeNullAttribute))
{
arguments.GetOrCreateData<ReturnTypeWellKnownAttributeData>().HasMaybeNullAttribute = true;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NotNullAttribute))
{
arguments.GetOrCreateData<ReturnTypeWellKnownAttributeData>().HasNotNullAttribute = true;
}
}
private void DecodeDllImportAttribute(ref DecodeWellKnownAttributeArguments<AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments)
......@@ -1501,6 +1511,23 @@ internal override void PostDecodeWellKnownAttributes(ImmutableArray<CSharpAttrib
base.PostDecodeWellKnownAttributes(boundAttributes, allAttributeSyntaxNodes, diagnostics, symbolPart, decodedData);
}
private static FlowAnalysisAnnotations DecodeReturnTypeAnnotationAttributes(ReturnTypeWellKnownAttributeData attributeData)
{
FlowAnalysisAnnotations annotations = FlowAnalysisAnnotations.None;
if (attributeData != null)
{
if (attributeData.HasMaybeNullAttribute)
{
annotations |= FlowAnalysisAnnotations.MaybeNull;
}
if (attributeData.HasNotNullAttribute)
{
annotations |= FlowAnalysisAnnotations.NotNull;
}
}
return annotations;
}
public sealed override bool HidesBaseMethodsByName
{
get
......
......@@ -227,6 +227,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return TypeWithAnnotations.Create(_returnType); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
get { return ImmutableArray<TypeWithAnnotations>.Empty; }
......
......@@ -4,9 +4,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
......@@ -140,6 +138,8 @@ public override bool ReturnsVoid
get { return ReturnType.IsVoidType(); }
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override MethodKind MethodKind
{
get { return MethodKind.Ordinary; }
......
......@@ -116,6 +116,8 @@ public override DllImportData GetDllImportData()
return null;
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
internal override MarshalPseudoCustomAttributeData ReturnValueMarshallingInformation
{
get { return null; }
......
......@@ -3,8 +3,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
......@@ -101,6 +99,8 @@ public sealed override TypeWithAnnotations ReturnTypeWithAnnotations
get { return _interfaceMethod.ReturnTypeWithAnnotations; }
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<ParameterSymbol> Parameters
{
get { return _parameters; }
......
......@@ -151,6 +151,8 @@ public sealed override TypeWithAnnotations ReturnTypeWithAnnotations
get { return TypeWithAnnotations.Create(ContainingAssembly.GetSpecialType(SpecialType.System_Void)); }
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
get { return ImmutableArray<CustomModifier>.Empty; }
......
......@@ -140,6 +140,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return TypeWithAnnotations.Create(_returnType); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
get { return ImmutableArray<CustomModifier>.Empty; }
......
......@@ -229,6 +229,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
get
......
......@@ -188,6 +188,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
get
......
......@@ -136,6 +136,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
get
......
......@@ -97,6 +97,26 @@ internal static TypeWithAnnotations Create(TypeSymbol typeSymbol, NullableAnnota
return CreateNonLazyType(typeSymbol, nullableAnnotation, customModifiers.NullToEmpty());
}
internal TypeWithAnnotations AsAnnotated()
{
if (NullableAnnotation.IsAnnotated() || (Type.IsValueType && Type.IsNullableType()))
{
return this;
}
return Create(Type, NullableAnnotation.Annotated, CustomModifiers);
}
internal TypeWithAnnotations AsNotAnnotated()
{
if (NullableAnnotation.IsNotAnnotated() || (Type.IsValueType && !Type.IsNullableType()))
{
return this;
}
return Create(Type, NullableAnnotation.NotAnnotated, CustomModifiers);
}
internal bool IsPossiblyNullableTypeTypeParameter()
{
return NullableAnnotation.IsNotAnnotated() &&
......
// 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 Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
......@@ -28,6 +29,35 @@ public static TypeWithState Create(TypeSymbol type, NullableFlowState defaultSta
return new TypeWithState(type, state);
}
public static TypeWithState Create(TypeWithAnnotations typeWithAnnotations, FlowAnalysisAnnotations annotations = FlowAnalysisAnnotations.None)
{
var type = typeWithAnnotations.Type;
Debug.Assert((object)type != null);
NullableFlowState state;
if (type.CanContainNull())
{
if ((annotations & FlowAnalysisAnnotations.MaybeNull) == FlowAnalysisAnnotations.MaybeNull)
{
state = NullableFlowState.MaybeNull;
}
else if ((annotations & FlowAnalysisAnnotations.NotNull) == FlowAnalysisAnnotations.NotNull)
{
state = NullableFlowState.NotNull;
}
else
{
return typeWithAnnotations.ToTypeWithState();
}
}
else
{
state = NullableFlowState.NotNull;
}
return new TypeWithState(type, state);
}
private TypeWithState(TypeSymbol type, NullableFlowState state)
{
Debug.Assert(state == NullableFlowState.NotNull || type?.CanContainNull() != false);
......
......@@ -297,6 +297,8 @@ internal override bool HasRuntimeSpecialName
}
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => UnderlyingMethod.ReturnTypeAnnotationAttributes;
internal override bool ReturnValueIsMarshalledExplicitly
{
get
......
......@@ -6,8 +6,6 @@
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.PooledObjects;
......@@ -297,6 +295,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
get { return GetTypeParametersAsTypeArguments(); }
......
......@@ -155,6 +155,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return _returnType; }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
bool Cci.ISignature.ReturnValueIsByRef
{
get { return true; }
......
......@@ -128,6 +128,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { throw ExceptionUtilities.Unreachable; }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
get { throw ExceptionUtilities.Unreachable; }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册