Having aggregate data types and syntactically having methods seems like a very facile definition of "OOP", versus the conventional uses referring to Smalltalk style message passing or inheritance and overrides. Other than being able to call functions as x.foo() rather than foo(x) or foo x or similar, languages like Haskell and C seem to satisfy the requirements for being OOP, which seems to make "OOP" completely useless as a category.
In any case, this point is been argued at length for every language, including Rust.
I actually think having syntactic methods is an important (if not the most important) part of "OOP". You compared x.foo() with foo(x), but that's the wrong comparison. The correct comparison is that when x if of type Tree, x.foo() vs tree_foo(x). Otherwise you get name clashes.
That is, I think the essence of "OOP", OOP-as-used, not any theoretical OOP, is function name resolution depending on type. That and syntax. So first, you write x.tree_foo() instead of tree_foo(x) which is purely syntactic. And then you shorten x.tree_foo() to x.foo(), because x is a tree, which is a great semantic help.
According to this definition, Haskell and C are not "OOP", which matches common understanding.
Function name resolution isn't OOP, it's attaching a namespace to a type. The _really_ important part is dynamic dispatch. You can have proper OOP without method syntax, it just looks awkward to our eyes. In fact, in Objective C,
I already agreed function name resolution isn't OOP. My argument was that it is "OOP", with quotes. My supporting evidence is that people consider C++ without any dynamic dispatch as "OOP", with quotes.
In any case, this point is been argued at length for every language, including Rust.