The three rules to apply to quite directly to standard OO C:
1. If t1 is a subclass of t2, t1 is also consistent with t2. (But not the other way around.)
Using the standard OO C method of subclassing structs, ie.
struct t2 {...}; struct t1 {struct t2 t2; ...};
This is obviously true and the normal subclass relationship, though the C syntax to use this is a bit awkward:
t2_method(&t1->t2, arg1, arg2);
2. Any is consistent with every type. (But Any is not a subclass of every type.)
In C the Any type is void. Using the class definitions above this is entirely valid and produces no warnings:
void v;
struct t1 = v;
So if you have an object of void type you can use it wherever you might require a stricter type. If you pass in something which is not consistent you'll get a runtime error (usually a segfault in the case of C).
3. Every type is a subclass of Any. (Which also makes every type consistent with Any, via rule 1.)
This just says that you can do the following without getting any warnings: struct t1 t1; void v = t1;
And this works quite well in C.
The extension to the C type system, beyond the type inference, is to make these rules recursive, especially in function types. For example, this produces a warning under GCC, though it will compile and run fine:
void f(int* func(int b, int c)) {}
void* g(void b, void c) {return b;}
f(g);
That might just be a limitation of GCC's type checking though.
I think this is quite a good direction to take. C's type system has proven sufficiently powerful over the decades to build large systems and at the same time is trivially bypassed when you paint yourself into a typed corner or you want flexibility strict static type checking finds cumbersome to provide.