Skip to content

Commit 71afb81

Browse files
committed
Use target rather than expression type as narrowing base case
1 parent ea90624 commit 71afb81

File tree

5 files changed

+53
-18
lines changed

5 files changed

+53
-18
lines changed

src/Bicep.Core.IntegrationTests/ScenarioTests.cs

+35
Original file line numberDiff line numberDiff line change
@@ -6258,4 +6258,39 @@ public void Recursive_types_generate_diagnostics_where_referenced()
62586258
("BCP062", DiagnosticLevel.Error, """The referenced declaration with name "invalidRecursiveObjectType" is not valid."""),
62596259
]);
62606260
}
6261+
6262+
// https://github.com/Azure/bicep/issues/15114
6263+
[TestMethod]
6264+
public void Test_Issue15114()
6265+
{
6266+
var result = CompilationHelper.Compile("""
6267+
param recoverDeleted bool
6268+
6269+
resource KeyVaultResource 'Microsoft.KeyVault/vaults@2023-07-01' = {
6270+
name: 'vault'
6271+
location: resourceGroup().location
6272+
properties: recoverDeleted
6273+
? {
6274+
createMode: 'recover'
6275+
sku: {
6276+
name: 'standard'
6277+
family: 'A'
6278+
}
6279+
tenantId: tenant().tenantId
6280+
}
6281+
: {
6282+
createMode: 'default'
6283+
sku: {
6284+
name: 'standard'
6285+
family: 'A'
6286+
}
6287+
tenantId: tenant().tenantId
6288+
}
6289+
}
6290+
6291+
output keyvaultUri string = KeyVaultResource.properties.vaultUri
6292+
""");
6293+
6294+
result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics();
6295+
}
62616296
}

src/Bicep.Core.Samples/Files/baselines/Functions_LF/main.symbols.bicep

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ func objReturnType(name string) object => {
2323

2424
func arrayReturnType(name string) array => [
2525
//@[21:025) Local name. Type: string. Declaration start char: 21, length: 11
26-
//@[05:020) Function arrayReturnType. Type: string => [string]. Declaration start char: 0, length: 53
26+
//@[05:020) Function arrayReturnType. Type: string => [any]. Declaration start char: 0, length: 53
2727
name
2828
]
2929

3030
func asdf(name string) array => [
3131
//@[10:014) Local name. Type: string. Declaration start char: 10, length: 11
32-
//@[05:009) Function asdf. Type: string => ['asdf', string]. Declaration start char: 0, length: 51
32+
//@[05:009) Function asdf. Type: string => [any, any]. Declaration start char: 0, length: 51
3333
'asdf'
3434
name
3535
]
@@ -43,10 +43,10 @@ func typedArg(input string[]) positiveInt => length(input)
4343
//@[05:013) Function typedArg. Type: string[] => int. Declaration start char: 0, length: 58
4444

4545
func barTest() array => ['abc', 'def']
46-
//@[05:012) Function barTest. Type: () => ['abc', 'def']. Declaration start char: 0, length: 38
46+
//@[05:012) Function barTest. Type: () => [any, any]. Declaration start char: 0, length: 38
4747
func fooTest() array => map(barTest(), a => 'Hello ${a}!')
4848
//@[39:040) Local a. Type: any. Declaration start char: 39, length: 1
49-
//@[05:012) Function fooTest. Type: () => string[]. Declaration start char: 0, length: 58
49+
//@[05:012) Function fooTest. Type: () => array. Declaration start char: 0, length: 58
5050

5151
output fooValue array = fooTest()
5252
//@[07:015) Output fooValue. Type: array. Declaration start char: 0, length: 33

src/Bicep.Core.Samples/Files/baselines/InvalidFunctions_LF/main.symbols.bicep

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
func useRuntimeFunction() string => reference('foo').bar
2-
//@[05:23) Function useRuntimeFunction. Type: () => any. Declaration start char: 0, length: 56
2+
//@[05:23) Function useRuntimeFunction. Type: () => string. Declaration start char: 0, length: 56
33

44
func missingArgType(input) string => input
55
//@[20:25) Local input. Type: any. Declaration start char: 20, length: 5
6-
//@[05:19) Function missingArgType. Type: any => any. Declaration start char: 0, length: 42
6+
//@[05:19) Function missingArgType. Type: any => string. Declaration start char: 0, length: 42
77

88
func missingOutputType(input string) => input
99
//@[23:28) Local input. Type: string. Declaration start char: 23, length: 12
@@ -35,7 +35,7 @@ func argLengthMismatch(a string, b string, c string) array => ([a, b, c])
3535
//@[23:24) Local a. Type: string. Declaration start char: 23, length: 8
3636
//@[33:34) Local b. Type: string. Declaration start char: 33, length: 8
3737
//@[43:44) Local c. Type: string. Declaration start char: 43, length: 8
38-
//@[05:22) Function argLengthMismatch. Type: (string, string, string) => string[]. Declaration start char: 0, length: 73
38+
//@[05:22) Function argLengthMismatch. Type: (string, string, string) => array. Declaration start char: 0, length: 73
3939
var sdf = argLengthMismatch('asdf')
4040
//@[04:07) Variable sdf. Type: error. Declaration start char: 0, length: 35
4141

@@ -58,7 +58,7 @@ type validStringLiteralUnion = 'foo'|'bar'|'baz'
5858
func invalidArgs(a validStringLiteralUnion, b string) string => a
5959
//@[17:18) Local a. Type: 'bar' | 'baz' | 'foo'. Declaration start char: 17, length: 25
6060
//@[44:45) Local b. Type: string. Declaration start char: 44, length: 8
61-
//@[05:16) Function invalidArgs. Type: (('bar' | 'baz' | 'foo'), string) => ('bar' | 'baz' | 'foo'). Declaration start char: 0, length: 65
61+
//@[05:16) Function invalidArgs. Type: (('bar' | 'baz' | 'foo'), string) => string. Declaration start char: 0, length: 65
6262
func invalidOutput() validStringLiteralUnion => 'foo'
6363
//@[05:18) Function invalidOutput. Type: () => 'foo'. Declaration start char: 0, length: 53
6464

src/Bicep.Core.UnitTests/TypeSystem/TypeValidatorAssignabilityTests.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,11 @@ static object[] Row(TypeSymbol sourceType, TypeSymbol targetType, TypeSymbol exp
279279
// A source type whose domain is disjoint from the domain of the target should error and not narrow
280280
Row(TypeFactory.CreateStringType(minLength: 10),
281281
TypeFactory.CreateStringType(maxLength: 9),
282-
TypeFactory.CreateStringType(minLength: 10),
282+
TypeFactory.CreateStringType(maxLength: 9),
283283
("BCP332", DiagnosticLevel.Error, "The provided value (whose length will always be greater than or equal to 10) is too long to assign to a target for which the maximum allowable length is 9.")),
284284
Row(TypeFactory.CreateStringType(maxLength: 9),
285285
TypeFactory.CreateStringType(minLength: 10),
286-
TypeFactory.CreateStringType(maxLength: 9),
286+
TypeFactory.CreateStringType(minLength: 10),
287287
("BCP333", DiagnosticLevel.Error, "The provided value (whose length will always be less than or equal to 9) is too short to assign to a target for which the minimum allowable length is 10.")),
288288
Row(TypeFactory.CreateStringLiteralType("0123456789"),
289289
TypeFactory.CreateStringType(maxLength: 9),
@@ -369,19 +369,19 @@ static object[] Row(TypeSymbol sourceType, TypeSymbol targetType, TypeSymbol exp
369369
// A source type whose domain is disjoint from the domain of the target should error and not narrow
370370
Row(TypeFactory.CreateIntegerType(minValue: 10),
371371
TypeFactory.CreateIntegerType(maxValue: 9),
372-
TypeFactory.CreateIntegerType(minValue: 10),
372+
TypeFactory.CreateIntegerType(maxValue: 9),
373373
("BCP327", DiagnosticLevel.Error, "The provided value (which will always be greater than or equal to 10) is too large to assign to a target for which the maximum allowable value is 9.")),
374374
Row(TypeFactory.CreateIntegerType(maxValue: 9),
375375
TypeFactory.CreateIntegerType(minValue: 10),
376-
TypeFactory.CreateIntegerType(maxValue: 9),
376+
TypeFactory.CreateIntegerType(minValue: 10),
377377
("BCP328", DiagnosticLevel.Error, "The provided value (which will always be less than or equal to 9) is too small to assign to a target for which the minimum allowable value is 10.")),
378378
Row(TypeFactory.CreateIntegerLiteralType(10),
379379
TypeFactory.CreateIntegerType(maxValue: 9),
380-
TypeFactory.CreateIntegerLiteralType(10),
380+
TypeFactory.CreateIntegerType(maxValue: 9),
381381
("BCP327", DiagnosticLevel.Error, "The provided value (which will always be greater than or equal to 10) is too large to assign to a target for which the maximum allowable value is 9.")),
382382
Row(TypeFactory.CreateIntegerLiteralType(9),
383383
TypeFactory.CreateIntegerType(minValue: 10),
384-
TypeFactory.CreateIntegerLiteralType(9),
384+
TypeFactory.CreateIntegerType(minValue: 10),
385385
("BCP328", DiagnosticLevel.Error, "The provided value (which will always be less than or equal to 9) is too small to assign to a target for which the minimum allowable value is 10.")),
386386
Row(TypeFactory.CreateIntegerType(minValue: 10, validationFlags: TypeSymbolValidationFlags.AllowLooseAssignment),
387387
TypeFactory.CreateIntegerLiteralType(9),

src/Bicep.Core/TypeSystem/TypeValidator.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ private TypeSymbol NarrowType(TypeValidatorConfig config, SyntaxBase expression,
362362
return NarrowLambdaType(config, sourceLambda, targetLambdaType);
363363
}
364364

365-
return expressionType;
365+
return targetType;
366366
}
367367

368368
private static SyntaxBase UnwrapIfConditionBody(SyntaxBase expression) => expression switch
@@ -457,7 +457,7 @@ private TypeSymbol NarrowIntegerAssignmentType(TypeValidatorConfig config, Synta
457457
return expressionIntegerLiteral;
458458
}
459459

460-
return expressionType;
460+
return targetType;
461461
}
462462

463463
private TypeSymbol NarrowIntegerLiteralAssignmentType(TypeValidatorConfig config, SyntaxBase expression, TypeSymbol expressionType, IntegerLiteralType targetType)
@@ -548,7 +548,7 @@ private TypeSymbol NarrowStringAssignmentType(TypeValidatorConfig config, Syntax
548548
return expressionStringLiteral;
549549
}
550550

551-
return expressionType;
551+
return targetType;
552552
}
553553

554554
private TypeSymbol NarrowStringLiteralAssignmentType(TypeValidatorConfig config, SyntaxBase expression, TypeSymbol expressionType, StringLiteralType targetType)
@@ -1049,7 +1049,7 @@ static TypeSymbol RemoveImplicitNull(TypeSymbol type, bool typeWasPreserved)
10491049
// we should not return the parse errors however because they will get double collected
10501050
if (this.parsingErrorLookup.Contains(expression))
10511051
{
1052-
return targetType;
1052+
return null;
10531053
}
10541054

10551055
if (expressionType is ObjectType expressionObjectType)

0 commit comments

Comments
 (0)