Skip to content

Commit d181c97

Browse files
Use right error; only drop unneeded fields from spreads
1 parent 8c0e9ce commit d181c97

File tree

3 files changed

+41
-17
lines changed

3 files changed

+41
-17
lines changed

src/Compiler/Checking/Expressions/CheckExpressions.fs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8074,13 +8074,17 @@ and TcNewAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, unsortedField
80748074
match fieldsAndSpreads with
80758075
| [] ->
80768076
// If the target type is a known anonymous record type,
8077-
// keep only those fields that are present in that type.
8077+
// keep only those fields that are present in that type
8078+
// or that are explicitly defined in this one.
80788079
let checkedFields =
80798080
maybeAnonRecdTargetTy
80808081
|> ValueOption.map (fun (anonInfo, _) ->
80818082
let sortedNames = anonInfo.SortedNames
80828083
checkedFields
8083-
|> Map.filter (fun fieldId _ -> Array.BinarySearch (sortedNames, fieldId) >= 0))
8084+
|> Map.filter (fun fieldId field ->
8085+
match field with
8086+
| LeftwardExplicit, _ -> true
8087+
| NoLeftwardExplicit, _ -> Array.BinarySearch (sortedNames, fieldId) >= 0))
80848088
|> ValueOption.defaultValue checkedFields
80858089

80868090
// We must emit let-bindings for the source expressions in their original order.
@@ -8122,7 +8126,7 @@ and TcNewAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, unsortedField
81228126
//
81238127
// Keep both, but error.
81248128
| Some (LeftwardExplicit, dupes) ->
8125-
errorR (Duplicate ("field", fieldId.idText, m))
8129+
errorR (Error (FSComp.SR.tcAnonRecdDuplicateFieldId fieldId.idText, m))
81268130
Some (LeftwardExplicit, (i, fieldId, ty, expr) :: dupes)
81278131

81288132
// Rightward explicit field shadowing leftward spread field.
@@ -8334,7 +8338,8 @@ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (or
83348338
match fieldsAndSpreads with
83358339
| [] ->
83368340
// If the target type is a known anonymous record type,
8337-
// keep only those fields that are present in that type.
8341+
// keep only those fields that are present in that type
8342+
// or that are explicitly defined in this one.
83388343
let shouldKeep =
83398344
match tryDestAnonRecdTy g overallTy with
83408345
| ValueSome (anonInfo, _) ->
@@ -8345,7 +8350,9 @@ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (or
83458350
let fieldsInOriginalOrder =
83468351
flds
83478352
|> Map.toList
8348-
|> List.collect (fun (fieldId, (_, dupes)) -> if shouldKeep fieldId then dupes else [])
8353+
|> List.collect (function
8354+
| _, (LeftwardExplicit, dupes) -> dupes
8355+
| fieldId, (NoLeftwardExplicit, dupes) -> if shouldKeep fieldId then dupes else [])
83498356
|> List.sortBy (fun (i, _) -> i)
83508357
|> List.map (fun (_, field) -> field)
83518358

@@ -8375,7 +8382,7 @@ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (or
83758382
//
83768383
// Keep both, but error.
83778384
| Some (LeftwardExplicit, dupes) ->
8378-
errorR (Duplicate ("field", fieldId.idText, m))
8385+
errorR (Error (FSComp.SR.tcAnonRecdDuplicateFieldId fieldId.idText, m))
83798386
Some (LeftwardExplicit, (i, field) :: dupes)
83808387

83818388
// Rightward explicit field shadowing leftward spread field.

tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsSpread.fs.il.bsl

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,8 @@
461461
.custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
462462
.field static assembly class assembly/R1 spreadSrc@4
463463
.custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
464+
.field static assembly int32 B@4
465+
.custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
464466
.method public specialname static class assembly/R1 get_r1() cil managed
465467
{
466468

@@ -485,6 +487,14 @@
485487
IL_0005: ret
486488
}
487489

490+
.method assembly specialname static int32 get_B@4() cil managed
491+
{
492+
493+
.maxstack 8
494+
IL_0000: ldsfld int32 assembly::B@4
495+
IL_0005: ret
496+
}
497+
488498
.method private specialname rtspecialname static void .cctor() cil managed
489499
{
490500

@@ -499,7 +509,7 @@
499509
.method assembly specialname static void staticInitialization@() cil managed
500510
{
501511

502-
.maxstack 8
512+
.maxstack 4
503513
IL_0000: ldc.i4.1
504514
IL_0001: ldc.i4.2
505515
IL_0002: newobj instance void assembly/R1::.ctor(int32,
@@ -508,14 +518,16 @@
508518
IL_000c: ldc.i4.s 99
509519
IL_000e: newobj instance void class '<>f__AnonymousType1722350077`1'<int32>::.ctor(!0)
510520
IL_0013: stsfld class assembly/R1 assembly::spreadSrc@4
511-
IL_0018: call class assembly/R1 assembly::get_spreadSrc@4()
512-
IL_001d: call instance !0 class '<>f__AnonymousType1722350077`1'<int32>::get_A()
513-
IL_0022: call class assembly/R1 assembly::get_r1()
514-
IL_0027: ldfld int32 assembly/R1::B@
515-
IL_002c: newobj instance void assembly/R1::.ctor(int32,
521+
IL_0018: call class assembly/R1 assembly::get_r1()
522+
IL_001d: ldfld int32 assembly/R1::B@
523+
IL_0022: stsfld int32 assembly::B@4
524+
IL_0027: call class assembly/R1 assembly::get_spreadSrc@4()
525+
IL_002c: call instance !0 class '<>f__AnonymousType1722350077`1'<int32>::get_A()
526+
IL_0031: call int32 assembly::get_B@4()
527+
IL_0036: newobj instance void assembly/R1::.ctor(int32,
516528
int32)
517-
IL_0031: stsfld class assembly/R1 assembly::'r1\'@4'
518-
IL_0036: ret
529+
IL_003b: stsfld class assembly/R1 assembly::'r1\'@4'
530+
IL_0040: ret
519531
}
520532

521533
.property class assembly/R1
@@ -536,6 +548,11 @@
536548
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 )
537549
.get class assembly/R1 assembly::get_spreadSrc@4()
538550
}
551+
.property int32 B@4()
552+
{
553+
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 )
554+
.get int32 assembly::get_B@4()
555+
}
539556
}
540557

541558
.class private abstract auto ansi sealed '<StartupCode$assembly>'.$assembly

tests/FSharp.Compiler.ComponentTests/Language/SpreadTests.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ module NominalAndAnonymousRecords =
659659
|> shouldFail
660660
|> withDiagnostics [
661661
Warning 3883, Line 4, Col 42, Line 4, Col 47, "Spread field 'A: int' shadows an explicitly declared field with the same name."
662-
Error 37, Line 4, Col 49, Line 4, Col 57, "Duplicate definition of field 'A'"
662+
Error 3522, Line 4, Col 49, Line 4, Col 57, "The field 'A' appears multiple times in this record expression."
663663
Error 3522, Line 5, Col 31, Line 5, Col 71, "The field 'A' appears multiple times in this record expression."
664664
]
665665

@@ -680,7 +680,7 @@ module NominalAndAnonymousRecords =
680680
|> shouldFail
681681
|> withDiagnostics [
682682
Warning 3883, Line 5, Col 49, Line 5, Col 54, "Spread field 'A: int' shadows an explicitly declared field with the same name."
683-
Error 37, Line 5, Col 56, Line 5, Col 64, "Duplicate definition of field 'A'"
683+
Error 3522, Line 5, Col 56, Line 5, Col 64, "The field 'A' appears multiple times in this record expression."
684684
Error 3522, Line 6, Col 31, Line 6, Col 78, "The field 'A' appears multiple times in this record expression."
685685
]
686686

@@ -1206,7 +1206,7 @@ module NominalAndAnonymousRecords =
12061206
Error 37, Line 4, Col 46, Line 4, Col 51, "Duplicate definition of field 'A'"
12071207
Warning 3883, Line 4, Col 53, Line 4, Col 67, "Spread field 'A: int' shadows an explicitly declared field with the same name."
12081208
Error 37, Line 4, Col 69, Line 4, Col 74, "Duplicate definition of field 'A'"
1209-
Error 668, Line 4, Col 69, Line 4, Col 70, "The field 'A' appears multiple times in this record expression or pattern"
1209+
Error 668, Line 4, Col 59, Line 4, Col 60, "The field 'A' appears multiple times in this record expression or pattern"
12101210
]
12111211

12121212
/// Extra fields are ignored.

0 commit comments

Comments
 (0)