diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 81c5761..fb99bfc 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,3 +1,8 @@
+#### 8.9.0 - April 23, 2026
+
+- Tests: Add `GenerativeNestedTypesTests` — 5 tests for generative nested types: constructors, instance/static properties, instance methods inside nested classes
+- Refactor: `GetNestedTypes`/`GetMembers` on `ProvidedTypeDefinition` now use `canBindNestedType` for consistent BindingFlags-aware filtering of nested types
+
#### 8.8.0 - April 21, 2026
- Tests: Add `GenerativeInheritanceTests` — 5 tests for generative type inheritance: abstract base class, concrete derived classes, virtual method override dispatch verified at runtime
diff --git a/src/ProvidedTypes.fs b/src/ProvidedTypes.fs
index 1547219..6e1c33f 100644
--- a/src/ProvidedTypes.fs
+++ b/src/ProvidedTypes.fs
@@ -1613,7 +1613,7 @@ and ProvidedTypeDefinition(isTgt: bool, container:TypeContainer, className: stri
override __.GetNestedTypes bindingFlags =
(//save ("nested", bindingFlags, None) (fun () ->
getMembers()
- |> Array.choose (function :? Type as m when memberBinds true bindingFlags false m.IsPublic || m.IsNestedPublic -> Some m | _ -> None)
+ |> Array.choose (function :? Type as m when canBindNestedType bindingFlags m -> Some m | _ -> None)
|> (if hasFlag bindingFlags BindingFlags.DeclaredOnly || isNull this.BaseType then id else (fun mems -> Array.append mems (this.ErasedBaseType.GetNestedTypes(bindingFlags)))))
override this.GetConstructorImpl(bindingFlags, _binder, _callConventions, _types, _modifiers) =
@@ -1687,7 +1687,7 @@ and ProvidedTypeDefinition(isTgt: bool, container:TypeContainer, className: stri
| :? FieldInfo as m when memberBinds false bindingFlags m.IsStatic m.IsPublic -> yield (m :> _)
| :? PropertyInfo as m when memberBinds false bindingFlags m.IsStatic m.IsPublic -> yield (m :> _)
| :? EventInfo as m when memberBinds false bindingFlags m.IsStatic m.IsPublic -> yield (m :> _)
- | :? Type as m when memberBinds true bindingFlags false m.IsPublic || m.IsNestedPublic -> yield (m :> _)
+ | :? Type as m when canBindNestedType bindingFlags m -> yield (m :> _)
| _ -> () |]
override this.GetMember(name, mt, _bindingFlags) =
diff --git a/tests/FSharp.TypeProviders.SDK.Tests.fsproj b/tests/FSharp.TypeProviders.SDK.Tests.fsproj
index 9f39319..adbd809 100644
--- a/tests/FSharp.TypeProviders.SDK.Tests.fsproj
+++ b/tests/FSharp.TypeProviders.SDK.Tests.fsproj
@@ -26,6 +26,7 @@
+
diff --git a/tests/GenerativeNestedTypesTests.fs b/tests/GenerativeNestedTypesTests.fs
new file mode 100644
index 0000000..7477a8e
--- /dev/null
+++ b/tests/GenerativeNestedTypesTests.fs
@@ -0,0 +1,172 @@
+module TPSDK.GenerativeNestedTypesTests
+
+// Tests for generative nested types: one ProvidedTypeDefinition hosting other
+// ProvidedTypeDefinitions as nested (inner) types.
+//
+// Scenario:
+// class Library
+// nested class Book { Title: string; Author: string; ctor(t,a); GetSummary(): string }
+// nested class Shelf { Label: string; ctor(label); MaxItems: int (static) }
+//
+// Tests verify that nested types are emitted correctly, that their constructors,
+// fields, instance methods, and static members are all accessible at runtime.
+
+#nowarn "760" // IDisposable needs new
+
+open System
+open System.Reflection
+open Microsoft.FSharp.Core.CompilerServices
+open Microsoft.FSharp.Quotations
+open Xunit
+open ProviderImplementation.ProvidedTypes
+open ProviderImplementation.ProvidedTypesTesting
+open UncheckedQuotations
+
+[]
+type GenerativeNestedProvider (config: TypeProviderConfig) as this =
+ inherit TypeProviderForNamespaces (config)
+
+ let ns = "Nested.Provided"
+ let tempAssembly = ProvidedAssembly()
+ let container = ProvidedTypeDefinition(tempAssembly, ns, "Library", Some typeof, isErased = false)
+
+ do
+ // ── nested class: Book ───────────────────────────────────────────────
+ let bookType = ProvidedTypeDefinition("Book", Some typeof, isErased = false)
+
+ let titleField = ProvidedField("_title", typeof)
+ let authorField = ProvidedField("_author", typeof)
+ bookType.AddMember titleField
+ bookType.AddMember authorField
+
+ // constructor: Book(title: string, author: string)
+ bookType.AddMember
+ (ProvidedConstructor(
+ [ ProvidedParameter("title", typeof)
+ ProvidedParameter("author", typeof) ],
+ invokeCode = fun args ->
+ Expr.Sequential(
+ Expr.FieldSetUnchecked(args.[0], titleField, args.[1]),
+ Expr.FieldSetUnchecked(args.[0], authorField, args.[2]))))
+
+ // property: Title : string
+ let titleProp =
+ ProvidedProperty("Title", typeof,
+ getterCode = fun args -> Expr.FieldGetUnchecked(args.[0], titleField))
+ bookType.AddMember titleProp
+
+ // instance method: GetSummary() : string → "«title» by «author»"
+ let getSummaryMethod =
+ ProvidedMethod("GetSummary", [], typeof, isStatic = false,
+ invokeCode = fun args ->
+ let t = Expr.FieldGetUnchecked(args.[0], titleField)
+ let a = Expr.FieldGetUnchecked(args.[0], authorField)
+ <@@ (%%t : string) + " by " + (%%a : string) @@>)
+ bookType.AddMember getSummaryMethod
+
+ // ── nested class: Shelf ──────────────────────────────────────────────
+ let shelfType = ProvidedTypeDefinition("Shelf", Some typeof, isErased = false)
+
+ let labelField = ProvidedField("_label", typeof)
+ shelfType.AddMember labelField
+
+ // constructor: Shelf(label: string)
+ shelfType.AddMember
+ (ProvidedConstructor(
+ [ ProvidedParameter("label", typeof) ],
+ invokeCode = fun args ->
+ Expr.FieldSetUnchecked(args.[0], labelField, args.[1])))
+
+ // property: Label : string
+ let labelProp =
+ ProvidedProperty("Label", typeof,
+ getterCode = fun args -> Expr.FieldGetUnchecked(args.[0], labelField))
+ shelfType.AddMember labelProp
+
+ // static property: MaxItems : int
+ let maxItemsProp =
+ ProvidedProperty("MaxItems", typeof, isStatic = true,
+ getterCode = fun _args -> <@@ 100 @@>)
+ shelfType.AddMember maxItemsProp
+
+ // ── register both nested types ───────────────────────────────────────
+ container.AddMember bookType
+ container.AddMember shelfType
+
+ tempAssembly.AddTypes [container]
+ this.AddNamespace(ns, [container])
+
+let loadTestAssembly () =
+ let runtimeAssemblyRefs = Targets.DotNetStandard20FSharpRefs()
+ let runtimeAssembly = runtimeAssemblyRefs.[0]
+ let cfg = Testing.MakeSimulatedTypeProviderConfig (__SOURCE_DIRECTORY__, runtimeAssembly, runtimeAssemblyRefs)
+ let tp = GenerativeNestedProvider(cfg) :> TypeProviderForNamespaces
+ let providedType = tp.Namespaces.[0].GetTypes().[0] :?> ProvidedTypeDefinition
+ Assert.Equal("Library", providedType.Name)
+ let bytes = (tp :> ITypeProvider).GetGeneratedAssemblyContents(providedType.Assembly)
+ let assem = Assembly.Load bytes
+ assem.ExportedTypes |> Seq.find (fun t -> t.Name = "Library")
+
+[]
+let ``Nested types Book and Shelf are present in generated assembly``() =
+ let library = loadTestAssembly ()
+ let book = library.GetNestedType("Book", BindingFlags.Public)
+ let shelf = library.GetNestedType("Shelf", BindingFlags.Public)
+ Assert.NotNull(book)
+ Assert.NotNull(shelf)
+ Assert.Equal("Book", book.Name)
+ Assert.Equal("Shelf", shelf.Name)
+
+[]
+let ``Book nested type has Title property and GetSummary method``() =
+ let library = loadTestAssembly ()
+ let book = library.GetNestedType("Book", BindingFlags.Public)
+ Assert.NotNull(book)
+
+ let titleProp = book.GetProperty("Title", BindingFlags.Instance ||| BindingFlags.Public)
+ let summaryMeth = book.GetMethod ("GetSummary", BindingFlags.Instance ||| BindingFlags.Public)
+ Assert.NotNull(titleProp)
+ Assert.NotNull(summaryMeth)
+ Assert.Equal(typeof, titleProp.PropertyType)
+ Assert.Equal(typeof, summaryMeth.ReturnType)
+
+[]
+let ``Book nested type constructor sets fields; GetSummary returns expected string``() =
+ let library = loadTestAssembly ()
+ let book = library.GetNestedType("Book", BindingFlags.Public)
+ Assert.NotNull(book)
+
+ let ctor = book.GetConstructor([| typeof; typeof |])
+ Assert.NotNull(ctor)
+ let instance = ctor.Invoke([| box "FSharp for Fun"; box "Don Syme" |])
+ Assert.NotNull(instance)
+
+ let summaryMeth = book.GetMethod("GetSummary", BindingFlags.Instance ||| BindingFlags.Public)
+ let result = summaryMeth.Invoke(instance, [||]) :?> string
+ Assert.Equal("FSharp for Fun by Don Syme", result)
+
+[]
+let ``Shelf nested type Label property reflects constructor argument``() =
+ let library = loadTestAssembly ()
+ let shelf = library.GetNestedType("Shelf", BindingFlags.Public)
+ Assert.NotNull(shelf)
+
+ let ctor = shelf.GetConstructor([| typeof |])
+ Assert.NotNull(ctor)
+ let instance = ctor.Invoke([| box "Science Fiction" |])
+
+ let labelProp = shelf.GetProperty("Label", BindingFlags.Instance ||| BindingFlags.Public)
+ Assert.NotNull(labelProp)
+ let value = labelProp.GetValue(instance) :?> string
+ Assert.Equal("Science Fiction", value)
+
+[]
+let ``Shelf nested type static property MaxItems returns 100``() =
+ let library = loadTestAssembly ()
+ let shelf = library.GetNestedType("Shelf", BindingFlags.Public)
+ Assert.NotNull(shelf)
+
+ let maxItemsProp = shelf.GetProperty("MaxItems", BindingFlags.Static ||| BindingFlags.Public)
+ Assert.NotNull(maxItemsProp)
+ let value = maxItemsProp.GetValue(null) :?> int
+ Assert.Equal(100, value)