@@ -6218,6 +6218,44 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
62186218 }
62196219}
62206220
6221+ static void zend_is_intersection_redundant_with_intersection (const zend_type a , const zend_type b )
6222+ {
6223+ zend_type outer ;
6224+ zend_type inner ;
6225+ zend_type * single_outer ;
6226+ zend_type * single_inner ;
6227+
6228+ if (ZEND_TYPE_LIST (b )-> num_types < ZEND_TYPE_LIST (a )-> num_types ) {
6229+ outer = b ;
6230+ inner = a ;
6231+ } else {
6232+ outer = a ;
6233+ inner = b ;
6234+ }
6235+
6236+ /* As outer is the intersection type with the least number of types,
6237+ * it means that it is only redundant if all types of it are found in inner */
6238+ ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (outer ), single_outer ) {
6239+ bool is_found = false;
6240+ ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (inner ), single_inner ) {
6241+ if (zend_string_equals_ci (ZEND_TYPE_NAME (* single_outer ), ZEND_TYPE_NAME (* single_inner ))) {
6242+ is_found = true;
6243+ break ;
6244+ }
6245+ } ZEND_TYPE_LIST_FOREACH_END ();
6246+ /* Type not found in inner, thus cannot be redundant */
6247+ if (!is_found ) {
6248+ return ;
6249+ }
6250+ } ZEND_TYPE_LIST_FOREACH_END ();
6251+
6252+ /* Type is redundant */
6253+ zend_string * inner_type_str = zend_type_to_string (inner );
6254+ zend_string * outer_type_str = zend_type_to_string (outer );
6255+ zend_error_noreturn (E_COMPILE_ERROR ,
6256+ "Type %s is redundant with %s" , ZSTR_VAL (inner_type_str ), ZSTR_VAL (outer_type_str ));
6257+ }
6258+
62216259static zend_type zend_compile_typename (
62226260 zend_ast * ast , bool force_allow_null ) /* {{{ */
62236261{
@@ -6258,7 +6296,28 @@ static zend_type zend_compile_typename(
62586296
62596297 type_list -> types [type_list -> num_types ++ ] = single_type ;
62606298
6261- /* TODO Check for trivially redundant class types? */
6299+ /* Check for trivially redundant class types */
6300+ zend_type * individual_intersection_type ;
6301+ for (size_t i = 0 ; i < type_list -> num_types - 1 ; i ++ ) {
6302+ if (ZEND_TYPE_HAS_LIST (type_list -> types [i ])) {
6303+ ZEND_ASSERT (ZEND_TYPE_IS_INTERSECTION (type_list -> types [i ]));
6304+ zend_is_intersection_redundant_with_intersection (single_type , type_list -> types [i ]);
6305+ continue ;
6306+ }
6307+ ZEND_ASSERT (ZEND_TYPE_HAS_NAME (type_list -> types [i ]));
6308+
6309+ ZEND_TYPE_FOREACH (single_type , individual_intersection_type ) {
6310+ ZEND_ASSERT (ZEND_TYPE_HAS_NAME (* individual_intersection_type ));
6311+ if (zend_string_equals_ci ( ZEND_TYPE_NAME (type_list -> types [i ]),
6312+ ZEND_TYPE_NAME (* individual_intersection_type ))) {
6313+ zend_string * single_type_str = zend_type_to_string (single_type );
6314+ zend_string * duplicate_type_str = zend_type_to_string (* individual_intersection_type );
6315+ zend_error_noreturn (E_COMPILE_ERROR ,
6316+ "Type %s is redundant with %s" , ZSTR_VAL (single_type_str ),
6317+ ZSTR_VAL (duplicate_type_str ));
6318+ }
6319+ } ZEND_TYPE_FOREACH_END ();
6320+ }
62626321 continue ;
62636322 }
62646323
@@ -6298,6 +6357,18 @@ static zend_type zend_compile_typename(
62986357 /* Check for trivially redundant class types */
62996358 for (size_t i = 0 ; i < type_list -> num_types - 1 ; i ++ ) {
63006359 if (ZEND_TYPE_IS_INTERSECTION (type_list -> types [i ])) {
6360+ zend_type * individual_intersection_type ;
6361+ ZEND_TYPE_FOREACH (type_list -> types [i ], individual_intersection_type ) {
6362+ ZEND_ASSERT (ZEND_TYPE_HAS_NAME (* individual_intersection_type ));
6363+ if (zend_string_equals_ci (ZEND_TYPE_NAME (single_type ),
6364+ ZEND_TYPE_NAME (* individual_intersection_type ))) {
6365+ zend_string * single_type_str = zend_type_to_string (single_type );
6366+ zend_string * intersection_str = zend_type_to_string (type_list -> types [i ]);
6367+ zend_error_noreturn (E_COMPILE_ERROR ,
6368+ "Type %s is redundant with %s" , ZSTR_VAL (intersection_str ),
6369+ ZSTR_VAL (single_type_str ));
6370+ }
6371+ } ZEND_TYPE_FOREACH_END ();
63016372 continue ;
63026373 }
63036374 if (zend_string_equals_ci (
0 commit comments