Question: I created a type using `defrecord` with type hints for the fields. However, I found that these type hints are not enforced in the constructors and I am able to do some strange things with them. Look at the snippet below for example:

```
user=> (defrecord Person [#^String name #^Integer age])
user.Person
user=> (seq (.getConstructors Person))
(#<Constructor public user.Person(java.lang.Object,java.lang.Object,
java.lang.Object,java.lang.Object)>
#<Constructor public user.Person(java.lang.Object,java.lang.Object)>)
user=> (Person. (Integer. 123) "abhinav")
#:user.Person{:name 123, :age "abhinav"}

```

The constructor signatures shown do not match with the type hints provided (they use `Object` for both `String` and `Integer`) and I am able to construct objects with wrong field types.

Is there something wrong with my code or is it a bug in Clojure?

I am on Clojure 1.2.0-beta1.

Answer: 
Type-hints are used to avoid reflection; they are not (currently) used to statically type function or constructor args (the exception being primitives since they can't be subsumed under `Object`). As such, they don't do much for a simple record, but they do matter when it comes to adding protocol implementation, e.g.:

```

user=> (set! *warn-on-reflection* true)
true
user=> (defprotocol P (foo [p]))
P
user=> (defrecord R [s] P (foo [_] (.getBytes s)))  ; getBytes is a method on String
Reflection warning, NO_SOURCE_PATH:6 - reference to field getBytes can't be resolved.
user.R
user=> (foo (R. 5))
java.lang.IllegalArgumentException: No matching field found: getBytes for class java.lang.Integer (NO_SOURCE_FILE:0)
user=> (defrecord R [^String s] P (foo [_] (.getBytes s)))
user.R
user=> (foo (R. 5))
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String (NO_SOURCE_FILE:0)

```

The difference between the two versions is that the latter emits bytecode calling `String.getBytecode()` (hence the ClassCastException when passed an Integer), whereas the former needs to look up what exactly `.getBytes` means with respect to the runtime object passed to the function (and that process fails when passed an Integer).
As far as I can tell, type hints on `deftype` and `defprotocol` fields are currently only enforced when a primitive type is involved:

```
(deftype Foo [^int x])

(Foo. 5)    ; => OK
(Foo. :foo) ; => no go

;; ... and likewise with defprotocol

```

I have a very vague recollection of this being a recognised issue, though I'm not sure if the plan is to document this behaviour or to enforce non-primitive hints... I'll try to find out.