diff --git a/src/fsharp/AccessibilityLogic.fs b/src/fsharp/AccessibilityLogic.fs index ca267ce2ff138e8238a44870b6604ebd648bfd02..6c4362d9a4f809232941a134d11d882b50450be9 100644 --- a/src/fsharp/AccessibilityLogic.fs +++ b/src/fsharp/AccessibilityLogic.fs @@ -90,7 +90,15 @@ let private IsILMemberAccessible g amap m (tcrefOfViewedItem : TyconRef) ad acce (access = ILMemberAccess.Assembly || access = ILMemberAccess.FamilyOrAssembly) && canAccessFromOneOf cpaths tcrefOfViewedItem.CompilationPath - (access = ILMemberAccess.Public) || accessibleByFamily || accessibleByInternalsVisibleTo + let accessibleByFamilyAndAssembly = + access = ILMemberAccess.FamilyAndAssembly && + canAccessFromOneOf cpaths tcrefOfViewedItem.CompilationPath && + match tcrefViewedFromOption with + | None -> false + | Some tcrefViewedFrom -> + ExistsHeadTypeInEntireHierarchy g amap m (generalizedTyconRef tcrefViewedFrom) tcrefOfViewedItem + + (access = ILMemberAccess.Public) || accessibleByFamily || accessibleByInternalsVisibleTo || accessibleByFamilyAndAssembly | AccessibleFromSomewhere -> true diff --git a/tests/fsharpqa/Source/Import/AccessibilityTests.cs b/tests/fsharpqa/Source/Import/AccessibilityTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..e3df6a9fb7055cd3f120ce9a1237af70c5cb2c6e --- /dev/null +++ b/tests/fsharpqa/Source/Import/AccessibilityTests.cs @@ -0,0 +1,18 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("FamAndAssembly")] +[assembly: InternalsVisibleTo("FamOrAssembly")] + + +public class Accessibility +{ + public int Public { get; set; } + private int Private { get; set; } + protected int Protected { get; set; } + internal int Internal { get; set; } + // Note: accessibility was modified using dnspy + public int FamOrAssembly { get; set; } + // Note: accessibility was modified using dnspy + public int FamAndAssembly { get; set; } +} + diff --git a/tests/fsharpqa/Source/Import/AccessibilityTests.dll b/tests/fsharpqa/Source/Import/AccessibilityTests.dll new file mode 100644 index 0000000000000000000000000000000000000000..0e01f245a7d15069221ccb8c6cc4561078833f20 Binary files /dev/null and b/tests/fsharpqa/Source/Import/AccessibilityTests.dll differ diff --git a/tests/fsharpqa/Source/Import/FamAndAssembly.fs b/tests/fsharpqa/Source/Import/FamAndAssembly.fs new file mode 100644 index 0000000000000000000000000000000000000000..50c621a50eeb75f949acee658bb0fdbe26ca9906 --- /dev/null +++ b/tests/fsharpqa/Source/Import/FamAndAssembly.fs @@ -0,0 +1,8 @@ +// #Regression #NoMT #Import + +namespace NS + +type T() = + // note: the assembly 'Accessibility' has an IVT to this assembly + inherit Accessibility() + member x.Test() = base.FamAndAssembly diff --git a/tests/fsharpqa/Source/Import/FamAndAssembly_NoIVT.fs b/tests/fsharpqa/Source/Import/FamAndAssembly_NoIVT.fs new file mode 100644 index 0000000000000000000000000000000000000000..cf4a423707dca0292ba8ba114bc1c34dd5229bff --- /dev/null +++ b/tests/fsharpqa/Source/Import/FamAndAssembly_NoIVT.fs @@ -0,0 +1,8 @@ +// #Regression #NoMT #Import +//The field, constructor or member 'FamAndAssembly' is not defined. +namespace NS + +type T() = + // note: the assembly 'Accessibility' does NOT have an IVT to this assembly, so it is expected to fail. + inherit Accessibility() + member x.Test() = base.FamAndAssembly diff --git a/tests/fsharpqa/Source/Import/FamOrAssembly.fs b/tests/fsharpqa/Source/Import/FamOrAssembly.fs new file mode 100644 index 0000000000000000000000000000000000000000..99f782d5e5c85db7045ca97dae8554974ddbb724 --- /dev/null +++ b/tests/fsharpqa/Source/Import/FamOrAssembly.fs @@ -0,0 +1,12 @@ +// #Regression #NoMT #Import + +namespace NS + +// note: the assembly 'Accessibility' has an IVT to this assembly + +type T() = + inherit Accessibility() + member x.Test() = base.FamOrAssembly + +module M = + let Test() = Accessibility().FamOrAssembly diff --git a/tests/fsharpqa/Source/Import/FamOrAssembly_NoIVT.fs b/tests/fsharpqa/Source/Import/FamOrAssembly_NoIVT.fs new file mode 100644 index 0000000000000000000000000000000000000000..e3bb98b76c6f0a72c4157d1278a5df78eabe089c --- /dev/null +++ b/tests/fsharpqa/Source/Import/FamOrAssembly_NoIVT.fs @@ -0,0 +1,12 @@ +// #Regression #NoMT #Import +//The member or object constructor 'FamOrAssembly' is not accessible. Private members may only be accessed from within the declaring type. Protected members may only be accessed from an extending type and cannot be accessed from inner lambda expressions. +namespace NS + +// with FamOrAssembly, this should succeed, even though there is no IVT +type T() = + inherit Accessibility() + member x.Test() = base.FamOrAssembly + +module M = + // note: the assembly 'Accessibility' does NOT have an IVT to this assembly, so it is expected to fail. + let Test() = Accessibility().FamOrAssembly diff --git a/tests/fsharpqa/Source/Import/env.lst b/tests/fsharpqa/Source/Import/env.lst index 2e274f177187ffa560caf49621665d420756ab2f..792c23a3ace18adb7d8c44c5eac95b6e19fbb765 100644 --- a/tests/fsharpqa/Source/Import/env.lst +++ b/tests/fsharpqa/Source/Import/env.lst @@ -80,6 +80,15 @@ NOMONO SOURCE=reference2.fsx SCFLAGS="--nologo -r:reference1.dll" PRECMD="\$FSC_ SOURCE=InternalsConsumer.fs SCFLAGS="-r:InternalsConsumer.CSAssembly.dll" PRECMD="\$CSC_PIPE /t:library InternalsConsumer.CSAssembly.cs" # InternalsConsumer.fs SOURCE=E_InternalsConsumer.fs SCFLAGS="-r:InternalsConsumer.CSAssembly.dll" PRECMD="\$CSC_PIPE /t:library InternalsConsumer.CSAssembly.cs" # E_InternalsConsumer.fs +### +### F# can consume FamOrAssembly and FamAndAssembly in combination with IVT +### + SOURCE=FamAndAssembly.fs SCFLAGS="-a -r:AccessibilityTests.dll" # FamAndAssembly.fs + ### See issue https://github.com/Microsoft/visualfsharp/issues/2496 + ### SOURCE=FamOrAssembly.fs SCFLAGS="-a -r:AccessibilityTests.dll" # FamOrAssembly.fs + SOURCE=FamAndAssembly_NoIVT.fs SCFLAGS="-a -r:AccessibilityTests.dll" # FamAndAssembly_NoIVT.fs + ### SOURCE=FamOrAssembly_NoIVT.fs SCFLAGS="-a -r:AccessibilityTests.dll" # FamOrAssembly_NoIVT.fs + ### ### Iterate over BCL collections ###