JsonSchema and CFG are unhashable: defining __eq__ without __hash__ sets __hash__ = None
Bug Description
JsonSchema and CFG both define __eq__ without defining __hash__. Per the Python data model, when a class defines __eq__ but not __hash__, Python silently sets __hash__ = None, making instances unhashable. This means neither type can be used in a set or as a dict key.
Affected files
src/outlines/types/dsl.py—JsonSchema.__eq__at line 447 (no__hash__defined)src/outlines/types/dsl.py—CFGis a@dataclassthat defines explicit__eq__at line 258, which suppresses the dataclass-generated__hash__
Minimal reproducer
from outlines.types.dsl import JsonSchema, CFG
js = JsonSchema('{"type": "string"}')
print(JsonSchema.__hash__) # None
hash(js) # TypeError: unhashable type: 'JsonSchema'
{js} # TypeError: unhashable type: 'JsonSchema'
cfg = CFG("root ::= [0-9]+")
print(CFG.__hash__) # None
hash(cfg) # TypeError: unhashable type: 'CFG'
{cfg: "value"} # TypeError: unhashable type: 'CFG'Why this matters
Any code that stores output types in a set or uses them as dict keys will fail at runtime with a TypeError. This includes cache key construction, deduplication of output types, and any future caching layer over JsonSchema or CFG instances.
Suggested fix
Add __hash__ implementations consistent with the __eq__ semantics already defined.
JsonSchema — hash on normalised JSON (sorted keys) so equivalent schemas hash equally:
def __hash__(self):
try:
normalised = json.dumps(json.loads(self.schema), sort_keys=True)
except json.JSONDecodeError:
normalised = self.schema
return hash((normalised, self.whitespace_pattern))CFG — add unsafe_hash=True to the @dataclass decorator, or add:
def __hash__(self):
return hash(self.definition)Environment
Reproduced on Python 3.12 with Outlines main branch (2026-08-13).
Source: dottxt-ai/outlines