As long as the result of the PUT is a complete replacement from the client's understanding of the resource (i.e., the previous values for those properties not passed do not influence their value after the PUT), it should succeed. However, it does make it a bit confusing to look at, since so many people have a tendency to equivocate this use of PUT with field-level update semantics (rather than complete replacement).
While there's technically no violation of REST constraints here, it's probably a better idea to pass in all values and not resort to server defaults, because that will help preserve forward compatibility. Defaults can change over time, so generally they should be avoided.
Your example of links, however, is not referring to not passing defaults, so it's not a good example of an "incomplete representation." Rather, links aren't part of the client's representation of the resource to the server. I think you're bringing another concept into the mix here: properties which are only returned from the server to the client. This is what I was talking about on the other thread which sparked this post.
What I am talking about is not an incomplete representation; it's a different representation. You are really dealing with two different media types (i.e., representations) describing the same resource. One originates from the client (we'll call it application/vnd.example.api.client), and the other originates from the server (application/vnd.example.api.server). They may not explicitly be labeled as such, but that's at least implicitly what's happening. Therefore, since they are two different media types, they express different things about the same resource.
Since you mentioned HAL, consider that a client doesn't usually POST a message of media type application/hal+json to the server. Take a look at the signup rel from HALTalk for an example. The expected content type is application/json, not application/hal+json. And, if you look at the example post, there is nothing HAL-ish about it. No links, no embedded objects, etc. But... if you then GET the URL returned from the Location header returned from this POST, it will, assuming your client accepts HAL over JSON, return a response of type application/hal+json (i.e., a user with links). Two different media types, two different representations of the same resource.
So let me decorate your example with Accept and Content-Type headers to illustrate my point.
Request
PUT /api/users/1 HTTP/1.1
Content-Type: application/vnd.example.api.client+json
{'username': 'joeydoey',
'email': '[email protected]'}
Response
200 OK
Content-Type: application/hal+json;profile=application/vnd.example.api.server
{'id': 1,
'username': 'joeydoey',
'email': '[email protected]',
'password_hash': '9039dmk38f84uf4029i339kf32f0932i',
'_links': {'self': {'href': 'http://foo.bar.com/api/users/1'}}
}
Most systems don't go to this amount of detail to describe their media types. Usually it's just framed in a more generic type (like application/json or only one custom media type). However, none of this changes that fact that while it is the same underlying resource, these are two different representations. Make sense?