@@ -179,6 +179,43 @@ static void dd_load_files(const char *files_file) {
179179
180180#define dd_load_files (file ) EXPECTED(get_global_DD_AUTOLOAD_NO_COMPILE() == false) ? dd_load_file("bridge/_generated_" file) : dd_load_files("bridge/_files_" file)
181181
182+ // Remove mixed return types for PHP 7.4 support. OpenTelemetry v2 now requires ": mixed" and drops PHP 7.4, but we fixup the AST here so that OpenTelemetry v1 still works with PHP 7.4.
183+ #if PHP_VERSION_ID >= 70400 && PHP_VERSION_ID < 80000
184+ void dd_walk_ast_top_stmt (zend_ast * ast ) {
185+ if (ast -> kind == ZEND_AST_STMT_LIST ) {
186+ zend_ast_list * list = zend_ast_get_list (ast );
187+ uint32_t i ;
188+ for (i = 0 ; i < list -> children ; ++ i ) {
189+ dd_walk_ast_top_stmt (list -> child [i ]);
190+ }
191+ } else if (ast -> kind == ZEND_AST_FUNC_DECL || ast -> kind == ZEND_AST_METHOD ) {
192+ zend_ast_decl * decl = (zend_ast_decl * ) ast ;
193+ zend_ast * return_type_ast = decl -> child [3 ];
194+ if (return_type_ast && return_type_ast -> kind != ZEND_AST_TYPE ) {
195+ if (zend_string_equals_literal (zend_ast_get_str (return_type_ast ), "mixed" )) {
196+ decl -> child [3 ] = NULL ;
197+ zend_ast_destroy (return_type_ast );
198+ }
199+ }
200+ } else if (ast -> kind == ZEND_AST_CLASS ) {
201+ zend_ast_decl * decl = (zend_ast_decl * ) ast ;
202+ zend_ast * stmt_ast = decl -> child [2 ];
203+
204+ dd_walk_ast_top_stmt (stmt_ast );
205+ } else if (ast -> kind == ZEND_AST_NAMESPACE && ast -> child [1 ]) {
206+ dd_walk_ast_top_stmt (ast -> child [1 ]);
207+ }
208+ }
209+
210+ zend_ast_process_t dd_prev_ast_process = NULL ;
211+ void dd_remove_mixed_return (zend_ast * ast ) {
212+ dd_walk_ast_top_stmt (ast );
213+ if (dd_prev_ast_process ) {
214+ dd_prev_ast_process (ast );
215+ }
216+ }
217+ #endif
218+
182219// We have, at this place, the luxury of knowing that we'll always be called before composers autoloader.
183220// Note that this code will also be called during opcache.preload, allowing us to not consider that scenario separately.
184221// The first time the autoloader gets invoked for ddtrace\\, we load the API
@@ -213,7 +250,14 @@ static zend_class_entry *dd_perform_autoload(zend_string *class_name, zend_strin
213250
214251 if ((get_DD_TRACE_OTEL_ENABLED () || get_DD_METRICS_OTEL_ENABLED ()) && zend_string_starts_with_literal (lc_name , "opentelemetry\\" ) && !DDTRACE_G (otel_is_loaded )) {
215252 DDTRACE_G (otel_is_loaded ) = 1 ;
253+ #if PHP_VERSION_ID >= 70400 && PHP_VERSION_ID < 80000
254+ dd_prev_ast_process = zend_ast_process ;
255+ zend_ast_process = dd_remove_mixed_return ;
216256 dd_load_files ("opentelemetry" );
257+ zend_ast_process = dd_prev_ast_process ;
258+ #else
259+ dd_load_files ("opentelemetry" );
260+ #endif
217261 if ((ce = zend_hash_find_ptr (EG (class_table ), lc_name ))) {
218262 return ce ;
219263 }
0 commit comments