Skip to content

Commit e1814d4

Browse files
committed
Fix problem with parameterized record types
1 parent 00729d3 commit e1814d4

File tree

5 files changed

+35
-30
lines changed

5 files changed

+35
-30
lines changed

ppx_src/src/Records.ml

+6-9
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ let wrapInSpreadEncoders parsedFields baseExpr =
4444
(fun spreadExpr acc -> [%expr [%e spreadExpr] [%e acc]])
4545
spreadExprs baseExpr
4646

47-
let generateEncoder parsedFields unboxed (rootTypeNameOfRecord : label) =
47+
let generateEncoder parsedFields unboxed (rootRecordTypeInfo : typeInfo) =
4848
(* If we've got a record with a spread type in it, we'll need to omit the spread
4949
from the generated fields, and handle its encoding differently. *)
5050
let parsedFieldsWithoutSpread =
@@ -58,7 +58,7 @@ let generateEncoder parsedFields unboxed (rootTypeNameOfRecord : label) =
5858
do more construction of things by hand with Ast_helper. *)
5959
Ast_helper.Pat.constraint_
6060
[%pat? valueToEncode]
61-
(Utils.labelToCoreType rootTypeNameOfRecord)
61+
(Utils.typeNameAndParamsToTypeDeclaration rootRecordTypeInfo)
6262
in
6363
match unboxed with
6464
| true ->
@@ -204,7 +204,7 @@ let generateDecoder decls unboxed =
204204
| Js.Json.JSONObject dict -> [%e generateNestedSwitches decls]
205205
| _ -> Decco.error "Not an object" v]
206206

207-
let parseRecordField encodeDecodeFlags (rootTypeNameOfRecord : label)
207+
let parseRecordField encodeDecodeFlags
208208
{pld_name = {txt}; pld_loc; pld_type; pld_attributes} =
209209
let default =
210210
match getAttributeByName pld_attributes "decco.default" with
@@ -247,16 +247,13 @@ let parseRecordField encodeDecodeFlags (rootTypeNameOfRecord : label)
247247
}
248248

249249
let generateCodecs ({doEncode; doDecode} as encodeDecodeFlags)
250-
recordFieldDeclarations unboxed (rootTypeNameOfRecord : label) =
250+
recordFieldDeclarations unboxed (rootRecordTypeInfo : typeInfo) =
251251
let parsedFieldDeclarations =
252-
List.map
253-
(parseRecordField encodeDecodeFlags rootTypeNameOfRecord)
254-
recordFieldDeclarations
252+
List.map (parseRecordField encodeDecodeFlags) recordFieldDeclarations
255253
in
256254
( (match doEncode with
257255
| true ->
258-
Some
259-
(generateEncoder parsedFieldDeclarations unboxed rootTypeNameOfRecord)
256+
Some (generateEncoder parsedFieldDeclarations unboxed rootRecordTypeInfo)
260257
| false -> None),
261258
match doDecode with
262259
| true -> Some (generateDecoder parsedFieldDeclarations unboxed)

ppx_src/src/Structure.ml

+21-20
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,19 @@ let buildRightHandSideOfEqualSignForCodecDeclarations (paramNames : label list)
5757
(* This is where the value bindings get made for the codec functions
5858
but it isn't where the codec functions themselves are generated. Those
5959
get passed in. This is the outermost layer of the t_encode and t_decode functions *)
60-
let generateCodecDecls typeName paramNames (encoder, decoder) =
61-
let encoderPat = Pat.var (mknoloc (typeName ^ Utils.encoderFuncSuffix)) in
62-
let encoderParamNames = List.map (fun s -> encoderVarPrefix ^ s) paramNames in
63-
let decoderPat = Pat.var (mknoloc (typeName ^ Utils.decoderFuncSuffix)) in
64-
let decoderParamNames = List.map (fun s -> decoderVarPrefix ^ s) paramNames in
60+
let generateCodecDecls (typeInfo : typeInfo) (encoder, decoder) =
61+
let encoderPat =
62+
Pat.var (mknoloc (typeInfo.typeName ^ Utils.encoderFuncSuffix))
63+
in
64+
let encoderParamNames =
65+
List.map (fun s -> encoderVarPrefix ^ s) typeInfo.typeParams
66+
in
67+
let decoderPat =
68+
Pat.var (mknoloc (typeInfo.typeName ^ Utils.decoderFuncSuffix))
69+
in
70+
let decoderParamNames =
71+
List.map (fun s -> decoderVarPrefix ^ s) typeInfo.typeParams
72+
in
6573
let encoderBindings =
6674
match encoder with
6775
| None -> []
@@ -71,9 +79,7 @@ let generateCodecDecls typeName paramNames (encoder, decoder) =
7179
~attrs:[attrWarning [%expr "-39"]]
7280
encoderPat
7381
(buildRightHandSideOfEqualSignForCodecDeclarations encoderParamNames
74-
encoder
75-
{typeName; typeParams = paramNames}
76-
true);
82+
encoder typeInfo true);
7783
]
7884
in
7985
let decoderBindings =
@@ -85,9 +91,7 @@ let generateCodecDecls typeName paramNames (encoder, decoder) =
8591
~attrs:[attrWarning [%expr "-4"]; attrWarning [%expr "-39"]]
8692
decoderPat
8793
(buildRightHandSideOfEqualSignForCodecDeclarations decoderParamNames
88-
decoder
89-
{typeName; typeParams = paramNames}
90-
false);
94+
decoder typeInfo false);
9195
]
9296
in
9397
[] @ encoderBindings @ decoderBindings
@@ -114,6 +118,7 @@ let mapTypeDecl decl =
114118
match makeEncodeDecodeFlagsFromDecoratorAttributes ptype_attributes with
115119
| Ok None -> []
116120
| Ok (Some encodeDecodeFlags) -> (
121+
let typeInfo = {typeName; typeParams = getParamNames ptype_params} in
117122
(* Here we call the code to generate the codecs and build their
118123
value bindings (the let t_decode = ... part). We have various different
119124
types to handle, so there's a switch. Most simple cases are covered in
@@ -126,21 +131,17 @@ let mapTypeDecl decl =
126131
fail ptype_loc "Can't generate codecs for unspecified type"
127132
| Some {ptyp_desc = Ptyp_variant (rowFields, _, _)}, Ptype_abstract ->
128133
let rowFieldsDec = List.map (fun row -> row.prf_desc) rowFields in
129-
generateCodecDecls typeName
130-
(getParamNames ptype_params)
134+
generateCodecDecls typeInfo
131135
(Polyvariants.generateCodecs encodeDecodeFlags rowFieldsDec isUnboxed)
132136
| Some manifest, _ ->
133-
generateCodecDecls typeName
134-
(getParamNames ptype_params)
137+
generateCodecDecls typeInfo
135138
(Codecs.generateCodecs encodeDecodeFlags manifest)
136139
| None, Ptype_variant decls ->
137-
generateCodecDecls typeName
138-
(getParamNames ptype_params)
140+
generateCodecDecls typeInfo
139141
(Variants.generateCodecs encodeDecodeFlags decls isUnboxed)
140142
| None, Ptype_record decls ->
141-
generateCodecDecls typeName
142-
(getParamNames ptype_params)
143-
(Records.generateCodecs encodeDecodeFlags decls isUnboxed typeName)
143+
generateCodecDecls typeInfo
144+
(Records.generateCodecs encodeDecodeFlags decls isUnboxed typeInfo)
144145
| _ -> fail ptype_loc "This type is not handled by decco")
145146
| Error s -> fail ptype_loc s
146147

ppx_src/src/Utils.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,5 +141,5 @@ let labelToCoreType label = Ast_helper.Typ.constr (lid label) []
141141

142142
type typeInfo = {typeName: label; typeParams: label list}
143143

144-
let typeNameAndParamsToTypeDeclaration {typeName; typeParams} =
144+
let typeNameAndParamsToTypeDeclaration ({typeName; typeParams} : typeInfo) =
145145
Typ.constr (lid typeName) (List.map (fun s -> Typ.var s) typeParams)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// At one point we had a regression where
2+
// the PPX failed to generate the type parameters
3+
// for the type of the decoder when using a parameterized
4+
// record. This test ensures that the issue is fixed.
5+
@decco
6+
type t<'param> = {blob: 'param}

test/compiler_only_tests/ReadMe.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This directory just contains rescript files that will be typechecked when `rescript build` runs. They don't run jest tests. But if they have a compiler error, they should fail the build.

0 commit comments

Comments
 (0)