-
Notifications
You must be signed in to change notification settings - Fork 790
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
SRTP doesn't handle calling member hiding inherited members #5531
Comments
I've successfully looked into this and apparently there's definitely no check prior to filter out any methods which are higher in the object hirachy (if they're matching in signature). |
This is a working fix for the example of dotnet#5531. However there are still some points open before I think it's a good idea to merge this: - Discuss the change of this proposal, is it OK to prefer overrides of methods and so ignore base implementations? - Extend the check to the complete inheritance graph instead of a single "look-back" - Only ignore a methinfo if the signature of both match (so respect different overloads) @dsyme It would be great if you could have a look whether this check is allowed at this location or should appear earlier.
How should the compiler act for such an example: type Base() =
abstract member Foo : unit -> unit
default this.Foo() = printfn "Base"
type Derived() =
inherit Base()
member this.Foo() = printfn "Derived"
type DerivedDerived() =
inherit Derived()
member this.Foo() = printfn "DerivedDerived"
let inline callFoo< ^T when ^T : (member Foo: unit -> unit) > (t: ^T) =
(^T : (member Foo: unit -> unit) (t))
let b = Base()
let d = Derived()
let dd = DerivedDerived()
let bd = d :> Base
callFoo<Derived> d
callFoo<DerivedDerived> dd Should |
If you are looking for overload resolution / late binding semantics corner cases, take a look at here and combine it with SRTPs: eg.: let inline callUpCv< ^T when ^T : (member Cv: Top -> unit) > (t: ^T) =
(^T : (member Cv: Top -> unit) (t)) |
@realvictorprm Compiler should have one single behavior. It's currently behaving one way when these methods are called without SRTP and should act exactly the same when SRTP is involved. type Base() =
abstract member Foo : unit -> unit
default this.Foo() = printfn "Base"
type Derived() =
inherit Base()
member this.Foo() = printfn "Derived"
type DerivedDerived() =
inherit Derived()
member this.Foo() = printfn "DerivedDerived"
let inline callFoo< ^T when ^T : (member Foo: unit -> unit) > (t: ^T) =
(^T : (member Foo: unit -> unit) (t))
let b = Base()
let d = Derived()
let dd = DerivedDerived()
let bd = d :> Base
d.Foo() //callFoo<Derived> d
dd.Foo() //callFoo<DerivedDerived> dd
bd.Foo() //callFoo<Base> bd Prints:
|
OK great, I have the same opinion on this. |
When SRTP is used to call a member that is hiding an inherited member (C#
new
modifier) it fail to compile with the following error:Repro steps
The last line of this program should compile as the type is fully known and the correct
Foo
method can be chosen (The compiler does it correctly when the method is called directly without SRTP)Known workarounds
None AFAIK, if a library you use suddenly does it (Like Roslyn just did between 2.8.2 and 2.9.0) you must rewrite everything without SRTP.
Related information
Tested on SDK 2.1.300 & 2.1.400
The text was updated successfully, but these errors were encountered: