@@ -179,6 +179,41 @@ 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+ }
206+ }
207+
208+ zend_ast_process_t dd_prev_ast_process = NULL ;
209+ void dd_remove_mixed_return (zend_ast * ast ) {
210+ dd_walk_ast_top_stmt (ast );
211+ if (dd_prev_ast_process ) {
212+ dd_prev_ast_process (ast );
213+ }
214+ }
215+ #endif
216+
182217// We have, at this place, the luxury of knowing that we'll always be called before composers autoloader.
183218// Note that this code will also be called during opcache.preload, allowing us to not consider that scenario separately.
184219// The first time the autoloader gets invoked for ddtrace\\, we load the API
@@ -213,7 +248,14 @@ static zend_class_entry *dd_perform_autoload(zend_string *class_name, zend_strin
213248
214249 if ((get_DD_TRACE_OTEL_ENABLED () || get_DD_METRICS_OTEL_ENABLED ()) && zend_string_starts_with_literal (lc_name , "opentelemetry\\" ) && !DDTRACE_G (otel_is_loaded )) {
215250 DDTRACE_G (otel_is_loaded ) = 1 ;
251+ #if PHP_VERSION_ID >= 70400 && PHP_VERSION_ID < 80000
252+ dd_prev_ast_process = zend_ast_process ;
253+ zend_ast_process = dd_remove_mixed_return ;
216254 dd_load_files ("opentelemetry" );
255+ zend_ast_process = dd_prev_ast_process ;
256+ #else
257+ dd_load_files ("opentelemetry" );
258+ #endif
217259 if ((ce = zend_hash_find_ptr (EG (class_table ), lc_name ))) {
218260 return ce ;
219261 }
0 commit comments