Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3e53374

Browse files
authored
Merge pull request #5206 from jwosty/warning-fs0104-fix
Fix incomplete pattern matches over C# enums producing the wrong warning
2 parents247ea87 +9885bfd commit3e53374

File tree

5 files changed

+61
-29
lines changed

5 files changed

+61
-29
lines changed

‎src/fsharp/PatternMatchCompilation.fs‎

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module internal Microsoft.FSharp.Compiler.PatternMatchCompilation
44

55
openSystem.Collections.Generic
66
openMicrosoft.FSharp.Compiler
7+
openMicrosoft.FSharp.Compiler.AbstractIL.IL
78
openMicrosoft.FSharp.Compiler.AbstractIL.Internal.Library
89
openMicrosoft.FSharp.Compiler.AbstractIL.Diagnostics
910
openMicrosoft.FSharp.Compiler.Range
@@ -169,6 +170,25 @@ type RefutedSet =
169170
letnotNullText="some-non-null-value"
170171
letotherSubtypeText="some-other-subtype"
171172

173+
/// Create a TAST const value from an IL-initialized field read from .NET metadata
174+
// (Originally moved from TcFieldInit in TypeChecker.fs -- feel free to move this somewhere more appropriate)
175+
letilFieldToTastConst lit=
176+
match litwith
177+
| ILFieldInit.String s-> Const.String s
178+
| ILFieldInit.Null-> Const.Zero
179+
| ILFieldInit.Bool b-> Const.Bool b
180+
| ILFieldInit.Char c-> Const.Char(char(int c))
181+
| ILFieldInit.Int8 x-> Const.SByte x
182+
| ILFieldInit.Int16 x-> Const.Int16 x
183+
| ILFieldInit.Int32 x-> Const.Int32 x
184+
| ILFieldInit.Int64 x-> Const.Int64 x
185+
| ILFieldInit.UInt8 x-> Const.Byte x
186+
| ILFieldInit.UInt16 x-> Const.UInt16 x
187+
| ILFieldInit.UInt32 x-> Const.UInt32 x
188+
| ILFieldInit.UInt64 x-> Const.UInt64 x
189+
| ILFieldInit.Single f-> Const.Single f
190+
| ILFieldInit.Double f-> Const.Double f
191+
172192
exception CannotRefute
173193
letRefuteDiscrimSet g m path discrims=
174194
letmkUnknown ty= snd(mkCompGenLocal m"_" ty)
@@ -238,16 +258,28 @@ let RefuteDiscrimSet g m path discrims =
238258
| Some c->
239259
match tryDestAppTy g tywith
240260
| Some tcrefwhen tcref.IsEnumTycon->
241-
// search for an enum value that pattern match (consts) does not contain
242-
letnonCoveredEnumValues=
243-
tcref.AllFieldsArray|> Array.tryFind(fun f->
244-
match f.rfield_constwith
245-
| None->false
246-
| Some fieldValue->(not(consts.Contains fieldValue))&& f.rfield_static)
261+
// We must distinguish between F#-defined enums and other .NET enums, as they are represented differently in the TAST
262+
letenumValues=
263+
if tcref.IsILEnumTyconthen
264+
let(TILObjectReprData(_,_,tdef))= tcref.ILTyconInfo
265+
tdef.Fields.AsList
266+
|> Seq.choose(fun ilField->
267+
if ilField.IsStaticthen
268+
ilField.LiteralValue|> Option.map(fun ilValue->
269+
ilField.Name, ilFieldToTastConst ilValue)
270+
else None)
271+
else
272+
tcref.AllFieldsArray|> Seq.choose(fun fsField->
273+
match fsField.rfield_const, fsField.rfield_staticwith
274+
| Some fsFieldValue,true-> Some(fsField.rfield_id.idText, fsFieldValue)
275+
|_-> None)
276+
277+
letnonCoveredEnumValues= Seq.tryFind(fun(_,fldValue)->not(consts.Contains fldValue)) enumValues
278+
247279
match nonCoveredEnumValueswith
248280
| None-> Expr.Const(c,m,ty),true
249-
| Somef->
250-
letv= RecdFieldRef.RFRef(tcref,f.rfield_id.idText)
281+
| Some(fldName,_)->
282+
letv= RecdFieldRef.RFRef(tcref,fldName)
251283
Expr.Op(TOp.ValFieldGet v,[ty],[], m),false
252284
|_-> Expr.Const(c,m,ty),false
253285

‎src/fsharp/PatternMatchCompilation.fsi‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
moduleinternalMicrosoft.FSharp.Compiler.PatternMatchCompilation
44

5+
openMicrosoft.FSharp.Compiler.AbstractIL.IL
56
openMicrosoft.FSharp.Compiler
67
openMicrosoft.FSharp.Compiler.Tast
78
openMicrosoft.FSharp.Compiler.Tastops
@@ -42,6 +43,8 @@ and PatternValBinding =
4243
andTypedMatchClause=
4344
| TClauseofPattern*Exproption*DecisionTreeTarget*range
4445

46+
valilFieldToTastConst:ILFieldInit->Tast.Const
47+
4548
/// Compile a pattern into a decision tree and a set of targets.
4649
valinternalCompilePattern:
4750
TcGlobals->

‎src/fsharp/TypeChecker.fs‎

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -907,23 +907,7 @@ let TcConst cenv ty m env c =
907907
| SynConst.Bytes _ -> error (InternalError(FSComp.SR.tcUnexpectedConstByteArray(), m))
908908

909909
/// Convert an Abstract IL ILFieldInit value read from .NET metadata to a TAST constant
910-
let TcFieldInit (_m:range) lit =
911-
match lit with
912-
| ILFieldInit.String s -> Const.String s
913-
| ILFieldInit.Null -> Const.Zero
914-
| ILFieldInit.Bool b -> Const.Bool b
915-
| ILFieldInit.Char c -> Const.Char (char (int c))
916-
| ILFieldInit.Int8 x -> Const.SByte x
917-
| ILFieldInit.Int16 x -> Const.Int16 x
918-
| ILFieldInit.Int32 x -> Const.Int32 x
919-
| ILFieldInit.Int64 x -> Const.Int64 x
920-
| ILFieldInit.UInt8 x -> Const.Byte x
921-
| ILFieldInit.UInt16 x -> Const.UInt16 x
922-
| ILFieldInit.UInt32 x -> Const.UInt32 x
923-
| ILFieldInit.UInt64 x -> Const.UInt64 x
924-
| ILFieldInit.Single f -> Const.Single f
925-
| ILFieldInit.Double f -> Const.Double f
926-
910+
let TcFieldInit (_m:range) lit = PatternMatchCompilation.ilFieldToTastConst lit
927911

928912
//-------------------------------------------------------------------------
929913
// Arities. These serve two roles in the system:

‎tests/fsharp/typecheck/sigs/neg102.bsl‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ neg102.fs(18,14,18,22): typecheck error FS0025: Incomplete pattern matches on th
99

1010
neg102.fs(22,14,22,22): typecheck error FS0025: Incomplete pattern matches on this expression.For example, the value 'Some (EnumABC.C)' may indicate a casenot covered by the pattern(s).
1111

12-
neg102.fs(29,14,29,22): typecheck errorFS0104:Enums may take values outside known cases.For example, the value 'enum<EnumABC> (2)' may indicate a casenot covered by the pattern(s).
12+
neg102.fs(27,14,27,22): typecheck errorFS0025: Incomplete pattern matches on this expression.For example, the value 'System.DateTimeKind.Utc' may indicate a casenot covered by the pattern(s).
1313

14-
neg102.fs(34,14,34,22): typecheck error FS0104:Enums may take values outside known cases.For example, the value 'Some (enum<EnumABC> (2))' may indicate a casenot covered by the pattern(s).
14+
neg102.fs(32,14,32,22): typecheck error FS0104:Enums may take values outside known cases.For example, the value 'enum<EnumABC> (2)' may indicate a casenot covered by the pattern(s).
15+
16+
neg102.fs(37,14,37,22): typecheck error FS0104:Enums may take values outside known cases.For example, the value 'Some (enum<EnumABC> (2))' may indicate a casenot covered by the pattern(s).
17+
18+
neg102.fs(44,14,44,22): typecheck error FS0104:Enums may take values outside known cases.For example, the value 'enum<System.DateTimeKind> (3)' may indicate a casenot covered by the pattern(s).

‎tests/fsharp/typecheck/sigs/neg102.fs‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ type UnionAB = A | B
44

55
moduleFS0025=
66
// All of these should emit warning FS0025 ("Incomplete pattern match....")
7-
7+
88

99
letf1=function
1010
| UnionAB.A->"A"
@@ -23,6 +23,9 @@ module FS0025 =
2323
| Some(EnumABC.A)| Some(EnumABC.B)->"A|B"
2424
| None->"neither"
2525

26+
// try a non-F#-defined enum
27+
letf6=function System.DateTimeKind.Unspecified->0
28+
2629
moduleFS0104=
2730
// These should emit warning FS0104 ("Enums may take values outside of known cases....")
2831

@@ -35,4 +38,10 @@ module FS0104 =
3538
| Some(EnumABC.A)->"A"
3639
| Some(EnumABC.B)->"B"
3740
| Some(EnumABC.C)->"C"
38-
| None->"none"
41+
| None->"none"
42+
43+
// try a non-F#-defined enum
44+
letf3=function
45+
| System.DateTimeKind.Unspecified->"Unspecified"
46+
| System.DateTimeKind.Utc->"Utc"
47+
| System.DateTimeKind.Local->"Local"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp