The question is not why this fails for int[], but why it works for all the other types! Unfortunately, you have fallen prey to ADL which is actually calling std::size instead of the size function you have written. This is because all overloads of your function fail, and so it looks in the namespace of the first argument for a matching function, where it finds std::size. Rerun your program with the function renamed to something else:
template<typename T>
size_t my_size(std::span<T> s)
{
return s.size();
}
And on GCC 12 I get
prog.cc:18:25: error: no matching function for call to 'my_size(std::array<int, 5>&)'
18 | std::cout << my_size(arr) << my_size(vec) << my_size(il) << my_size(c_arr);
| ~~~~~~~^~~~~
prog.cc:7:8: note: candidate: 'template<class T> size_t my_size(std::span<_Type, 18446744073709551615>)'
7 | size_t my_size(std::span<T> s)
| ^~~~~~~
prog.cc:7:8: note: template argument deduction/substitution failed:
prog.cc:18:25: note: 'std::array<int, 5>' is not derived from 'std::span<_Type, 18446744073709551615>'
18 | std::cout << my_size(arr) << my_size(vec) << my_size(il) << my_size(c_arr);
| ~~~~~~~^~~~~
plus similar errors for all the other types. If your question is why is this failing; then the short answer is that template type deduction is far more strict than regular type deduction and so unless you give it an exact match (more or less), it will fail. For a more detailed explanation, read a similar question such as this one which deals with something similar.