-
Notifications
You must be signed in to change notification settings - Fork 831
Allow extension methods without type attribute. #13839
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
Changes from all commits
d83428f
c1fbfc1
c7b0f57
7fa66cf
710bedd
9a853ec
c0c3425
a336508
f99916a
723563f
45a3649
34f6c9b
31c08f5
c058bb6
ae5030c
e62423c
1cd9c55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -530,14 +530,18 @@ let IsMethInfoPlainCSharpStyleExtensionMember g m isEnclExtTy (minfo: MethInfo) | |
| /// Get the info for all the .NET-style extension members listed as static members in the type. | ||
| let private GetCSharpStyleIndexedExtensionMembersForTyconRef (amap: Import.ImportMap) m (tcrefOfStaticClass: TyconRef) = | ||
| let g = amap.g | ||
|
|
||
| if IsTyconRefUsedForCSharpStyleExtensionMembers g m tcrefOfStaticClass then | ||
| let pri = NextExtensionMethodPriority() | ||
|
|
||
| if g.langVersion.SupportsFeature(LanguageFeature.CSharpExtensionAttributeNotRequired) then | ||
| let ty = generalizedTyconRef g tcrefOfStaticClass | ||
|
|
||
| let minfos = | ||
| GetImmediateIntrinsicMethInfosOfType (None, AccessorDomain.AccessibleFromSomeFSharpCode) g amap m ty | ||
| |> List.filter (IsMethInfoPlainCSharpStyleExtensionMember g m true) | ||
|
Comment on lines
535
to
+539
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm concerned about the performance implications of this preview feature. If my late-night analysis is correct it seems to me we're now looking into the methods of every type in every opened namespace. This must be traversing a lot more metadata than previously. This will be very significant both from a perf question - think what happens if there are types in referenced assemblies that were previously unused that contain 100,000 methods. It also has some correctness implications see #15158. Given the feature being implemented this is a little tricky to avoid. We really have to be looking for the Now, these attributes will be correctly present in compiled reference assemblies because they are either explicit or added in CheckDeclarations, so for referenced assemblies we can just look at them. However these attributes are not necessarily present yet in the assembly being compiled - e.g. in the case of My (late night dont-take-as-gospel) recommendation is that this code be adjusted to look for |
||
|
|
||
| let minfos = GetImmediateIntrinsicMethInfosOfType (None, AccessorDomain.AccessibleFromSomeFSharpCode) g amap m ty | ||
| [ for minfo in minfos do | ||
| if IsMethInfoPlainCSharpStyleExtensionMember g m true minfo then | ||
| if IsTyconRefUsedForCSharpStyleExtensionMembers g m tcrefOfStaticClass || not minfos.IsEmpty then | ||
| let pri = NextExtensionMethodPriority() | ||
|
|
||
| [ for minfo in minfos do | ||
| let ilExtMem = ILExtMem (tcrefOfStaticClass, minfo, pri) | ||
|
|
||
| // The results are indexed by the TyconRef of the first 'this' argument, if any. | ||
|
|
@@ -584,9 +588,60 @@ let private GetCSharpStyleIndexedExtensionMembersForTyconRef (amap: Import.Impor | |
| | None -> () | ||
| | Some (Some tcref) -> yield Choice1Of2(tcref, ilExtMem) | ||
| | Some None -> yield Choice2Of2 ilExtMem ] | ||
| else | ||
| [] | ||
| else | ||
| [] | ||
|
|
||
| if IsTyconRefUsedForCSharpStyleExtensionMembers g m tcrefOfStaticClass then | ||
| let pri = NextExtensionMethodPriority() | ||
| let ty = generalizedTyconRef g tcrefOfStaticClass | ||
| let minfos = GetImmediateIntrinsicMethInfosOfType (None, AccessorDomain.AccessibleFromSomeFSharpCode) g amap m ty | ||
|
|
||
| [ for minfo in minfos do | ||
| if IsMethInfoPlainCSharpStyleExtensionMember g m true minfo then | ||
| let ilExtMem = ILExtMem (tcrefOfStaticClass, minfo, pri) | ||
| // The results are indexed by the TyconRef of the first 'this' argument, if any. | ||
| // So we need to go and crack the type of the 'this' argument. | ||
| // | ||
| // This is convoluted because we only need the ILTypeRef of the first argument, and we don't | ||
| // want to read any other metadata as it can trigger missing-assembly errors. It turns out ImportILTypeRef | ||
| // is less eager in reading metadata than GetParamTypes. | ||
| // | ||
| // We don't use the index for the IL extension method for tuple of F# function types (e.g. if extension | ||
| // methods for tuple occur in C# code) | ||
| let thisTyconRef = | ||
| try | ||
| let rs = | ||
| match metadataOfTycon tcrefOfStaticClass.Deref, minfo with | ||
| | ILTypeMetadata (TILObjectReprData(scoref, _, _)), ILMeth(_, ILMethInfo(_, _, _, ilMethod, _), _) -> | ||
| match ilMethod.ParameterTypes with | ||
| | firstTy :: _ -> | ||
| match firstTy with | ||
| | ILType.Boxed tspec | ILType.Value tspec -> | ||
| let tref = (tspec |> rescopeILTypeSpec scoref).TypeRef | ||
| if Import.CanImportILTypeRef amap m tref then | ||
| let tcref = tref |> Import.ImportILTypeRef amap m | ||
| if isCompiledTupleTyconRef g tcref || tyconRefEq g tcref g.fastFunc_tcr then None | ||
| else Some tcref | ||
| else None | ||
| | _ -> None | ||
| | _ -> None | ||
| | _ -> | ||
| // The results are indexed by the TyconRef of the first 'this' argument, if any. | ||
| // So we need to go and crack the type of the 'this' argument. | ||
| let thisTy = minfo.GetParamTypes(amap, m, generalizeTypars minfo.FormalMethodTypars).Head.Head | ||
| match thisTy with | ||
| | AppTy g (tcrefOfTypeExtended, _) when not (isByrefTy g thisTy) -> Some tcrefOfTypeExtended | ||
| | _ -> None | ||
|
Comment on lines
+611
to
+634
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to duplicate the code up above - could we have factored this out to prevent the duplication? |
||
| Some rs | ||
| with e -> // Import of the ILType may fail, if so report the error and skip on | ||
| errorRecovery e m | ||
| None | ||
| match thisTyconRef with | ||
| | None -> () | ||
| | Some (Some tcref) -> yield Choice1Of2(tcref, ilExtMem) | ||
| | Some None -> yield Choice2Of2 ilExtMem ] | ||
| else | ||
| [] | ||
|
|
||
| /// Query the declared properties of a type (including inherited properties) | ||
| let IntrinsicPropInfosOfTypeInScope (infoReader: InfoReader) optFilter ad findFlag m ty = | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.