From ca3ddafa7914f27cfd8363cb2d4a709552aa2aea Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Fri, 24 Jun 2016 10:43:53 +0200 Subject: [PATCH 1/4] Better error message when a record was given - fixes #1280 --- src/fsharp/FSComp.txt | 1 + src/fsharp/TypeChecker.fs | 3 +++ tests/fsharpqa/Source/Warnings/InvalidRecord.fs | 9 +++++++++ tests/fsharpqa/Source/Warnings/env.lst | 1 + 4 files changed, 14 insertions(+) create mode 100644 tests/fsharpqa/Source/Warnings/InvalidRecord.fs diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 309f121046d..a26aca562c8 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -957,6 +957,7 @@ lexfltSeparatorTokensOfPatternMatchMisaligned,"The '|' tokens separating rules o 1127,nrIsNotConstructorOrLiteral,"This is not a constructor or literal, or a constructor is being used incorrectly" 1128,nrUnexpectedEmptyLongId,"Unexpected empty long identifier" 1129,nrTypeDoesNotContainSuchField,"The type '%s' does not contain a field '%s'" +1129,nrTypeIsNotARecord,"This expression was expected to have type '%s' but here an incompatible record type was given." 1129,nrRecordDoesNotContainSuchLabel,"The record type '%s' does not contain a label '%s'." 1130,nrInvalidFieldLabel,"Invalid field label" 1132,nrInvalidExpression,"Invalid expression '%s'" diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index b5da2a0281b..b8e29ea5bee 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -6645,6 +6645,9 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr match flds with | [] -> [] | _ -> + if not (isRecdTy cenv.g overallTy) then + let typeName = NicePrint.minimalStringOfType env.NameEnv.eDisplayEnv overallTy + error(Error(FSComp.SR.nrTypeIsNotARecord(typeName),mWholeExpr)) let tcref,_,fldsList = BuildFieldMap cenv env (isSome optOrigExpr) overallTy flds mWholeExpr let _,_,_,gtyp = infoOfTyconRef mWholeExpr tcref UnifyTypes cenv env mWholeExpr overallTy gtyp diff --git a/tests/fsharpqa/Source/Warnings/InvalidRecord.fs b/tests/fsharpqa/Source/Warnings/InvalidRecord.fs new file mode 100644 index 00000000000..040fee3711e --- /dev/null +++ b/tests/fsharpqa/Source/Warnings/InvalidRecord.fs @@ -0,0 +1,9 @@ +// #Warnings +//This expression was expected to have + +type Record = {field1:int; field2:int} +let doSomething (xs) = List.map (fun {field1=x} -> x) xs + +doSomething {Record.field1=0; field2=0} + +exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index da119ba25d2..3ed17922c22 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -2,6 +2,7 @@ SOURCE=WarnIfMissingElseBranch.fs # WarnIfMissingElseBranch.fs SOURCE=ReturnInsteadOfReturnBang.fs # ReturnInsteadOfReturnBang.fs SOURCE=YieldInsteadOfYieldBang.fs # YieldInsteadOfYieldBang.fs + SOURCE=InvalidRecord.fs # InvalidRecord.fs SOURCE=CommaInRecCtor.fs # CommaInRecCtor.fs SOURCE=ValidCommaInRecCtor.fs # ValidCommaInRecCtor.fs SOURCE=ElseBranchHasWrongType.fs # ElseBranchHasWrongType.fs From e5d30b7d0dcbdc4de544c2552f447490a1369de4 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Fri, 24 Jun 2016 11:14:04 +0200 Subject: [PATCH 2/4] Better error message when a record was given - fixes #1280 --- src/fsharp/FSComp.txt | 1 - src/fsharp/NameResolution.fs | 8 ++++---- src/fsharp/NameResolution.fsi | 2 +- src/fsharp/TypeChecker.fs | 7 ++----- .../RecordTypes/E_RecordCloning01.fs | 2 +- .../MethodsAndProperties/E_SettersMustHaveUnit01.fs | 2 +- 6 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index a26aca562c8..91fe6dbe4fb 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -956,7 +956,6 @@ lexfltSeparatorTokensOfPatternMatchMisaligned,"The '|' tokens separating rules o 1126,nrGlobalUsedOnlyAsFirstName,"'global' may only be used as the first name in a qualified path" 1127,nrIsNotConstructorOrLiteral,"This is not a constructor or literal, or a constructor is being used incorrectly" 1128,nrUnexpectedEmptyLongId,"Unexpected empty long identifier" -1129,nrTypeDoesNotContainSuchField,"The type '%s' does not contain a field '%s'" 1129,nrTypeIsNotARecord,"This expression was expected to have type '%s' but here an incompatible record type was given." 1129,nrRecordDoesNotContainSuchLabel,"The record type '%s' does not contain a label '%s'." 1130,nrInvalidFieldLabel,"Invalid field label" diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 52345ff8c43..491008d741e 100755 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -2546,7 +2546,7 @@ let SuggestLabelsOfRelatedRecords (nenv:NameResolutionEnv) (id:Ident) (allFields UndefinedName(0,FSComp.SR.undefinedNameRecordLabel, id, predictedLabels) /// Resolve a long identifier representing a record field -let ResolveFieldPrim (ncenv:NameResolver) nenv ad typ (mp,id:Ident) allFields = +let ResolveFieldPrim (ncenv:NameResolver) nenv ad typ mWholeExpr (mp,id:Ident) allFields = let typeNameResInfo = TypeNameResolutionInfo.Default let g = ncenv.g let m = id.idRange @@ -2561,7 +2561,7 @@ let ResolveFieldPrim (ncenv:NameResolver) nenv ad typ (mp,id:Ident) allFields = // record label doesn't belong to record type -> predict other labels of same record error(Error(SuggestOtherLabelsOfSameRecordType nenv typeName id allFields,m)) else - error(Error(FSComp.SR.nrTypeDoesNotContainSuchField(typeName, id.idText),m)) + error(Error(FSComp.SR.nrTypeIsNotARecord(typeName),mWholeExpr)) else let frefs = try Map.find id.idText nenv.eFieldLabels @@ -2594,8 +2594,8 @@ let ResolveFieldPrim (ncenv:NameResolver) nenv ad typ (mp,id:Ident) allFields = if nonNil rest then errorR(Error(FSComp.SR.nrInvalidFieldLabel(),(List.head rest).idRange)); [(resInfo,item)] -let ResolveField sink ncenv nenv ad typ (mp,id) allFields = - let res = ResolveFieldPrim ncenv nenv ad typ (mp,id) allFields +let ResolveField sink ncenv nenv ad typ mWholeExpr (mp,id) allFields = + let res = ResolveFieldPrim ncenv nenv ad typ mWholeExpr (mp,id) allFields // Register the results of any field paths "Module.Type" in "Module.Type.field" as a name resolution. (Note, the path resolution // info is only non-empty if there was a unique resolution of the field) for (resInfo,_rfref) in res do diff --git a/src/fsharp/NameResolution.fsi b/src/fsharp/NameResolution.fsi index 590f8a07016..c96bcbd48ba 100755 --- a/src/fsharp/NameResolution.fsi +++ b/src/fsharp/NameResolution.fsi @@ -366,7 +366,7 @@ val internal ResolveTypeLongIdentInTyconRef : TcResultsSink -> NameResol val internal ResolveTypeLongIdent : TcResultsSink -> NameResolver -> ItemOccurence -> FullyQualifiedFlag -> NameResolutionEnv -> AccessorDomain -> Ident list -> TypeNameResolutionStaticArgsInfo -> PermitDirectReferenceToGeneratedType -> ResultOrException /// Resolve a long identifier to a field -val internal ResolveField : TcResultsSink -> NameResolver -> NameResolutionEnv -> AccessorDomain -> TType -> Ident list * Ident -> Ident list -> FieldResolution list +val internal ResolveField : TcResultsSink -> NameResolver -> NameResolutionEnv -> AccessorDomain -> TType -> range -> Ident list * Ident -> Ident list -> FieldResolution list /// Resolve a long identifier occurring in an expression position val internal ResolveExprLongIdent : TcResultsSink -> NameResolver -> range -> AccessorDomain -> NameResolutionEnv -> TypeNameResolutionInfo -> Ident list -> Item * Ident list diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index b8e29ea5bee..8492f65565a 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1872,7 +1872,7 @@ let BuildFieldMap cenv env isPartial ty flds m = let frefSets = let allFields = flds |> List.map (fun ((_,ident),_) -> ident) flds |> List.map (fun (fld,fldExpr) -> - let frefSet = ResolveField cenv.tcSink cenv.nameResolver env.eNameResEnv ad ty fld allFields + let frefSet = ResolveField cenv.tcSink cenv.nameResolver env.eNameResEnv ad ty m fld allFields fld,frefSet, fldExpr) let relevantTypeSets = frefSets |> List.map (fun (_,frefSet,_) -> frefSet |> List.choose (fun (FieldResolution(rfref,_)) -> Some rfref.TyconRef)) @@ -6644,10 +6644,7 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr ] match flds with | [] -> [] - | _ -> - if not (isRecdTy cenv.g overallTy) then - let typeName = NicePrint.minimalStringOfType env.NameEnv.eDisplayEnv overallTy - error(Error(FSComp.SR.nrTypeIsNotARecord(typeName),mWholeExpr)) + | _ -> let tcref,_,fldsList = BuildFieldMap cenv env (isSome optOrigExpr) overallTy flds mWholeExpr let _,_,_,gtyp = infoOfTyconRef mWholeExpr tcref UnifyTypes cenv env mWholeExpr overallTy gtyp diff --git a/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/RecordTypes/E_RecordCloning01.fs b/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/RecordTypes/E_RecordCloning01.fs index aa2172850b0..3d3c467b6c9 100644 --- a/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/RecordTypes/E_RecordCloning01.fs +++ b/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/RecordTypes/E_RecordCloning01.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #TypesAndModules #Records // Verify error when trying to clone a non-record type -//The type 'int \[\]' does not contain a field 'B'$ +//This expression was expected to have type 'int \[\]' but here an incompatible record type was given.$ type RecType = { A : int; B : string } diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/MethodsAndProperties/E_SettersMustHaveUnit01.fs b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/MethodsAndProperties/E_SettersMustHaveUnit01.fs index 131df38108f..30ba26d42d8 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/MethodsAndProperties/E_SettersMustHaveUnit01.fs +++ b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/MethodsAndProperties/E_SettersMustHaveUnit01.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DeclarationElements #MemberDefinitions #MethodsAndProperties // Verify property setters must have type unit -//The type 'unit' does not contain a field 'immutStr' +//This expression was expected to have type 'unit' but here an incompatible record type was given. type immut = { From 0efa7982bcb896a3c4ddbfe44218c4196f0a6887 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Sat, 25 Jun 2016 16:56:44 +0200 Subject: [PATCH 3/4] Make the error a type error - fixes #1280 --- VisualFSharp.sln | 5 +-- src/fsharp/NameResolution.fs | 32 ++++++++++--------- src/fsharp/NameResolution.fsi | 2 +- src/fsharp/TypeChecker.fs | 2 +- .../RecordTypes/E_RecordCloning01.fs | 2 +- .../E_SettersMustHaveUnit01.fs | 2 +- .../fsharpqa/Source/Warnings/InvalidRecord.fs | 2 +- 7 files changed, 23 insertions(+), 24 deletions(-) diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 002dbd63f6b..a203741dcd3 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler", "src\fsharp\FSharp.Compiler\FSharp.Compiler.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject @@ -126,9 +126,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProjectSection EndProject Global - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 491008d741e..2f270d2625a 100755 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -2546,23 +2546,13 @@ let SuggestLabelsOfRelatedRecords (nenv:NameResolutionEnv) (id:Ident) (allFields UndefinedName(0,FSComp.SR.undefinedNameRecordLabel, id, predictedLabels) /// Resolve a long identifier representing a record field -let ResolveFieldPrim (ncenv:NameResolver) nenv ad typ mWholeExpr (mp,id:Ident) allFields = +let ResolveFieldPrim (ncenv:NameResolver) nenv ad typ (mp,id:Ident) allFields = let typeNameResInfo = TypeNameResolutionInfo.Default let g = ncenv.g let m = id.idRange match mp with | [] -> - if isAppTy g typ then - match ncenv.InfoReader.TryFindRecdOrClassFieldInfoOfType(id.idText,m,typ) with - | Some (RecdFieldInfo(_,rfref)) -> [ResolutionInfo.Empty, FieldResolution(rfref,false)] - | None -> - let typeName = NicePrint.minimalStringOfType nenv.eDisplayEnv typ - if isRecdTy g typ then - // record label doesn't belong to record type -> predict other labels of same record - error(Error(SuggestOtherLabelsOfSameRecordType nenv typeName id allFields,m)) - else - error(Error(FSComp.SR.nrTypeIsNotARecord(typeName),mWholeExpr)) - else + let lookup() = let frefs = try Map.find id.idText nenv.eFieldLabels with :? KeyNotFoundException -> @@ -2573,7 +2563,19 @@ let ResolveFieldPrim (ncenv:NameResolver) nenv ad typ mWholeExpr (mp,id:Ident) a frefs |> ListSet.setify (fun fref1 fref2 -> tyconRefEq g fref1.TyconRef fref2.TyconRef) |> List.map (fun x -> ResolutionInfo.Empty, FieldResolution(x,false)) - + + if isAppTy g typ then + match ncenv.InfoReader.TryFindRecdOrClassFieldInfoOfType(id.idText,m,typ) with + | Some (RecdFieldInfo(_,rfref)) -> [ResolutionInfo.Empty, FieldResolution(rfref,false)] + | None -> + let typeName = NicePrint.minimalStringOfType nenv.eDisplayEnv typ + if isRecdTy g typ then + // record label doesn't belong to record type -> predict other labels of same record + error(Error(SuggestOtherLabelsOfSameRecordType nenv typeName id allFields,m)) + else + lookup() + else + lookup() | _ -> let lid = (mp@[id]) let tyconSearch ad = @@ -2594,8 +2596,8 @@ let ResolveFieldPrim (ncenv:NameResolver) nenv ad typ mWholeExpr (mp,id:Ident) a if nonNil rest then errorR(Error(FSComp.SR.nrInvalidFieldLabel(),(List.head rest).idRange)); [(resInfo,item)] -let ResolveField sink ncenv nenv ad typ mWholeExpr (mp,id) allFields = - let res = ResolveFieldPrim ncenv nenv ad typ mWholeExpr (mp,id) allFields +let ResolveField sink ncenv nenv ad typ (mp,id) allFields = + let res = ResolveFieldPrim ncenv nenv ad typ (mp,id) allFields // Register the results of any field paths "Module.Type" in "Module.Type.field" as a name resolution. (Note, the path resolution // info is only non-empty if there was a unique resolution of the field) for (resInfo,_rfref) in res do diff --git a/src/fsharp/NameResolution.fsi b/src/fsharp/NameResolution.fsi index c96bcbd48ba..590f8a07016 100755 --- a/src/fsharp/NameResolution.fsi +++ b/src/fsharp/NameResolution.fsi @@ -366,7 +366,7 @@ val internal ResolveTypeLongIdentInTyconRef : TcResultsSink -> NameResol val internal ResolveTypeLongIdent : TcResultsSink -> NameResolver -> ItemOccurence -> FullyQualifiedFlag -> NameResolutionEnv -> AccessorDomain -> Ident list -> TypeNameResolutionStaticArgsInfo -> PermitDirectReferenceToGeneratedType -> ResultOrException /// Resolve a long identifier to a field -val internal ResolveField : TcResultsSink -> NameResolver -> NameResolutionEnv -> AccessorDomain -> TType -> range -> Ident list * Ident -> Ident list -> FieldResolution list +val internal ResolveField : TcResultsSink -> NameResolver -> NameResolutionEnv -> AccessorDomain -> TType -> Ident list * Ident -> Ident list -> FieldResolution list /// Resolve a long identifier occurring in an expression position val internal ResolveExprLongIdent : TcResultsSink -> NameResolver -> range -> AccessorDomain -> NameResolutionEnv -> TypeNameResolutionInfo -> Ident list -> Item * Ident list diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 8492f65565a..07f6ef7d7c6 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1872,7 +1872,7 @@ let BuildFieldMap cenv env isPartial ty flds m = let frefSets = let allFields = flds |> List.map (fun ((_,ident),_) -> ident) flds |> List.map (fun (fld,fldExpr) -> - let frefSet = ResolveField cenv.tcSink cenv.nameResolver env.eNameResEnv ad ty m fld allFields + let frefSet = ResolveField cenv.tcSink cenv.nameResolver env.eNameResEnv ad ty fld allFields fld,frefSet, fldExpr) let relevantTypeSets = frefSets |> List.map (fun (_,frefSet,_) -> frefSet |> List.choose (fun (FieldResolution(rfref,_)) -> Some rfref.TyconRef)) diff --git a/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/RecordTypes/E_RecordCloning01.fs b/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/RecordTypes/E_RecordCloning01.fs index 3d3c467b6c9..16e53eca0a5 100644 --- a/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/RecordTypes/E_RecordCloning01.fs +++ b/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/RecordTypes/E_RecordCloning01.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #TypesAndModules #Records // Verify error when trying to clone a non-record type -//This expression was expected to have type 'int \[\]' but here an incompatible record type was given.$ +//This expression was expected to have type type RecType = { A : int; B : string } diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/MethodsAndProperties/E_SettersMustHaveUnit01.fs b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/MethodsAndProperties/E_SettersMustHaveUnit01.fs index 30ba26d42d8..7097557c72d 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/MethodsAndProperties/E_SettersMustHaveUnit01.fs +++ b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/MethodsAndProperties/E_SettersMustHaveUnit01.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DeclarationElements #MemberDefinitions #MethodsAndProperties // Verify property setters must have type unit -//This expression was expected to have type 'unit' but here an incompatible record type was given. +//This expression was expected to have type type immut = { diff --git a/tests/fsharpqa/Source/Warnings/InvalidRecord.fs b/tests/fsharpqa/Source/Warnings/InvalidRecord.fs index 040fee3711e..d3148fbeddc 100644 --- a/tests/fsharpqa/Source/Warnings/InvalidRecord.fs +++ b/tests/fsharpqa/Source/Warnings/InvalidRecord.fs @@ -1,5 +1,5 @@ // #Warnings -//This expression was expected to have +//This expression was expected to have type Record = {field1:int; field2:int} let doSomething (xs) = List.map (fun {field1=x} -> x) xs From 5eceaf1f68567fee0ae4a5d734254e2525013861 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Sat, 25 Jun 2016 18:17:14 +0200 Subject: [PATCH 4/4] Remove unused message --- src/fsharp/FSComp.txt | 1 - tests/fsharpqa/Source/Warnings/InvalidRecord.fs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 91fe6dbe4fb..f9ecb656b11 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -956,7 +956,6 @@ lexfltSeparatorTokensOfPatternMatchMisaligned,"The '|' tokens separating rules o 1126,nrGlobalUsedOnlyAsFirstName,"'global' may only be used as the first name in a qualified path" 1127,nrIsNotConstructorOrLiteral,"This is not a constructor or literal, or a constructor is being used incorrectly" 1128,nrUnexpectedEmptyLongId,"Unexpected empty long identifier" -1129,nrTypeIsNotARecord,"This expression was expected to have type '%s' but here an incompatible record type was given." 1129,nrRecordDoesNotContainSuchLabel,"The record type '%s' does not contain a label '%s'." 1130,nrInvalidFieldLabel,"Invalid field label" 1132,nrInvalidExpression,"Invalid expression '%s'" diff --git a/tests/fsharpqa/Source/Warnings/InvalidRecord.fs b/tests/fsharpqa/Source/Warnings/InvalidRecord.fs index d3148fbeddc..f04f24e4576 100644 --- a/tests/fsharpqa/Source/Warnings/InvalidRecord.fs +++ b/tests/fsharpqa/Source/Warnings/InvalidRecord.fs @@ -1,5 +1,5 @@ // #Warnings -//This expression was expected to have +//This expression was expected to have type type Record = {field1:int; field2:int} let doSomething (xs) = List.map (fun {field1=x} -> x) xs