@@ -8,6 +8,9 @@ extern SEXP ns_S7;
8
8
extern SEXP sym_obj_dispatch ;
9
9
extern SEXP sym_dispatch_args ;
10
10
extern SEXP sym_methods ;
11
+ extern SEXP sym_S7_dispatch ;
12
+ extern SEXP sym_name ;
13
+
11
14
extern SEXP fn_base_quote ;
12
15
extern SEXP fn_base_missing ;
13
16
@@ -181,8 +184,8 @@ SEXP method_call_(SEXP call_, SEXP op_, SEXP args_, SEXP env_) {
181
184
SEXP mcall_tail = mcall ;
182
185
183
186
PROTECT_INDEX arg_pi , val_pi ;
184
- PROTECT_WITH_INDEX (R_NilValue , & arg_pi );
185
- PROTECT_WITH_INDEX (R_NilValue , & val_pi );
187
+ PROTECT_WITH_INDEX (R_NilValue , & arg_pi ); // unnecessary, for rchk only
188
+ PROTECT_WITH_INDEX (R_NilValue , & val_pi ); // unnecessary, for rchk only
186
189
187
190
// For each of the arguments to the generic
188
191
for (R_xlen_t i = 0 ; i < n_args ; ++ i ) {
@@ -205,9 +208,9 @@ SEXP method_call_(SEXP call_, SEXP op_, SEXP args_, SEXP env_) {
205
208
// Instead of Rf_eval(arg, R_EmptyEnv), we do Rf_eval(name, envir), so that
206
209
// - if TYPEOF(arg) == LANGSXP or SYMSXP, arg doesn't need to be enquoted and
207
210
// - if TYPEOF(arg) == PROMSXP, arg is updated in place.
208
- REPROTECT (arg , arg_pi ); // not really necessary, but rchk flags spuriously
211
+ REPROTECT (arg , arg_pi ); // unnecessary, for rchk only
209
212
SEXP val = Rf_eval (name , envir );
210
- REPROTECT (val , val_pi );
213
+ REPROTECT (val , val_pi ); // unnecessary, for rchk only
211
214
212
215
if (Rf_inherits (val , "S7_super" )) {
213
216
@@ -250,7 +253,20 @@ SEXP method_call_(SEXP call_, SEXP op_, SEXP args_, SEXP env_) {
250
253
251
254
// Now that we have all the classes, we can look up what method to call
252
255
SEXP m = method_ (generic , dispatch_classes , envir , R_TRUE );
253
- SETCAR (mcall , m );
256
+ REPROTECT (m , val_pi ); // unnecessary, for rchk only
257
+
258
+ /// Inlining the method closure in the call like `SETCAR(mcall, m);`
259
+ /// leads to extremely verbose (unreadable) traceback()s. So,
260
+ /// for nicer tracebacks, we set a SYMSXP at the head.
261
+ SEXP method_name = Rf_getAttrib (m , sym_name );
262
+ if (TYPEOF (method_name ) != SYMSXP ) {
263
+ // if name is missing, fallback to masking the `S7_dispatch` symbol.
264
+ // we could alternatively fallback to inlining m: SETCAR(mcall, m)
265
+ method_name = sym_S7_dispatch ;
266
+ }
267
+
268
+ Rf_defineVar (method_name , m , envir );
269
+ SETCAR (mcall , method_name );
254
270
255
271
SEXP out = Rf_eval (mcall , envir );
256
272
UNPROTECT (4 );
0 commit comments