in src/Bicep.Core/TypeSystem/TypeValidator.cs [500:571]
private TypeSymbol NarrowStringAssignmentType(TypeValidatorConfig config, SyntaxBase expression, TypeSymbol expressionType, StringType targetType)
{
bool shouldWarn = config.IsResourceDeclaration || ShouldWarn(targetType);
switch (expressionType)
{
case StringType expressionString:
if (expressionString.MinLength.HasValue && targetType.MaxLength.HasValue && expressionString.MinLength.Value > targetType.MaxLength.Value)
{
diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression)
.SourceValueLengthDomainDisjointFromTargetValueLengthDomain_SourceHigh(shouldWarn, expressionString.MinLength.Value, targetType.MaxLength.Value));
break;
}
if (expressionString.MaxLength.HasValue && targetType.MinLength.HasValue && expressionString.MaxLength.Value < targetType.MinLength.Value)
{
diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression)
.SourceValueLengthDomainDisjointFromTargetValueLengthDomain_SourceLow(shouldWarn, expressionString.MaxLength.Value, targetType.MinLength.Value));
break;
}
if (expressionString.MinLength.HasValue && targetType.MinLength.HasValue && expressionString.MinLength.Value < targetType.MinLength.Value)
{
diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression).SourceValueLengthDomainExtendsBelowTargetValueLengthDomain(expressionString.MinLength.Value, targetType.MinLength.Value));
}
if (expressionString.MaxLength.HasValue && targetType.MaxLength.HasValue && expressionString.MaxLength.Value > targetType.MaxLength.Value)
{
diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression).SourceValueLengthDomainExtendsAboveTargetValueLengthDomain(expressionString.MaxLength.Value, targetType.MaxLength.Value));
}
return TypeFactory.CreateStringType(
minLength: Math.Max(expressionString.MinLength ?? 0, targetType.MinLength ?? 0) switch
{
<= 0 => null,
long otherwise => otherwise,
},
maxLength: Math.Min(expressionString.MaxLength ?? long.MaxValue, targetType.MaxLength ?? long.MaxValue) switch
{
long.MaxValue => null,
long otherwise => otherwise,
},
validationFlags: targetType.ValidationFlags);
case StringLiteralType expressionStringLiteral:
if (targetType.MaxLength.HasValue && expressionStringLiteral.RawStringValue.Length > targetType.MaxLength.Value)
{
diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression).SourceValueLengthDomainDisjointFromTargetValueLengthDomain_SourceHigh(
shouldWarn,
expressionStringLiteral.RawStringValue.Length,
targetType.MaxLength.Value));
}
else if (targetType.MinLength.HasValue && expressionStringLiteral.RawStringValue.Length < targetType.MinLength.Value)
{
diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression).SourceValueLengthDomainDisjointFromTargetValueLengthDomain_SourceLow(
shouldWarn,
expressionStringLiteral.RawStringValue.Length,
targetType.MinLength.Value));
}
if (targetType.Pattern is not null &&
TypeHelper.MatchesPattern(targetType.Pattern, expressionStringLiteral.RawStringValue) is false)
{
diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression)
.SuppliedStringDoesNotMatchExpectedPattern(shouldWarn, targetType.Pattern));
}
// if a literal was assignable to a string-typed target, the literal will always be the most narrow type
return expressionStringLiteral;
}
return expressionType;
}