@@ -18,10 +18,15 @@ r_obj* ffi_ptype_common(r_obj* ffi_call, r_obj* op, r_obj* args, r_obj* env) {
1818 struct r_lazy xs_arg_lazy = { .x = syms .dot_arg , .env = env };
1919 struct vctrs_arg xs_arg = new_lazy_arg (& xs_arg_lazy );
2020
21+ // User calls to `vec_ptype_common()` are always finalised and never fall back
22+ const enum ptype_finalise finalise = PTYPE_FINALISE_true ;
23+ const enum s3_fallback s3_fallback = S3_FALLBACK_false ;
24+
2125 r_obj * out = vec_ptype_common (
2226 xs ,
2327 ptype ,
24- S3_FALLBACK_false ,
28+ finalise ,
29+ s3_fallback ,
2530 & xs_arg ,
2631 call
2732 );
@@ -35,17 +40,22 @@ r_obj* ffi_ptype_common_params(r_obj* ffi_call, r_obj* op, r_obj* args, r_obj* e
3540
3641 r_obj * xs = r_node_car (args ); args = r_node_cdr (args );
3742 r_obj * ptype = r_node_car (args ); args = r_node_cdr (args );
43+ r_obj * ffi_finalise = r_node_car (args ); args = r_node_cdr (args );
3844 r_obj * opts = r_node_car (args );
3945
4046 struct r_lazy call = { .x = syms .dot_call , .env = env };
4147 struct r_lazy xs_arg_lazy = { .x = syms .dot_arg , .env = env };
4248 struct vctrs_arg xs_arg = new_lazy_arg (& xs_arg_lazy );
4349
50+ const enum ptype_finalise finalise = r_arg_as_bool (ffi_finalise , "finalise" ) ?
51+ PTYPE_FINALISE_true :
52+ PTYPE_FINALISE_false ;
4453 const enum s3_fallback s3_fallback = s3_fallback_from_opts (opts );
4554
4655 r_obj * out = vec_ptype_common (
4756 xs ,
4857 ptype ,
58+ finalise ,
4959 s3_fallback ,
5060 & xs_arg ,
5161 call
@@ -55,39 +65,50 @@ r_obj* ffi_ptype_common_params(r_obj* ffi_call, r_obj* op, r_obj* args, r_obj* e
5565}
5666
5767// Invariant of `vec_ptype_common()` is that the output is always a finalised `ptype`,
58- // even if the user provided their own
68+ // even if the user provided their own, unless `PTYPE_FINALISE_false` is specified.
5969r_obj * vec_ptype_common (
6070 r_obj * dots ,
6171 r_obj * ptype ,
72+ enum ptype_finalise finalise ,
6273 enum s3_fallback s3_fallback ,
6374 struct vctrs_arg * p_arg ,
6475 struct r_lazy call
6576) {
77+ int n_prot = 0 ;
78+
79+ r_obj * out ;
80+
6681 if (ptype != r_null ) {
67- return vec_ptype_final (ptype , vec_args .dot_ptype , call );
82+ out = KEEP_N (vec_ptype (ptype , vec_args .dot_ptype , call ), & n_prot );
83+ } else {
84+ if (r_is_true (r_peek_option ("vctrs.no_guessing" ))) {
85+ r_abort_lazy_call (r_lazy_null , "strict mode is activated; you must supply complete `.ptype`." );
86+ }
87+
88+ struct ptype_common_reduce_opts reduce_opts = {
89+ .call = call ,
90+ .s3_fallback = s3_fallback
91+ };
92+
93+ out = KEEP_N (
94+ reduce (
95+ r_null ,
96+ vec_args .empty ,
97+ p_arg ,
98+ dots ,
99+ & ptype2_common ,
100+ & reduce_opts
101+ ),
102+ & n_prot
103+ );
68104 }
69105
70- if (r_is_true ( r_peek_option ( "vctrs.no_guessing" ) )) {
71- r_abort_lazy_call ( r_lazy_null , "strict mode is activated; you must supply complete `.ptype`." );
106+ if (should_finalise ( finalise )) {
107+ out = KEEP_N ( vec_ptype_finalise ( out ), & n_prot );
72108 }
73109
74- struct ptype_common_reduce_opts reduce_opts = {
75- .call = call ,
76- .s3_fallback = s3_fallback
77- };
78-
79- r_obj * type = KEEP (reduce (
80- r_null ,
81- vec_args .empty ,
82- p_arg ,
83- dots ,
84- & ptype2_common ,
85- & reduce_opts
86- ));
87- type = vec_ptype_finalise (type );
88-
89- FREE (1 );
90- return type ;
110+ FREE (n_prot );
111+ return out ;
91112}
92113
93114static
0 commit comments