Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does VB.NET's "missing return value" warning specifically exclude "non-intrinsic value types"?

Consider the following code example:

Function f1() As Object     ' yields warning BC42353
End Function

Function f2() As Int32      ' yields warning BC42353
End Function

Function f3() As DateTime   ' yields warning BC42353
End Function

Function f4() As Guid       ' no warning
End Function

and the following project settings:

project settings

Apparently, VB.NET makes a difference between the following three categories of types:

  1. reference types [Example f1],
  2. "intrinsic" value types (some apparently undocumented subcategory of value type, see What is an intrinsic value type?) [Examples f2 and f3],
  3. "non-intrinsic" value types [Example f4],

and offers "missing return value" warnings for 1 + 2, but not for 3 (no such compiler option available).

What is so special about "non-intrinsic value types" that the language designers decided to omit this feature for this category of types?

(I suspect that this was a deliberate decision, since (I assume) it would have been easier to implement the feature for all value types than to check for some hard-coded "intrinsic" white-list first.)

like image 991
Heinzi Avatar asked Nov 29 '18 13:11

Heinzi


1 Answers

Given the source code of Roslyn VB compiler flow analysis source code and especially in the data flow pass that can be found here in line 1232 starts the sub that decides if this warning should be generated. Please note that I assume that based on various searches I performed in the repository.

The if statement starts in line 1250 which is as follows:

                If type.IsIntrinsicValueType Then


                    Select Case MethodSymbol.MethodKind
                        Case MethodKind.Conversion, MethodKind.UserDefinedOperator
                            warning = ERRID.WRN_DefAsgNoRetValOpVal1
                        Case MethodKind.PropertyGet
                            warning = ERRID.WRN_DefAsgNoRetValPropVal1
                        Case Else
                            Debug.Assert(MethodSymbol.MethodKind = MethodKind.Ordinary OrElse MethodSymbol.MethodKind = MethodKind.LambdaMethod)
                            warning = ERRID.WRN_DefAsgNoRetValFuncVal1
                    End Select


                ElseIf type.IsReferenceType Then


                    Select Case MethodSymbol.MethodKind
                        Case MethodKind.Conversion, MethodKind.UserDefinedOperator
                            warning = ERRID.WRN_DefAsgNoRetValOpRef1
                        Case MethodKind.PropertyGet
                            warning = ERRID.WRN_DefAsgNoRetValPropRef1
                        Case Else
                            Debug.Assert(MethodSymbol.MethodKind = MethodKind.Ordinary OrElse MethodSymbol.MethodKind = MethodKind.LambdaMethod)
                            warning = ERRID.WRN_DefAsgNoRetValFuncRef1
                    End Select


                ElseIf type.TypeKind = TypeKind.TypeParameter Then
                    ' IsReferenceType was false, so this type parameter was not known to be a reference type.
                    ' Following past practice, no warning is given in this case.


                Else
                    Debug.Assert(type.IsValueType)
                    Select Case MethodSymbol.MethodKind
                        Case MethodKind.Conversion, MethodKind.UserDefinedOperator
                            ' no warning is given in this case.
                        Case MethodKind.PropertyGet
                            warning = ERRID.WRN_DefAsgNoRetValPropRef1
                        Case MethodKind.EventAdd
                            ' In Dev11, there wasn't time to change the syntax of AddHandler to allow the user
                            ' to specify a return type (necessarily, EventRegistrationToken) for WinRT events.
                            ' DevDiv #376690 reflects the fact that this leads to an incredibly confusing user
                            ' experience if nothing is return: no diagnostics are reported, but RemoveHandler
                            ' statements will silently fail.  To prompt the user, (1) warn if there is no
                            ' explicit return, and (2) modify the error message to say "AddHandler As 
                            ' EventRegistrationToken" to hint at the nature of the problem.
                            ' Update: Dev11 just mangles an existing error message, but we'll introduce a new, 
                            ' clearer, one.


                            warning = ERRID.WRN_DefAsgNoRetValWinRtEventVal1
                            localName = MethodSymbol.AssociatedSymbol.Name
                        Case Else
                            warning = ERRID.WRN_DefAsgNoRetValFuncRef1
                    End Select
                End If

As you can see the only condition that a warning is not generated is if the type TypeKind property equals to TypeParameter. I really don't know more about those kind of types but I assume that there are some classes / types in the .NET framework (GUID must be one of them) that behave this way.

It doesn't seem to be a decision at all rather than a designed behavior of the compiler in certain types. However I can see from the code that it isn't so hard to add that warning based on the type of the method (function in this case) regardless the returning type which in my opinion is the best thing to do.

Hope this helps.

like image 157
ChD Computers Avatar answered Oct 27 '22 00:10

ChD Computers