diff --git a/src/Fable.Transforms/Fable2Babel.fs b/src/Fable.Transforms/Fable2Babel.fs index a546e7b2b..08f484b9d 100644 --- a/src/Fable.Transforms/Fable2Babel.fs +++ b/src/Fable.Transforms/Fable2Babel.fs @@ -1406,6 +1406,9 @@ module Util = List.append entGenParams info.GenericParameters |> List.map (fun g -> g.Name) |> set + // Keep type parameters already in scope (e.g. from an enclosing generic + // function) so nested members/lambdas don't redeclare and shadow them. + |> Set.union ctx.ScopedTypeParams let declaredTypeParams = if isAttached then diff --git a/tests/Js/Main/TypeTests.fs b/tests/Js/Main/TypeTests.fs index c39f7bbb2..0347b92f1 100644 --- a/tests/Js/Main/TypeTests.fs +++ b/tests/Js/Main/TypeTests.fs @@ -679,6 +679,16 @@ type GenericMethodEncodableClass() = interface IGenericMethodEncodable with member _.Encode<'json>(helpers: IGenericMethodHelpers<'json>) = helpers.encodeString "x" +type IGenericMethodBox<'T> = + abstract Get: unit -> 'T + +// The lambda inside `Get` references the outer generic parameter 'item (via the +// captured `value`); it must not redeclare and shadow it. +let mapGenericMethodBox<'item> (value: 'item) : IGenericMethodBox<'item seq> = + { new IGenericMethodBox<'item seq> with + member _.Get() : 'item seq = Seq.map (fun (x: 'item) -> value) [ value ] + } + type ConcreteClass1() = inherit MangledAbstractClass5(2) @@ -1760,4 +1770,8 @@ let tests = let encodable = GenericMethodEncodableClass() :> IGenericMethodEncodable encodable.Encode(helpers) |> equal "S:x" + + testCase "Nested lambda does not shadow an outer generic type parameter" <| fun () -> + let box = mapGenericMethodBox 42 + box.Get() |> List.ofSeq |> equal [ 42 ] ]