-
Notifications
You must be signed in to change notification settings - Fork 791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix issues around type directed conversion #13673
Fix issues around type directed conversion #13673
Conversation
Maybe this should be combined with similar work in #13063? I had similar thoughts that it may need a richer model to capture the different tdc forms, though ideally it should just be one big thing IMO. |
Fun test failure, the dumped IL is different on my machine by one dot, probably some ildasm culture output difference. CI error:
Changing it locally to include the |
@vzarytovskii @NinoFloris I'll need to review this very carefully. I'll be back at work properly next week and suggest we do it then |
5f8d5fc
to
b06451f
Compare
I included the fix for #12946 as well (could easily be split out if preferred). I've written about the source of the current broken behavior here #12946 (comment). |
47cbab8
to
69d109a
Compare
a81a9ce
to
ffa2e0d
Compare
I think this case should match coercion type-drected conversions - which are originate in CheckExpressions.fs via MustCoerce and so on.
It might be (I need to double check) that these specific coercions were present in F# 5.0 for "nullable interop" i.e. https://github.com/fsharp/fslang-design/blob/main/FSharp-5.0/FS-1075-nullable-interop.md. Or else yes, the checking in AdjustCalledArgTypeForOptionals should be sufficient - there is no specific need to guard again. |
Fixes test failures for cases where separate overloads have args like Nullable<int> and Nullable<int64> in the same position
ffa2e0d
to
a84386a
Compare
a84386a
to
5c67835
Compare
""" [] | ||
|
||
[<Test>] | ||
let ``Picking overload for typar does not favor any form of System.Nullable nor produce ambiguity warnings``() = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the name of this test still correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also could you add the cases
- With the
Nullable<float>
overload - With the
Nullable<float>
overload and withoutNullable<'T>
overload
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as it's compatible with the current definition of 'producing ambiguity warnings' I'd say yes. I also opened an issue that tracks the rest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a failing test for #13731
[<Test>] | ||
let ``C# method with an optional parameter and called with an option type should compile`` () = | ||
[<TestCase("5.0")>] | ||
[<TestCase("latest")>] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should preview
be added here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about it, that'd be fine. The commit that introduces this change specifically mentions it's to test the compiler pre and post FS-1093 additional conversions but preview would be compatible with that wording.
Also the baseline test that this test was copied from is running on preview and 4.7 (that's fsfromfsviacs
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to preview here too
@@ -119,7 +119,7 @@ type CallerArgs<'T> = | |||
/// has been used in F# code | |||
[<RequireQualifiedAccess>] | |||
type TypeDirectedConversionUsed = | |||
| Yes of (DisplayEnv -> exn) | |||
| Yes of (DisplayEnv -> exn) * isDoubleConversion: bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name DoubleConversion
is problematic - does it mean "int to double" or "there are two conversions".
Also could this better be an integer indicating the number of conversion rules applied?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point, something like isTwoStepConversion
would be a worse sounding but unambiguous name.
Regardless of naming this is a kludge to fix the immediate issue. I would suggest that the PR that fixes #13731 and fully resolves #13437 would introduce richer types like you did in #13063. that would be where we could capture potentially as a linked list (or just an integer indeed) all the conversions done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes isTwoStepConversion
please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed
@@ -5385,7 +5385,7 @@ and TcAdjustExprForTypeDirectedConversions (cenv: cenv) (overallTy: OverallTy) a | |||
let g = cenv.g | |||
|
|||
match overallTy with | |||
| MustConvertTo (_, reqdTy) when g.langVersion.SupportsFeature LanguageFeature.AdditionalTypeDirectedConversions -> | |||
| MustConvertTo (isMethodArg, reqdTy) when g.langVersion.SupportsFeature LanguageFeature.AdditionalTypeDirectedConversions || (g.langVersion.SupportsFeature LanguageFeature.NullableOptionalInterop && isMethodArg) -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking aloud: The conditional here is now quite complex - maybe it would have been better originally to just always call AdjustExprForTypeDirectedConversions
and have the conditions on the specific rules in that method.
No need to change anything here though.
This is looking good - a couple of minor nits |
Ok so as mentioned offline, the only thing that's left to decide on is whether we should actually begin to emit the 'builtin conversion' warning under test here for Nullable<'T> 88ae3f8 The strongest argument for this change is that it brings those conversions in line with the other supported conversions. The downside for this implementation in particular is that it will only emit a warning when full type info is available, basically until this problem #13673 (comment) is tackled (captured in #13731) we'll have cases like 'T being converted to Nullable<'T> where the compiler won't warn yet. I think that's acceptable but maybe we want to do it all in one go. @dsyme please let me know, I'd like to get this off my list :) |
I think we won't do this as part of this PR, partly because emitting the warning (even optional) would take it from being a fix to a possible RFC. So I'll review now, and accept as is. Thank you sooooo much for your detailed work here. |
@NinoFloris thanks a lot for this! |
@NinoFloris pointed out privately that this does emit the FS3389 off-by-default warning in an additional case, seen here https://github.com/dotnet/fsharp/pull/13673/files#diff-0020979b647768e28019703c22e81771d97b9e9b26eb7c3cb518c692e6596beaR264 This is ok and I consider this a bug fix as it's definitely a type-directed conversion outside the scope of optional-arg interop (the argument is not labelled optional in metadata, it just has explicit type Nullable). Additionally, the presence of the warning doesn't affect overload resolution because this rule would already take this into account in overload resolution In short, all OK, I'm just noting this in case it comes up later |
Add notes summarizing my knowledge of the current state of this RFC after writing dotnet/fsharp#13673
This PR is split into a few parts:
The type 'bool' is not compatible with type 'float'
toThe type 'bool' is not compatible with type 'Nullable<float>'
which is what users would expect to see.Why integrate with the code for FS-1093? De-facto it already is; op_Implicit would trigger if FS-1075 would not exist in most cases (except the double conversion ones).
float
toNullable<float>
results inop_Implicit
without a warning being emitted today.@dsyme Maybe this needs a new RFC or change to FS-1093? Adding the diag seemed so small to me that it would fit under tidying up things.
In neither implementation nothing beyond the diag has been widened past what was specified in FS-1093 and FS-1075, notably:
let x: Nullable<float> = 1: int
as expected.@dsyme related, looking at line
fsharp/src/Compiler/Checking/MethodCalls.fs
Line 1306 in 9f65a3b
box unbox.any
due to the coerce. I assume this only happened because the type checks were more lenient than the expr adjustments?Also, none of the nullable interop conversions in
AdjustCallerArgForOptional
were guarded by the language feature flag, it is now guarded inAdjustExprForTypeDirectedConversions
. Maybe it was ok because it was already checked underAdjustCalledArgTypeForOptionals
?