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

Commita6b72a4

Browse files
jwostyKevinRansom
authored andcommitted
Enum match warning (dotnet#4522)
* Add compiler warning for enum matches* Refactor* Make incomplete enum match warning only show itself when the pattern match covers all known enum values* small change* Update xlf* Update xlf (take 2)* Fix xlf format mistake* Add green test* Remove leftover printfn and register test* Attempt to make enum warning work in more cases* Fix inverted logic mistake* Update tests* Fix enum match warning not producing locations* New items should use translation state "new"* Update a test* Update another test* Undo changes out of the scope of this PR* Undo more whitespace
1 parent65d87f0 commita6b72a4

23 files changed

+175
-28
lines changed

‎src/fsharp/CompileOps.fs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ let GetRangeOfDiagnostic(err:PhasedDiagnostic) =
154154
| InterfaceNotRevealed(_,_, m)
155155
| WrappedError(_, m)
156156
| PatternMatchCompilation.MatchIncomplete(_,_, m)
157+
| PatternMatchCompilation.EnumMatchIncomplete(_,_, m)
157158
| PatternMatchCompilation.RuleNeverMatched m
158159
| ValNotMutable(_,_, m)
159160
| ValNotLocal(_,_, m)
@@ -355,6 +356,7 @@ let GetDiagnosticNumber(err:PhasedDiagnostic) =
355356
| ExtensionTyping.ProvidedTypeResolutionNoRange_
356357
| ExtensionTyping.ProvidedTypeResolution_->103
357358
#endif
359+
| PatternMatchCompilation.EnumMatchIncomplete_->104
358360
(* DO NOT CHANGE THE NUMBERS*)
359361

360362
// Strip TargetInvocationException wrappers
@@ -560,6 +562,7 @@ let MatchIncomplete2E() = DeclareResourceString("MatchIncomplete2", "%s")
560562
letMatchIncomplete3E()= DeclareResourceString("MatchIncomplete3","%s")
561563
letMatchIncomplete4E()= DeclareResourceString("MatchIncomplete4","")
562564
letRuleNeverMatchedE()= DeclareResourceString("RuleNeverMatched","")
565+
letEnumMatchIncomplete1E()= DeclareResourceString("EnumMatchIncomplete1","")
563566
letValNotMutableE()= DeclareResourceString("ValNotMutable","%s")
564567
letValNotLocalE()= DeclareResourceString("ValNotLocal","")
565568
letObsolete1E()= DeclareResourceString("Obsolete1","")
@@ -1402,6 +1405,15 @@ let OutputPhasedErrorR (os:StringBuilder) (err:PhasedDiagnostic) =
14021405
if isCompthen
14031406
os.Append(MatchIncomplete4E().Format)|> ignore
14041407

1408+
| PatternMatchCompilation.EnumMatchIncomplete(isComp, cexOpt,_)->
1409+
os.Append(EnumMatchIncomplete1E().Format)|> ignore
1410+
match cexOptwith
1411+
| None->()
1412+
| Some(cex,false)-> os.Append(MatchIncomplete2E().Format cex)|> ignore
1413+
| Some(cex,true)-> os.Append(MatchIncomplete3E().Format cex)|> ignore
1414+
if isCompthen
1415+
os.Append(MatchIncomplete4E().Format)|> ignore
1416+
14051417
| PatternMatchCompilation.RuleNeverMatched_-> os.Append(RuleNeverMatchedE().Format)|> ignore
14061418

14071419
| ValNotMutable(_, valRef,_)-> os.Append(ValNotMutableE().Format(valRef.DisplayName))|> ignore

‎src/fsharp/FSStrings.resx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,9 @@
969969
<dataname="MatchIncomplete4"xml:space="preserve">
970970
<value> Unmatched elements will be ignored.</value>
971971
</data>
972+
<dataname="EnumMatchIncomplete1"xml:space="preserve">
973+
<value>Enums may take values outside known cases.</value>
974+
</data>
972975
<dataname="RuleNeverMatched"xml:space="preserve">
973976
<value>This rule will never be matched</value>
974977
</data>

‎src/fsharp/PatternMatchCompilation.fs‎

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ open Microsoft.FSharp.Compiler.Lib
1919

2020
exception MatchIncompleteofbool*(string*bool)option*range
2121
exception RuleNeverMatchedofrange
22+
exception EnumMatchIncompleteofbool*(string*bool)option*range
2223

2324
typeActionOnFailure=
2425
| ThrowIncompleteMatchException
@@ -177,33 +178,37 @@ let RefuteDiscrimSet g m path discrims =
177178
| PathConj(p,_j)->
178179
go p tm
179180
| PathTuple(p,tys,j)->
180-
go p(fun _-> mkRefTupled g m(mkOneKnown tm j tys) tys)
181+
letk,eCoversVals= mkOneKnown tm j tys
182+
go p(fun _-> mkRefTupled g m k tys, eCoversVals)
181183
| PathRecd(p,tcref,tinst,j)->
182-
letflds= tcref|> actualTysOfInstanceRecdFields(mkTyconRefInst tcref tinst)|> mkOneKnown tm j
183-
go p(fun _-> Expr.Op(TOp.Recd(RecdExpr, tcref),tinst, flds,m))
184+
letflds,eCoversVals= tcref|> actualTysOfInstanceRecdFields(mkTyconRefInst tcref tinst)|> mkOneKnown tm j
185+
go p(fun _-> Expr.Op(TOp.Recd(RecdExpr, tcref),tinst, flds,m), eCoversVals)
184186

185187
| PathUnionConstr(p,ucref,tinst,j)->
186-
letflds= ucref|> actualTysOfUnionCaseFields(mkTyconRefInst ucref.TyconRef tinst)|> mkOneKnown tm j
187-
go p(fun _-> Expr.Op(TOp.UnionCase(ucref),tinst, flds,m))
188+
letflds,eCoversVals= ucref|> actualTysOfUnionCaseFields(mkTyconRefInst ucref.TyconRef tinst)|> mkOneKnown tm j
189+
go p(fun _-> Expr.Op(TOp.UnionCase(ucref),tinst, flds,m), eCoversVals)
188190

189191
| PathArray(p,ty,len,n)->
190-
go p(fun _-> Expr.Op(TOp.Array,[ty], mkOneKnown tm n(List.replicate len ty),m))
192+
letflds,eCoversVals= mkOneKnown tm n(List.replicate len ty)
193+
go p(fun _-> Expr.Op(TOp.Array,[ty], flds,m), eCoversVals)
191194

192195
| PathExnConstr(p,ecref,n)->
193-
letflds= ecref|> recdFieldTysOfExnDefRef|> mkOneKnown tm n
194-
go p(fun _-> Expr.Op(TOp.ExnConstr(ecref),[], flds,m))
196+
letflds,eCoversVals= ecref|> recdFieldTysOfExnDefRef|> mkOneKnown tm n
197+
go p(fun _-> Expr.Op(TOp.ExnConstr(ecref),[], flds,m), eCoversVals)
195198

196199
| PathEmpty(ty)-> tm ty
197200

198-
andmkOneKnown tm n tys= List.mapi(fun i ty->if i= nthen tm tyelse mkUnknown ty) tys
199-
andmkUnknowns tys= List.map mkUnknown tys
201+
andmkOneKnown tm n tys=
202+
letflds= List.mapi(fun i ty->if i= nthen tm tyelse(mkUnknown ty,false)) tys
203+
List.map fst flds, List.fold(fun acc(_,eCoversVals)-> eCoversVals|| acc)false flds
204+
andmkUnknowns tys= List.map(fun x-> mkUnknown x) tys
200205

201206
lettm ty=
202207
match discrimswith
203208
|[DecisionTreeTest.IsNull]->
204-
snd(mkCompGenLocal m notNullText ty)
209+
snd(mkCompGenLocal m notNullText ty),false
205210
|[DecisionTreeTest.IsInst(_,_)]->
206-
snd(mkCompGenLocal m otherSubtypeText ty)
211+
snd(mkCompGenLocal m otherSubtypeText ty),false
207212
|(DecisionTreeTest.Const c:: rest)->
208213
letconsts= Set.ofList(c:: List.choose(function DecisionTreeTest.Const(c)-> Some c|_-> None) rest)
209214
letc'=
@@ -227,12 +232,23 @@ let RefuteDiscrimSet g m path discrims =
227232
| Const.Decimal_->seq{1.. System.Int32.MaxValue}|> Seq.map(fun v-> Const.Decimal(decimal v))
228233
|_->
229234
raise CannotRefute)
235+
236+
letcoversKnownEnumValues=
237+
match tryDestAppTy g tywith
238+
| Some tcrefwhen tcref.IsEnumTycon->
239+
letknownValues=
240+
tcref.AllFieldsArray|> Array.choose(fun f->
241+
match f.rfield_const, f.rfield_staticwith
242+
| Some value,true-> Some value
243+
|_,_-> None)
244+
Array.forall(fun ev-> consts.Contains ev) knownValues
245+
|_->false
230246

231247
(* REVIEW: we could return a better enumeration literal field here if a field matches one of the enumeration cases*)
232248

233249
match c'with
234250
| None-> raise CannotRefute
235-
| Some c-> Expr.Const(c,m,ty)
251+
| Some c-> Expr.Const(c,m,ty), coversKnownEnumValues
236252

237253
|(DecisionTreeTest.UnionCase(ucref1,tinst):: rest)->
238254
letucrefs= ucref1:: List.choose(function DecisionTreeTest.UnionCase(ucref,_)-> Some ucref|_-> None) rest
@@ -246,10 +262,10 @@ let RefuteDiscrimSet g m path discrims =
246262
|[]-> raise CannotRefute
247263
| ucref2::_->
248264
letflds= ucref2|> actualTysOfUnionCaseFields(mkTyconRefInst tcref tinst)|> mkUnknowns
249-
Expr.Op(TOp.UnionCase(ucref2),tinst, flds,m)
265+
Expr.Op(TOp.UnionCase(ucref2),tinst, flds,m),false
250266

251267
|[DecisionTreeTest.ArrayLength(n,ty)]->
252-
Expr.Op(TOp.Array,[ty], mkUnknowns(List.replicate(n+1) ty),m)
268+
Expr.Op(TOp.Array,[ty], mkUnknowns(List.replicate(n+1) ty),m),false
253269

254270
|_->
255271
raise CannotRefute
@@ -302,15 +318,16 @@ let rec CombineRefutations g r1 r2 =
302318
letShowCounterExample g denv m refuted=
303319
try
304320
letrefutations= refuted|> List.collect(function RefutedWhenClause->[]|(RefutedInvestigation(path,discrim))->[RefuteDiscrimSet g m path discrim])
305-
letcounterExample=
321+
letcounterExample,enumCoversKnown=
306322
match refutationswith
307323
|[]-> raise CannotRefute
308-
| h:: t->
309-
if verbosethen dprintf"h =%s\n"(Layout.showL(exprL h))
310-
List.fold(CombineRefutations g) h t
324+
|(r, eck):: t->
325+
if verbosethen dprintf"r =%s (enumCoversKnownValue =%b)\n"(Layout.showL(exprL r)) eck
326+
List.fold(fun(rAcc,eckAcc)(r,eck)->
327+
CombineRefutations g rAcc r, eckAcc|| eck)(r, eck) t
311328
lettext= Layout.showL(NicePrint.dataExprL denv counterExample)
312329
letfailingWhenClause= refuted|> List.exists(function RefutedWhenClause->true|_->false)
313-
Some(text,failingWhenClause)
330+
Some(text,failingWhenClause,enumCoversKnown)
314331

315332
with
316333
| CannotRefute->
@@ -689,10 +706,15 @@ let CompilePatternBasic
689706
(* Emit the incomplete match warning*)
690707
if warnOnIncompletethen
691708
match actionOnFailurewith
692-
| ThrowIncompleteMatchException->
693-
warning(MatchIncomplete(false,ShowCounterExample g denv matchm refuted, matchm))
694-
| IgnoreWithWarning->
695-
warning(MatchIncomplete(true,ShowCounterExample g denv matchm refuted, matchm))
709+
| ThrowIncompleteMatchException| IgnoreWithWarning->
710+
letignoreWithWarning=(actionOnFailure= IgnoreWithWarning)
711+
match ShowCounterExample g denv matchm refutedwith
712+
| Some(text,failingWhenClause,true)->
713+
warning(EnumMatchIncomplete(ignoreWithWarning, Some(text,failingWhenClause), matchm))
714+
| Some(text,failingWhenClause,false)->
715+
warning(MatchIncomplete(ignoreWithWarning, Some(text,failingWhenClause), matchm))
716+
| None->
717+
warning(MatchIncomplete(ignoreWithWarning, None, matchm))
696718
|_->
697719
()
698720

‎src/fsharp/PatternMatchCompilation.fsi‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,4 @@ val internal CompilePattern :
6767

6868
exceptioninternal MatchIncompleteofbool*(string*bool)option*range
6969
exceptioninternal RuleNeverMatchedofrange
70+
exceptioninternal EnumMatchIncompleteofbool*(string*bool)option*range

‎src/fsharp/xlf/FSStrings.cs.xlf‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,11 @@
14221422
<targetstate="translated"> Nespárované prvky se budou ignorovat.</target>
14231423
<note />
14241424
</trans-unit>
1425+
<trans-unitid="EnumMatchIncomplete1">
1426+
<source>Enums may take values outside known cases.</source>
1427+
<targetstate="new">Enums may take values outside known cases.</target>
1428+
<note />
1429+
</trans-unit>
14251430
<trans-unitid="RuleNeverMatched">
14261431
<source>This rule will never be matched</source>
14271432
<targetstate="translated">Pro toto pravidlo nebude nikdy existovat shoda.</target>

‎src/fsharp/xlf/FSStrings.de.xlf‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,11 @@
14221422
<targetstate="translated"> Nicht zugeordnete Elemente werden ignoriert.</target>
14231423
<note />
14241424
</trans-unit>
1425+
<trans-unitid="EnumMatchIncomplete1">
1426+
<source>Enums may take values outside known cases.</source>
1427+
<targetstate="new">Enums may take values outside known cases.</target>
1428+
<note />
1429+
</trans-unit>
14251430
<trans-unitid="RuleNeverMatched">
14261431
<source>This rule will never be matched</source>
14271432
<targetstate="translated">Für diese Regel wird niemals eine Übereinstimmung gefunden.</target>

‎src/fsharp/xlf/FSStrings.en.xlf‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,11 @@
14221422
<targetstate="new"> Unmatched elements will be ignored.</target>
14231423
<note />
14241424
</trans-unit>
1425+
<trans-unitid="EnumMatchIncomplete1">
1426+
<source>Enums may take values outside known cases.</source>
1427+
<targetstate="new">Enums may take values outside known cases.</target>
1428+
<note />
1429+
</trans-unit>
14251430
<trans-unitid="RuleNeverMatched">
14261431
<source>This rule will never be matched</source>
14271432
<targetstate="new">This rule will never be matched</target>

‎src/fsharp/xlf/FSStrings.es.xlf‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,11 @@
14221422
<targetstate="translated"> Los elementos que no coinciden se omitirán.</target>
14231423
<note />
14241424
</trans-unit>
1425+
<trans-unitid="EnumMatchIncomplete1">
1426+
<source>Enums may take values outside known cases.</source>
1427+
<targetstate="new">Enums may take values outside known cases.</target>
1428+
<note />
1429+
</trans-unit>
14251430
<trans-unitid="RuleNeverMatched">
14261431
<source>This rule will never be matched</source>
14271432
<targetstate="translated">Nunca se buscarán coincidencias con esta regla.</target>

‎src/fsharp/xlf/FSStrings.fr.xlf‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,11 @@
14221422
<targetstate="translated"> Les éléments non appariés seront ignorés.</target>
14231423
<note />
14241424
</trans-unit>
1425+
<trans-unitid="EnumMatchIncomplete1">
1426+
<source>Enums may take values outside known cases.</source>
1427+
<targetstate="new">Enums may take values outside known cases.</target>
1428+
<note />
1429+
</trans-unit>
14251430
<trans-unitid="RuleNeverMatched">
14261431
<source>This rule will never be matched</source>
14271432
<targetstate="translated">Cette règle n'aura aucune correspondance</target>

‎src/fsharp/xlf/FSStrings.it.xlf‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,11 @@
14221422
<targetstate="translated"> Gli elementi senza corrispondenza verranno ignorati.</target>
14231423
<note />
14241424
</trans-unit>
1425+
<trans-unitid="EnumMatchIncomplete1">
1426+
<source>Enums may take values outside known cases.</source>
1427+
<targetstate="new">Enums may take values outside known cases.</target>
1428+
<note />
1429+
</trans-unit>
14251430
<trans-unitid="RuleNeverMatched">
14261431
<source>This rule will never be matched</source>
14271432
<targetstate="translated">Questa regola non avrà mai alcuna corrispondenza</target>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp