Weird stuff. Some stuff I didn't previously know the details of...
This is all by design. The type-inference algorithm is described in some gory detail in the spec, but the rough idea is that it's top-to-bottom, outside-in, left-to-right inference. "o" is of type Other, but what is the type of "o.Foo"? It's obvious if you look at the body of "Other.Foo" and see "foo", but F# hasn't got to that point yet, it's still just starting to go inside bodies in top-to-bottom fashion. As a result, you can make the error go away like suggested here:
type foo () =
member x.Z = 100
type
bar(o:Other) =
member x.AAA = o.Foo.Z // Error here, unless
and
Other() =
let f = new foo()
member x.Foo(*:foo*) = f // you uncomment this
(e.g. by adding an annotation on the 'outside' of the 'Foo' property, so its type is known before looking into its body).
Alternatively, of course, you can reorder the types in this example (type Other...and bar...). It is a little strange that the order of 'type...and...' can 'matter', but those are the consequences of the language type inference rules.
Records have different semantics, largely due to OCaml-compatibility; a uniquely-named record field automagically implies a type of the expression it's a part of, for example
type MyRecord = { Yadda : string }
let f x = x.Yadda
infers the type of 'f' (that 'x' is a 'MyRecord'). But that rule is kinda ridiculous in an OO context:
let g x = x.Name // is x a System.Type, or a System.ServiceModel.Description.ContractDescription, or ...
where lots and lots of classes exist and lots of property names overlap. So effectively 'records' (and their field names) are 'special' to be more like OCaml, but they are the exception rather than the rule. Most of the time, if you want to do x.Blah, you must already 'know' the type of 'x'.