未验证 提交 61a287ab 编写于 作者: R Rikki Gibson 提交者: GitHub

Input param postconditions (#49576)

上级 46c97fe4
......@@ -1850,6 +1850,22 @@ private static bool ShouldReportNullableAssignment(TypeWithAnnotations type, Nul
ReportDiagnostic(ErrorCode.WRN_NullReferenceArgument, location,
GetParameterAsDiagnosticArgument(parameterOpt),
GetContainingSymbolAsDiagnosticArgument(parameterOpt));
if (targetType.Type.IsPossiblyNullableReferenceTypeTypeParameter())
{
var slotBuilder = ArrayBuilder<int>.GetInstance();
GetSlotsToMarkAsNotNullable(value, slotBuilder);
foreach (var slot in slotBuilder)
{
Debug.Assert(State[slot] == NullableFlowState.MaybeDefault);
State[slot] = NullableFlowState.MaybeNull;
}
slotBuilder.Free();
}
else
{
LearnFromNonNullTest(value, ref State);
}
}
else if (useLegacyWarnings)
{
......@@ -4230,7 +4246,7 @@ private static TypeWithState GetNullCoalescingResultType(TypeWithState rightResu
// Per LDM 2019-02-13 decision, the result of a conditional access "may be null" even if
// both the receiver and right-hand-side are believed not to be null.
SetResultType(node, TypeWithState.Create(resultType, NullableFlowState.MaybeNull));
SetResultType(node, TypeWithState.Create(resultType, NullableFlowState.MaybeDefault));
_currentConditionalReceiverVisitResult = default;
_lastConditionalAccessSlot = previousConditionalAccessSlot;
return null;
......@@ -5308,7 +5324,10 @@ private VisitArgumentResult VisitArgumentEvaluate(BoundExpression argument, RefK
stateForLambda: result.StateForLambda);
// If the parameter has annotations, we perform an additional check for nullable value types
CheckDisallowedNullAssignment(stateAfterConversion, parameterAnnotations, argumentNoConversion.Syntax.Location);
if (CheckDisallowedNullAssignment(stateAfterConversion, parameterAnnotations, argumentNoConversion.Syntax.Location))
{
LearnFromNonNullTest(argumentNoConversion, ref State);
}
SetResultType(argumentNoConversion, stateAfterConversion, updateAnalyzedNullability: false);
}
break;
......@@ -5340,19 +5359,23 @@ private VisitArgumentResult VisitArgumentEvaluate(BoundExpression argument, RefK
Debug.Assert(!this.IsConditionalState);
}
private void CheckDisallowedNullAssignment(TypeWithState state, FlowAnalysisAnnotations annotations, Location location, BoundExpression? boundValueOpt = null)
/// <summary>Returns <see langword="true"/> if this is an assignment forbidden by DisallowNullAttribute, otherwise <see langword="false"/>.</summary>
private bool CheckDisallowedNullAssignment(TypeWithState state, FlowAnalysisAnnotations annotations, Location location, BoundExpression? boundValueOpt = null)
{
if (boundValueOpt is { WasCompilerGenerated: true })
{
// We need to skip `return backingField;` in auto-prop getters
return;
return false;
}
// We do this extra check for types whose non-nullable version cannot be represented
if (IsDisallowedNullAssignment(state, annotations))
{
ReportDiagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, location);
return true;
}
return false;
}
private static bool IsDisallowedNullAssignment(TypeWithState valueState, FlowAnalysisAnnotations targetAnnotations)
......@@ -5595,10 +5618,6 @@ void learnFromPostConditions(BoundExpression argument, TypeWithAnnotations param
// Note: NotNull = NotNullWhen(true) + NotNullWhen(false)
bool notNullWhenTrue = (parameterAnnotations & FlowAnalysisAnnotations.NotNullWhenTrue) != 0;
bool notNullWhenFalse = (parameterAnnotations & FlowAnalysisAnnotations.NotNullWhenFalse) != 0;
bool disallowNull = (parameterAnnotations & FlowAnalysisAnnotations.DisallowNull) != 0;
bool setNotNullFromParameterType = !argument.IsSuppressed
&& !parameterType.Type.IsPossiblyNullableReferenceTypeTypeParameter()
&& parameterType.NullableAnnotation.IsNotAnnotated();
// Note: MaybeNull = MaybeNullWhen(true) + MaybeNullWhen(false)
bool maybeNullWhenTrue = (parameterAnnotations & FlowAnalysisAnnotations.MaybeNullWhenTrue) != 0;
......@@ -5608,7 +5627,7 @@ void learnFromPostConditions(BoundExpression argument, TypeWithAnnotations param
{
LearnFromNullTest(argument, ref State);
}
else if (((notNullWhenTrue && notNullWhenFalse) || disallowNull || setNotNullFromParameterType)
else if (notNullWhenTrue && notNullWhenFalse
&& !IsConditionalState
&& !(maybeNullWhenTrue || maybeNullWhenFalse))
{
......@@ -7045,9 +7064,9 @@ static bool dependsOnTypeParameter(TypeParameterSymbol typeParameter1, TypeParam
diagnosticLocation: operandLocation);
// in the case of a lifted conversion, we assume that the call to the operator occurs only if the argument is not-null
if (!isLiftedConversion)
if (!isLiftedConversion && CheckDisallowedNullAssignment(operandType, parameterAnnotations, conversionOperand.Syntax.Location))
{
CheckDisallowedNullAssignment(operandType, parameterAnnotations, conversionOperand.Syntax.Location);
LearnFromNonNullTest(conversionOperand, ref State);
}
// method parameter type -> method return type
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册