-
Notifications
You must be signed in to change notification settings - Fork 803
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 for issue 8351 #8354
Fix for issue 8351 #8354
Conversation
src/fsharp/AccessibilityLogic.fs
Outdated
let getA = (resolveILMethodRef tdef mrefGet).Access | ||
let setA = (resolveILMethodRef tdef mrefSet).Access | ||
// pick most accessible | ||
max getA setA |
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.
Please let me know if using max
here is problematic and how you'd work around it.
@KevinRansom @dsyme can you take a look? |
Added another property that is expected to fail, exhibiting inconsistencies in how the error is reported depending if the type is defined in F# or not.
9b28332
to
b799113
Compare
Sigh!!! whilst this seems like a hack, if we look at how this function is used in the compiler, we can find this comment: Here // For IL properties, we get an approximate accessibility that at least reports "internal" as "internal" and "private" as "private" You have testing that shows, that later on we fix up the approximate nature of this resolution, and correctly fail when the setter is not visible here:(https://github.com/dotnet/fsharp/pull/8354/files#diff-ae28350224587d202ca4111c1125f62a) Whilst I hate using the ordinal position of visibility in that list, it's probably the simplest and least error prone mechanism available. I do however reserve the right to moan about it continuously |
My role model ... right there |
Yay, tests pass! @KevinRansom further thoughts? |
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.
Having a mechanism to determine visibility based on the "broadest visible item, is a good solution. I wish we didn't encode visibility broadness based on the ordinal position in the ILMemberAccess enum, however, this approach does accurately compute visibility.
Thanks for taking care of this
src/absil/il.fsi
Outdated
@@ -727,16 +727,17 @@ type ILMethodBody = | |||
SourceMarker: ILSourceMarker option } | |||
|
|||
/// Member Access | |||
// important: order of definition matters for AccessibilityLogic.GetILAccessOfILPropInfo |
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.
We might want to avoid having to rely on the order of this.
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.
@TIHan , I hate it too, however, every time I tried to reproduce the actual broadening algorithm, it ended up being horrific. One thing I think we could do, is to assign a specific value to each enum value, that way it is specific and deterministic, and not determined by the order in the source file.
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.
But relying on the order of declarations is how we F#. 😄
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.
@KevinRansom I think we can do this without having to do some broadening algorithm.
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.
Lol you are not wrong ... but some developer who is not familiar with the ordering, might prefer to alphabetize the enum and break everything.
Arguably that is covered, by a comment that says, "the order is important".
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.
Can we cover it with a test instead of a comment (or maybe choose a testing approach that makes comments actually useful by verifying their correctness with regard to the code)?
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.
@jonsequitur I've just added such test in tests/fsharp/Compiler/ILMemberAccessTests.fs : https://github.com/dotnet/fsharp/pull/8354/files#diff-6415f4a32cd76160025147135e46baaa
If cases are added/removed, the test, if not updated, will fail, and if some of the existing comparisons don't hold true anymore, it will also fail.
Please let me know if that fits the bill.
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.
Roslyn also does ordering: http://sourceroslyn.io/#Microsoft.CodeAnalysis/Symbols/Accessibility.cs , http://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp/Symbols/PropertyOrEventSymbolExtensions.cs,b31562460f5b74cc,references
I think for us, we technically don't need it for correctness in the compiler because the compiler simply asks a question if it is visible or not - all we need to do is ask if the get or set method is visible. However, the tooling, such as Symbols.fs
, does need to know which is more accessible in terms of ILMemberAccess
.
If we are going to do ordering, let's make the order just like Roslyn:
[<RequireQualifiedAccess>]
type ILMemberAccess =
| CompilerControlled
| Private
| FamilyAndAssembly // protected and internal
| Family // protected
| Assembly // internal
| FamilyOrAssembly // protected or internal
| Public
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.
@TIHan I've updated it to match your order, thanks!
| FSProp (_, _, None, Some vref) -> IsValAccessible ad vref | ||
| FSProp (_, _, Some vrefGet, Some vrefSet) -> | ||
// pick most accessible | ||
IsValAccessible ad vrefGet || IsValAccessible ad vrefSet |
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.
So this makes a lot of sense. I feel like we need to do something similar on the ILProp
side, maybe inside IsILPropInfoAccessible
?
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.
@TIHan I think this is handled:
fsharp/src/fsharp/AccessibilityLogic.fs
Lines 255 to 265 in 1ccb4b1
| Some mrefGet, Some mrefSet -> | |
let getA = (resolveILMethodRef tdef mrefGet).Access | |
let setA = (resolveILMethodRef tdef mrefSet).Access | |
// pick most accessible | |
max getA setA | |
| None, None -> ILMemberAccess.Public | |
ilAccess | |
let IsILPropInfoAccessible g amap m ad pinfo = | |
let ilAccess = GetILAccessOfILPropInfo pinfo | |
IsILTypeAndMemberAccessible g amap m ad ad pinfo.ILTypeInfo ilAccess |
it returns the max accessible in GetILAccessOfILPropInfo
which is then checked against IsILTypeAndMemberAccessible
.
Does that make sense?
@smoothdeveloper, i have an alternative way of doing the comparison that doesn't rely on the specification order of ILMemberAccess du. I'm taking a crack at tests that use the compiler instead of ILMemberAccessTests, to verify the visibility calculation which is kind of a complicated way of verifying that ILMember orders don't change :-) Anyway don't hate on me for this, if you can think of a better alternative or reasons why this won't worl I would welcome the feedback.
|
The drawbacks I see:
Nonetheless, I'm ok to go with the consensus in the team about what is the best approach, just let me know for me to make the adjustments. |
@smoothdeveloper, I don't like it either and I'm wondering if a comparer might be a better. Honestly, it's annoying that the compiler needs a notion of property visibility rather than relying on the visibility of the method implementing the operation being performed. However, it is there, whats super fun, is this is only an approximation, because of the disconnect between F# visibilities and the CLR notion of visibilities. All that said, at least the implementation detail this is dependent upon is the function responsible for doing this stuff. Anyway, I'm going to look at it some more. I'm not confident that I love either solution yet. |
@smoothdeveloper please take a look at this PR: #9445 it contains additional testing. It no longer is dependent on DU ordering. But will perform a lot worse. |
Co-authored-by: Gauthier Segay <[email protected]>
61e4dfe
to
24b4d28
Compare
@KevinRansom conflicts :) |
tentative fix for #8351, not sure of the implication, picking the most visible of both getter and setter when both are defined in AccessibilityLogic.fs, otherwise same logic as before when only either is defined.